diff options
author | RHE <rebirthmonkey@gmail.com> | 2017-11-24 13:54:26 +0100 |
---|---|---|
committer | RHE <rebirthmonkey@gmail.com> | 2017-11-24 13:54:26 +0100 |
commit | 920a49cfa055733d575282973e23558c33087a4a (patch) | |
tree | d371dab34efa5028600dad2e7ca58063626e7ba4 /keystone-moon/keystone/token/providers/fernet/utils.py | |
parent | ef3eefca70d8abb4a00dafb9419ad32738e934b2 (diff) |
remove keystone-moon
Change-Id: I80d7c9b669f19d5f6607e162de8e0e55c2f80fdd
Signed-off-by: RHE <rebirthmonkey@gmail.com>
Diffstat (limited to 'keystone-moon/keystone/token/providers/fernet/utils.py')
-rw-r--r-- | keystone-moon/keystone/token/providers/fernet/utils.py | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/keystone-moon/keystone/token/providers/fernet/utils.py b/keystone-moon/keystone/token/providers/fernet/utils.py deleted file mode 100644 index 1c3552d4..00000000 --- a/keystone-moon/keystone/token/providers/fernet/utils.py +++ /dev/null @@ -1,270 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import stat - -from cryptography import fernet -from oslo_config import cfg -from oslo_log import log - -from keystone.i18n import _LE, _LW, _LI - - -LOG = log.getLogger(__name__) - -CONF = cfg.CONF - - -def validate_key_repository(requires_write=False): - """Validate permissions on the key repository directory.""" - # NOTE(lbragstad): We shouldn't need to check if the directory was passed - # in as None because we don't set allow_no_values to True. - - # ensure current user has sufficient access to the key repository - is_valid = (os.access(CONF.fernet_tokens.key_repository, os.R_OK) and - os.access(CONF.fernet_tokens.key_repository, os.X_OK)) - if requires_write: - is_valid = (is_valid and - os.access(CONF.fernet_tokens.key_repository, os.W_OK)) - - if not is_valid: - LOG.error( - _LE('Either [fernet_tokens] key_repository does not exist or ' - 'Keystone does not have sufficient permission to access it: ' - '%s'), CONF.fernet_tokens.key_repository) - else: - # ensure the key repository isn't world-readable - stat_info = os.stat(CONF.fernet_tokens.key_repository) - if(stat_info.st_mode & stat.S_IROTH or - stat_info.st_mode & stat.S_IXOTH): - LOG.warning(_LW( - '[fernet_tokens] key_repository is world readable: %s'), - CONF.fernet_tokens.key_repository) - - return is_valid - - -def _convert_to_integers(id_value): - """Cast user and group system identifiers to integers.""" - # NOTE(lbragstad) os.chown() will raise a TypeError here if - # keystone_user_id and keystone_group_id are not integers. Let's - # cast them to integers if we can because it's possible to pass non-integer - # values into the fernet_setup utility. - try: - id_int = int(id_value) - except ValueError as e: - msg = _LE('Unable to convert Keystone user or group ID. Error: %s') - LOG.error(msg, e) - raise - - return id_int - - -def create_key_directory(keystone_user_id=None, keystone_group_id=None): - """If the configured key directory does not exist, attempt to create it.""" - if not os.access(CONF.fernet_tokens.key_repository, os.F_OK): - LOG.info(_LI( - '[fernet_tokens] key_repository does not appear to exist; ' - 'attempting to create it')) - - try: - os.makedirs(CONF.fernet_tokens.key_repository, 0o700) - except OSError: - LOG.error(_LE( - 'Failed to create [fernet_tokens] key_repository: either it ' - 'already exists or you don\'t have sufficient permissions to ' - 'create it')) - - if keystone_user_id and keystone_group_id: - os.chown( - CONF.fernet_tokens.key_repository, - keystone_user_id, - keystone_group_id) - elif keystone_user_id or keystone_group_id: - LOG.warning(_LW( - 'Unable to change the ownership of [fernet_tokens] ' - 'key_repository without a keystone user ID and keystone group ' - 'ID both being provided: %s') % - CONF.fernet_tokens.key_repository) - - -def _create_new_key(keystone_user_id, keystone_group_id): - """Securely create a new encryption key. - - Create a new key that is readable by the Keystone group and Keystone user. - """ - key = fernet.Fernet.generate_key() # key is bytes - - # This ensures the key created is not world-readable - old_umask = os.umask(0o177) - if keystone_user_id and keystone_group_id: - old_egid = os.getegid() - old_euid = os.geteuid() - os.setegid(keystone_group_id) - os.seteuid(keystone_user_id) - elif keystone_user_id or keystone_group_id: - LOG.warning(_LW( - 'Unable to change the ownership of the new key without a keystone ' - 'user ID and keystone group ID both being provided: %s') % - CONF.fernet_tokens.key_repository) - # Determine the file name of the new key - key_file = os.path.join(CONF.fernet_tokens.key_repository, '0') - try: - with open(key_file, 'w') as f: - f.write(key.decode('utf-8')) # convert key to str for the file. - finally: - # After writing the key, set the umask back to it's original value. Do - # the same with group and user identifiers if a Keystone group or user - # was supplied. - os.umask(old_umask) - if keystone_user_id and keystone_group_id: - os.seteuid(old_euid) - os.setegid(old_egid) - - LOG.info(_LI('Created a new key: %s'), key_file) - - -def initialize_key_repository(keystone_user_id=None, keystone_group_id=None): - """Create a key repository and bootstrap it with a key. - - :param keystone_user_id: User ID of the Keystone user. - :param keystone_group_id: Group ID of the Keystone user. - - """ - # make sure we have work to do before proceeding - if os.access(os.path.join(CONF.fernet_tokens.key_repository, '0'), - os.F_OK): - LOG.info(_LI('Key repository is already initialized; aborting.')) - return - - # bootstrap an existing key - _create_new_key(keystone_user_id, keystone_group_id) - - # ensure that we end up with a primary and secondary key - rotate_keys(keystone_user_id, keystone_group_id) - - -def rotate_keys(keystone_user_id=None, keystone_group_id=None): - """Create a new primary key and revoke excess active keys. - - :param keystone_user_id: User ID of the Keystone user. - :param keystone_group_id: Group ID of the Keystone user. - - Key rotation utilizes the following behaviors: - - - The highest key number is used as the primary key (used for encryption). - - All keys can be used for decryption. - - New keys are always created as key "0," which serves as a placeholder - before promoting it to be the primary key. - - This strategy allows you to safely perform rotation on one node in a - cluster, before syncing the results of the rotation to all other nodes - (during both key rotation and synchronization, all nodes must recognize all - primary keys). - - """ - # read the list of key files - key_files = dict() - for filename in os.listdir(CONF.fernet_tokens.key_repository): - path = os.path.join(CONF.fernet_tokens.key_repository, str(filename)) - if os.path.isfile(path): - try: - key_id = int(filename) - except ValueError: # nosec : name isn't a number, ignore the file. - pass - else: - key_files[key_id] = path - - LOG.info(_LI('Starting key rotation with %(count)s key files: %(list)s'), { - 'count': len(key_files), - 'list': list(key_files.values())}) - - # determine the number of the new primary key - current_primary_key = max(key_files.keys()) - LOG.info(_LI('Current primary key is: %s'), current_primary_key) - new_primary_key = current_primary_key + 1 - LOG.info(_LI('Next primary key will be: %s'), new_primary_key) - - # promote the next primary key to be the primary - os.rename( - os.path.join(CONF.fernet_tokens.key_repository, '0'), - os.path.join(CONF.fernet_tokens.key_repository, str(new_primary_key))) - key_files.pop(0) - key_files[new_primary_key] = os.path.join( - CONF.fernet_tokens.key_repository, - str(new_primary_key)) - LOG.info(_LI('Promoted key 0 to be the primary: %s'), new_primary_key) - - # add a new key to the rotation, which will be the *next* primary - _create_new_key(keystone_user_id, keystone_group_id) - - max_active_keys = CONF.fernet_tokens.max_active_keys - # check for bad configuration - if max_active_keys < 1: - LOG.warning(_LW( - '[fernet_tokens] max_active_keys must be at least 1 to maintain a ' - 'primary key.')) - max_active_keys = 1 - - # purge excess keys - - # Note that key_files doesn't contain the new active key that was created, - # only the old active keys. - keys = sorted(key_files.keys(), reverse=True) - while len(keys) > (max_active_keys - 1): - index_to_purge = keys.pop() - key_to_purge = key_files[index_to_purge] - LOG.info(_LI('Excess key to purge: %s'), key_to_purge) - os.remove(key_to_purge) - - -def load_keys(): - """Load keys from disk into a list. - - The first key in the list is the primary key used for encryption. All - other keys are active secondary keys that can be used for decrypting - tokens. - - """ - if not validate_key_repository(): - return [] - - # build a dictionary of key_number:encryption_key pairs - keys = dict() - for filename in os.listdir(CONF.fernet_tokens.key_repository): - path = os.path.join(CONF.fernet_tokens.key_repository, str(filename)) - if os.path.isfile(path): - with open(path, 'r') as key_file: - try: - key_id = int(filename) - except ValueError: # nosec : filename isn't a number, ignore - # this file since it's not a key. - pass - else: - keys[key_id] = key_file.read() - - if len(keys) != CONF.fernet_tokens.max_active_keys: - # If there haven't been enough key rotations to reach max_active_keys, - # or if the configured value of max_active_keys has changed since the - # last rotation, then reporting the discrepancy might be useful. Once - # the number of keys matches max_active_keys, this log entry is too - # repetitive to be useful. - LOG.info(_LI( - 'Loaded %(count)d encryption keys (max_active_keys=%(max)d) from: ' - '%(dir)s'), { - 'count': len(keys), - 'max': CONF.fernet_tokens.max_active_keys, - 'dir': CONF.fernet_tokens.key_repository}) - - # return the encryption_keys, sorted by key number, descending - return [keys[x] for x in sorted(keys.keys(), reverse=True)] |