Generate keystone PKI into JSON file
For devtest scripts it's more useful to generate keystone PKI into JSON Heat env file directly instead of reading PKI files and adding them into JSON file manually. If keystone key/certs already exist in JSON file, they are not overwritten. Change-Id: Iad9c670dba0f57219f47792f44d60341ab58cdb3
This commit is contained in:
parent
9102604e74
commit
78e62e6117
@ -70,3 +70,49 @@ Where /tmp/one-node contains::
|
||||
"cpu": "1"
|
||||
}
|
||||
]
|
||||
|
||||
----------------------------------------------------------
|
||||
Generating keys and certificates for use with Keystone PKI
|
||||
----------------------------------------------------------
|
||||
|
||||
The generate-keystone-pki line utility generates keys and certificates
|
||||
which Keystone uses for signing authentication tokens.
|
||||
|
||||
- Keys and certificates can be generated into separate files::
|
||||
|
||||
generate-keystone-pki /tmp/certificates
|
||||
|
||||
That creates four files with signing and CA keys and certificates in
|
||||
/tmp/certificates directory.
|
||||
|
||||
- Key and certificates can be generated into heat environment file::
|
||||
|
||||
generate-keystone-pki -j overcloud-env.json
|
||||
|
||||
That adds following values into overcloud-env.json file::
|
||||
|
||||
{
|
||||
"parameters": {
|
||||
"KeystoneSigningKey": "some_key",
|
||||
"KeystoneSigningCertificate": "some_cert",
|
||||
"KeystoneCACertificate": "some_cert"
|
||||
}
|
||||
}
|
||||
|
||||
CA key is not added because this file is not needed by Keystone PKI.
|
||||
|
||||
- Key and certificates can be generated into os-apply-config metadata file::
|
||||
|
||||
generate-keystone-pki -s -j local.json
|
||||
|
||||
This adds following values into local.json file::
|
||||
|
||||
{
|
||||
"keystone": {
|
||||
"signing_certificate": "some_cert",
|
||||
"signing_key": "some_key",
|
||||
"ca_certificate": "some_cert"
|
||||
}
|
||||
}
|
||||
|
||||
CA key is not added because this file is not needed by Keystone PKI.
|
||||
|
@ -28,6 +28,9 @@ def parse_args():
|
||||
signing_cert.pem - certificate for verifying token validity, the
|
||||
certificate itself is verifiable by ca_cert.pem
|
||||
|
||||
Alternatively write generated key/certs into <heatenv> JSON file
|
||||
or into an os-apply-config metadata file for use without Heat.
|
||||
|
||||
ca_key.pem doesn't have to (shouldn't) be uploaded to Keystone nodes.
|
||||
""")
|
||||
|
||||
@ -35,14 +38,24 @@ def parse_args():
|
||||
description=description,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument(
|
||||
'directory',
|
||||
metavar='<directory>',
|
||||
help='directory where keys/certs will be generated',
|
||||
)
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-d', '--directory', dest='directory',
|
||||
help='directory where keys/certs will be generated')
|
||||
group.add_argument('-j', '--heatenv', dest='heatenv',
|
||||
help='write signing key/cert and CA cert into JSON '
|
||||
'Heat environment file, CA key is omitted')
|
||||
parser.add_argument('-s', '--seed', action='store_true',
|
||||
help='JSON file for seed machine has different '
|
||||
'structure (for seed machine we update directly '
|
||||
'heat metadata file injected into image). '
|
||||
'Different key/certs names and different '
|
||||
'parent node are used (default: false)')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
keystone_pki.create_and_write_ca_and_signing_pairs(args.directory)
|
||||
if args.heatenv:
|
||||
keystone_pki.generate_certs_into_json(args.heatenv, args.seed)
|
||||
else:
|
||||
keystone_pki.create_and_write_ca_and_signing_pairs(args.directory)
|
||||
|
@ -15,6 +15,7 @@
|
||||
import logging
|
||||
import os
|
||||
from os import path
|
||||
import simplejson
|
||||
import stat
|
||||
|
||||
from OpenSSL import crypto
|
||||
@ -136,6 +137,57 @@ def create_and_write_ca_and_signing_pairs(directory):
|
||||
_write_pki_file(path.join(directory, 'signing_cert.pem'), signing_cert_pem)
|
||||
|
||||
|
||||
def generate_certs_into_json(jsonfile, seed):
|
||||
"""Create and write out CA certificate and signing certificate/key.
|
||||
|
||||
Generate CA certificate, signing certificate and signing key and
|
||||
add them into a JSON file. If key/certs already exist in JSON file, no
|
||||
change is done.
|
||||
|
||||
:param jsonfile: JSON file where certs and key will be written
|
||||
:type jsonfile: string
|
||||
:param seed: JSON file for seed machine has different structure. Different
|
||||
key/certs names and different parent node are used
|
||||
:type seed: boolean
|
||||
"""
|
||||
if os.path.isfile(jsonfile):
|
||||
with open(jsonfile) as json_fd:
|
||||
all_data = simplejson.load(json_fd)
|
||||
else:
|
||||
all_data = {}
|
||||
|
||||
if seed:
|
||||
parent = 'keystone'
|
||||
ca_cert_name = 'ca_certificate'
|
||||
signing_key_name = 'signing_key'
|
||||
signing_cert_name = 'signing_certificate'
|
||||
else:
|
||||
parent = 'parameters'
|
||||
ca_cert_name = 'KeystoneCACertificate'
|
||||
signing_key_name = 'KeystoneSigningKey'
|
||||
signing_cert_name = 'KeystoneSigningCertificate'
|
||||
|
||||
if parent not in all_data:
|
||||
all_data[parent] = {}
|
||||
parent_node = all_data[parent]
|
||||
|
||||
if not (ca_cert_name in parent_node and
|
||||
signing_key_name in parent_node and
|
||||
signing_cert_name in parent_node):
|
||||
ca_key_pem, ca_cert_pem = create_ca_pair()
|
||||
signing_key_pem, signing_cert_pem = create_signing_pair(ca_key_pem,
|
||||
ca_cert_pem)
|
||||
parent_node.update({ca_cert_name: ca_cert_pem,
|
||||
signing_key_name: signing_key_pem,
|
||||
signing_cert_name: signing_cert_pem})
|
||||
with open(jsonfile, 'w') as json_fd:
|
||||
simplejson.dump(all_data, json_fd, sort_keys=True)
|
||||
LOG.debug("Wrote key/certs into '%s'.", path.abspath(jsonfile))
|
||||
else:
|
||||
LOG.info("Key/certs are already present in '%s', skipping.",
|
||||
path.abspath(jsonfile))
|
||||
|
||||
|
||||
def _write_pki_file(file_path, contents):
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(contents)
|
||||
|
@ -98,3 +98,43 @@ class KeystonePKITest(base.TestCase):
|
||||
mock.call('mock_signing_key'),
|
||||
mock.call('mock_signing_cert'),
|
||||
])
|
||||
|
||||
@mock.patch('os_cloud_config.keystone_pki.path.isfile', create=True)
|
||||
@mock.patch('os_cloud_config.keystone_pki.create_ca_pair')
|
||||
@mock.patch('os_cloud_config.keystone_pki.create_signing_pair')
|
||||
@mock.patch('os_cloud_config.keystone_pki.open', create=True)
|
||||
@mock.patch('os_cloud_config.keystone_pki.simplejson.dump')
|
||||
def test_generate_certs_into_json(
|
||||
self, mock_json, open_, create_signing, create_ca, isfile):
|
||||
create_ca.return_value = ('mock_ca_key', 'mock_ca_cert')
|
||||
create_signing.return_value = ('mock_signing_key', 'mock_signing_cert')
|
||||
isfile.return_value = False
|
||||
|
||||
keystone_pki.generate_certs_into_json('/jsonfile', False)
|
||||
|
||||
params = mock_json.call_args[0][0]['parameters']
|
||||
self.assertEqual(params['KeystoneCACertificate'], 'mock_ca_cert')
|
||||
self.assertEqual(params['KeystoneSigningKey'], 'mock_signing_key')
|
||||
self.assertEqual(params['KeystoneSigningCertificate'],
|
||||
'mock_signing_cert')
|
||||
|
||||
@mock.patch('os_cloud_config.keystone_pki.path.isfile', create=True)
|
||||
@mock.patch('os_cloud_config.keystone_pki.create_ca_pair')
|
||||
@mock.patch('os_cloud_config.keystone_pki.create_signing_pair')
|
||||
@mock.patch('os_cloud_config.keystone_pki.open', create=True)
|
||||
@mock.patch('os_cloud_config.keystone_pki.simplejson.load')
|
||||
@mock.patch('os_cloud_config.keystone_pki.simplejson.dump')
|
||||
def test_generate_certs_into_json_with_existing_certs(
|
||||
self, mock_json_dump, mock_json_load, open_, create_signing,
|
||||
create_ca, isfile):
|
||||
create_ca.return_value = ('mock_ca_key', 'mock_ca_cert')
|
||||
create_signing.return_value = ('mock_signing_key', 'mock_signing_cert')
|
||||
isfile.return_value = True
|
||||
mock_json_load.return_value = {
|
||||
'KeystoneCACertificate': 'mock_ca_cert',
|
||||
'KeystoneSigningKey': 'mock_signing_key',
|
||||
'KeystoneSigningCertificate': 'mock_signing_cert'
|
||||
}
|
||||
|
||||
keystone_pki.generate_certs_into_json('/jsonfile', False)
|
||||
mock_json_dump.assert_not_called()
|
||||
|
Loading…
Reference in New Issue
Block a user