Package ganeti :: Package utils :: Module security
[hide private]
[frames] | no frames]

Source Code for Module ganeti.utils.security

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2013 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  """Utility functions for security features of Ganeti. 
 31   
 32  """ 
 33   
 34  import logging 
 35  import OpenSSL 
 36  import os 
 37  import uuid as uuid_module 
 38  import time 
 39   
 40  from ganeti.utils import io 
 41  from ganeti.utils import x509 
 42  from ganeti import constants 
 43  from ganeti import errors 
 44  from ganeti import pathutils 
 45   
 46   
47 -def UuidToInt(uuid):
48 uuid_obj = uuid_module.UUID(uuid) 49 return uuid_obj.int # pylint: disable=E1101
50 51
52 -def GetCertificateDigest(cert_filename=pathutils.NODED_CLIENT_CERT_FILE):
53 """Reads the SSL certificate and returns the sha1 digest. 54 55 """ 56 cert_plain = io.ReadFile(cert_filename) 57 cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, 58 cert_plain) 59 return cert.digest("sha1")
60 61
62 -def GenerateNewSslCert(new_cert, cert_filename, serial_no, log_msg, 63 uid=-1, gid=-1):
64 """Creates a new server SSL certificate and backups the old one. 65 66 @type new_cert: boolean 67 @param new_cert: whether a new certificate should be created 68 @type cert_filename: string 69 @param cert_filename: filename of the certificate file 70 @type serial_no: int 71 @param serial_no: serial number of the certificate 72 @type log_msg: string 73 @param log_msg: log message to be written on certificate creation 74 @type uid: int 75 @param uid: the user ID of the user who will be owner of the certificate file 76 @type gid: int 77 @param gid: the group ID of the group who will own the certificate file 78 79 """ 80 cert_exists = os.path.exists(cert_filename) 81 if new_cert or not cert_exists: 82 if cert_exists: 83 io.CreateBackup(cert_filename) 84 85 logging.debug(log_msg) 86 x509.GenerateSelfSignedSslCert(cert_filename, serial_no, uid=uid, gid=gid)
87 88
89 -def GenerateNewClientSslCert(cert_filename, signing_cert_filename, 90 hostname):
91 """Creates a new server SSL certificate and backups the old one. 92 93 @type cert_filename: string 94 @param cert_filename: filename of the certificate file 95 @type signing_cert_filename: string 96 @param signing_cert_filename: name of the certificate to be used for signing 97 @type hostname: string 98 @param hostname: name of the machine whose cert is created 99 100 """ 101 serial_no = int(time.time()) 102 x509.GenerateSignedSslCert(cert_filename, serial_no, signing_cert_filename, 103 common_name=hostname)
104 105
106 -def VerifyCertificate(filename):
107 """Verifies a SSL certificate. 108 109 @type filename: string 110 @param filename: Path to PEM file 111 112 """ 113 try: 114 cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, 115 io.ReadFile(filename)) 116 except Exception, err: # pylint: disable=W0703 117 return (constants.CV_ERROR, 118 "Failed to load X509 certificate %s: %s" % (filename, err)) 119 120 (errcode, msg) = \ 121 x509.VerifyX509Certificate(cert, constants.SSL_CERT_EXPIRATION_WARN, 122 constants.SSL_CERT_EXPIRATION_ERROR) 123 124 if msg: 125 fnamemsg = "While verifying %s: %s" % (filename, msg) 126 else: 127 fnamemsg = None 128 129 if errcode is None: 130 return (None, fnamemsg) 131 elif errcode == x509.CERT_WARNING: 132 return (constants.CV_WARNING, fnamemsg) 133 elif errcode == x509.CERT_ERROR: 134 return (constants.CV_ERROR, fnamemsg) 135 136 raise errors.ProgrammerError("Unhandled certificate error code %r" % errcode)
137 138
139 -def IsCertificateSelfSigned(cert_filename):
140 """Checks whether the certificate issuer is the same as the owner. 141 142 Note that this does not actually verify the signature, it simply 143 compares the certificates common name and the issuer's common 144 name. This is sufficient, because now that Ganeti started creating 145 non-self-signed client-certificates, it uses their hostnames 146 as common names and thus they are distinguishable by common name 147 from the server certificates. 148 149 @type cert_filename: string 150 @param cert_filename: filename of the certificate to examine 151 152 """ 153 try: 154 cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, 155 io.ReadFile(cert_filename)) 156 except Exception, err: # pylint: disable=W0703 157 return (constants.CV_ERROR, 158 "Failed to load X509 certificate %s: %s" % (cert_filename, err)) 159 160 if cert.get_subject().CN == cert.get_issuer().CN: 161 msg = "The certificate '%s' is self-signed. Please run 'gnt-cluster" \ 162 " renew-crypto --new-node-certificates' to get a properly signed" \ 163 " certificate." % cert_filename 164 return (constants.CV_WARNING, msg) 165 166 return (None, None)
167