示例#1
0
    def get_secret(self, secret_metadata, context):
        """Retrieve a secret.

        :param secret_metadata: secret metadata
        :param context: StoreCryptoContext for secret
        :returns: SecretDTO that contains secret
        """
        if (not context.secret_model
                or not context.secret_model.encrypted_data):
            raise sstore.SecretNotFoundException()

        # TODO(john-wood-w) Need to revisit 1 to many datum relationship.
        datum_model = context.secret_model.encrypted_data[0]

        # Find HSM-style 'crypto' plugin.
        decrypting_plugin = manager.get_manager().get_plugin_retrieve(
            datum_model.kek_meta_project.plugin_name)

        # wrap the KEKDatum instance in our DTO
        kek_meta_dto = crypto.KEKMetaDTO(datum_model.kek_meta_project)

        # Convert from text-based storage format to binary.
        encrypted = base64.b64decode(datum_model.cypher_text)
        decrypt_dto = crypto.DecryptDTO(encrypted)

        # Decrypt the secret.
        secret = decrypting_plugin.decrypt(decrypt_dto, kek_meta_dto,
                                           datum_model.kek_meta_extended,
                                           context.project_model.external_id)
        key_spec = sstore.KeySpec(alg=context.secret_model.algorithm,
                                  bit_length=context.secret_model.bit_length,
                                  mode=context.secret_model.mode)

        return sstore.SecretDTO(sstore.SecretType.SYMMETRIC, secret, key_spec,
                                datum_model.content_type)
示例#2
0
    def test_plugin_created_as_per_mulitple_backend_conf(self):
        """Check plugins are created as per multiple backend conf"""

        store_plugin_names = ['store_crypto', 'kmip_plugin', 'store_crypto']
        crypto_plugin_names = ['p11_crypto', '', 'simple_crypto']

        self.init_via_conf_file(store_plugin_names,
                                crypto_plugin_names, enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11') as m_pkcs11, \
                mock.patch('kmip.pie.client.ProxyKmipClient') as m_kmip:

            manager = str.SecretStorePluginManager()

            # check pkcs11 and kmip plugin instantiation call is invoked
            m_pkcs11.called_once_with(mock.ANY, mock.ANY)
            m_kmip.called_once_with(mock.ANY)
            # check store crypto adapter is matched as its defined first.
            keySpec = str.KeySpec(str.KeyAlgorithm.AES, 128)
            plugin_found = manager.get_plugin_store(keySpec)
            self.assertIsInstance(plugin_found,
                                  store_crypto.StoreCryptoAdapterPlugin)

            # check pkcs11 crypto is matched as its defined first.
            crypto_plugin = cm.get_manager().get_plugin_store_generate(
                base.PluginSupportTypes.ENCRYPT_DECRYPT)
            self.assertIsInstance(crypto_plugin, p11_crypto.P11CryptoPlugin)
示例#3
0
    def generate_symmetric_key(self, key_spec, context):
        """Generate a symmetric key.

        :param key_spec: KeySpec that contains details on the type of key to
        generate
        :param context: StoreCryptoContext for secret
        :returns: a dictionary that contains metadata about the key
        """

        # Find HSM-style 'crypto' plugin.
        plugin_type = _determine_generation_type(key_spec.alg)
        if crypto.PluginSupportTypes.SYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)
        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type, key_spec.alg, key_spec.bit_length, key_spec.mode)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        # Create an encrypted datum instance and add the created cypher text.
        generate_dto = crypto.GenerateDTO(key_spec.alg, key_spec.bit_length,
                                          key_spec.mode, None)
        # Create the encrypted meta.
        response_dto = generating_plugin.generate_symmetric(
            generate_dto, kek_meta_dto, context.project_model.external_id)

        # Convert binary data into a text-based format.
        _store_secret_and_datum(context, context.secret_model, kek_datum_model,
                                response_dto)

        return None
