summaryrefslogtreecommitdiff
path: root/nova/crypto.py
diff options
context:
space:
mode:
authorClaudiu Belu <cbelu@cloudbasesolutions.com>2014-06-24 15:33:23 +0300
committerClaudiu Belu <cbelu@cloudbasesolutions.com>2015-03-05 21:30:34 +0200
commit80aae8fcf45fdc38fcb6c9fea503cecbe42e42b6 (patch)
tree7c431701d02db6de746cedb4a10fd14e6d3c9b2d /nova/crypto.py
parent6b3ebfd9ddecc8cca323d6828dee0b2179c613e7 (diff)
downloadnova-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.py51
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(