diff options
author | Claudiu Belu <cbelu@cloudbasesolutions.com> | 2014-06-24 15:33:23 +0300 |
---|---|---|
committer | Claudiu Belu <cbelu@cloudbasesolutions.com> | 2015-03-05 21:30:34 +0200 |
commit | 80aae8fcf45fdc38fcb6c9fea503cecbe42e42b6 (patch) | |
tree | 7c431701d02db6de746cedb4a10fd14e6d3c9b2d /nova/crypto.py | |
parent | 6b3ebfd9ddecc8cca323d6828dee0b2179c613e7 (diff) | |
download | nova-80aae8fcf45fdc38fcb6c9fea503cecbe42e42b6.tar.gz |
Adds x509 certificate keypair support
X509 certificates are used by Windows for passwordless
authentication (WinRM) in a way which can be considered
consistent with the usage of SSH keys on Linux, as both
are based on public / private keypairs.
Adds x509 certificate creation implementation.
Adds 'keys' in InstanceMetadata.
Implements: blueprint keypair-x509-certificates
Depends-On: Id5b210d7afe5c0a590abcbd42b9ff85b071a5c55
Change-Id: I1ab518553cf757ae35548fa89b6c8fee7ec32b8d
Diffstat (limited to 'nova/crypto.py')
-rw-r--r-- | nova/crypto.py | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/nova/crypto.py b/nova/crypto.py index 8f68b4b7d9..d358681cab 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -144,6 +144,19 @@ def generate_fingerprint(public_key): reason=_('failed to generate fingerprint')) +def generate_x509_fingerprint(pem_key): + try: + (out, _err) = utils.execute('openssl', 'x509', '-inform', 'PEM', + '-fingerprint', '-noout', + process_input=pem_key) + fingerprint = string.strip(out.rpartition('=')[2]) + return fingerprint + except processutils.ProcessExecutionError as ex: + raise exception.InvalidKeypair( + reason=_('failed to generate X509 fingerprint. ' + 'Error message: %s') % ex) + + def generate_key_pair(bits=None): with utils.tempdir() as tmpdir: keyfile = os.path.join(tmpdir, 'temp') @@ -352,6 +365,44 @@ def generate_x509_cert(user_id, project_id, bits=2048): return (private_key, signed_csr) +def generate_winrm_x509_cert(user_id, project_id, bits=2048): + """Generate a cert for passwordless auth for user in project.""" + subject = '/CN=%s-%s' % (project_id, user_id) + upn = '%s@localhost' % user_id + + with utils.tempdir() as tmpdir: + keyfile = os.path.abspath(os.path.join(tmpdir, 'temp.key')) + conffile = os.path.abspath(os.path.join(tmpdir, 'temp.conf')) + + _create_x509_openssl_config(conffile, upn) + + (certificate, _err) = utils.execute( + 'openssl', 'req', '-x509', '-nodes', '-days', '3650', + '-config', conffile, '-newkey', 'rsa:%s' % bits, + '-outform', 'PEM', '-keyout', keyfile, '-subj', subject, + '-extensions', 'v3_req_client') + + (out, _err) = utils.execute('openssl', 'pkcs12', '-export', + '-inkey', keyfile, '-password', 'pass:', + process_input=certificate) + + private_key = out.encode('base64') + fingerprint = generate_x509_fingerprint(certificate) + + return (private_key, certificate, fingerprint) + + +def _create_x509_openssl_config(conffile, upn): + content = ("distinguished_name = req_distinguished_name\n" + "[req_distinguished_name]\n" + "[v3_req_client]\n" + "extendedKeyUsage = clientAuth\n" + "subjectAltName = otherName:""1.3.6.1.4.1.311.20.2.3;UTF8:%s\n") + + with open(conffile, 'w') as file: + file.write(content % upn) + + def _ensure_project_folder(project_id): if not os.path.exists(ca_path(project_id)): geninter_sh_path = os.path.abspath( |