示例#4
0
    def update_policy(self, data, project_id):
        policy_type = data['policy']
        attribute = data['attribute']
        enc_keys = _get_enc_keys(project_id)
        if enc_keys:
            encrypting_plugin = manager.get_manager(
            ).get_plugin_store_generate(
                crypto.PluginSupportTypes.ENCRYPT_DECRYPT)
            response = _get_project_policy(project_id)
            if response:
                mk_mr_e = response['attribute']
                mk_attribute = None
                try:
                    mk_attribute = encrypting_plugin.mk_encrypt(
                        enc_keys, attribute, project_id, mk_mr_e)
                except Exception as e:
                    return {
                        'status':
                        'Unable to decrypt with valid Session Key of this project. Unauthorized to update policy.'
                    }
            else:
                mk_attribute = encrypting_plugin.mk_encrypt(
                    enc_keys, attribute, project_id, None)
            _store_project_policy(project_id, policy_type, mk_attribute)
        else:
            return {
                'status':
                'Session key not yet provisioned for this project. Please perform Remote/Mutual Attestation first.'
            }

        return {'status': 'OK'}
示例#5
0
    def test_plugin_created_as_per_mulitple_backend_conf(self):
        """Check plugins are created as per multiple backend conf"""

        store_plugin_names = ['store_crypto', 'kmip_plugin', 'store_crypto']
        crypto_plugin_names = ['p11_crypto', '', 'simple_crypto']

        self.init_via_conf_file(store_plugin_names,
                                crypto_plugin_names,
                                enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11') as m_pkcs11, \
                mock.patch('kmip.pie.client.ProxyKmipClient') as m_kmip:

            manager = str.SecretStorePluginManager()

            # check pkcs11 and kmip plugin instantiation call is invoked
            m_pkcs11.called_once_with(mock.ANY, mock.ANY)
            m_kmip.called_once_with(mock.ANY)
            # check store crypto adapter is matched as its defined first.
            keySpec = str.KeySpec(str.KeyAlgorithm.AES, 128)
            plugin_found = manager.get_plugin_store(keySpec)
            self.assertIsInstance(plugin_found,
                                  store_crypto.StoreCryptoAdapterPlugin)

            # check pkcs11 crypto is matched as its defined first.
            crypto_plugin = cm.get_manager().get_plugin_store_generate(
                base.PluginSupportTypes.ENCRYPT_DECRYPT)
            self.assertIsInstance(crypto_plugin, p11_crypto.P11CryptoPlugin)
示例#6
0
    def store_secret(self, secret_dto, context):
        """Store a secret.

        :param secret_dto: SecretDTO for secret
        :param context: StoreCryptoContext for secret
        :returns: an optional dictionary containing metadata about the secret
        """

        # Find HSM-style 'crypto' plugin.
        encrypting_plugin = manager.get_manager().get_plugin_store_generate(
            crypto.PluginSupportTypes.ENCRYPT_DECRYPT)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            encrypting_plugin, context.project_model)

        # Secrets are base64 encoded before being passed to the secret stores.
        secret_bytes = base64.b64decode(secret_dto.secret)

        encrypt_dto = crypto.EncryptDTO(secret_bytes)

        # Enhance the context with content_type, This is needed to build
        # datum_model to store
        if not context.content_type:
            context.content_type = secret_dto.content_type

        # Create an encrypted datum instance and add the encrypted cyphertext.
        response_dto = encrypting_plugin.encrypt(
            encrypt_dto, kek_meta_dto, context.project_model.external_id)

        # Convert binary data into a text-based format.
        _store_secret_and_datum(context, context.secret_model, kek_datum_model,
                                response_dto)

        return None
