def test_bootstrap_is_idempotent_when_password_does_not_change(self): # NOTE(morganfainberg): Ensure we can run bootstrap with the same # configuration multiple times without erroring. bootstrap = cli.BootStrap() self._do_test_bootstrap(bootstrap) v3_token_controller = controllers.Auth() v3_password_data = { 'identity': { "methods": ["password"], "password": { "user": { "name": bootstrap.username, "password": bootstrap.password, "domain": { "id": CONF.identity.default_domain_id } } } } } auth_response = v3_token_controller.authenticate_for_token( self.make_request(), v3_password_data) token = auth_response.headers['X-Subject-Token'] self._do_test_bootstrap(bootstrap) # build validation request request = self.make_request(is_admin=True) request.context_dict['subject_token_id'] = token # Make sure the token we authenticate for is still valid. v3_token_controller.validate_token(request)
def test_bootstrap_is_not_idempotent_when_password_does_change(self): # NOTE(lbragstad): Ensure bootstrap isn't idempotent when run with # different arguments or configuration values. bootstrap = cli.BootStrap() self._do_test_bootstrap(bootstrap) v3_token_controller = controllers.Auth() v3_password_data = { 'identity': { "methods": ["password"], "password": { "user": { "name": bootstrap.username, "password": bootstrap.password, "domain": { "id": CONF.identity.default_domain_id } } } } } auth_response = v3_token_controller.authenticate_for_token( self.make_request(), v3_password_data) token = auth_response.headers['X-Subject-Token'] os.environ['OS_BOOTSTRAP_PASSWORD'] = uuid.uuid4().hex self._do_test_bootstrap(bootstrap) # build validation request request = self.make_request(is_admin=True) request.context_dict['subject_token_id'] = token # Since the user account was recovered with a different password, we # shouldn't be able to validate this token. Bootstrap should have # persisted a revocation event because the user's password was updated. # Since this token was obtained using the original password, it should # now be invalid. self.assertRaises(exception.TokenNotFound, v3_token_controller.validate_token, request)
def test_issue_token_from_rules_without_user(self): api = auth_controllers.Auth() context = {'environment': {}} self._inject_assertion(context, 'BAD_TESTER_ASSERTION') self.assertRaises(exception.Unauthorized, api.authenticate_for_token, context, self.UNSCOPED_V3_SAML2_REQ)
def append_v3_routers(mapper, routers): auth_controller = controllers.Auth() mapper.connect('/auth/tokens', controller=auth_controller, action='authenticate_for_token', conditions=dict(method=['POST'])) # NOTE(morganfainberg): For policy enforcement reasons, the # ``validate_token_head`` method is still used for HEAD requests. # The controller method makes the same call as the validate_token # call and lets wsgi.render_response remove the body data. mapper.connect('/auth/tokens', controller=auth_controller, action='check_token', conditions=dict(method=['HEAD'])) mapper.connect('/auth/tokens', controller=auth_controller, action='revoke_token', conditions=dict(method=['DELETE'])) mapper.connect('/auth/tokens', controller=auth_controller, action='validate_token', conditions=dict(method=['GET'])) mapper.connect('/auth/tokens/OS-PKI/revoked', controller=auth_controller, action='revocation_list', conditions=dict(method=['GET']))
def list_projects_for_user(self, request): """List all projects available to an authenticated user. :param context: request context :returns: list of accessible projects """ controller = auth_controllers.Auth() return controller.get_auth_projects(request)
def append_v3_routers(self, mapper, routers): auth_controller = controllers.Auth() self._add_resource( mapper, auth_controller, path='/auth/tokens', get_action='validate_token', head_action='check_token', post_action='authenticate_for_token', delete_action='revoke_token', rel=json_home.build_v3_resource_relation('auth_tokens')) self._add_resource( mapper, auth_controller, path='/auth/tokens/OS-PKI/revoked', get_head_action='revocation_list', rel=json_home.build_v3_extension_resource_relation( 'OS-PKI', '1.0', 'revocations')) self._add_resource( mapper, auth_controller, path='/auth/catalog', get_head_action='get_auth_catalog', rel=json_home.build_v3_resource_relation('auth_catalog')) self._add_resource( mapper, auth_controller, path='/auth/projects', get_head_action='get_auth_projects', rel=json_home.build_v3_resource_relation('auth_projects')) self._add_resource( mapper, auth_controller, path='/auth/domains', get_head_action='get_auth_domains', rel=json_home.build_v3_resource_relation('auth_domains')) # NOTE(morgan): explicitly add json_home data for auth_projects and # auth_domains for OS-FEDERATION here, as auth will always own it # based upon how the flask scaffolding works. This bit is transitional # for the move to flask. for element in ['projects', 'domains']: resource_data = {'href': '/auth/%s' % element} json_home.Status.update_resource_data( resource_data, status=json_home.Status.STABLE) json_home.JsonHomeResources.append_resource( json_home_relations.os_federation_resource_rel_func( resource_name=element), resource_data) self._add_resource( mapper, auth_controller, path='/auth/system', get_head_action='get_auth_system', rel=json_home.build_v3_resource_relation('auth_system'))
def append_v3_routers(self, mapper, routers): auth_controller = controllers.Auth() self._add_resource( mapper, auth_controller, path='/auth/tokens', get_action='validate_token', head_action='check_token', post_action='authenticate_for_token', delete_action='revoke_token', rel=json_home.build_v3_resource_relation('auth_tokens')) self._add_resource(mapper, auth_controller, path='/auth/tokens/OS-PKI/revoked', get_head_action='revocation_list', rel=json_home.build_v3_extension_resource_relation( 'OS-PKI', '1.0', 'revocations')) self._add_resource( mapper, auth_controller, path='/auth/catalog', get_head_action='get_auth_catalog', rel=json_home.build_v3_resource_relation('auth_catalog')) self._add_resource( mapper, auth_controller, path='/auth/projects', get_head_action='get_auth_projects', rel=json_home.build_v3_resource_relation('auth_projects')) self._add_resource( mapper, auth_controller, path='/auth/domains', get_head_action='get_auth_domains', rel=json_home.build_v3_resource_relation('auth_domains')) self._add_resource( mapper, auth_controller, path='/auth/system', get_head_action='get_auth_system', rel=json_home.build_v3_resource_relation('auth_system'))
def append_v3_routers(self, mapper, routers): auth_controller = controllers.Auth() # NOTE(morganfainberg): For policy enforcement reasons, the # ``validate_token_head`` method is still used for HEAD requests. # The controller method makes the same call as the validate_token # call and lets wsgi.render_response remove the body data. self._add_resource( mapper, auth_controller, path='/auth/tokens', get_action='validate_token', head_action='check_token', post_action='authenticate_for_token', delete_action='revoke_token', rel=json_home.build_v3_resource_relation('auth_tokens')) self._add_resource(mapper, auth_controller, path='/auth/tokens/OS-PKI/revoked', get_action='revocation_list', rel=json_home.build_v3_extension_resource_relation( 'OS-PKI', '1.0', 'revocations')) self._add_resource( mapper, auth_controller, path='/auth/catalog', get_action='get_auth_catalog', rel=json_home.build_v3_resource_relation('auth_catalog')) self._add_resource( mapper, auth_controller, path='/auth/projects', get_action='get_auth_projects', rel=json_home.build_v3_resource_relation('auth_projects')) self._add_resource( mapper, auth_controller, path='/auth/domains', get_action='get_auth_domains', rel=json_home.build_v3_resource_relation('auth_domains'))
def append_v3_routers(mapper, routers): auth_controller = controllers.Auth() mapper.connect('/auth/tokens', controller=auth_controller, action='authenticate_for_token', conditions=dict(method=['POST'])) mapper.connect('/auth/tokens', controller=auth_controller, action='check_token', conditions=dict(method=['HEAD'])) mapper.connect('/auth/tokens', controller=auth_controller, action='revoke_token', conditions=dict(method=['DELETE'])) mapper.connect('/auth/tokens', controller=auth_controller, action='validate_token', conditions=dict(method=['GET'])) mapper.connect('/auth/tokens/OS-PKI/revoked', controller=auth_controller, action='revocation_list', conditions=dict(method=['GET']))
def load_federation_sample_data(self): """Inject additional data.""" # Create and add domains self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.domainC = self.new_domain_ref() self.assignment_api.create_domain(self.domainC['id'], self.domainC) # Create and add projects self.proj_employees = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.proj_employees['id'], self.proj_employees) self.proj_customers = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.proj_customers['id'], self.proj_customers) self.project_all = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.project_all['id'], self.project_all) # Create and add groups self.group_employees = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_employees['id'], self.group_employees) self.group_customers = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_customers['id'], self.group_customers) self.group_admins = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_admins['id'], self.group_admins) # Create and add roles self.role_employee = self.new_role_ref() self.assignment_api.create_role(self.role_employee['id'], self.role_employee) self.role_customer = self.new_role_ref() self.assignment_api.create_role(self.role_customer['id'], self.role_customer) self.role_admin = self.new_role_ref() self.assignment_api.create_role(self.role_admin['id'], self.role_admin) # Employees can access # * proj_employees # * project_all self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], project_id=self.proj_employees['id']) self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], project_id=self.project_all['id']) # Customers can access # * proj_customers self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], project_id=self.proj_customers['id']) # Admins can access: # * proj_customers # * proj_employees # * project_all self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.proj_customers['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.proj_employees['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.project_all['id']) self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], domain_id=self.domainA['id']) # Customers can access: # * domain A self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], domain_id=self.domainA['id']) # Employees can access: # * domain A # * domain B self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], domain_id=self.domainB['id']) # Admins can access: # * domain A # * domain B # * domain C self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainB['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainC['id']) self.rules = { 'rules': [ { 'local': [ { 'group': { 'id': self.group_employees['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Employee' ] } ] }, { 'local': [ { 'group': { 'id': self.group_customers['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Customer' ] } ] }, { 'local': [ { 'group': { 'id': self.group_admins['id'] } }, { 'group': { 'id': self.group_employees['id'] } }, { 'group': { 'id': self.group_customers['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Admin', 'Chief' ] } ] }, { 'local': [ { 'group': { 'id': 'bad_group_id' } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName', }, { 'type': 'FirstName', 'any_one_of': [ 'Jill' ] }, { 'type': 'LastName', 'any_one_of': [ 'Smith' ] } ] }, ] } # Add IDP self.idp = self.idp_ref(id=self.IDP) self.federation_api.create_idp(self.idp['id'], self.idp) # Add a mapping self.mapping = self.mapping_ref() self.federation_api.create_mapping(self.mapping['id'], self.mapping) # Add protocols self.proto_saml = self.proto_ref(mapping_id=self.mapping['id']) self.proto_saml['id'] = self.PROTOCOL self.federation_api.create_protocol(self.idp['id'], self.proto_saml['id'], self.proto_saml) # Generate fake tokens context = {'environment': {}} self.tokens = {} VARIANTS = ('EMPLOYEE_ASSERTION', 'CUSTOMER_ASSERTION', 'ADMIN_ASSERTION') api = auth_controllers.Auth() for variant in VARIANTS: self._inject_assertion(context, variant) r = api.authenticate_for_token(context, self.UNSCOPED_V3_SAML2_REQ) self.tokens[variant] = r.headers.get('X-Subject-Token') self.TOKEN_SCOPE_PROJECT_FROM_NONEXISTENT_TOKEN = self._scope_request( uuid.uuid4().hex, 'project', self.proj_customers['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_EMPLOYEE = self._scope_request( self.tokens['EMPLOYEE_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_PROJECT_CUSTOMER_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'project', self.proj_customers['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_DOMAIN_A_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainA['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_A_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainA['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_C_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainC['id'])
def _issue_unscoped_token(self, assertion='EMPLOYEE_ASSERTION'): api = auth_controllers.Auth() context = {'environment': {}} self._inject_assertion(context, assertion) r = api.authenticate_for_token(context, self.UNSCOPED_V3_SAML2_REQ) return r