def _validate_token_data(openrc): keystone_session = openstack_utils.get_keystone_session(openrc) keystone_client = openstack_utils.get_keystone_session_client( keystone_session) token = keystone_session.get_token() if (openstack_utils.get_os_release() < openstack_utils.get_os_release('xenial_ocata')): if len(token) != 32: raise zaza_exceptions.KeystoneWrongTokenProvider( 'We expected a UUID token and got this: "{}"'.format( token)) else: if len(token) < 180: raise zaza_exceptions.KeystoneWrongTokenProvider( 'We expected a Fernet token and got this: "{}"'.format( token)) logging.info('token: "{}"'.format(pprint.pformat(token))) if (openstack_utils.get_os_release() < openstack_utils.get_os_release('trusty_mitaka')): logging.info('skip: tokens.get_token_data() not allowed prior ' 'to trusty_mitaka') return # get_token_data call also gets the service catalog token_data = keystone_client.tokens.get_token_data(token) if token_data.get('token', {}).get('catalog', None) is None: raise zaza_exceptions.KeystoneAuthorizationStrict( # NOTE(fnordahl) the above call will probably throw a # http.Forbidden exception, but just in case 'Regular end user not allowed to retrieve the service ' 'catalog. ("{}")'.format(pprint.pformat(token_data))) logging.info('token_data: "{}"'.format(pprint.pformat(token_data)))
def setUpClass(cls): """Run class setup for running Keystone charm operation tests.""" super(BaseKeystoneTest, cls).setUpClass() # Check if we are related to Vault TLS certificates cls.tls_rid = zaza.model.get_relation_id( 'keystone', 'vault', remote_interface_name='certificates') # Check for VIP cls.vip = (zaza.model.get_application_config('keystone') .get('vip').get('value')) cls.keystone_ips = zaza.model.get_app_ips('keystone') # If we have a VIP set and we are using TLS only check the VIP # If you check the individual IP haproxy may send to a different # back end which leads to mismatched certificates. if cls.vip: if cls.tls_rid: cls.keystone_ips = [cls.vip] else: cls.keystone_ips.append(cls.vip) if (openstack_utils.get_os_release() < openstack_utils.get_os_release('xenial_queens')): cls.default_api_version = '2' else: cls.default_api_version = '3' cls.admin_keystone_session = ( openstack_utils.get_overcloud_keystone_session()) cls.admin_keystone_client = ( openstack_utils.get_keystone_session_client( cls.admin_keystone_session, client_api_version=cls.default_api_version))
def main(argv): cli_utils.setup_logging() overcloud_novarc = openstack_utils.get_overcloud_auth() user_file = mojo_utils.get_mojo_file('keystone_users.yaml') user_config = generic_utils.get_yaml_config(user_file) try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) except FileNotFoundError: cacert = None keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystone_client = openstack_utils.get_keystone_session_client( keystone_session) if overcloud_novarc.get('API_VERSION', 2) == 2: projects = [user['project'] for user in user_config] mojo_os_utils.project_create(keystone_client, projects) mojo_os_utils.user_create_v2(keystone_client, user_config) # TODO validate this works without adding roles # mojo_os_utils.add_users_to_roles(keystone_client, user_config) else: for user in user_config: mojo_os_utils.domain_create(keystone_client, [user['domain']]) mojo_os_utils.project_create(keystone_client, [user['project']], user['domain']) mojo_os_utils.user_create_v3(keystone_client, user_config)
def _v2(): keystone_session = openstack_utils.get_overcloud_keystone_session() keystone_client = openstack_utils.get_keystone_session_client( keystone_session, client_api_version=2) tenant = keystone_client.tenants.create(tenant_name=DEMO_TENANT, description='Demo Tenant', enabled=True) keystone_client.users.create(name=DEMO_USER, password=DEMO_PASSWORD, tenant_id=tenant.id)
def _v3(): keystone_session = openstack_utils.get_overcloud_keystone_session() keystone_client = openstack_utils.get_keystone_session_client( keystone_session) domain = keystone_client.domains.create( DEMO_DOMAIN, description='Demo Domain', enabled=True) project = keystone_client.projects.create( DEMO_PROJECT, domain, description='Demo Project', enabled=True) demo_user = keystone_client.users.create( DEMO_USER, domain=domain, project=project, password=DEMO_PASSWORD, email='*****@*****.**', description='Demo User', enabled=True) member_role = keystone_client.roles.find(name='Member') keystone_client.roles.grant( member_role, user=demo_user, project_domain=domain, project=project) demo_admin_user = keystone_client.users.create( DEMO_ADMIN_USER, domain=domain, project=project, password=DEMO_ADMIN_USER_PASSWORD, email='*****@*****.**', description='Demo Admin User', enabled=True) admin_role = keystone_client.roles.find(name='Admin') keystone_client.roles.grant( admin_role, user=demo_admin_user, domain=domain) keystone_client.roles.grant( member_role, user=demo_admin_user, project_domain=domain, project=project) keystone_client.roles.grant( admin_role, user=demo_admin_user, project_domain=domain, project=project)
def setUpClass(cls): """Run class setup for running Keystone charm operation tests.""" super(BaseKeystoneTest, cls).setUpClass() cls.keystone_ips = zaza.model.get_app_ips('keystone') if (openstack_utils.get_os_release() < openstack_utils.get_os_release('xenial_queens')): cls.default_api_version = '2' else: cls.default_api_version = '3' cls.admin_keystone_session = ( openstack_utils.get_overcloud_keystone_session()) cls.admin_keystone_client = ( openstack_utils.get_keystone_session_client( cls.admin_keystone_session, client_api_version=cls.default_api_version))
def test_admin_project_scoped_access(self): """Verify cloud admin access using project scoped token. `admin` user in `admin_domain` should be able to access API methods guarded by `rule:cloud_admin` policy using a token scoped to `admin` project in `admin_domain`. We implement a policy that enables domain segregation and administration delegation [0]. It is important to understand that this differs from the default policy. In the initial implementation it was necessary to switch between using a `domain` scoped and `project` scoped token to successfully manage a cloud, but since the introduction of `is_admin` functionality in Keystone [1][2][3] and our subsequent adoption of it in Keystone charm [4], this is no longer necessary. This test here to validate this behaviour. 0: https://github.com/openstack/keystone/commit/c7a5c6c 1: https://github.com/openstack/keystone/commit/e702369 2: https://github.com/openstack/keystone/commit/e923a14 3: https://github.com/openstack/keystone/commit/9804081 4: https://github.com/openstack/charm-keystone/commit/10e3d84 """ if (openstack_utils.get_os_release() < openstack_utils.get_os_release('trusty_mitaka')): logging.info('skipping test < trusty_mitaka') return with self.config_change( {'preferred-api-version': self.default_api_version}, {'preferred-api-version': '3'}, application_name="keystone"): for ip in self.keystone_ips: try: logging.info('keystone IP {}'.format(ip)) ks_session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) ks_client = openstack_utils.get_keystone_session_client( ks_session) result = ks_client.domains.list() logging.info('.domains.list: "{}"'.format( pprint.pformat(result))) except keystoneauth1.exceptions.http.Forbidden as e: raise zaza_exceptions.KeystoneAuthorizationStrict( 'Retrieve domain list as admin with project scoped ' 'token FAILED. ({})'.format(e)) logging.info('OK')
def test_end_user_domain_admin_access(self): """Verify that end-user domain admin does not have elevated privileges. In additon to validating that the `policy.json` is written and the service is restarted on config-changed, the test validates that our `policy.json` is correct. Catch regressions like LP: #1651989 """ if (openstack_utils.get_os_release() < openstack_utils.get_os_release('xenial_ocata')): logging.info('skipping test < xenial_ocata') return with self.config_change( {'preferred-api-version': self.default_api_version}, {'preferred-api-version': '3'}, application_name="keystone"): for ip in self.keystone_ips: openrc = { 'API_VERSION': 3, 'OS_USERNAME': DEMO_ADMIN_USER, 'OS_PASSWORD': DEMO_ADMIN_USER_PASSWORD, 'OS_AUTH_URL': 'http://{}:5000/v3'.format(ip), 'OS_USER_DOMAIN_NAME': DEMO_DOMAIN, 'OS_DOMAIN_NAME': DEMO_DOMAIN, } if self.tls_rid: openrc['OS_CACERT'] = openstack_utils.KEYSTONE_LOCAL_CACERT openrc['OS_AUTH_URL'] = (openrc['OS_AUTH_URL'].replace( 'http', 'https')) logging.info('keystone IP {}'.format(ip)) keystone_session = openstack_utils.get_keystone_session( openrc, scope='DOMAIN') keystone_client = openstack_utils.get_keystone_session_client( keystone_session) try: # expect failure keystone_client.domains.list() except keystoneauth1.exceptions.http.Forbidden as e: logging.debug('Retrieve domain list as end-user domain ' 'admin NOT allowed...OK ({})'.format(e)) pass else: raise zaza_exceptions.KeystoneAuthorizationPermissive( 'Retrieve domain list as end-user domain admin ' 'allowed when it should not be.') logging.info('OK')
def keystone_federation_setup(): """Configure Keystone Federation.""" cli_utils.setup_logging() keystone_session = openstack_utils.get_overcloud_keystone_session() keystone_client = openstack_utils.get_keystone_session_client( keystone_session) try: domain = keystone_client.domains.find(name=FEDERATED_DOMAIN) except keystoneauth1.exceptions.http.NotFound: domain = keystone_client.domains.create(FEDERATED_DOMAIN, description="Federated Domain", enabled=True) try: group = keystone_client.groups.find(name=FEDERATED_GROUP, domain=domain) except keystoneauth1.exceptions.http.NotFound: group = keystone_client.groups.create(FEDERATED_GROUP, domain=domain, enabled=True) role = keystone_client.roles.find(name=MEMBER) keystone_client.roles.grant(role, group=group, domain=domain) try: idp = keystone_client.federation.identity_providers.find( name=IDP, domain_id=domain.id) except keystoneauth1.exceptions.http.NotFound: idp = keystone_client.federation.identity_providers.create( IDP, remote_ids=[REMOTE_ID], domain_id=domain.id, enabled=True) JSON_RULES = json.loads(MAP_TEMPLATE.format(domain_id=domain.id)) try: keystone_client.federation.mappings.find(name=MAP_NAME) except keystoneauth1.exceptions.http.NotFound: keystone_client.federation.mappings.create(MAP_NAME, rules=JSON_RULES) try: keystone_client.federation.protocols.get(IDP, PROTOCOL_NAME) except keystoneauth1.exceptions.http.NotFound: keystone_client.federation.protocols.create(PROTOCOL_NAME, mapping=MAP_NAME, identity_provider=idp)
def keystone_v3_domain_setup(): overcloud_novarc = openstack_utils.get_overcloud_auth() if overcloud_novarc.get('API_VERSION', 2) == 3: try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) except FileNotFoundError: cacert = None keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystone_client = openstack_utils.get_keystone_session_client( keystone_session) mojo_os_utils.project_create(keystone_client, ['admin'], 'admin_domain') admin_project_id = openstack_utils.get_project_id( keystone_client, 'admin', api_version=3, domain_name='admin_domain') role = keystone_client.roles.find(name='admin') user = keystone_client.users.find(name='admin') keystone_client.roles.grant(role, user=user, project=admin_project_id)
def main(argv): cli_utils.setup_logging() parser = argparse.ArgumentParser() default_machines = ["cirros:m1.tiny:1"] parser.add_argument("machines", default=default_machines, nargs="*") parser.add_argument("--active_wait", default=180) parser.add_argument("--cloudinit_wait", default=180) parser.add_argument("--ping_wait", default=180) options = parser.parse_args() machines = cli_utils.parse_arg(options, 'machines', multiargs=True) active_wait = int(cli_utils.parse_arg(options, 'active_wait')) cloudinit_wait = int(cli_utils.parse_arg(options, 'cloudinit_wait')) ping_wait = int(cli_utils.parse_arg(options, 'ping_wait')) overcloud_novarc = openstack_utils.get_overcloud_auth() try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) except FileNotFoundError: cacert = None keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystonec = openstack_utils.get_keystone_session_client(keystone_session) domain = overcloud_novarc.get('OS_PROJECT_DOMAIN_NAME') project_id = openstack_utils.get_project_id( keystonec, 'admin', api_version=overcloud_novarc['API_VERSION'], domain_name=domain) novac = openstack_utils.get_nova_session_client(keystone_session) neutronc = openstack_utils.get_neutron_session_client(keystone_session) init_flavors(novac) priv_key = mojo_os_utils.create_keypair(novac, 'mojo') openstack_utils.add_neutron_secgroup_rules(neutronc, project_id) for server in novac.servers.list(): novac.servers.delete(server.id) for instanceset in machines: image_name, flavor_name, count = instanceset.split(":") # when instance count allows boot instances off both regular instance # storage and volume storage # # account for count=1 and odd numbers # NOTE(fnordahl) temporarilly disable test while tests settle # regular_boot_count = int(int(count) / 2) + (int(count) % 2) # volume_boot_count = int(int(count) / 2) regular_boot_count = int(count) volume_boot_count = 0 mojo_os_utils.boot_and_test( novac, neutronc, image_name=image_name, flavor_name=flavor_name, number=regular_boot_count, privkey=priv_key, active_wait=active_wait, cloudinit_wait=cloudinit_wait, ping_wait=ping_wait, ) mojo_os_utils.boot_and_test( novac, neutronc, image_name=image_name, flavor_name=flavor_name, number=volume_boot_count, privkey=priv_key, active_wait=active_wait, cloudinit_wait=cloudinit_wait, ping_wait=ping_wait, boot_from_volume=True, )
def setup_sdn(network_config, keystone_session=None): """Perform setup for Software Defined Network. :param network_config: Network configuration settings dictionary :type network_config: dict :param keystone_session: Keystone session object for overcloud :type keystone_session: keystoneauth1.session.Session object :returns: None :rtype: None """ # If a session has not been provided, acquire one if not keystone_session: keystone_session = openstack_utils.get_overcloud_keystone_session() # Get authenticated clients keystone_client = openstack_utils.get_keystone_session_client( keystone_session) neutron_client = openstack_utils.get_neutron_session_client( keystone_session) admin_domain = None if openstack_utils.get_keystone_api_version() > 2: admin_domain = "admin_domain" # Resolve the project name from the overcloud openrc into a project id project_id = openstack_utils.get_project_id( keystone_client, "admin", domain_name=admin_domain, ) # Network Setup subnetpools = False if network_config.get("subnetpool_prefix"): subnetpools = True logging.info("Configuring overcloud network") # Create the external network ext_network = openstack_utils.create_external_network( neutron_client, project_id, network_config.get("dvr_enabled", False), network_config["external_net_name"]) openstack_utils.create_external_subnet( neutron_client, project_id, ext_network, network_config["default_gateway"], network_config["external_net_cidr"], network_config["start_floating_ip"], network_config["end_floating_ip"], network_config["external_subnet_name"]) provider_router = (openstack_utils.create_provider_router( neutron_client, project_id)) openstack_utils.plug_extnet_into_router(neutron_client, provider_router, ext_network) ip_version = network_config.get("ip_version") or 4 subnetpool = None if subnetpools: address_scope = openstack_utils.create_address_scope( neutron_client, project_id, network_config.get("address_scope"), ip_version=ip_version) subnetpool = openstack_utils.create_subnetpool( neutron_client, project_id, network_config.get("subnetpool_name"), network_config.get("subnetpool_prefix"), address_scope) project_network = openstack_utils.create_project_network( neutron_client, project_id, shared=False, network_type=network_config["network_type"]) project_subnet = openstack_utils.create_project_subnet( neutron_client, project_id, project_network, network_config.get("private_net_cidr"), subnetpool=subnetpool, ip_version=ip_version) openstack_utils.update_subnet_dns(neutron_client, project_subnet, network_config["external_dns"]) openstack_utils.plug_subnet_into_router(neutron_client, network_config["router_name"], project_network, project_subnet) openstack_utils.add_neutron_secgroup_rules(neutron_client, project_id)