示例#7
0
 def do_provision_kek(self, data, project_id):
     encrypting_plugin = manager.get_manager().get_plugin_store_generate(
         crypto.PluginSupportTypes.ENCRYPT_DECRYPT)
     enc_keys = _get_enc_keys(project_id)
     response, output = encrypting_plugin.do_provision_kek(
         data, project_id, enc_keys)
     if output:
         _store_enc_keys(project_id, output['sk'], output['mk'])
     return response
    def test_no_preferred_default_plugin(self, dataset):
        """Check name, plugin and crypto class used for default secret store

        Secret store name is crypto class plugin name if defined otherwise user
        friendly name is derived from store class plugin name
        """

        self.init_via_conf_file(dataset['store_plugins'],
                                dataset['crypto_plugins'],
                                enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11'), \
                mock.patch('kmip.pie.client.ProxyKmipClient'):
            manager = secret_store.SecretStorePluginManager()

        keySpec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128)

        plugin_found = manager.get_plugin_store(keySpec)
        self.assertIsInstance(plugin_found,
                              dataset['default_store_class'])

        global_secret_store = multiple_backends.\
            get_global_default_secret_store()

        if dataset['default_crypto_class']:
            crypto_plugin = cm.get_manager().get_plugin_store_generate(
                base.PluginSupportTypes.ENCRYPT_DECRYPT)
            self.assertIsInstance(crypto_plugin,
                                  dataset['default_crypto_class'])

            # make sure secret store name is same as crypto class friendly name
            # as store_plugin class is not direct impl of SecretStoreBase
            self.assertEqual(global_secret_store.name,
                             crypto_plugin.get_plugin_name())
        else:  # crypto class is not used
            # make sure secret store name is same as store plugin class
            # friendly name
            self.assertEqual(global_secret_store.name,
                             plugin_found.get_plugin_name())
            # error raised for no crypto plugin
            self.assertRaises(base.CryptoPluginNotFound,
                              cm.get_manager().get_plugin_store_generate,
                              base.PluginSupportTypes.ENCRYPT_DECRYPT)
    def test_no_preferred_default_plugin(self, dataset):
        """Check name, plugin and crypto class used for default secret store

        Secret store name is crypto class plugin name if defined otherwise user
        friendly name is derived from store class plugin name
        """

        self.init_via_conf_file(dataset['store_plugins'],
                                dataset['crypto_plugins'],
                                enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11'), \
                mock.patch('kmip.pie.client.ProxyKmipClient'):
            manager = secret_store.SecretStorePluginManager()

        keySpec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128)

        plugin_found = manager.get_plugin_store(keySpec)
        self.assertIsInstance(plugin_found,
                              dataset['default_store_class'])

        global_secret_store = multiple_backends.\
            get_global_default_secret_store()

        if dataset['default_crypto_class']:
            crypto_plugin = cm.get_manager().get_plugin_store_generate(
                base.PluginSupportTypes.ENCRYPT_DECRYPT)
            self.assertIsInstance(crypto_plugin,
                                  dataset['default_crypto_class'])

            # make sure secret store name is same as crypto class friendly name
            # as store_plugin class is not direct impl of SecretStoreBase
            self.assertEqual(global_secret_store.name,
                             crypto_plugin.get_plugin_name())
        else:  # crypto class is not used
            # make sure secret store name is same as store plugin class
            # friendly name
            self.assertEqual(global_secret_store.name,
                             plugin_found.get_plugin_name())
            # error raised for no crypto plugin
            self.assertRaises(base.CryptoPluginNotFound,
                              cm.get_manager().get_plugin_store_generate,
                              base.PluginSupportTypes.ENCRYPT_DECRYPT)
示例#10
0
    def setUp(self):
        super(WhenTestingManager, self).setUp()

        self.plugin_returned = mock.MagicMock()
        self.plugin_type = crypto.PluginSupportTypes.ENCRYPT_DECRYPT
        self.plugin_returned.supports.return_value = True
        self.plugin_name = common_utils.generate_fullname_for(self.plugin_returned)
        self.plugin_loaded = mock.MagicMock(obj=self.plugin_returned)
        self.manager = cm.get_manager()
        self.manager.extensions = [self.plugin_loaded]
示例#11
0
    def test_can_override_enabled_plugins(self):
        """Verify can override default configuration for plugin selection."""
        manager.CONF.set_override("enabled_crypto_plugins", ['foo_plugin'],
                                  group='crypto')

        manager_to_test = manager.get_manager()

        self.assertIsInstance(manager_to_test, manager._CryptoPluginManager)

        self.assertListEqual(['foo_plugin'], manager_to_test._names)
示例#12
0
    def do_attestation(self, data, external_project_id, is_mutual, context):
        encrypting_plugin = manager.get_manager().get_plugin_store_generate(
            crypto.PluginSupportTypes.ENCRYPT_DECRYPT)
        enc_keys = _get_enc_keys(external_project_id)
        policy_dict = _get_project_policy(external_project_id)
        response, output = encrypting_plugin.do_attestation(
            data, external_project_id, enc_keys, is_mutual, policy_dict)
        if output:
            _store_enc_keys(external_project_id, output['sk'], output['mk'])

        return response
