Credential Providers

These library interfaces are used to deal with allocating credentials on demand either dynamically by calling Keystone to allocate new credentials, or from a list of preprovisioned credentials. These 2 modules are implementations of the same abstract credential providers class and can be used interchangeably. However, each implementation has some additional parameters that are used to influence the behavior of the modules. The API reference at the bottom of this doc shows the interface definitions for both modules, however, that may be a bit opaque. You can see some examples of how to leverage this interface below.

Initialization Example

This example is from Tempest itself (from tempest/common/credentials_factory.py just modified slightly) and is how it initializes the credential provider based on config:

from tempest import config
from tempest.lib.common import dynamic_creds
from tempest.lib.common import preprov_creds

CONF = config.CONF

def get_credentials_provider(name, network_resources=None,
                             force_tenant_isolation=False,
                             identity_version=None):
    # If a test requires a new account to work, it can have it via forcing
    # dynamic credentials. A new account will be produced only for that test.
    # In case admin credentials are not available for the account creation,
    # the test should be skipped else it will fail.
    identity_version = identity_version or CONF.identity.auth_version
    if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
        admin_creds = get_configured_admin_credentials(
            fill_in=True, identity_version=identity_version)
        return dynamic_creds.DynamicCredentialProvider(
            name=name,
            network_resources=network_resources,
            identity_version=identity_version,
            admin_creds=admin_creds,
            identity_admin_domain_scope=CONF.identity.admin_domain_scope,
            identity_admin_role=CONF.identity.admin_role,
            extra_roles=CONF.auth.tempest_roles,
            neutron_available=CONF.service_available.neutron,
            project_network_cidr=CONF.network.project_network_cidr,
            project_network_mask_bits=CONF.network.project_network_mask_bits,
            public_network_id=CONF.network.public_network_id,
            create_networks=(CONF.auth.create_isolated_networks and not
                             CONF.network.shared_physical_network),
            resource_prefix='tempest',
            credentials_domain=CONF.auth.default_credentials_domain_name,
            admin_role=CONF.identity.admin_role,
            identity_uri=CONF.identity.uri_v3,
            identity_admin_endpoint_type=CONF.identity.v3_endpoint_type)
    else:
        if CONF.auth.test_accounts_file:
            # Most params are not relevant for pre-created accounts
            return preprov_creds.PreProvisionedCredentialProvider(
                name=name, identity_version=identity_version,
                accounts_lock_dir=lockutils.get_lock_path(CONF),
                test_accounts_file=CONF.auth.test_accounts_file,
                object_storage_operator_role=CONF.object_storage.operator_role,
                object_storage_reseller_admin_role=reseller_admin_role,
                credentials_domain=CONF.auth.default_credentials_domain_name,
                admin_role=CONF.identity.admin_role,
                identity_uri=CONF.identity.uri_v3,
                identity_admin_endpoint_type=CONF.identity.v3_endpoint_type)
        else:
            raise exceptions.InvalidConfiguration(
                'A valid credential provider is needed')

This function just returns an initialized credential provider class based on the config file. The consumer of this function treats the output as the same regardless of whether it’s a dynamic or preprovisioned provider object.

Dealing with Credentials

Once you have a credential provider object created the access patterns for allocating and removing credentials are the same across both the dynamic and preprovisioned credentials. These are defined in the abstract CredentialProvider class. At a high level, the credentials provider enables you to get 3 basic types of credentials at once (per object): primary, alt, and admin. You’re also able to allocate a credential by role. These credentials are tracked by the provider object and delete must be called manually, otherwise, the created resources will not be deleted (or returned to the pool in the case of preprovisioned creds).

Examples

Continuing from the example above, to allocate credentials by the 3 basic types you can do the following:

provider = get_credentials_provider('my_tests')
primary_creds = provider.get_primary_creds()
alt_creds = provider.get_alt_creds()
admin_creds = provider.get_admin_creds()
# Make sure to delete the credentials when you're finished
provider.clear_creds()

To create and interact with credentials by role you can do the following:

