diff --git a/doc/source/library/credential_providers.rst b/doc/source/library/credential_providers.rst index 6e142966b..7e831cc9a 100644 --- a/doc/source/library/credential_providers.rst +++ b/doc/source/library/credential_providers.rst @@ -5,8 +5,133 @@ 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. +a list of preprovisioned credentials. These 2 modules are implementations of +the same abstract credential providers class and can be used interchangably. +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 would 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=CONF.resources_prefix, + 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): a 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 manually be called 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