示例#13
0
    def setUp(self):
        super(WhenTestingManager, self).setUp()

        self.plugin_returned = mock.MagicMock()
        self.plugin_type = crypto.PluginSupportTypes.ENCRYPT_DECRYPT
        self.plugin_returned.supports.return_value = True
        self.plugin_name = common_utils.generate_fullname_for(
            self.plugin_returned)
        self.plugin_loaded = mock.MagicMock(obj=self.plugin_returned)
        self.manager = cm.get_manager()
        self.manager.extensions = [self.plugin_loaded]
示例#14
0
    def generate_asymmetric_key(self, key_spec, context):
        """Generates an asymmetric key.

        Returns a AsymmetricKeyMetadataDTO object containing
        metadata(s) for asymmetric key components. The metadata
        can be used to retrieve individual components of
        asymmetric key pair.
        """

        plugin_type = _determine_generation_type(key_spec.alg)
        if crypto.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)

        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type, key_spec.alg, key_spec.bit_length,
            project_id=context.project_model.id)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        generate_dto = crypto.GenerateDTO(key_spec.alg,
                                          key_spec.bit_length,
                                          None, key_spec.passphrase)

        # Create the encrypted meta.
        private_key_dto, public_key_dto, passwd_dto = (
            generating_plugin.generate_asymmetric(
                generate_dto, kek_meta_dto, context.project_model.external_id
            )
        )

        _store_secret_and_datum(
            context,
            context.private_secret_model,
            kek_datum_model,
            private_key_dto)

        _store_secret_and_datum(
            context,
            context.public_secret_model,
            kek_datum_model,
            public_key_dto)

        if key_spec.passphrase and passwd_dto:
            _store_secret_and_datum(
                context,
                context.passphrase_secret_model,
                kek_datum_model,
                passwd_dto)

        return sstore.AsymmetricKeyMetadataDTO()
示例#15
0
    def generate_asymmetric_key(self, key_spec, context):
        """Generates an asymmetric key.

        Returns a AsymmetricKeyMetadataDTO object containing
        metadata(s) for asymmetric key components. The metadata
        can be used to retrieve individual components of
        asymmetric key pair.
        """

        plugin_type = _determine_generation_type(key_spec.alg)
        if base.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)

        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type, key_spec.alg, key_spec.bit_length,
            project_id=context.project_model.id)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        generate_dto = base.GenerateDTO(key_spec.alg,
                                        key_spec.bit_length,
                                        None, key_spec.passphrase)

        # Create the encrypted meta.
        private_key_dto, public_key_dto, passwd_dto = (
            generating_plugin.generate_asymmetric(
                generate_dto, kek_meta_dto, context.project_model.external_id
            )
        )

        _store_secret_and_datum(
            context,
            context.private_secret_model,
            kek_datum_model,
            private_key_dto)

        _store_secret_and_datum(
            context,
            context.public_secret_model,
            kek_datum_model,
            public_key_dto)

        if key_spec.passphrase and passwd_dto:
            _store_secret_and_datum(
                context,
                context.passphrase_secret_model,
                kek_datum_model,
                passwd_dto)

        return sstore.AsymmetricKeyMetadataDTO()
示例#16
0
    def test_can_override_enabled_plugins(self):
        """Verify can override default configuration for plugin selection."""
        # Reset manager singleton otherwise we have test execution
        # order problems
        cm._PLUGIN_MANAGER = None

        cm.CONF.set_override("enabled_crypto_plugins", ["foo_plugin"], group="crypto", enforce_type=True)

        manager_to_test = cm.get_manager()

        self.assertIsInstance(manager_to_test, cm._CryptoPluginManager)

        self.assertListEqual(["foo_plugin"], manager_to_test._names)
示例#17
0
    def test_can_override_enabled_plugins(self):
        """Verify can override default configuration for plugin selection."""
        # Reset manager singleton otherwise we have test execution
        # order problems
        cm._PLUGIN_MANAGER = None

        cm.CONF.set_override("enabled_crypto_plugins", ['foo_plugin'],
                             group='crypto')

        manager_to_test = cm.get_manager()

        self.assertIsInstance(manager_to_test, cm._CryptoPluginManager)

        self.assertListEqual(['foo_plugin'], manager_to_test._names)