provider = get_credentials_provider('my_tests')
my_role_creds = provider.get_creds_by_role({'roles': ['my_role']})
# provider.clear_creds() will clear all creds including those allocated by
# role
provider.clear_creds()

When multiple roles are specified a set of creds with all the roles assigned will be allocated:

provider = get_credentials_provider('my_tests')
my_role_creds = provider.get_creds_by_role({'roles': ['my_role',
                                                      'my_other_role']})
# provider.clear_creds() will clear all creds including those allocated by
# role
provider.clear_creds()

If you need multiple sets of credentials with the same roles you can also do this by leveraging the force_new kwarg:

provider = get_credentials_provider('my_tests')
my_role_creds = provider.get_creds_by_role({'roles': ['my_role']})
my_role_other_creds = provider.get_creds_by_role({'roles': ['my_role']},
                                                 force_new=True)
# provider.clear_creds() will clear all creds including those allocated by
# role
provider.clear_creds()

API Reference

The dynamic credentials module

class DynamicCredentialProvider(identity_version, name=None, network_resources=None, credentials_domain=None, admin_role=None, admin_creds=None, identity_admin_domain_scope=False, identity_admin_role='admin', extra_roles=None, neutron_available=False, create_networks=True, project_network_cidr=None, project_network_mask_bits=None, public_network_id=None, resource_prefix=None, identity_admin_endpoint_type='public', identity_uri=None)[source]

Creates credentials dynamically for tests

A credential provider that, based on an initial set of admin credentials, creates new credentials on the fly for tests to use and then discard.

Parameters:
  • identity_version (str) – identity API version to use v2 or v3

  • admin_role (str) – name of the admin role added to admin users

  • name (str) – names of dynamic resources include this parameter when specified

  • credentials_domain (str) – name of the domain where the users are created. If not defined, the project domain from admin_credentials is used

  • network_resources (dict) – network resources to be created for the created credentials

  • admin_creds (Credentials) – initial admin credentials

  • identity_admin_domain_scope (bool) – Set to true if admin should be scoped to the domain. By default this is False and the admin role is scoped to the project.

  • identity_admin_role (str) – The role name to use for admin

  • extra_roles (list) – A list of strings for extra roles that should be assigned to all created users

  • neutron_available (bool) – Whether we are running in an environment with neutron

  • create_networks (bool) – Whether dynamic project networks should be created or not

  • project_network_cidr – The CIDR to use for created project networks

  • project_network_mask_bits – The network mask bits to use for created project networks

  • public_network_id – The id for the public network to use

  • identity_admin_endpoint_type – The endpoint type for identity admin clients. Defaults to public.

  • identity_uri – Identity URI of the target cloud

The pre-provisioned credentials module

class PreProvisionedCredentialProvider(identity_version, test_accounts_file, accounts_lock_dir, name=None, credentials_domain=None, admin_role=None, object_storage_operator_role=None, object_storage_reseller_admin_role=None, identity_uri=None)[source]

Credentials provider using pre-provisioned accounts

This credentials provider loads the details of pre-provisioned accounts from a YAML file, in the format specified by etc/accounts.yaml.sample. It locks accounts while in use, using the external locking mechanism, allowing for multiple python processes to share a single account file, and thus running tests in parallel.

The accounts_lock_dir must be generated using lockutils.get_lock_path from the oslo.concurrency library. For instance:

accounts_lock_dir = os.path.join(lockutils.get_lock_path(CONF),
                                 'test_accounts')

Role names for object storage are optional as long as the operator and reseller_admin credential types are not used in the accounts file.

Parameters:
  • identity_version – identity version of the credentials

  • admin_role – name of the admin role

  • test_accounts_file – path to the accounts YAML file

  • accounts_lock_dir – the directory for external locking

  • name – name of the hash file (optional)

  • credentials_domain – name of the domain credentials belong to (if no domain is configured)

  • object_storage_operator_role – name of the role

  • object_storage_reseller_admin_role – name of the role

  • identity_uri – Identity URI of the target cloud