def get_key_reference(scope, name, user=None): """ Given a key name and user this method returns a new name (string ref) to address the key value pair in the context of that user. :param user: User to whom key belongs. :type user: ``str`` :param name: Original name of the key. :type name: ``str`` :rtype: ``str`` """ if scope == SYSTEM_SCOPE or scope == FULL_SYSTEM_SCOPE: return name elif scope == USER_SCOPE or scope == FULL_USER_SCOPE: if not user: raise InvalidUserException( "A valid user must be specified for user key ref." ) return UserKeyReference(name=name, user=user).ref else: raise InvalidScopeException( 'Scope "%s" is not valid. Allowed scopes are %s.' % (scope, ALLOWED_SCOPES) )
def to_model(cls, kvp): if not KeyValuePairAPI.crypto_setup: KeyValuePairAPI._setup_crypto() kvp_id = getattr(kvp, 'id', None) name = getattr(kvp, 'name', None) description = getattr(kvp, 'description', None) value = kvp.value secret = False if getattr(kvp, 'ttl', None): expire_timestamp = (date_utils.get_datetime_utc_now() + datetime.timedelta(seconds=kvp.ttl)) else: expire_timestamp = None secret = getattr(kvp, 'secret', False) if secret: if not KeyValuePairAPI.crypto_key: msg = ( 'Crypto key not found in %s. Unable to encrypt value for key %s.' % (KeyValuePairAPI.crypto_key_path, name)) raise CryptoKeyNotSetupException(msg) value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value) scope = getattr(kvp, 'scope', FULL_SYSTEM_SCOPE) if scope not in ALLOWED_SCOPES: raise InvalidScopeException( 'Invalid scope "%s"! Allowed scopes are %s.' % (scope, ALLOWED_SCOPES)) model = cls.model(id=kvp_id, name=name, description=description, value=value, secret=secret, scope=scope, expire_timestamp=expire_timestamp) return model
def to_model(cls, kvp): if not KeyValuePairAPI.crypto_setup: KeyValuePairAPI._setup_crypto() kvp_id = getattr(kvp, "id", None) name = getattr(kvp, "name", None) description = getattr(kvp, "description", None) value = kvp.value original_value = value secret = False if getattr(kvp, "ttl", None): expire_timestamp = date_utils.get_datetime_utc_now( ) + datetime.timedelta(seconds=kvp.ttl) else: expire_timestamp = None encrypted = getattr(kvp, "encrypted", False) secret = getattr(kvp, "secret", False) # If user transmitted the value in an pre-encrypted format, we perform the decryption here # to ensure data integrity. Besides that, we store data as-is. # Keep in mind that encrypted=True also always implies secret=True. If we didn't do # that and supported encrypted=True, secret=False, this would allow users to decrypt # any encrypted value. if encrypted: secret = True cls._verif_key_is_set_up(name=name) try: symmetric_decrypt(KeyValuePairAPI.crypto_key, value) except Exception: msg = ( 'Failed to verify the integrity of the provided value for key "%s". Ensure ' "that the value is encrypted with the correct key and not corrupted." % (name)) raise ValueError(msg) # Additional safety check to ensure that the value hasn't been decrypted if value != original_value: raise ValueError( f"The encrypted value {value} is not the" f" same original encrypted value {original_value}.") elif secret: cls._verif_key_is_set_up(name=name) value = symmetric_encrypt(KeyValuePairAPI.crypto_key, value) scope = getattr(kvp, "scope", FULL_SYSTEM_SCOPE) if scope not in ALLOWED_SCOPES: raise InvalidScopeException( 'Invalid scope "%s"! Allowed scopes are %s.' % (scope, ALLOWED_SCOPES)) # NOTE: For security reasons, encrypted always implies secret=True. See comment # above for explanation. if encrypted and not secret: raise ValueError( "encrypted option can only be used in combination with secret " "option") model = cls.model( id=kvp_id, name=name, description=description, value=value, secret=secret, scope=scope, expire_timestamp=expire_timestamp, ) return model