示例#18
0
    def get_secret(self, secret_type, metadata, context):
        """Retrieve a secret.

        :param secret_type: secret type
        :param metadata: secret metadata
        :param context: StoreCryptoContext for secret
        :returns: SecretDTO that contains secret
        """
        if (not context.secret_model or
                not context.secret_model.encrypted_data):
            raise sstore.SecretNotFoundException()

        # TODO(john-wood-w) Need to revisit 1 to many datum relationship.
        datum_model = context.secret_model.encrypted_data[0]

        # Find HSM-style 'crypto' plugin.
        decrypting_plugin = manager.get_manager().get_plugin_retrieve(
            datum_model.kek_meta_project.plugin_name)

        # wrap the KEKDatum instance in our DTO
        kek_meta_dto = crypto.KEKMetaDTO(datum_model.kek_meta_project)

        # Convert from text-based storage format to binary.
        encrypted = base64.b64decode(datum_model.cypher_text)
        decrypt_dto = crypto.DecryptDTO(encrypted)

        # Decrypt the secret.
        secret = decrypting_plugin.decrypt(decrypt_dto,
                                           kek_meta_dto,
                                           datum_model.kek_meta_extended,
                                           context.project_model.external_id)
        secret = base64.b64encode(secret)
        key_spec = sstore.KeySpec(alg=context.secret_model.algorithm,
                                  bit_length=context.secret_model.bit_length,
                                  mode=context.secret_model.mode)

        return sstore.SecretDTO(secret_type,
                                secret, key_spec,
                                datum_model.content_type)
示例#19
0
    def store_secret(self, secret_dto, context):
        """Store a secret.

        :param secret_dto: SecretDTO for secret
        :param context: StoreCryptoContext for secret
        :returns: an optional dictionary containing metadata about the secret
        """

        # Find HSM-style 'crypto' plugin.
        encrypting_plugin = manager.get_manager().get_plugin_store_generate(
            base.PluginSupportTypes.ENCRYPT_DECRYPT,
            project_id=context.project_model.id
        )

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            encrypting_plugin, context.project_model)

        # Secrets are base64 encoded before being passed to the secret stores.
        secret_bytes = base64.b64decode(secret_dto.secret)

        encrypt_dto = base.EncryptDTO(secret_bytes)

        # Enhance the context with content_type, This is needed to build
        # datum_model to store
        if not context.content_type:
            context.content_type = secret_dto.content_type

        # Create an encrypted datum instance and add the encrypted cyphertext.
        response_dto = encrypting_plugin.encrypt(
            encrypt_dto, kek_meta_dto, context.project_model.external_id
        )

        # Convert binary data into a text-based format.
        _store_secret_and_datum(
            context, context.secret_model, kek_datum_model, response_dto)

        return None
示例#20
0
    def get_policy(self, project_id):
        response = _get_project_policy(project_id)
        if response:
            attribute = response['attribute']
            enc_keys = _get_enc_keys(project_id)
            if enc_keys:
                sk_attribute = None
                encrypting_plugin = manager.get_manager(
                ).get_plugin_store_generate(
                    crypto.PluginSupportTypes.ENCRYPT_DECRYPT)
                sk_attribute = encrypting_plugin.mk_decrypt(
                    enc_keys, attribute, project_id)

                response['attribute'] = sk_attribute
            else:
                return {
                    'status':
                    'Session Key not provisioned for this project. Please perform Remote/Mutual Attestation first'
                }
        else:
            return {'status': 'No Policy set for this project.'}

        return response
示例#21
0
    def generate_symmetric_key(self, key_spec, context):
        """Generate a symmetric key.

        :param key_spec: KeySpec that contains details on the type of key to
        generate
        :param context: StoreCryptoContext for secret
        :returns: a dictionary that contains metadata about the key
        """

        # Find HSM-style 'crypto' plugin.
        plugin_type = _determine_generation_type(key_spec.alg)
        if base.PluginSupportTypes.SYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)
        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type,
            key_spec.alg,
            key_spec.bit_length,
            key_spec.mode,
            project_id=context.project_model.id)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        # Create an encrypted datum instance and add the created cypher text.
        generate_dto = base.GenerateDTO(key_spec.alg,
                                        key_spec.bit_length,
                                        key_spec.mode, None)
        # Create the encrypted meta.
        response_dto = generating_plugin.generate_symmetric(
            generate_dto, kek_meta_dto, context.project_model.external_id)

        # Convert binary data into a text-based format.
        _store_secret_and_datum(
            context, context.secret_model, kek_datum_model, response_dto)

        return None
