Package ganeti :: Package tools :: Module common
[hide private]
[frames] | no frames]

Source Code for Module ganeti.tools.common

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2014 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Common functions for tool scripts. 
 31   
 32  """ 
 33   
 34  import logging 
 35  import OpenSSL 
 36  import os 
 37  import time 
 38  from cStringIO import StringIO 
 39   
 40  from ganeti import constants 
 41  from ganeti import pathutils 
 42  from ganeti import utils 
 43  from ganeti import serializer 
 44  from ganeti import ssconf 
 45   
 46   
47 -def VerifyOptions(parser, opts, args):
48 """Verifies options and arguments for correctness. 49 50 """ 51 if args: 52 parser.error("No arguments are expected") 53 54 return opts
55 56
57 -def _VerifyCertificate(cert_pem, error_fn, 58 _check_fn=utils.CheckNodeCertificate):
59 """Verifies a certificate against the local node daemon certificate. 60 61 @type cert_pem: string 62 @param cert_pem: Certificate and key in PEM format 63 @type error_fn: callable 64 @param error_fn: function to call in case of an error 65 @rtype: string 66 @return: Formatted key and certificate 67 68 """ 69 try: 70 cert = \ 71 OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_pem) 72 except Exception, err: 73 raise error_fn("(stdin) Unable to load certificate: %s" % err) 74 75 try: 76 key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, cert_pem) 77 except OpenSSL.crypto.Error, err: 78 raise error_fn("(stdin) Unable to load private key: %s" % err) 79 80 # Check certificate with given key; this detects cases where the key given on 81 # stdin doesn't match the certificate also given on stdin 82 try: 83 utils.X509CertKeyCheck(cert, key) 84 except OpenSSL.SSL.Error: 85 raise error_fn("(stdin) Certificate is not signed with given key") 86 87 # Standard checks, including check against an existing local certificate 88 # (no-op if that doesn't exist) 89 _check_fn(cert) 90 91 key_encoded = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) 92 cert_encoded = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, 93 cert) 94 complete_cert_encoded = key_encoded + cert_encoded 95 if not cert_pem == complete_cert_encoded: 96 logging.error("The certificate differs after being reencoded. Please" 97 " renew the certificates cluster-wide to prevent future" 98 " inconsistencies.") 99 100 # Format for storing on disk 101 buf = StringIO() 102 buf.write(cert_pem) 103 return buf.getvalue()
104 105
106 -def VerifyCertificate(data, error_fn, _verify_fn=_VerifyCertificate):
107 """Verifies cluster certificate. 108 109 @type data: dict 110 @type error_fn: callable 111 @param error_fn: function to call in case of an error 112 @rtype: string 113 @return: Formatted key and certificate 114 115 """ 116 cert = data.get(constants.NDS_NODE_DAEMON_CERTIFICATE) 117 if not cert: 118 raise error_fn("Node daemon certificate must be specified") 119 120 return _verify_fn(cert, error_fn)
121 122
123 -def VerifyClusterName(data, error_fn, 124 _verify_fn=ssconf.VerifyClusterName):
125 """Verifies cluster name. 126 127 @type data: dict 128 129 """ 130 name = data.get(constants.SSHS_CLUSTER_NAME) 131 if name: 132 _verify_fn(name) 133 else: 134 raise error_fn("Cluster name must be specified")
135 136
137 -def LoadData(raw, data_check):
138 """Parses and verifies input data. 139 140 @rtype: dict 141 142 """ 143 return serializer.LoadAndVerifyJson(raw, data_check)
144 145
146 -def GenerateClientCertificate( 147 data, error_fn, client_cert=pathutils.NODED_CLIENT_CERT_FILE, 148 signing_cert=pathutils.NODED_CERT_FILE):
149 """Regenerates the client certificate of the node. 150 151 @type data: string 152 @param data: the JSON-formated input data 153 154 """ 155 if not os.path.exists(signing_cert): 156 raise error_fn("The signing certificate '%s' cannot be found." 157 % signing_cert) 158 159 # TODO: This sets the serial number to the number of seconds 160 # since epoch. This is technically not a correct serial number 161 # (in the way SSL is supposed to be used), but it serves us well 162 # enough for now, as we don't have any infrastructure for keeping 163 # track of the number of signed certificates yet. 164 serial_no = int(time.time()) 165 166 # The hostname of the node is provided with the input data. 167 hostname = data.get(constants.NDS_NODE_NAME) 168 if not hostname: 169 raise error_fn("No hostname found.") 170 171 utils.GenerateSignedSslCert(client_cert, serial_no, signing_cert, 172 common_name=hostname)
173