示例#22
0
def sync_secret_stores(secretstore_manager, crypto_manager=None):
    """Synchronize secret store plugin names between service conf and database

    This method reads secret and crypto store plugin name from service
    configuration and then synchronizes corresponding data maintained in
    database SecretStores table.

    Any new plugin name(s) added in service configuration is added as a new
    entry in SecretStores table. If global_default value is changed for
    existing plugins, then global_default flag is updated to reflect that
    change in database. If plugin name is removed from service configuration,
    then removal is possible as long as respective plugin names are NOT set as
    preferred secret store for a project. If it is used and plugin name is
    removed, then error is raised. This logic is intended to be invoked at
    server startup so any error raised here will result in critical failure.
    """
    if not utils.is_multiple_backends_enabled():
        return

    # doing local import to avoid circular dependency between manager and
    # current utils module
    from barbican.plugin.crypto import manager as cm

    secret_stores_repo = db_repos.get_secret_stores_repository()
    proj_store_repo = db_repos.get_project_secret_store_repository()
    if crypto_manager is None:
        crypto_manager = cm.get_manager()

    def get_friendly_name_dict(ext_manager):
        """Returns dict of plugin internal name and friendly name entries."""
        names_dict = {}
        for ext in ext_manager.extensions:
            if ext.obj and hasattr(ext.obj, 'get_plugin_name'):
                names_dict[ext.name] = ext.obj.get_plugin_name()
        return names_dict

    ss_friendly_names = get_friendly_name_dict(secretstore_manager)
    crypto_friendly_names = get_friendly_name_dict(crypto_manager)
    # get existing secret stores data from database
    db_stores = secret_stores_repo.get_all()

    # read secret store data from service configuration
    conf_stores = []
    for parsed_store in secretstore_manager.parsed_stores:
        crypto_plugin = parsed_store.crypto_plugin
        if not crypto_plugin:
            crypto_plugin = None

        if crypto_plugin:
            friendly_name = crypto_friendly_names.get(crypto_plugin)
        else:
            friendly_name = ss_friendly_names.get(parsed_store.store_plugin)

        conf_stores.append(db_models.SecretStores(
            name=friendly_name, store_plugin=parsed_store.store_plugin,
            crypto_plugin=crypto_plugin,
            global_default=parsed_store.global_default))

    if db_stores:
        def fn_match(lh_store, rh_store):
            return (lh_store.store_plugin == rh_store.store_plugin and
                    lh_store.crypto_plugin == rh_store.crypto_plugin)

        for conf_store in conf_stores:
            # find existing db entry for plugin using conf based plugin names
            db_store_match = next((db_store for db_store in db_stores if
                                   fn_match(conf_store, db_store)), None)
            if db_store_match:
                # update existing db entry if global default is changed now
                if db_store_match.global_default != conf_store.global_default:
                    db_store_match.global_default = conf_store.global_default
                    # persist flag change.
                    db_store_match.save()
                # remove matches store from local list after processing
                db_stores.remove(db_store_match)
            else:  # new conf entry as no match found in existing entries
                secret_stores_repo.create_from(conf_store)

        # entries still present in db list are no longer configured in service
        # configuration, so try to remove them provided there is no project
        # is using it as preferred secret store.
        for db_store in db_stores:
            if proj_store_repo.get_count_by_secret_store(db_store.id) == 0:
                secret_stores_repo.delete_entity_by_id(db_store.id, None)
            else:
                raise exception.MultipleStorePluginStillInUse(db_store.name)
    else:  # initial setup case when there is no secret stores data in db
        for conf_store in conf_stores:
            secret_stores_repo.create_from(conf_store)
示例#23
0
 def run(self):
     self.results[self.index] = cm.get_manager()
示例#24
0
 def run(self):
     self.results[self.index] = cm.get_manager()
    def test_project_preferred_default_plugin(self, dataset):
        """Check project preferred behavior with different global default"""

        self.init_via_conf_file(dataset['store_plugins'],
                                dataset['crypto_plugins'],
                                enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11'), \
                mock.patch('kmip.pie.client.ProxyKmipClient'):
            manager = secret_store.SecretStorePluginManager()

        pkcs11_secret_store = self._get_secret_store_entry('store_crypto',
                                                           'p11_crypto')
        kmip_secret_store = self._get_secret_store_entry('kmip_plugin', None)
        db_secret_store = self._get_secret_store_entry('store_crypto',
                                                       'simple_crypto')

        project1 = self._create_project()
        project2 = self._create_project()
        project3 = self._create_project()

        # For project1 , make pkcs11 as preferred secret store
        self._create_project_store(project1.id, pkcs11_secret_store.id)
        # For project2 , make kmip as preferred secret store
        self._create_project_store(project2.id, kmip_secret_store.id)
        # For project3 , make db backend as preferred secret store
        self._create_project_store(project3.id, db_secret_store.id)

        keySpec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128)
        cm_manager = cm.get_manager()

        # For project1, verify store and crypto plugin instance used are pkcs11
        # specific
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project1.id)
        self.assertIsInstance(plugin_found,
                              store_crypto.StoreCryptoAdapterPlugin)
        crypto_plugin = cm.get_manager().get_plugin_store_generate(
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project1.id)
        self.assertIsInstance(crypto_plugin, p11_crypto.P11CryptoPlugin)

        # For project2, verify store plugin instance is kmip specific
        # and there is no crypto plugin instance
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project2.id)
        self.assertIsInstance(plugin_found, kss.KMIPSecretStore)

        self.assertRaises(
            base.CryptoPluginNotFound, cm_manager.get_plugin_store_generate,
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project2.id)

        # For project3, verify store and crypto plugin instance used are db
        # backend specific
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project3.id)
        self.assertIsInstance(plugin_found,
                              store_crypto.StoreCryptoAdapterPlugin)
        crypto_plugin = cm.get_manager().get_plugin_store_generate(
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project3.id)
        self.assertIsInstance(crypto_plugin, simple_crypto.SimpleCryptoPlugin)

        # Make sure for project with no preferred setting, uses global default
        project4 = self._create_project()
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project4.id)
        self.assertIsInstance(plugin_found,
                              dataset['default_store_class'])
    def test_project_preferred_default_plugin(self, dataset):
        """Check project preferred behavior with different global default"""

        self.init_via_conf_file(dataset['store_plugins'],
                                dataset['crypto_plugins'],
                                enabled=True)

        with mock.patch('barbican.plugin.crypto.p11_crypto.P11CryptoPlugin.'
                        '_create_pkcs11'), \
                mock.patch('kmip.pie.client.ProxyKmipClient'):
            manager = secret_store.SecretStorePluginManager()

        pkcs11_secret_store = self._get_secret_store_entry('store_crypto',
                                                           'p11_crypto')
        kmip_secret_store = self._get_secret_store_entry('kmip_plugin', None)
        db_secret_store = self._get_secret_store_entry('store_crypto',
                                                       'simple_crypto')

        project1 = self._create_project()
        project2 = self._create_project()
        project3 = self._create_project()

        # For project1 , make pkcs11 as preferred secret store
        self._create_project_store(project1.id, pkcs11_secret_store.id)
        # For project2 , make kmip as preferred secret store
        self._create_project_store(project2.id, kmip_secret_store.id)
        # For project3 , make db backend as preferred secret store
        self._create_project_store(project3.id, db_secret_store.id)

        keySpec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128)
        cm_manager = cm.get_manager()

        # For project1, verify store and crypto plugin instance used are pkcs11
        # specific
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project1.id)
        self.assertIsInstance(plugin_found,
                              store_crypto.StoreCryptoAdapterPlugin)
        crypto_plugin = cm.get_manager().get_plugin_store_generate(
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project1.id)
        self.assertIsInstance(crypto_plugin, p11_crypto.P11CryptoPlugin)

        # For project2, verify store plugin instance is kmip specific
        # and there is no crypto plugin instance
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project2.id)
        self.assertIsInstance(plugin_found, kss.KMIPSecretStore)

        self.assertRaises(
            base.CryptoPluginNotFound, cm_manager.get_plugin_store_generate,
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project2.id)

        # For project3, verify store and crypto plugin instance used are db
        # backend specific
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project3.id)
        self.assertIsInstance(plugin_found,
                              store_crypto.StoreCryptoAdapterPlugin)
        crypto_plugin = cm.get_manager().get_plugin_store_generate(
            base.PluginSupportTypes.ENCRYPT_DECRYPT, project_id=project3.id)
        self.assertIsInstance(crypto_plugin, simple_crypto.SimpleCryptoPlugin)

        # Make sure for project with no preferred setting, uses global default
        project4 = self._create_project()
        plugin_found = manager.get_plugin_store(keySpec,
                                                project_id=project4.id)
        self.assertIsInstance(plugin_found,
                              dataset['default_store_class'])
示例#27
0
 def do_provision_kek(self, external_project_id):
     encrypting_plugin = manager.get_manager().get_plugin_store_generate(
         crypto.PluginSupportTypes.ENCRYPT_DECRYPT)
     response = encrypting_plugin.do_provision_kek(external_project_id)
     return response
示例#28
0
def sync_secret_stores(secretstore_manager, crypto_manager=None):
    """Synchronize secret store plugin names between service conf and database

    This method reads secret and crypto store plugin name from service
    configuration and then synchronizes corresponding data maintained in
    database SecretStores table.

    Any new plugin name(s) added in service configuration is added as a new
    entry in SecretStores table. If global_default value is changed for
    existing plugins, then global_default flag is updated to reflect that
    change in database. If plugin name is removed from service configuration,
    then removal is possible as long as respective plugin names are NOT set as
    preferred secret store for a project. If it is used and plugin name is
    removed, then error is raised. This logic is intended to be invoked at
    server startup so any error raised here will result in critical failure.
    """
    if not utils.is_multiple_backends_enabled():
        return

    # doing local import to avoid circular dependency between manager and
    # current utils module
    from barbican.plugin.crypto import manager as cm

    secret_stores_repo = db_repos.get_secret_stores_repository()
    proj_store_repo = db_repos.get_project_secret_store_repository()
    if crypto_manager is None:
        crypto_manager = cm.get_manager()

    def get_friendly_name_dict(ext_manager):
        """Returns dict of plugin internal name and friendly name entries."""
        names_dict = {}
        for ext in ext_manager.extensions:
            if ext.obj and hasattr(ext.obj, 'get_plugin_name'):
                names_dict[ext.name] = ext.obj.get_plugin_name()
        return names_dict

    ss_friendly_names = get_friendly_name_dict(secretstore_manager)
    crypto_friendly_names = get_friendly_name_dict(crypto_manager)
    # get existing secret stores data from database
    db_stores = secret_stores_repo.get_all()

    # read secret store data from service configuration
    conf_stores = []
    for parsed_store in secretstore_manager.parsed_stores:
        crypto_plugin = parsed_store.crypto_plugin
        if not crypto_plugin:
            crypto_plugin = None

        if crypto_plugin:
            friendly_name = crypto_friendly_names.get(crypto_plugin)
        else:
            friendly_name = ss_friendly_names.get(parsed_store.store_plugin)

        conf_stores.append(
            db_models.SecretStores(name=friendly_name,
                                   store_plugin=parsed_store.store_plugin,
                                   crypto_plugin=crypto_plugin,
                                   global_default=parsed_store.global_default))

    if db_stores:

        def fn_match(lh_store, rh_store):
            return (lh_store.store_plugin == rh_store.store_plugin
                    and lh_store.crypto_plugin == rh_store.crypto_plugin)

        for conf_store in conf_stores:
            # find existing db entry for plugin using conf based plugin names
            db_store_match = next(
                (db_store
                 for db_store in db_stores if fn_match(conf_store, db_store)),
                None)
            if db_store_match:
                # update existing db entry if global default is changed now
                if db_store_match.global_default != conf_store.global_default:
                    db_store_match.global_default = conf_store.global_default
                    # persist flag change.
                    db_store_match.save()
                # remove matches store from local list after processing
                db_stores.remove(db_store_match)
            else:  # new conf entry as no match found in existing entries
                secret_stores_repo.create_from(conf_store)

        # entries still present in db list are no longer configured in service
        # configuration, so try to remove them provided there is no project
        # is using it as preferred secret store.
        for db_store in db_stores:
            if proj_store_repo.get_count_by_secret_store(db_store.id) == 0:
                secret_stores_repo.delete_entity_by_id(db_store.id, None)
            else:
                raise exception.MultipleStorePluginStillInUse(db_store.name)
    else:  # initial setup case when there is no secret stores data in db
        for conf_store in conf_stores:
            secret_stores_repo.create_from(conf_store)