def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user sys_role_config = { 'name': 'system_role', 'system': True } def_role_config = { 'name': 'default_role', 'platform_default': True } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save()
def setUp(self): """Set up the access view tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user self.access_data = { "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save()
def setUp(self): """Set up the access view tests.""" super().setUp() request = self.request_context['request'] user = User() user.username = self.user_data['username'] user.account = self.customer_data['account_id'] request.user = user self.access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save()
def setUp(self): """Set up the group view nonadmin tests.""" super().setUp() self.user_data = self._create_user_data() self.customer = self._create_customer_data() self.request_context = self._create_request_context(self.customer, self.user_data, is_org_admin=False) request = self.request_context['request'] self.headers = request.META self.access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save()
def setUp(self): """Set up the group view nonadmin tests.""" super().setUp() self.user_data = self._create_user_data() self.customer = self._create_customer_data() self.request_context = self._create_request_context(self.customer, self.user_data, is_org_admin=False) request = self.request_context["request"] self.headers = request.META self.access_data = { "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save()
class PrincipalViewsetTests(IdentityRequest): """Test the principal viewset.""" def setUp(self): """Set up the principal viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], email=self.user_data['email'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username'], email=self.user_data['email']) self.principal.save() def tearDown(self): """Tear down principal viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Principal.objects.all().delete() def test_read_principal_success(self): """Test that we can read a principal.""" url = reverse('principal-detail', kwargs={'username': self.principal.username}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('username')) self.assertEqual(self.principal.username, response.data.get('username')) def test_read_principal_invalid(self): """Test that reading an invalid principal returns an error.""" url = reverse('principal-detail', kwargs={'username': uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_principal_list_success(self): """Test that we can read a list of principals.""" url = reverse('principal-list') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) principal = response.data.get('data')[0] self.assertIsNotNone(principal.get('username')) self.assertEqual(principal.get('username'), self.principal.username)
class GroupViewNonAdminTests(IdentityRequest): """Test the group view for nonadmin user.""" def setUp(self): """Set up the group view nonadmin tests.""" super().setUp() self.user_data = self._create_user_data() self.customer = self._create_customer_data() self.request_context = self._create_request_context(self.customer, self.user_data, is_org_admin=False) request = self.request_context["request"] self.headers = request.META self.access_data = { "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down group view tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() def test_nonadmin_RonR_list(self): """Test that a nonadmin user can list groups in tenant""" url = "{}?application={}".format(reverse("group-list"), "rbac") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_nonadmin_RonR_retrieve(self): """Test that a nonadmin user can't retrieve group RBAC resources""" url = reverse("group-detail", kwargs={"uuid": self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
class GroupViewNonAdminTests(IdentityRequest): """Test the group view for nonadmin user.""" def setUp(self): """Set up the group view nonadmin tests.""" super().setUp() self.user_data = self._create_user_data() self.customer = self._create_customer_data() self.request_context = self._create_request_context(self.customer, self.user_data, is_org_admin=False) request = self.request_context['request'] self.headers = request.META self.access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down group view tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() def test_nonadmin_RonR_list(self): """Test that a nonadmin user can list groups in tenant""" url = '{}?application={}'.format(reverse('group-list'), 'rbac') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_nonadmin_RonR_retrieve(self): """Test that a nonadmin user can't retrieve group RBAC resources""" url = reverse('group-detail', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def setUp(self): """Set up the principal viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username='******') self.principal.save()
def setUp(self): """Set up the principal viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user with tenant_context(self.tenant): self.principal = Principal(username="******") self.principal.save()
def process_request(self, request): # noqa: C901 """Process request for csrf checks. Args: request (object): The request object """ if is_no_auth(request): request.user = User('', '') return try: json_rh_auth = extract_header(request, self.header) username = json_rh_auth['identity']['user']['username'] email = json_rh_auth['identity']['user']['email'] account = json_rh_auth['identity']['account_number'] except (KeyError, JSONDecodeError): logger.warning('Could not obtain identity on request.') return if (username and email and account): # Check for customer creation & user creation query_string = '' if request.META['QUERY_STRING']: query_string = '?{}'.format(request.META['QUERY_STRING']) logger.info(f'API: {request.path}{query_string}' # pylint: disable=W1203 f' -- ACCOUNT: {account} USER: {username}') try: schema_name = create_schema_name(account) tenant = Tenant.objects.filter(schema_name=schema_name).get() except Tenant.DoesNotExist: tenant = IdentityHeaderMiddleware._create_tenant(account) try: user = User.objects.get(username=username) except User.DoesNotExist: user = IdentityHeaderMiddleware._create_user( username, email, tenant, request) request.user = user # Temporarily add principals based on API interaction with tenant_context(tenant): try: Principal.objects.get(username=username) except Principal.DoesNotExist: try: with transaction.atomic(): principal = Principal(username=username, email=email) principal.save() logger.info( 'Created new principal for account_id %s.', account) except IntegrityError: pass
def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save()
def setUp(self): """Set up the policy viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save()
def setUp(self): """Set up the policy viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save() Permission.objects.create(permission="app:*:*") with tenant_context(Tenant.objects.get(schema_name="public")): Permission.objects.create(permission="app:*:*")
def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context['request'] user = User() user.username = self.user_data['username'] user.account = self.customer_data['account_id'] request.user = user sys_role_config = {'name': 'system_role', 'system': True} def_role_config = {'name': 'default_role', 'platform_default': True} self.display_fields = { 'applications', 'description', 'uuid', 'name', 'system', 'created', 'policyCount', 'accessCount', 'modified', 'platform_default' } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.policy = Policy.objects.create(name='policyA') self.group = Group(name='groupA', description='groupA description') self.group.save() self.group.principals.add(self.principal) self.group.policies.add(self.policy) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save() self.defRole.save() self.policy.roles.add(self.defRole, self.sysRole) self.policy.save() self.access = Access.objects.create(permission='app:*:*', role=self.defRole)
def setUp(self): """Set up the group viewset tests.""" super().setUp() request = self.request_context['request'] user = User() user.username = self.user_data['username'] user.account = self.customer_data['account_id'] request.user = user self.dummy_role_id = uuid4() with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.principalB = Principal(username='******') self.principalB.save() self.principalC = Principal( username='******') self.principalC.save() self.group = Group(name='groupA') self.group.save() self.role = Role.objects.create(name='roleA', description='A role for a group.') self.policy = Policy.objects.create(name='policyA', group=self.group) self.policy.roles.add(self.role) self.policy.save() self.group.policies.add(self.policy) self.group.principals.add(self.principal, self.principalB) self.group.save() self.defGroup = Group(name='groupDef', platform_default=True, system=True) self.defGroup.save() self.defGroup.principals.add(self.principal) self.defGroup.save() self.emptyGroup = Group(name='groupE') self.emptyGroup.save() self.groupB = Group.objects.create(name='groupB') self.groupB.principals.add(self.principal) self.policyB = Policy.objects.create(name='policyB', group=self.groupB) self.roleB = Role.objects.create(name='roleB') self.policyB.roles.add(self.roleB) self.policyB.save() # role that's not assigned to principal self.roleOrphan = Role.objects.create(name='roleOrphan') # group that associates with multipal roles self.groupMultiRole = Group.objects.create(name='groupMultiRole') self.policyMultiRole = Policy.objects.create( name='policyMultiRole') self.policyMultiRole.roles.add(self.role) self.policyMultiRole.roles.add(self.roleB) self.groupMultiRole.policies.add(self.policyMultiRole)
def setUp(self): """Set up the group viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user self.dummy_role_id = uuid4() with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.principalB = Principal(username="******") self.principalB.save() self.principalC = Principal( username="******") self.principalC.save() self.group = Group(name="groupA") self.group.save() self.role = Role.objects.create(name="roleA", description="A role for a group.") self.policy = Policy.objects.create(name="policyA", group=self.group) self.policy.roles.add(self.role) self.policy.save() self.group.policies.add(self.policy) self.group.principals.add(self.principal, self.principalB) self.group.save() self.defGroup = Group(name="groupDef", platform_default=True, system=True) self.defGroup.save() self.defGroup.principals.add(self.principal) self.defGroup.save() self.emptyGroup = Group(name="groupE") self.emptyGroup.save() self.groupB = Group.objects.create(name="groupB") self.groupB.principals.add(self.principal) self.policyB = Policy.objects.create(name="policyB", group=self.groupB) self.roleB = Role.objects.create(name="roleB") self.policyB.roles.add(self.roleB) self.policyB.save() # role that's not assigned to principal self.roleOrphan = Role.objects.create(name="roleOrphan") # group that associates with multipal roles self.groupMultiRole = Group.objects.create(name="groupMultiRole") self.policyMultiRole = Policy.objects.create( name="policyMultiRole") self.policyMultiRole.roles.add(self.role) self.policyMultiRole.roles.add(self.roleB) self.groupMultiRole.policies.add(self.policyMultiRole)
def setUp(self): """Set up the group viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user self.dummy_role_id = uuid4() with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.role = Role.objects.create(name='roleA') self.policy = Policy.objects.create(name='policyA', group=self.group) self.policy.roles.add(self.role) self.policy.save() self.group.policies.add(self.policy) self.group.principals.add(self.principal) self.group.save() self.defGroup = Group(name='groupDef', platform_default=True, system=True) self.defGroup.save() self.defGroup.principals.add(self.principal) self.defGroup.save() self.groupB = Group.objects.create(name='groupB') self.groupB.principals.add(self.principal) self.policyB = Policy.objects.create(name='policyB', group=self.groupB) self.roleB = Role.objects.create(name='roleB') self.policyB.roles.add(self.roleB) self.policyB.save()
class PolicyViewsetTests(IdentityRequest): """Test the policy viewset.""" def setUp(self): """Set up the policy viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], email=self.user_data['email'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username'], email=self.user_data['email']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down policy viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() def create_role(self, role_name, in_access_data=None): """Create a role.""" access_data = { 'permission': 'app:*:*', 'resourceDefinition': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } if in_access_data: access_data = in_access_data test_data = {'name': role_name, 'access': [access_data]} # create a role url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) return response def create_policy(self, policy_name, group, roles, status=status.HTTP_201_CREATED): """Create a policy.""" # create a policy test_data = {'name': policy_name, 'group': group, 'roles': roles} url = reverse('policy-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status) return response def test_create_policy_success(self): """Test that we can create a policy.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # test that we can retrieve the policy url = reverse('policy-detail', kwargs={'uuid': response.data.get('uuid')}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertEqual(policy_name, response.data.get('name')) self.assertEqual(str(self.group.uuid), response.data.get('group').get('uuid')) def test_create_policy_invalid_group(self): """Test that we cannot create a policy with invalid group.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, uuid4(), [role_uuid], status.HTTP_400_BAD_REQUEST) def test_create_policy_invalid_role(self): """Test that we cannot create a policy with an invalid role.""" policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [uuid4()], status.HTTP_400_BAD_REQUEST) def test_create_policy_no_role(self): """Test that we cannot create a policy without roles.""" policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [], status.HTTP_400_BAD_REQUEST) def test_create_policy_invalid(self): """Test that creating an invalid policy returns an error.""" test_data = {} url = reverse('policy-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_policy_invalid(self): """Test that reading an invalid policy returns an error.""" url = reverse('policy-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_policy_list_success(self): """Test that we can read a list of policies.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # list a policies url = reverse('policy-list') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) policy = response.data.get('data')[0] self.assertIsNotNone(policy.get('name')) self.assertEqual(policy.get('name'), policy_name) def test_update_policy_success(self): """Test that we can update an existing policy.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) updated_name = policy_name + '_update' policy_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name test_data['group'] = self.group.uuid test_data['roles'] = [role_uuid] del test_data['uuid'] url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('uuid')) self.assertEqual(updated_name, response.data.get('name')) def test_update_policy_bad_group(self): """Test that we cannot update an existing policy with a bad group.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) updated_name = policy_name + '_update' policy_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name test_data['group'] = uuid4() test_data['roles'] = [role_uuid] del test_data['uuid'] url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_policy_bad_role(self): """Test that we cannot update an existing policy with a bad role.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) updated_name = policy_name + '_update' policy_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name test_data['group'] = self.group.uuid test_data['roles'] = [uuid4()] del test_data['uuid'] url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_policy_no_role(self): """Test that we can update an existing policy to have no roles.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) updated_name = policy_name + '_update' policy_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name test_data['group'] = self.group.uuid test_data['roles'] = [] del test_data['uuid'] url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_policy_invalid(self): """Test that updating an invalid policy returns an error.""" url = reverse('policy-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.put(url, {}, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_role_success(self): """Test that we can delete an existing role.""" role_name = 'roleA' response = self.create_role(role_name) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) policy_uuid = response.data.get('uuid') url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the policy no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_policy_invalid(self): """Test that deleting an invalid policy returns an error.""" url = reverse('policy-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_policy_removed_on_group_deletion(self): """Test that we can an existing policy is cleaned up when the group is deleted.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) policy_uuid = response.data.get('uuid') url = reverse('group-detail', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.delete(url, **self.headers) url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_policy_removed_on_all_role_deletion(self): """Test that we can an existing policy is cleaned up when the all roles are deleted.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) policy_uuid = response.data.get('uuid') url = reverse('role-detail', kwargs={'uuid': role_uuid}) client = APIClient() response = client.delete(url, **self.headers) url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_policy_removed_on_one_role_deletion(self): """Test that we can an existing policy remains when not all roles are deleted.""" roles = [] role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) roles.append(response.data.get('uuid')) role_name = 'roleB' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) roles.append(response.data.get('uuid')) policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, roles) policy_uuid = response.data.get('uuid') url = reverse('role-detail', kwargs={'uuid': roles[0]}) client = APIClient() response = client.delete(url, **self.headers) url = reverse('policy-detail', kwargs={'uuid': policy_uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK)
class PrincipalViewsetTests(IdentityRequest): """Test the principal viewset.""" def setUp(self): """Set up the principal viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user with tenant_context(self.tenant): self.principal = Principal(username="******") self.principal.save() def tearDown(self): """Tear down principal viewset tests.""" with tenant_context(self.tenant): Principal.objects.all().delete() @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": { "userCount": "1", "users": [{ "username": "******" }] } }, ) def test_read_principal_list_success(self, mock_request): """Test that we can read a list of principals.""" # Create a cross_account user in rbac. with tenant_context(self.tenant): cross_account_principal = Principal.objects.create( username="******", cross_account=True) url = reverse("principals") client = APIClient() response = client.get(url, **self.headers) mock_request.assert_called_once_with(ANY, limit=10, offset=0, options={ "sort_order": "asc", "status": "enabled", "admin_only": "false" }) # /principals/ endpoint won't return the cross_account_principal, which does not exist in IT. self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(int(response.data.get("meta").get("count")), 1) self.assertEqual(len(response.data.get("data")), 1) principal = response.data.get("data")[0] self.assertIsNotNone(principal.get("username")) self.assertEqual(principal.get("username"), self.principal.username) cross_account_principal.delete() @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": { "userCount": "2", "users": [ { "username": "******", "is_org_admin": "true" }, { "username": "******", "is_org_admin": "false" }, ], }, }, ) def test_check_principal_admin(self, mock_request): """Test that we can read a list of principals.""" url = reverse("principals") client = APIClient() response = client.get(url, **self.headers) mock_request.assert_called_once_with(ANY, limit=10, offset=0, options={ "sort_order": "asc", "status": "enabled", "admin_only": "false" }) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(int(response.data.get("meta").get("count")), 2) self.assertEqual(len(response.data.get("data")), 2) principal = response.data.get("data")[0] self.assertIsNotNone(principal.get("username")) self.assertEqual(principal.get("username"), "test_user1") self.assertIsNotNone(principal.get("is_org_admin")) self.assertTrue(principal.get("is_org_admin")) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [{ "username": "******" }] }, ) def test_read_principal_filtered_list_success(self, mock_request): """Test that we can read a filtered list of principals.""" # Create a cross_account user in rbac. with tenant_context(self.tenant): cross_account_principal = Principal.objects.create( username="******", cross_account=True) url = f'{reverse("principals")}?usernames=test_user,cross_account_user&offset=30' client = APIClient() response = client.get(url, **self.headers) mock_request.assert_called_once_with(["test_user"], account=ANY, limit=10, offset=30, options={"sort_order": "asc"}) # Cross account user won't be returned. self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) self.assertEqual(response.data.get("meta").get("count"), 1) principal = response.data.get("data")[0] self.assertIsNotNone(principal.get("username")) self.assertEqual(principal.get("username"), "test_user") cross_account_principal.delete() @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [{ "username": "******" }] }, ) def test_read_principal_filtered_list_success(self, mock_request): """Test that we can read a filtered list of principals.""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() response = client.get(url, **self.headers) mock_request.assert_called_once_with(["test_user"], account=ANY, limit=10, offset=30, options={"sort_order": "asc"}) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) self.assertEqual(response.data.get("meta").get("count"), 1) principal = response.data.get("data")[0] self.assertIsNotNone(principal.get("username")) self.assertEqual(principal.get("username"), "test_user") @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": [{ "username": "******" }] }, ) def test_read_principal_partial_matching(self, mock_request): """Test that we can read a list of principals by partial matching.""" url = f'{reverse("principals")}?usernames=test_us,no_op&offset=30&match_criteria=partial' client = APIClient() response = client.get(url, **self.headers) mock_request.assert_called_once_with( ANY, input="test_us", limit=10, offset=30, options={ "sort_order": "asc", "status": "enabled", "search_by": "partial_name" }, ) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) self.assertEqual(response.data.get("meta").get("count"), 1) principal = response.data.get("data")[0] self.assertIsNotNone(principal.get("username")) self.assertEqual(principal.get("username"), "test_user") def test_bad_query_param(self): """Test handling of bad query params.""" url = f'{reverse("principals")}?limit=foo' client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_bad_query_param_of_sort_order(self): """Test handling of bad query params.""" url = f'{reverse("principals")}?sort_order=det' client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": status.HTTP_500_INTERNAL_SERVER_ERROR, "errors": [{ "detail": "error" }] }, ) def test_read_principal_list_fail(self, mock_request): """Test that we can handle a failure with listing principals.""" url = reverse("principals") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) error = response.data.get("errors")[0] self.assertIsNotNone(error.get("detail")) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [{ "username": "******", "account_number": "1234", "id": "5678" }] }, ) def test_read_principal_list_account(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30&sort_order=desc' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) mock_request.assert_called_once_with(["test_user"], account=ANY, limit=10, offset=30, options={"sort_order": "desc"}) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), 1) resp = proxy._process_data(response.data.get("data"), account="1234", account_filter=True, return_id=True) self.assertEqual(len(resp), 1) self.assertEqual(resp[0]["username"], "test_user") self.assertEqual(resp[0]["user_id"], "5678") @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [{ "username": "******", "account_number": "54321" }] }, ) def test_read_principal_list_account_fail(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) resp = proxy._process_data(response.data.get("data"), account="1234", account_filter=True) self.assertEqual(len(resp), 0) self.assertNotEqual(resp, "test_user") @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [{ "username": "******", "account_number": "54321" }] }, ) def test_read_principal_list_account_filter(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), 1) resp = proxy._process_data(response.data.get("data"), account="1234", account_filter=False) self.assertEqual(len(resp), 1) self.assertEqual(resp[0]["username"], "test_user") @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": [{ "username": "******", "account_number": "54321" }] }, ) def test_read_principal_list_by_email(self, mock_request): """Test that we can handle a request with an email address""" url = f'{reverse("principals")}[email protected]' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), 1) resp = proxy._process_data(response.data.get("data"), account="54321", account_filter=False) self.assertEqual(len(resp), 1) mock_request.assert_called_once_with(ANY, input="*****@*****.**", limit=10, offset=0, options={ "sort_order": "asc", "search_by": "email" }) self.assertEqual(resp[0]["username"], "test_user") @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": { "userCount": "1", "users": [{ "username": "******", "is_org_admin": "true" }] }, }, ) def test_read_users_of_desired_status(self, mock_request): """Test that we can return users of desired status within an account""" url = f'{reverse("principals")}?status=disabled' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), "1") mock_request.assert_called_once_with(ANY, limit=10, offset=0, options={ "sort_order": "asc", "status": "disabled", "admin_only": "false" }) @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": { "userCount": "1", "users": [{ "username": "******", "is_org_admin": "true" }] }, }, ) def test_read_list_of_admins(self, mock_request): """Test that we can return only org admins within an account""" url = f'{reverse("principals")}?admin_only=true' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), "1") mock_request.assert_called_once_with(ANY, limit=10, offset=0, options={ "sort_order": "asc", "status": "enabled", "admin_only": "true" }) def test_read_users_with_invalid_status_value(self): """Test that reading user with invalid status value returns 400""" url = f'{reverse("principals")}?status=invalid' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_users_with_invalid_admin_only_value(self): """Test that reading user with invalid status value returns 400""" url = f'{reverse("principals")}?admin_only=invalid' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( "management.principal.proxy.PrincipalProxy.request_principals", return_value={ "status_code": 200, "data": [{ "username": "******", "account_number": "54321", "email": "*****@*****.**" }], }, ) def test_read_principal_list_by_email_partial_matching(self, mock_request): """Test that we can handle a request with a partial email address""" url = f'{reverse("principals")}?email=test_use&match_criteria=partial' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(response.data.get("meta").get("count"), 1) resp = proxy._process_data(response.data.get("data"), account="54321", account_filter=False) self.assertEqual(len(resp), 1) mock_request.assert_called_once_with( ANY, input="test_use", limit=10, offset=0, options={ "sort_order": "asc", "status": "enabled", "search_by": "partial_email" }, ) self.assertEqual(resp[0]["username"], "test_user")
class RoleViewsetTests(IdentityRequest): """Test the role viewset.""" def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down role viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() def create_role(self, role_name, in_access_data=None): """Create a role.""" access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } if in_access_data: access_data = in_access_data test_data = {'name': role_name, 'access': [access_data]} # create a role url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) return response def test_create_role_success(self): """Test that we can create a role.""" role_name = 'roleA' access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] } response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse('role-detail', kwargs={'uuid': response.data.get('uuid')}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertEqual(role_name, response.data.get('name')) self.assertIsInstance(response.data.get('access'), list) self.assertEqual(access_data, response.data.get('access')[0]) def test_create_role_invalid(self): """Test that creating an invalid role returns an error.""" test_data = {} url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_invalid_permission(self): """Test that creating an invalid role returns an error.""" test_data = { 'name': 'role1', 'access': [{ 'permission': 'foo:bar', 'resourceDefinitions': [] }] } url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_invalid(self): """Test that reading an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_list_success(self): """Test that we can read a list of roles.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # list a roles url = reverse('role-list') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) role = response.data.get('data')[0] self.assertIsNotNone(role.get('name')) self.assertEqual(role.get('name'), role_name) def test_update_role_success(self): """Test that we can update an existing role.""" role_name = 'roleA' response = self.create_role(role_name) updated_name = role_name + '_update' role_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name del test_data['uuid'] url = reverse('role-detail', kwargs={'uuid': role_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('uuid')) self.assertEqual(updated_name, response.data.get('name')) def test_update_role_invalid(self): """Test that updating an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.put(url, {}, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_role_success(self): """Test that we can delete an existing role.""" role_name = 'roleA' response = self.create_role(role_name) role_uuid = response.data.get('uuid') url = reverse('role-detail', kwargs={'uuid': role_uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the role no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_role_invalid(self): """Test that deleting an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user sys_role_config = { "name": "system_role", "display_name": "system_display", "system": True } def_role_config = { "name": "default_role", "display_name": "default_display", "platform_default": True } self.display_fields = { "applications", "description", "uuid", "name", "display_name", "system", "created", "policyCount", "accessCount", "modified", "platform_default", } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.policy = Policy.objects.create(name="policyA") self.group = Group(name="groupA", description="groupA description") self.group.save() self.group.principals.add(self.principal) self.group.policies.add(self.policy) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save() self.defRole.save() self.policy.roles.add(self.defRole, self.sysRole) self.policy.save() self.permission = Permission.objects.create(permission="app:*:*") self.permission2 = Permission.objects.create(permission="app2:*:*") self.access = Access.objects.create(permission=self.permission, role=self.defRole) self.access2 = Access.objects.create(permission=self.permission2, role=self.defRole) self.access3 = Access.objects.create(permission=self.permission2, role=self.sysRole) Permission.objects.create(permission="cost-management:*:*") # Create permission in public schema with tenant_context(Tenant.objects.get(schema_name="public")): Permission.objects.create(permission="cost-management:*:*") Permission.objects.create(permission="app:*:*") Permission.objects.create(permission="app2:*:*")
class RoleViewsetTests(IdentityRequest): """Test the role viewset.""" def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user sys_role_config = { "name": "system_role", "display_name": "system_display", "system": True } def_role_config = { "name": "default_role", "display_name": "default_display", "platform_default": True } self.display_fields = { "applications", "description", "uuid", "name", "display_name", "system", "created", "policyCount", "accessCount", "modified", "platform_default", } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.policy = Policy.objects.create(name="policyA") self.group = Group(name="groupA", description="groupA description") self.group.save() self.group.principals.add(self.principal) self.group.policies.add(self.policy) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save() self.defRole.save() self.policy.roles.add(self.defRole, self.sysRole) self.policy.save() self.permission = Permission.objects.create(permission="app:*:*") self.permission2 = Permission.objects.create(permission="app2:*:*") self.access = Access.objects.create(permission=self.permission, role=self.defRole) self.access2 = Access.objects.create(permission=self.permission2, role=self.defRole) self.access3 = Access.objects.create(permission=self.permission2, role=self.sysRole) Permission.objects.create(permission="cost-management:*:*") # Create permission in public schema with tenant_context(Tenant.objects.get(schema_name="public")): Permission.objects.create(permission="cost-management:*:*") Permission.objects.create(permission="app:*:*") Permission.objects.create(permission="app2:*:*") def create_role(self, role_name, role_display="", in_access_data=None): """Create a role.""" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], }] if in_access_data: access_data = in_access_data test_data = { "name": role_name, "display_name": role_display, "access": access_data } # create a role client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) return response def test_create_role_success(self): """Test that we can create a role.""" role_name = "roleA" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) uuid = response.data.get("uuid") role = Role.objects.get(uuid=uuid) self.assertIsNotNone(uuid) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsNotNone(response.data.get("display_name")) self.assertEqual(role_name, response.data.get("display_name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) self.assertEqual(role.tenant, self.tenant) for access in role.access.all(): self.assertEqual(access.tenant, self.tenant) for rd in ResourceDefinition.objects.filter(access=access): self.assertEqual(rd.tenant, self.tenant) # role also gets created in public schema with tenant_context(Tenant.objects.get(schema_name="public")): role_public = Role.objects.get(name="roleA") self.assertEqual(role_public.access.count(), 1) self.assertEqual(role_public.access.first().permission.permission, access_data[0]["permission"]) self.assertEqual( role_public.access.first().resourceDefinitions.first(). attributeFilter, access_data[0]["resourceDefinitions"][0]["attributeFilter"], ) def test_create_role_with_display_success(self): """Test that we can create a role.""" role_name = "roleD" role_display = "display name for roleD" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, role_display=role_display, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsNotNone(response.data.get("display_name")) self.assertEqual(role_display, response.data.get("display_name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) def test_create_role_invalid(self): """Test that creating an invalid role returns an error.""" test_data = {} client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_invalid_permission(self): """Test that creating a role with invalid access permission returns an error.""" test_data = { "name": "role1", "access": [{ "permission": "foo:bar", "resourceDefinitions": [] }] } client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_empty_application_in_permission(self): """Test that creating a role with empty application in access permission returns an error.""" test_data = { "name": "role1", "access": [{ "permission": ":foo:bar", "resourceDefinitions": [] }] } client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_allow_list(self): """Test that we can create a role in an allow_listed application via API.""" role_name = "C-MRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) def test_create_role_allow_list_fail(self): """Test that we cannot create a role for a non-allow_listed app.""" role_name = "roleFail" access_data = [{ "permission": "someApp:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_appfilter_structure_fail(self): """Test that we cannot create a role with invalid structure of resource definition.""" role_name = "operationFail" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": { "attributeFilter": { "key": "keyA", "operation": "in", "foo": "valueA" } }, }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data["errors"][0]["detail"].code, "not_a_list") def test_create_role_appfilter_fields_fail(self): """Test that we cannot create a role with an invalid key in the attributeFilter object.""" role_name = "operationFail" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "in", "foo": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_appfilter_operation_fail(self): """Test that we cannot create a role with an invalid operation.""" role_name = "operationFail" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "boop", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_permission_does_not_exist_fail(self): """Test that we cannot create a role with a permission that doesn't exist.""" role_name = "roleFailPermission" permission = "cost-management:foo:bar" access_data = [{ "permission": permission, "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( response.data.get("errors")[0].get("detail"), f"Permission does not exist: {permission}") def test_create_role_fail_with_access_not_list(self): """Test that we cannot create a role for a non-allow_listed app.""" role_name = "AccessNotList" access_data = "some data" response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_fail_with_invalid_access(self): """Test that we cannot create a role for invalid access data.""" role_name = "AccessInvalid" access_data = [{"per": "some data"}] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_invalid(self): """Test that reading an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_valid(self): """Test that reading a valid role returns expected fields/values.""" url = reverse("role-detail", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.get(url, **self.headers) response_data = response.data expected_fields = self.display_fields expected_fields.add("access") self.assertEqual(expected_fields, set(response_data.keys())) self.assertEqual(response_data.get("uuid"), str(self.defRole.uuid)) self.assertEqual(response_data.get("name"), self.defRole.name) self.assertEqual(response_data.get("display_name"), self.defRole.display_name) self.assertEqual(response_data.get("description"), self.defRole.description) self.assertCountEqual(response_data.get("applications"), ["app", "app2"]) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_read_role_access_success(self): """Test that reading a valid role returns access.""" url = reverse("role-access", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.get(url, **self.headers) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 2) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_read_role_access_invalid_uuid(self): """Test that reading a non-existent role uuid returns an error.""" url = reverse("role-access", kwargs={"uuid": "abc-123"}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_access_not_found_uuid(self): """Test that reading an invalid role uuid returns an error.""" url = reverse("role-access", kwargs={"uuid": uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_list_success(self): """Test that we can read a list of roles.""" role_name = "roleA" role_display = "Display name for roleA" response = self.create_role(role_name, role_display=role_display) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") # list a role client = APIClient() response = client.get(URL, **self.headers) # three parts in response: meta, links and data self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 3) role = None for iterRole in response.data.get("data"): self.assertIsNotNone(iterRole.get("name")) # fields displayed are same as defined self.assertEqual(self.display_fields, set(iterRole.keys())) if iterRole.get("name") == role_name: self.assertEqual(iterRole.get("accessCount"), 1) role = iterRole self.assertEqual(role.get("name"), role_name) self.assertEqual(role.get("display_name"), role_display) def test_get_role_by_application_single(self): """Test that getting roles by application returns roles based on permissions.""" url = "{}?application={}".format(URL, "app") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) self.assertEqual( response.data.get("data")[0].get("name"), self.defRole.name) def test_get_role_by_application_multiple(self): """Test that getting roles by multiple applications returns roles based on permissions.""" url = "{}?application={}".format(URL, "app2") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_application_duplicate_role(self): """Test that getting roles by application with permissions in the same role only returns the roles once.""" url = "{}?application={}".format(URL, "app,app2") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_application_does_not_exist(self): """Test that getting roles by application returns nothing when there is no match.""" url = "{}?application={}".format(URL, "foo") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_role_by_permission_single(self): """Test that getting roles by permission returns roles based on permissions.""" url = "{}?permission={}".format(URL, "app:*:*") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) self.assertEqual( response.data.get("data")[0].get("name"), self.defRole.name) def test_get_role_by_duplicate_permission(self): """Test that getting roles by duplicate permissions in the same role only returns the roles once.""" url = "{}?permission={}".format(URL, "app2:*:*") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_permission_multiple(self): """Test that getting roles by permissions .""" url = "{}?permission={}".format(URL, "app:*:*,app2:*:*") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_permission_does_not_exist(self): """Test that getting roles by permission returns nothing when there is no match.""" url = "{}?permission={}".format(URL, "foo:foo:foo") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_role_by_partial_name_by_default(self): """Test that getting roles by name returns partial match by default.""" url = "{}?name={}".format(URL, "role") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_partial_name_explicit(self): """Test that getting roles by name returns partial match when specified.""" url = "{}?name={}&name_match={}".format(URL, "role", "partial") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_name_invalid_criteria(self): """Test that getting roles by name fails with invalid name_match.""" url = "{}?name={}&name_match={}".format(URL, "role", "bad_criteria") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_role_by_exact_name_match(self): """Test that getting roles by name returns exact match.""" url = "{}?name={}&name_match={}".format(URL, self.sysRole.name, "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) role = response.data.get("data")[0] self.assertEqual(role.get("name"), self.sysRole.name) def test_get_role_by_exact_name_no_match(self): """Test that getting roles by name returns no results with exact match.""" url = "{}?name={}&name_match={}".format(URL, "role", "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_role_by_partial_display_name_by_default(self): """Test that getting roles by display_name returns partial match by default.""" url = "{}?display_name={}".format(URL, "display") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_partial_display_name_explicit(self): """Test that getting roles by display_name returns partial match when specified.""" url = "{}?display_name={}&name_match={}".format( URL, "display", "partial") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_display_name_invalid_criteria(self): """Test that getting roles by display_name fails with invalid name_match.""" url = "{}?display_name={}&name_match={}".format( URL, "display", "bad_criteria") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_role_by_exact_display_name_match(self): """Test that getting roles by display_name returns exact match.""" url = "{}?display_name={}&name_match={}".format( URL, self.sysRole.display_name, "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) role = response.data.get("data")[0] self.assertEqual(role.get("display_name"), self.sysRole.display_name) def test_get_role_by_exact_display_name_no_match(self): """Test that getting roles by display_name returns no results with exact match.""" url = "{}?display_name={}&name_match={}".format( URL, "display", "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_list_role_with_additional_fields_success(self): """Test that we can read a list of roles and add fields.""" role_name = "roleA" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) # list a role url = "{}?add_fields={},{}".format(URL, field_1, field_2) client = APIClient() response = client.get(url, **self.headers) # three parts in response: meta, links and data self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) role = None for iterRole in response.data.get("data"): # fields displayed are same as defined, groupsInCount is added self.assertEqual(new_diaplay_fields, set(iterRole.keys())) if iterRole.get("name") == role_name: self.assertEqual(iterRole.get("accessCount"), 1) role = iterRole self.assertIsNotNone(iterRole.get("groups_in")[0]["name"]) self.assertIsNotNone(iterRole.get("groups_in")[0]["uuid"]) self.assertIsNotNone(iterRole.get("groups_in")[0]["description"]) def test_list_role_with_username_forbidden_to_nonadmin(self): """Test that non admin can not read a list of roles for username.""" # Setup non admin request non_admin_request_context = self._create_request_context( self.customer_data, self.user_data, create_customer=False, is_org_admin=False) non_admin_request = non_admin_request_context["request"] url = "{}?username={}".format(URL, self.user_data["username"]) client = APIClient() response = client.get(url, **non_admin_request.META) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [] }, ) def test_list_role_fail_with_invalid_username(self, mock_request): """Test that non admin can not read a list of roles for username.""" url = "{}?username={}".format(URL, "foo") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_list_role_with_additional_fields_username_success(self): """Test that we can read a list of roles and add fields for username.""" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) url = "{}?add_fields={},{}&username={}".format( URL, field_1, field_2, self.user_data["username"]) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 2) role = response.data.get("data")[0] self.assertEqual(new_diaplay_fields, set(role.keys())) self.assertEqual(role["groups_in_count"], 1) def test_list_role_with_additional_fields_principal_success(self): """Test that we can read a list of roles and add fields for principal.""" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) url = "{}?add_fields={},{}&scope=principal".format( URL, field_1, field_2) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 2) role = response.data.get("data")[0] self.assertEqual(new_diaplay_fields, set(role.keys())) self.assertEqual(role["groups_in_count"], 1) def test_list_role_with_invalid_additional_fields(self): """Test that invalid additional fields will raise exception.""" add_field = "invalid_field" # list a role url = "{}?add_fields={}".format(URL, add_field) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_list_role_with_invalid_sort_order(self): """Test that an invalid sort order is ignored.""" url = "{}?sort_field=zombie".format(URL) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_patch_role_success(self): """Test that we can patch an existing role.""" role_name = "role" response = self.create_role(role_name) updated_name = role_name + "_update" updated_description = role_name + "This is a test" role_uuid = response.data.get("uuid") url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.patch( url, { "name": updated_name, "display_name": updated_name, "description": updated_description }, format="json", **self.headers, ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("uuid")) self.assertEqual(updated_name, response.data.get("name")) self.assertEqual(updated_name, response.data.get("display_name")) self.assertEqual(updated_description, response.data.get("description")) with tenant_context(Tenant.objects.get(schema_name="public")): role_in_public = Role.objects.get(name=updated_name, tenant=self.tenant) self.assertIsNotNone(role_in_public) self.assertEqual(updated_name, role_in_public.display_name) self.assertEqual(updated_description, role_in_public.description) def test_patch_role_failure(self): """Test that we return a 400 with invalid fields in the patch.""" role_name = "role" response = self.create_role(role_name) updated_name = role_name + "_update" updated_description = role_name + "This is a test" role_uuid = response.data.get("uuid") url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.patch( url, { "name": updated_name, "display_name": updated_name, "description": updated_description, "foo": "bar" }, format="json", **self.headers, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_role_success(self): """Test that we can update an existing role.""" role_name = "roleA" response = self.create_role(role_name) updated_name = role_name + "_update" role_uuid = response.data.get("uuid") test_data = response.data test_data["name"] = updated_name test_data["access"][0]["permission"] = "cost-management:*:*" del test_data["uuid"] url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("uuid")) self.assertEqual(updated_name, response.data.get("name")) self.assertEqual("cost-management:*:*", response.data.get("access")[0]["permission"]) with tenant_context(Tenant.objects.get(schema_name="public")): role_in_public = Role.objects.get(name=updated_name, tenant=self.tenant) self.assertIsNotNone(role_in_public) self.assertEqual( "cost-management:*:*", role_in_public.access.first().permission.permission) def test_update_role_invalid(self): """Test that updating an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.put( url, { "name": "updated_name", "display_name": "updated_name", "description": "updated_description" }, format="json", **self.headers, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_role_invalid_permission(self): """Test that updating a role with an invalid permission returns an error.""" # Set up role_name = "permRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") test_data = response.data test_data.get("access")[0]["permission"] = "foo:*:read" test_data["applications"] = ["foo"] # Test update failure url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_role_invalid_resource_defs_structure(self): """Test that updating a role with an invalid resource definitions returns an error.""" # Set up role_name = "permRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") test_data = response.data test_data.get("access")[0]["resourceDefinitions"] = { "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } } # Test update failure url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data["errors"][0]["detail"].code, "not_a_list") def test_update_role_appfilter_operation_fail(self): # Set up role_name = "permRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") test_data = response.data test_data.get("access")[0]["resourceDefinitions"][0].get( "attributeFilter")["operation"] = "foo" # Test update failure url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( str(response.data["errors"][0]["detail"]), "attributeFilter operation must be one of ['in', 'equal']") def test_update_role_permission_does_not_exist_fail(self): """Test that we cannot update a role with a permission that doesn't exist.""" # Set up role_name = "permRole" permission = "cost-management:foo:bar" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") test_data = response.data test_data.get("access")[0]["permission"] = permission test_data["applications"] = ["foo"] # Test update failure url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( response.data.get("errors")[0].get("detail"), f"Permission does not exist: {permission}") def test_delete_role_success(self): """Test that we can delete an existing role.""" role_name = "roleA" response = self.create_role(role_name) with tenant_context(Tenant.objects.get(schema_name="public")): self.assertIsNotNone( Role.objects.get(name=role_name, tenant=self.tenant)) role_uuid = response.data.get("uuid") url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the role no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) with tenant_context(Tenant.objects.get(schema_name="public")): self.assertIsNone( Role.objects.filter(name=role_name, tenant=self.tenant).first()) def test_delete_system_role(self): """Test that system roles are protected from deletion""" url = reverse("role-detail", kwargs={"uuid": self.sysRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_default_role(self): """Test that default roles are protected from deletion""" url = reverse("role-detail", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_role_invalid(self): """Test that deleting an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_system_flag_filter(self): """Test that we can filter roles based on system flag.""" client = APIClient() response = client.get(URL, **self.headers) self.assertEqual(len(response.data.get("data")), 2) url = f"{URL}?system=true" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 1) role = response.data.get("data")[0] self.assertEqual(role.get("system"), True) url = f"{URL}?system=false" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 1) role = response.data.get("data")[0] self.assertEqual(role.get("system"), False)
class RoleViewsetTests(IdentityRequest): """Test the role viewset.""" def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user sys_role_config = { "name": "system_role", "display_name": "system", "system": True } def_role_config = { "name": "default_role", "display_name": "default", "platform_default": True } self.display_fields = { "applications", "description", "uuid", "name", "display_name", "system", "created", "policyCount", "accessCount", "modified", "platform_default", } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.policy = Policy.objects.create(name="policyA") self.group = Group(name="groupA", description="groupA description") self.group.save() self.group.principals.add(self.principal) self.group.policies.add(self.policy) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save() self.defRole.save() self.policy.roles.add(self.defRole, self.sysRole) self.policy.save() self.access = Access.objects.create(permission="app:*:*", role=self.defRole) self.access2 = Access.objects.create(permission="app2:*:*", role=self.defRole) self.access3 = Access.objects.create(permission="app2:*:*", role=self.sysRole) def tearDown(self): """Tear down role viewset tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() def create_role(self, role_name, role_display="", in_access_data=None): """Create a role.""" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], }] if in_access_data: access_data = in_access_data test_data = { "name": role_name, "display_name": role_display, "access": access_data } # create a role client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) return response def test_create_role_success(self): """Test that we can create a role.""" role_name = "roleA" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsNotNone(response.data.get("display_name")) self.assertEqual(role_name, response.data.get("display_name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) def test_create_role_with_display_success(self): """Test that we can create a role.""" role_name = "roleD" role_display = "display name for roleD" access_data = [{ "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, role_display=role_display, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsNotNone(response.data.get("display_name")) self.assertEqual(role_display, response.data.get("display_name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) def test_create_role_invalid(self): """Test that creating an invalid role returns an error.""" test_data = {} client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_invalid_permission(self): """Test that creating an invalid role returns an error.""" test_data = { "name": "role1", "access": [{ "permission": "foo:bar", "resourceDefinitions": [] }] } client = APIClient() response = client.post(URL, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_allow_list(self): """Test that we can create a role in an allow_listed application via API.""" role_name = "C-MRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse("role-detail", kwargs={"uuid": response.data.get("uuid")}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(role_name, response.data.get("name")) self.assertIsInstance(response.data.get("access"), list) self.assertEqual(access_data, response.data.get("access")) def test_create_role_allow_list_fail(self): """Test that we cannot create a role for a non-allow_listed app.""" role_name = "roleFail" access_data = [{ "permission": "someApp:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_fail_with_access_not_list(self): """Test that we cannot create a role for a non-allow_listed app.""" role_name = "AccessNotList" access_data = "some data" response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_fail_with_invalid_access(self): """Test that we cannot create a role for invalid access data.""" role_name = "AccessInvalid" access_data = [{"per": "some data"}] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_invalid(self): """Test that reading an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_valid(self): """Test that reading a valid role returns expected fields/values.""" url = reverse("role-detail", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.get(url, **self.headers) response_data = response.data expected_fields = self.display_fields expected_fields.add("access") self.assertEqual(expected_fields, set(response_data.keys())) self.assertEqual(response_data.get("uuid"), str(self.defRole.uuid)) self.assertEqual(response_data.get("name"), self.defRole.name) self.assertEqual(response_data.get("display_name"), self.defRole.display_name) self.assertEqual(response_data.get("description"), self.defRole.description) self.assertCountEqual(response_data.get("applications"), ["app", "app2"]) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_read_role_access_success(self): """Test that reading a valid role returns access.""" url = reverse("role-access", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.get(url, **self.headers) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 2) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_read_role_access_invalid_uuid(self): """Test that reading a non-existent role uuid returns an error.""" url = reverse("role-access", kwargs={"uuid": "abc-123"}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_access_not_found_uuid(self): """Test that reading an invalid role uuid returns an error.""" url = reverse("role-access", kwargs={"uuid": uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_list_success(self): """Test that we can read a list of roles.""" role_name = "roleA" role_display = "Display name for roleA" response = self.create_role(role_name, role_display=role_display) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") # list a role client = APIClient() response = client.get(URL, **self.headers) # three parts in response: meta, links and data self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 3) role = None for iterRole in response.data.get("data"): self.assertIsNotNone(iterRole.get("name")) # fields displayed are same as defined self.assertEqual(self.display_fields, set(iterRole.keys())) if iterRole.get("name") == role_name: self.assertEqual(iterRole.get("accessCount"), 1) role = iterRole self.assertEqual(role.get("name"), role_name) self.assertEqual(role.get("display_name"), role_display) def test_get_role_by_application_single(self): """Test that getting roles by application returns roles based on permissions.""" url = "{}?application={}".format(URL, "app") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) self.assertEqual( response.data.get("data")[0].get("name"), self.defRole.name) def test_get_role_by_application_multiple(self): """Test that getting roles by multiple applications returns roles based on permissions.""" url = "{}?application={}".format(URL, "app2") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_application_duplicate_role(self): """Test that getting roles by application with permissions in the same role only returns the roles once.""" url = "{}?application={}".format(URL, "app,app2") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_application_does_not_exist(self): """Test that getting roles by application returns nothing when there is no match.""" url = "{}?application={}".format(URL, "foo") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_role_by_permission_single(self): """Test that getting roles by permission returns roles based on permissions.""" url = "{}?permission={}".format(URL, "app:*:*") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) self.assertEqual( response.data.get("data")[0].get("name"), self.defRole.name) def test_get_role_by_duplicate_permission(self): """Test that getting roles by duplicate permissions in the same role only returns the roles once.""" url = "{}?permission={}".format(URL, "app2:*:*") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_permission_multiple(self): """Test that getting roles by permissions .""" url = "{}?permission={}".format(URL, "app:*:*,app2:*:*") client = APIClient() response = client.get(url, **self.headers) role_names = [role.get("name") for role in response.data.get("data")] self.assertEqual(response.data.get("meta").get("count"), 2) self.assertCountEqual(role_names, [self.defRole.name, self.sysRole.name]) def test_get_role_by_permission_does_not_exist(self): """Test that getting roles by permission returns nothing when there is no match.""" url = "{}?permission={}".format(URL, "foo:foo:foo") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_role_by_partial_name_by_default(self): """Test that getting roles by name returns partial match by default.""" url = "{}?name={}".format(URL, "role") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_partial_name_explicit(self): """Test that getting roles by name returns partial match when specified.""" url = "{}?name={}&name_match={}".format(URL, "role", "partial") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 2) def test_get_role_by_name_invalid_criteria(self): """Test that getting roles by name fails with invalid name_match.""" url = "{}?name={}&name_match={}".format(URL, "role", "bad_criteria") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_role_by_exact_name_match(self): """Test that getting roles by name returns exact match.""" url = "{}?name={}&name_match={}".format(URL, self.sysRole.name, "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) role = response.data.get("data")[0] self.assertEqual(role.get("name"), self.sysRole.name) def test_get_role_by_exact_name_no_match(self): """Test that getting roles by name returns no results with exact match.""" url = "{}?name={}&name_match={}".format(URL, "role", "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_list_role_with_additional_fields_success(self): """Test that we can read a list of roles and add fields.""" role_name = "roleA" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) # list a role url = "{}?add_fields={},{}".format(URL, field_1, field_2) client = APIClient() response = client.get(url, **self.headers) # three parts in response: meta, links and data self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) role = None for iterRole in response.data.get("data"): # fields displayed are same as defined, groupsInCount is added self.assertEqual(new_diaplay_fields, set(iterRole.keys())) if iterRole.get("name") == role_name: self.assertEqual(iterRole.get("accessCount"), 1) role = iterRole self.assertIsNotNone(iterRole.get("groups_in")[0]["name"]) self.assertIsNotNone(iterRole.get("groups_in")[0]["uuid"]) self.assertIsNotNone(iterRole.get("groups_in")[0]["description"]) def test_list_role_with_additional_fields_username_success(self): """Test that we can read a list of roles and add fields for username.""" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) url = "{}?add_fields={},{}&username={}".format( URL, field_1, field_2, self.user_data["username"]) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 2) role = response.data.get("data")[0] self.assertEqual(new_diaplay_fields, set(role.keys())) self.assertEqual(role["groups_in_count"], 1) def test_list_role_with_additional_fields_principal_success(self): """Test that we can read a list of roles and add fields for principal.""" field_1 = "groups_in_count" field_2 = "groups_in" new_diaplay_fields = self.display_fields new_diaplay_fields.add(field_1) new_diaplay_fields.add(field_2) url = "{}?add_fields={},{}&scope=principal".format( URL, field_1, field_2) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 2) role = response.data.get("data")[0] self.assertEqual(new_diaplay_fields, set(role.keys())) self.assertEqual(role["groups_in_count"], 1) def test_list_role_with_invalid_additional_fields(self): """Test that invalid additional fields will raise exception.""" add_field = "invalid_field" # list a role url = "{}?add_fields={}".format(URL, add_field) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_role_success(self): """Test that we can update an existing role.""" role_name = "roleA" response = self.create_role(role_name) updated_name = role_name + "_update" role_uuid = response.data.get("uuid") test_data = response.data test_data["name"] = updated_name del test_data["uuid"] url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("uuid")) self.assertEqual(updated_name, response.data.get("name")) def test_update_role_invalid(self): """Test that updating an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.put(url, {}, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_role_invalid_permission(self): """Test that updating a role with an invalid permission returns an error.""" # Set up role_name = "permRole" access_data = [{ "permission": "cost-management:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], }] response = self.create_role(role_name, in_access_data=access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") test_data = response.data test_data.get("access")[0]["permission"] = "foo:*:read" test_data["applications"] = ["foo"] # Test update failure url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_delete_role_success(self): """Test that we can delete an existing role.""" role_name = "roleA" response = self.create_role(role_name) role_uuid = response.data.get("uuid") url = reverse("role-detail", kwargs={"uuid": role_uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the role no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_system_role(self): """Test that system roles are protected from deletion""" url = reverse("role-detail", kwargs={"uuid": self.sysRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_default_role(self): """Test that default roles are protected from deletion""" url = reverse("role-detail", kwargs={"uuid": self.defRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_role_invalid(self): """Test that deleting an invalid role returns an error.""" url = reverse("role-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
class RoleViewsetTests(IdentityRequest): """Test the role viewset.""" def setUp(self): """Set up the role viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user sys_role_config = {'name': 'system_role', 'system': True} def_role_config = {'name': 'default_role', 'platform_default': True} with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() self.sysRole = Role(**sys_role_config) self.sysRole.save() self.defRole = Role(**def_role_config) self.defRole.save() def tearDown(self): """Tear down role viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() def create_role(self, role_name, in_access_data=None): """Create a role.""" access_data = [{ 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] }] if in_access_data: access_data = in_access_data test_data = {'name': role_name, 'access': access_data} # create a role url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) return response def test_create_role_success(self): """Test that we can create a role.""" role_name = 'roleA' access_data = [{ 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] }] response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse('role-detail', kwargs={'uuid': response.data.get('uuid')}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertEqual(role_name, response.data.get('name')) self.assertIsInstance(response.data.get('access'), list) self.assertEqual(access_data, response.data.get('access')) def test_create_role_invalid(self): """Test that creating an invalid role returns an error.""" test_data = {} url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_invalid_permission(self): """Test that creating an invalid role returns an error.""" test_data = { 'name': 'role1', 'access': [{ 'permission': 'foo:bar', 'resourceDefinitions': [] }] } url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_whitelist(self): """Test that we can create a role in a whitelisted application via API.""" role_name = 'C-MRole' access_data = [{ 'permission': 'cost-management:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] }] response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the role url = reverse('role-detail', kwargs={'uuid': response.data.get('uuid')}) client = APIClient() response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertEqual(role_name, response.data.get('name')) self.assertIsInstance(response.data.get('access'), list) self.assertEqual(access_data, response.data.get('access')) def test_create_role_whitelist_fail(self): """Test that we cannot create a role for a non-whitelisted app.""" role_name = 'roleFail' access_data = [{ 'permission': 'someApp:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] }] response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_fail_with_access_not_list(self): """Test that we cannot create a role for a non-whitelisted app.""" role_name = 'AccessNotList' access_data = 'some data' response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_create_role_fail_with_invalid_access(self): """Test that we cannot create a role for invalid access data.""" role_name = 'AccessInvalid' access_data = [{'per': 'some data'}] response = self.create_role(role_name, access_data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_role_invalid(self): """Test that reading an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_role_list_success(self): """Test that we can read a list of roles.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') # list a role url = reverse('role-list') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 3) role = None for iterRole in response.data.get('data'): self.assertIsNotNone(iterRole.get('name')) if iterRole.get('name') == role_name: role = iterRole break self.assertEqual(role.get('name'), role_name) def test_update_role_success(self): """Test that we can update an existing role.""" role_name = 'roleA' response = self.create_role(role_name) updated_name = role_name + '_update' role_uuid = response.data.get('uuid') test_data = response.data test_data['name'] = updated_name del test_data['uuid'] url = reverse('role-detail', kwargs={'uuid': role_uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('uuid')) self.assertEqual(updated_name, response.data.get('name')) def test_update_role_invalid(self): """Test that updating an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.put(url, {}, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_role_success(self): """Test that we can delete an existing role.""" role_name = 'roleA' response = self.create_role(role_name) role_uuid = response.data.get('uuid') url = reverse('role-detail', kwargs={'uuid': role_uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the role no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_system_role(self): """Test that system roles are protected from deletion""" url = reverse('role-detail', kwargs={'uuid': self.sysRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_default_role(self): """Test that default roles are protected from deletion""" url = reverse('role-detail', kwargs={'uuid': self.defRole.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # verify the role still exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_role_invalid(self): """Test that deleting an invalid role returns an error.""" url = reverse('role-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
class AccessViewTests(IdentityRequest): """Test the access view.""" def setUp(self): """Set up the access view tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user self.access_data = { "permission": "app:*:*", "resourceDefinitions": [{ "attributeFilter": { "key": "key1", "operation": "equal", "value": "value1" } }], } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name="groupA") self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down access view tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() def create_role(self, role_name, in_access_data=None): """Create a role.""" access_data = self.access_data if in_access_data: access_data = in_access_data test_data = {"name": role_name, "access": [access_data]} # create a role url = reverse("role-list") client = APIClient() response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) return response def create_policy(self, policy_name, group, roles, status=status.HTTP_201_CREATED): """Create a policy.""" # create a policy test_data = {"name": policy_name, "group": group, "roles": roles} url = reverse("policy-list") client = APIClient() response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status) return response def test_get_access_success(self): """Test that we can obtain the expected access without pagination.""" role_name = "roleA" response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission="app2:foo:bar") policy_name = "policyA" response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # test that we can retrieve the principal access url = "{}?application={}&username={}".format(reverse("access"), "app", self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("data")) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) self.assertEqual(response.data.get("meta").get("limit"), 1000) self.assertEqual(self.access_data, response.data.get("data")[0]) def test_get_access_no_app_supplied(self): """Test that we return all permissions when no app supplied.""" role_name = "roleA" policy_name = "policyA" access_data = { "permission": "app:foo:bar", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], } response = self.create_role(role_name, access_data) role_uuid = response.data.get("uuid") role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission="app2:foo:bar") self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = "{}?application=&username={}".format(reverse("access"), self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("data")) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 2) self.assertEqual(response.data.get("meta").get("limit"), 1000) def test_get_access_multiple_apps_supplied(self): """Test that we return all permissions for multiple apps when supplied.""" role_name = "roleA" policy_name = "policyA" access_data = { "permission": "app:foo:bar", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], } response = self.create_role(role_name, access_data) role_uuid = response.data.get("uuid") role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission="app2:foo:bar") self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = "{}?application={}&username={}".format(reverse("access"), "app,app2", self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 2) def test_get_access_no_partial_match(self): """Test that we can have a partial match on app/permission.""" role_name = "roleA" policy_name = "policyA" access_data = { "permission": "app:foo:bar", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], } response = self.create_role(role_name, access_data) role_uuid = response.data.get("uuid") self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = "{}?application={}&username={}".format(reverse("access"), "ap", self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("data")) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 0) self.assertEqual(response.data.get("meta").get("limit"), 1000) def test_get_access_no_match(self): """Test that we only match on the application name of the permission data.""" role_name = "roleA" policy_name = "policyA" access_data = { "permission": "app:foo:bar", "resourceDefinitions": [{ "attributeFilter": { "key": "keyA", "operation": "equal", "value": "valueA" } }], } response = self.create_role(role_name, access_data) role_uuid = response.data.get("uuid") self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = "{}?application={}&username={}".format(reverse("access"), "foo", self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("data")) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 0) self.assertEqual(response.data.get("meta").get("limit"), 1000) def test_get_access_with_limit(self): """Test that we can obtain the expected access with pagination.""" role_name = "roleA" response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get("uuid") policy_name = "policyA" response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # test that we can retrieve the principal access url = "{}?application={}&username={}&limit=1".format( reverse("access"), "app", self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("data")) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) self.assertEqual(response.data.get("meta").get("count"), 1) self.assertEqual(response.data.get("meta").get("limit"), 1) self.assertEqual(self.access_data, response.data.get("data")[0]) def test_missing_query_params(self): """Test that we get expected failure when missing required query params.""" url = "{}?page={}".format(reverse("access"), "3") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": 200, "data": [] }, ) def test_missing_invalid_username(self, mock_request): """Test that we get expected failure when missing required query params.""" url = "{}?application={}&username={}".format(reverse("access"), "app", uuid4()) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
class GroupViewsetTests(IdentityRequest): """Test the group viewset.""" def setUp(self): """Set up the group viewset tests.""" super().setUp() request = self.request_context["request"] user = User() user.username = self.user_data["username"] user.account = self.customer_data["account_id"] request.user = user self.dummy_role_id = uuid4() with tenant_context(self.tenant): self.principal = Principal(username=self.user_data["username"]) self.principal.save() self.principalB = Principal(username="******") self.principalB.save() self.principalC = Principal(username="******") self.principalC.save() self.group = Group(name="groupA") self.group.save() self.role = Role.objects.create(name="roleA", description="A role for a group.", system=True) self.policy = Policy.objects.create(name="policyA", group=self.group) self.policy.roles.add(self.role) self.policy.save() self.group.policies.add(self.policy) self.group.principals.add(self.principal, self.principalB) self.group.save() self.defGroup = Group(name="groupDef", platform_default=True, system=True) self.defGroup.save() self.defGroup.principals.add(self.principal) self.defGroup.save() self.emptyGroup = Group(name="groupE") self.emptyGroup.save() self.groupB = Group.objects.create(name="groupB") self.groupB.principals.add(self.principal) self.policyB = Policy.objects.create(name="policyB", group=self.groupB) self.roleB = Role.objects.create(name="roleB", system=False) self.policyB.roles.add(self.roleB) self.policyB.save() # role that's not assigned to principal self.roleOrphan = Role.objects.create(name="roleOrphan") # group that associates with multipal roles self.groupMultiRole = Group.objects.create(name="groupMultiRole") self.policyMultiRole = Policy.objects.create(name="policyMultiRole") self.policyMultiRole.roles.add(self.role) self.policyMultiRole.roles.add(self.roleB) self.groupMultiRole.policies.add(self.policyMultiRole) def tearDown(self): """Tear down group viewset tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_create_group_success(self, mock_request): """Test that we can create a group.""" group_name = "groupC" test_data = {"name": group_name} # create a group url = reverse("group-list") client = APIClient() response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the group url = reverse("group-detail", kwargs={"uuid": response.data.get("uuid")}) response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertEqual(group_name, response.data.get("name")) def test_create_default_group(self): """Test that system groups can be created.""" group_name = "groupDef" # test group retrieval client = APIClient() url = reverse("group-detail", kwargs={"uuid": self.defGroup.uuid}) response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get("uuid")) self.assertIsNotNone(response.data.get("name")) self.assertTrue(response.data.get("platform_default")) self.assertEqual(group_name, response.data.get("name")) def test_create_group_invalid(self): """Test that creating an invalid group returns an error.""" test_data = {} url = reverse("group-list") client = APIClient() response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_group_filter_by_any_role_name_in_a_list_success(self): """Test default behaviour that filter groups by any role name in a list success.""" url = "{}?role_names={},{}".format(reverse("group-list"), "Rolea", "RoleB") client = APIClient() response = client.get(url, **self.headers) self.assertTrue(response.data.get("meta").get("count") == 3) expected_groups = [self.group.name, self.groupB.name, self.groupMultiRole.name] self.assertEqual(expected_groups, [group.get("name") for group in response.data.get("data")]) def test_group_filter_by_all_role_name_in_a_list_success(self): """Test that filter groups by all role names in a list success.""" url = "{}?role_names={},{}&role_discriminator=all".format(reverse("group-list"), "Rolea", "roleB") client = APIClient() response = client.get(url, **self.headers) self.assertTrue(response.data.get("meta").get("count") == 1) expected_groups = [self.groupMultiRole.name] self.assertEqual(expected_groups, [group.get("name") for group in response.data.get("data")]) def test_group_filter_with_invalid_discriminator_failure(self): """Test that filter groups with invalid discriminator returns failed validation.""" url = "{}?role_names={},{}&role_discriminator=invalid".format(reverse("group-list"), "roleA", "ROLEb") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_read_group_success(self, mock_request): """Test that we can read a group.""" url = reverse("group-detail", kwargs={"uuid": self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("name")) self.assertEqual(self.group.name, response.data.get("name")) self.assertEqual(len(response.data.get("roles")), 1) self.assertEqual(response.data.get("roles")[0]["uuid"], str(self.role.uuid)) def test_read_group_invalid(self): """Test that reading an invalid group returns an error.""" url = reverse("group-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_group_nonguid(self): """Test that reading a group with an invalid UUID returns an error.""" url = reverse("group-detail", kwargs={"uuid": "potato"}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_read_group_list_success(self): """Test that we can read a list of groups.""" url = reverse("group-list") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 5) group = response.data.get("data")[0] self.assertIsNotNone(group.get("name")) self.assertEqual(group.get("name"), self.group.name) def test_get_group_by_partial_name_by_default(self): """Test that getting groups by name returns partial match by default.""" url = reverse("group-list") url = "{}?name={}".format(url, "group") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 5) def test_get_group_by_partial_name_explicit(self): """Test that getting groups by name returns partial match when specified.""" url = reverse("group-list") url = "{}?name={}&name_match={}".format(url, "group", "partial") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 5) def test_get_group_by_name_invalid_criteria(self): """Test that getting groups by name fails with invalid name_match.""" url = reverse("group-list") url = "{}?name={}&name_match={}".format(url, "group", "bad_criteria") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_group_by_exact_name_match(self): """Test that getting groups by name returns exact match.""" url = reverse("group-list") url = "{}?name={}&name_match={}".format(url, self.group.name, "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) group = response.data.get("data")[0] self.assertEqual(group.get("name"), self.group.name) def test_get_group_by_exact_name_no_match(self): """Test that getting groups by name returns no results with exact match.""" url = reverse("group-list") url = "{}?name={}&name_match={}".format(url, "group", "exact") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_filter_group_list_by_uuid_success(self): """Test that we can filter a list of groups by uuid.""" url = f"{reverse('group-list')}?uuid={self.group.uuid}" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 1) group = response.data.get("data")[0] self.assertIsNotNone(group.get("name")) self.assertEqual(group.get("name"), self.group.name) def test_filter_group_list_by_uuid_multiple(self): """Test that we can filter a list of groups by uuid.""" url = f"{reverse('group-list')}?uuid={self.group.uuid},{self.groupB.uuid}" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get("data"), list) self.assertEqual(len(response.data.get("data")), 2) group = response.data.get("data")[0] self.assertIsNotNone(group.get("name")) self.assertEqual(group.get("name"), self.group.name) group = response.data.get("data")[1] self.assertIsNotNone(group.get("name")) self.assertEqual(group.get("name"), self.groupB.name) def test_filter_group_list_by_uuid_fail(self): """Test that filtering by a nonexistant uuid returns nothing.""" url = f"{reverse('group-list')}?uuid={uuid4()}" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ["meta", "links", "data"]: self.assertIn(keyname, response.data) self.assertEqual(response.data.get("data"), []) self.assertEqual(len(response.data.get("data")), 0) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_update_group_success(self, mock_request): """Test that we can update an existing group.""" group = Group.objects.first() updated_name = group.name + "_update" test_data = {"name": updated_name} url = reverse("group-detail", kwargs={"uuid": group.uuid}) client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get("uuid")) self.assertEqual(updated_name, response.data.get("name")) def test_update_default_group(self): """Test that platform_default groups are protected from updates""" url = reverse("group-detail", kwargs={"uuid": self.defGroup.uuid}) test_data = {"name": self.defGroup.name + "_updated"} client = APIClient() response = client.put(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_group_invalid(self): """Test that updating an invalid group returns an error.""" url = reverse("group-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.put(url, {}, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_group_success(self): """Test that we can delete an existing group.""" group = Group.objects.first() url = reverse("group-detail", kwargs={"uuid": group.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the group no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_default_group(self): """Test that platform_default groups are protected from deletion""" url = reverse("group-detail", kwargs={"uuid": self.defGroup.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_delete_group_invalid(self): """Test that deleting an invalid group returns an error.""" url = reverse("group-detail", kwargs={"uuid": uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_group_principals_invalid_method(self): """Test that using an unsupported REST method returns an error.""" url = reverse("group-principals", kwargs={"uuid": uuid4()}) client = APIClient() response = client.put(url, {}, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={ "status_code": status.HTTP_500_INTERNAL_SERVER_ERROR, "errors": [ { "detail": "Unexpected error.", "status": status.HTTP_500_INTERNAL_SERVER_ERROR, "source": "principals", } ], }, ) def test_add_group_principals_failure(self, mock_request): """Test that adding a principal to a group returns has proper response when it is failed.""" url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) client = APIClient() new_username = uuid4() test_data = {"principals": [{"username": self.principal.username}, {"username": new_username}]} response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) self.assertEqual(response.data[0]["detail"], "Unexpected error.") self.assertEqual(response.data[0]["status"], 500) self.assertEqual(response.data[0]["source"], "principals") @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": [{"username": "******"}]}, ) def test_add_group_principals_success(self, mock_request): """Test that adding a principal to a group returns successfully.""" # Create a group and a cross account user. with tenant_context(self.tenant): test_group = Group.objects.create(name="test") cross_account_user = Principal.objects.create(username="******", cross_account=True) url = reverse("group-principals", kwargs={"uuid": test_group.uuid}) client = APIClient() test_data = {"principals": [{"username": "******"}, {"username": "******"}]} response = client.post(url, test_data, format="json", **self.headers) # Only the user exists in IT will be added to the group. self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data.get("principals")), 1) self.assertEqual(response.data.get("principals")[0], {"username": "******"}) test_group.delete() cross_account_user.delete() @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_get_group_principals_empty(self, mock_request): """Test that getting principals from an empty group returns successfully.""" client = APIClient() url = reverse("group-principals", kwargs={"uuid": self.emptyGroup.uuid}) response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data.get("meta").get("count"), 0) self.assertEqual(response.data.get("data"), []) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_get_group_principals_nonempty(self, mock_request): """Test that getting principals from a nonempty group returns successfully.""" mock_request.return_value["data"] = [ {"username": self.principal.username}, {"username": self.principalB.username}, ] client = APIClient() url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) response = client.get(url, **self.headers) call_args, kwargs = mock_request.call_args_list[0] username_arg = call_args[0] for username in [self.principal.username, self.principalB.username]: self.assertTrue(username in username_arg) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data.get("meta").get("count"), 2) self.assertEqual(response.data.get("data")[0].get("username"), self.principal.username) self.assertEqual(response.data.get("data")[1].get("username"), self.principalB.username) def test_remove_group_principals_success(self): """Test that removing a principal to a group returns successfully.""" url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) client = APIClient() url = "{}?usernames={}".format(url, self.principal.username) response = client.delete(url, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_principals_invalid(self): """Test that removing a principal returns an error with invalid data format.""" url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) client = APIClient() response = client.delete(url, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_get_group_by_username(self, mock_request): """Test that getting groups for a principal returns successfully.""" url = reverse("group-list") url = "{}?username={}".format(url, self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 3) # User who is not added to a group explicitly will return platform default group url = reverse("group-list") url = "{}?username={}".format(url, self.principalC.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 1) # Return bad request when user does not exist url = reverse("group-list") url = "{}?username={}".format(url, uuid4()) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_group_by_username_for_cross_account_principal(self): """Test that getting groups for a cross account principal won't have platform default group.""" with tenant_context(self.tenant): self.principalC.cross_account = True self.principalC.save() url = reverse("group-list") url = "{}?username={}".format(url, self.principalC.username) client = APIClient() # User who is not added to a group explicitly will not return platform default group if he is cross account principal. response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 0) def test_get_group_by_username_with_capitalization(self): """Test that getting groups for a user name with capitalization returns successfully.""" url = reverse("group-list") username = "".join(random.choice([k.upper(), k]) for k in self.principal.username) url = "{}?username={}".format(url, username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get("meta").get("count"), 3) def test_get_group_roles_success(self): """Test that getting roles for a group returns successfully.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) self.assertEqual(roles[0].get("name"), self.role.name) self.assertEqual(roles[0].get("description"), self.role.description) def test_get_group_roles_with_exclude_false_success(self): """Test that getting roles with 'exclude=false' for a group works as default.""" url = "%s?exclude=FALSE" % (reverse("group-roles", kwargs={"uuid": self.group.uuid})) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) self.assertEqual(roles[0].get("name"), self.role.name) self.assertEqual(roles[0].get("description"), self.role.description) def test_get_group_roles_with_exclude_success(self): """Test that getting roles with 'exclude=True' for a group returns successfully.""" url = "%s?exclude=True" % (reverse("group-roles", kwargs={"uuid": self.group.uuid})) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 2) self.assertTrue(role.uuid in [self.roleB.uuid, self.roleOrphan.uuid] for role in roles) def test_get_group_roles_with_exclude_in_principal_scope_success(self): """Test that getting roles with 'exclude=True' for a group in principal scope.""" url = "%s?exclude=True&scope=principal" % (reverse("group-roles", kwargs={"uuid": self.group.uuid})) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.roleB.uuid)) self.assertEqual(roles[0].get("name"), self.roleB.name) self.assertEqual(roles[0].get("description"), self.roleB.description) def test_get_group_roles_ordered(self): """Test getting roles with 'order_by=' returns properly.""" url = f"{reverse('group-roles', kwargs={'uuid': self.group.uuid})}?order_by=-name" client = APIClient() test_data = {"roles": [self.roleB.uuid]} response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 2) self.assertEqual(roles[0].get("name"), self.roleB.name) self.assertEqual(roles[1].get("name"), self.role.name) def test_exclude_input_invalid(self): """Test that getting roles with 'exclude=' for a group returns failed validation.""" url = "%s?exclude=sth" % (reverse("group-roles", kwargs={"uuid": self.group.uuid})) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_role_name_filter_for_group_roles_no_match(self): """Test role_name filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_name=test".format(url) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 0) def test_role_name_filter_for_group_roles_match(self): """Test role_name filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_name={}".format(url, self.role.name) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) def test_role_display_name_filter_for_group_roles_no_match(self): """Test role_display_name filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_display_name=test".format(url) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 0) def test_role_display_name_filter_for_group_roles_match(self): """Test role_display_name filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_display_name={}".format(url, self.role.name) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) def test_role_description_filter_for_group_roles_no_match(self): """Test role_description filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_description=test".format(url) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 0) def test_role_description_filter_for_group_roles_match(self): """Test role_description filter for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_description={}".format(url, self.role.description) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) def test_all_role_filters_for_group_roles_no_match(self): """Test role filters for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_description=test&role_name=test".format(url) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 0) def test_all_role_filters_for_group_roles_match(self): """Test role filters for getting roles for a group.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) url = "{}?role_description={}&role_name={}".format(url, self.role.description, self.role.name) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) def test_role_system_filter_for_group_roles(self): """Test role_system filter for getting roles for a group.""" base_url = reverse("group-roles", kwargs={"uuid": self.groupMultiRole.uuid}) client = APIClient() response = client.get(base_url, **self.headers) self.assertEqual(len(response.data.get("data")), 2) url = f"{base_url}?role_system=true" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 1) role = response.data.get("data")[0] self.assertEqual(role.get("system"), True) url = f"{base_url}?role_system=false" client = APIClient() response = client.get(url, **self.headers) self.assertEqual(len(response.data.get("data")), 1) role = response.data.get("data")[0] self.assertEqual(role.get("system"), False) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": []}, ) def test_principal_username_filter_for_group_roles_no_match(self, mock_request): """Test principal_username filter for getting principals for a group.""" url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) url = "{}?principal_username=test".format(url) client = APIClient() response = client.get(url, **self.headers) principals = response.data.get("data") mock_request.assert_called_with([], ANY, options={"sort_order": None}) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(principals), 0) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": [{"username": "******"}]}, ) def test_principal_username_filter_for_group_roles_match(self, mock_request): """Test principal_username filter for getting principals for a group.""" url = reverse("group-principals", kwargs={"uuid": self.group.uuid}) url = "{}?principal_username={}".format(url, self.principal.username) client = APIClient() response = client.get(url, **self.headers) principals = response.data.get("data") mock_request.assert_called_with([self.principal.username], ANY, options={"sort_order": None}) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(principals), 1) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": [{"username": "******"}]}, ) def test_principal_get_ordering_username_success(self, mock_request): """Test that passing a username order_by parameter calls the proxy correctly.""" url = f"{reverse('group-principals', kwargs={'uuid': self.group.uuid})}?order_by=username" client = APIClient() response = client.get(url, **self.headers) principals = response.data.get("data") expected_principals = sorted([self.principal.username, self.principalB.username]) mock_request.assert_called_with(expected_principals, ANY, options={"sort_order": "asc"}) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(principals), 1) @patch( "management.principal.proxy.PrincipalProxy.request_filtered_principals", return_value={"status_code": 200, "data": [{"username": "******"}]}, ) def test_principal_get_ordering_nonusername_fail(self, mock_request): """Test that passing a username order_by parameter calls the proxy correctly.""" url = f"{reverse('group-principals', kwargs={'uuid': self.group.uuid})}?order_by=best_joke" client = APIClient() response = client.get(url, **self.headers) principals = response.data.get("data") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(principals, None) def test_add_group_roles_system_policy_create_success(self): """Test that adding a role to a group without a system policy returns successfully.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() test_data = {"roles": [self.roleB.uuid, self.dummy_role_id]} self.assertCountEqual([self.role], list(self.group.roles())) self.assertCountEqual([self.policy], list(self.group.policies.all())) response = client.post(url, test_data, format="json", **self.headers) roles = response.data.get("data") system_policies = Policy.objects.filter(system=True) system_policy = system_policies.get(group=self.group) self.assertEqual(len(system_policies), 1) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.role], list(self.policy.roles.all())) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(len(roles), 2) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) self.assertEqual(roles[0].get("name"), self.role.name) self.assertEqual(roles[0].get("description"), self.role.description) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_system_flag_update_on_add(self): """Test that adding a role to a platform_default group flips the system flag.""" url = reverse("group-roles", kwargs={"uuid": self.defGroup.uuid}) client = APIClient() test_data = {"roles": [self.roleB.uuid, self.dummy_role_id]} self.assertTrue(self.defGroup.system) response = client.post(url, test_data, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.defGroup.refresh_from_db() self.assertEqual(self.defGroup.name, "Custom default access") self.assertFalse(self.defGroup.system) def test_system_flag_update_on_remove(self): """Test that removing a role from a platform_default group flips the system flag.""" url = reverse("group-roles", kwargs={"uuid": self.defGroup.uuid}) client = APIClient() url = "{}?roles={}".format(url, self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertTrue(self.defGroup.system) response = client.delete(url, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.defGroup.refresh_from_db() self.assertEqual(self.defGroup.name, "Custom default access") self.assertFalse(self.defGroup.system) def test_add_group_roles_system_policy_create_new_group_success(self): """Test that adding a role to a group without a system policy returns successfully.""" group_url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) groupB_url = reverse("group-roles", kwargs={"uuid": self.groupB.uuid}) client = APIClient() test_data = {"roles": [self.roleB.uuid]} response = client.post(group_url, test_data, format="json", **self.headers) responseB = client.post(groupB_url, test_data, format="json", **self.headers) system_policies = Policy.objects.filter(system=True) system_policy = system_policies.get(group=self.group) system_policyB = system_policies.get(group=self.groupB) self.assertEqual(len(system_policies), 2) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.roleB], list(system_policyB.roles.all())) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(responseB.status_code, status.HTTP_200_OK) def test_add_group_roles_system_policy_get_success(self): """Test that adding a role to a group with existing system policy returns successfully.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() test_data = {"roles": [self.roleB.uuid, self.dummy_role_id]} system_policy_name = "System Policy for Group {}".format(self.group.uuid) system_policy = Policy.objects.create(system=True, group=self.group, name=system_policy_name) self.assertCountEqual([self.role], list(self.group.roles())) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) response = client.post(url, test_data, format="json", **self.headers) roles = response.data.get("data") system_policies = Policy.objects.filter(system=True, group=self.group) system_policy = system_policies.first() self.assertEqual(len(system_policies), 1) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.role], list(self.policy.roles.all())) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(len(roles), 2) self.assertEqual(roles[0].get("uuid"), str(self.role.uuid)) self.assertEqual(roles[0].get("name"), self.role.name) self.assertEqual(roles[0].get("description"), self.role.description) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_add_group_multiple_roles_success(self): """Test that adding multiple roles to a group returns successfully.""" with tenant_context(self.tenant): groupC = Group.objects.create(name="groupC") url = reverse("group-roles", kwargs={"uuid": groupC.uuid}) client = APIClient() test_data = {"roles": [self.role.uuid, self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format="json", **self.headers) self.assertCountEqual([self.role, self.roleB], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_add_group_multiple_roles_invalid(self): """Test that adding invalid roles to a group fails the request and does not add any.""" with tenant_context(self.tenant): groupC = Group.objects.create(name="groupC") url = reverse("group-roles", kwargs={"uuid": groupC.uuid}) client = APIClient() test_data = {"roles": ["abc123", self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format="json", **self.headers) self.assertCountEqual([], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_add_group_multiple_roles_not_found_success(self): """Test that adding roles to a group skips ids not found, and returns success.""" with tenant_context(self.tenant): groupC = Group.objects.create(name="groupC") url = reverse("group-roles", kwargs={"uuid": groupC.uuid}) client = APIClient() test_data = {"roles": [self.dummy_role_id, self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format="json", **self.headers) self.assertCountEqual([self.roleB], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_remove_group_roles_success(self): """Test that removing a role from a group returns successfully.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() url = "{}?roles={}".format(url, self.role.uuid) self.policyB.roles.add(self.role) self.policyB.save() self.assertCountEqual([self.role], list(self.group.roles())) response = client.delete(url, format="json", **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertCountEqual([self.role, self.roleB], list(self.groupB.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_multiple_roles_success(self): """Test that removing multiple roles from a group returns successfully.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() url = "{}?roles={},{}".format(url, self.role.uuid, self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format="json", **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_multiple_roles_invalid(self): """Test that removing invalid roles from a group fails the request and does not remove any.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() url = "{}?roles={},{}".format(url, "abc123", self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format="json", **self.headers) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_remove_group_multiple_roles_not_found_success(self): """Test that removing roles from a group skips ids not found, and returns success.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() url = "{}?roles={},{},{}".format(url, self.role.uuid, self.roleB.uuid, self.dummy_role_id) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format="json", **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_roles_invalid(self): """Test that removing a role returns an error with invalid data format.""" url = reverse("group-roles", kwargs={"uuid": self.group.uuid}) client = APIClient() response = client.delete(url, format="json", **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_admin_RonR(self): """Test that a admin user can group RBAC resources""" url = "{}?application={}".format(reverse("group-list"), "rbac") client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK)
class AccessViewTests(IdentityRequest): """Test the access view.""" def setUp(self): """Set up the access view tests.""" super().setUp() request = self.request_context['request'] user = User() user.username = self.user_data['username'] user.account = self.customer_data['account_id'] request.user = user self.access_data = { 'permission': 'app:*:*', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'key1', 'operation': 'equal', 'value': 'value1' } }] } with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.admin_principal = Principal(username="******") self.admin_principal.save() self.group = Group(name='groupA') self.group.save() self.group.principals.add(self.principal) self.group.save() def tearDown(self): """Tear down access view tests.""" with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() def create_role(self, role_name, in_access_data=None): """Create a role.""" access_data = self.access_data if in_access_data: access_data = in_access_data test_data = {'name': role_name, 'access': [access_data]} # create a role url = reverse('role-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) return response def create_policy(self, policy_name, group, roles, status=status.HTTP_201_CREATED): """Create a policy.""" # create a policy test_data = {'name': policy_name, 'group': group, 'roles': roles} url = reverse('policy-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status) return response def test_get_access_success(self): """Test that we can obtain the expected access without pagination.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission='app2:foo:bar') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # test that we can retrieve the principal access url = '{}?application={}&username={}'.format(reverse('access'), 'app', self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('data')) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) self.assertEqual(response.data.get('meta').get('limit'), 1000) self.assertEqual(self.access_data, response.data.get('data')[0]) def test_get_access_no_app_supplied(self): """Test that we return all permissions when no app supplied.""" role_name = 'roleA' policy_name = 'policyA' access_data = { 'permission': 'app:foo:bar', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] } response = self.create_role(role_name, access_data) role_uuid = response.data.get('uuid') role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission='app2:foo:bar') self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = '{}?application=&username={}'.format(reverse('access'), self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('data')) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 2) self.assertEqual(response.data.get('meta').get('limit'), 1000) def test_get_access_multiple_apps_supplied(self): """Test that we return all permissions for multiple apps when supplied.""" role_name = 'roleA' policy_name = 'policyA' access_data = { 'permission': 'app:foo:bar', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] } response = self.create_role(role_name, access_data) role_uuid = response.data.get('uuid') role = Role.objects.get(uuid=role_uuid) access = Access.objects.create(role=role, permission='app2:foo:bar') self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = '{}?application={}&username={}'.format(reverse('access'), 'app,app2', self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 2) def test_get_access_no_partial_match(self): """Test that we can have a partial match on app/permission.""" role_name = 'roleA' policy_name = 'policyA' access_data = { 'permission': 'app:foo:bar', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] } response = self.create_role(role_name, access_data) role_uuid = response.data.get('uuid') self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = '{}?application={}&username={}'.format(reverse('access'), 'ap', self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('data')) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 0) self.assertEqual(response.data.get('meta').get('limit'), 1000) def test_get_access_no_match(self): """Test that we only match on the application name of the permission data.""" role_name = 'roleA' policy_name = 'policyA' access_data = { 'permission': 'app:foo:bar', 'resourceDefinitions': [{ 'attributeFilter': { 'key': 'keyA', 'operation': 'equal', 'value': 'valueA' } }] } response = self.create_role(role_name, access_data) role_uuid = response.data.get('uuid') self.create_policy(policy_name, self.group.uuid, [role_uuid]) url = '{}?application={}&username={}'.format(reverse('access'), 'foo', self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('data')) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 0) self.assertEqual(response.data.get('meta').get('limit'), 1000) def test_get_access_with_limit(self): """Test that we can obtain the expected access with pagination.""" role_name = 'roleA' response = self.create_role(role_name) self.assertEqual(response.status_code, status.HTTP_201_CREATED) role_uuid = response.data.get('uuid') policy_name = 'policyA' response = self.create_policy(policy_name, self.group.uuid, [role_uuid]) # test that we can retrieve the principal access url = '{}?application={}&username={}&limit=1'.format( reverse('access'), 'app', self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('data')) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) self.assertEqual(response.data.get('meta').get('count'), 1) self.assertEqual(response.data.get('meta').get('limit'), 1) self.assertEqual(self.access_data, response.data.get('data')[0]) def test_missing_query_params(self): """Test that we get expected failure when missing required query params.""" url = '{}?page={}'.format(reverse('access'), '3') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_missing_invalid_username(self, mock_request): """Test that we get expected failure when missing required query params.""" url = '{}?application={}&username={}'.format(reverse('access'), 'app', uuid4()) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
class GroupViewsetTests(IdentityRequest): """Test the group viewset.""" def setUp(self): """Set up the group viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user self.dummy_role_id = uuid4() with tenant_context(self.tenant): self.principal = Principal(username=self.user_data['username']) self.principal.save() self.group = Group(name='groupA') self.group.save() self.role = Role.objects.create(name='roleA') self.policy = Policy.objects.create(name='policyA', group=self.group) self.policy.roles.add(self.role) self.policy.save() self.group.policies.add(self.policy) self.group.principals.add(self.principal) self.group.save() self.defGroup = Group(name='groupDef', platform_default=True, system=True) self.defGroup.save() self.defGroup.principals.add(self.principal) self.defGroup.save() self.groupB = Group.objects.create(name='groupB') self.groupB.principals.add(self.principal) self.policyB = Policy.objects.create(name='policyB', group=self.groupB) self.roleB = Role.objects.create(name='roleB') self.policyB.roles.add(self.roleB) self.policyB.save() def tearDown(self): """Tear down group viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Group.objects.all().delete() Principal.objects.all().delete() Role.objects.all().delete() Policy.objects.all().delete() @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_create_group_success(self, mock_request): """Test that we can create a group.""" group_name = 'groupC' test_data = {'name': group_name} # create a group url = reverse('group-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # test that we can retrieve the group url = reverse('group-detail', kwargs={'uuid': response.data.get('uuid')}) response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertEqual(group_name, response.data.get('name')) def test_create_default_group(self): """Test that system groups can be created.""" group_name = 'groupDef' # test group retrieval client = APIClient() url = reverse('group-detail', kwargs={'uuid': self.defGroup.uuid}) response = client.get(url, **self.headers) self.assertIsNotNone(response.data.get('uuid')) self.assertIsNotNone(response.data.get('name')) self.assertTrue(response.data.get('platform_default')) self.assertEqual(group_name, response.data.get('name')) def test_create_group_invalid(self): """Test that creating an invalid group returns an error.""" test_data = {} url = reverse('group-list') client = APIClient() response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_read_group_success(self, mock_request): """Test that we can read a group.""" url = reverse('group-detail', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('name')) self.assertEqual(self.group.name, response.data.get('name')) self.assertEqual(len(response.data.get('roles')), 1) self.assertEqual( response.data.get('roles')[0]['uuid'], str(self.role.uuid)) def test_read_group_invalid(self): """Test that reading an invalid group returns an error.""" url = reverse('group-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_read_group_list_success(self): """Test that we can read a list of groups.""" url = reverse('group-list') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 3) group = response.data.get('data')[0] self.assertIsNotNone(group.get('name')) self.assertEqual(group.get('name'), self.group.name) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_update_group_success(self, mock_request): """Test that we can update an existing group.""" group = Group.objects.first() updated_name = group.name + '_update' test_data = {'name': updated_name} url = reverse('group-detail', kwargs={'uuid': group.uuid}) client = APIClient() response = client.put(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.data.get('uuid')) self.assertEqual(updated_name, response.data.get('name')) def test_update_group_invalid(self): """Test that updating an invalid group returns an error.""" url = reverse('group-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.put(url, {}, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_group_success(self): """Test that we can delete an existing group.""" group = Group.objects.first() url = reverse('group-detail', kwargs={'uuid': group.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # verify the group no longer exists response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_delete_default_group(self): """Test that platform_default groups are protected from deletion""" url = reverse('group-detail', kwargs={'uuid': self.defGroup.uuid}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_delete_group_invalid(self): """Test that deleting an invalid group returns an error.""" url = reverse('group-detail', kwargs={'uuid': uuid4()}) client = APIClient() response = client.delete(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_group_principals_invalid_method(self): """Test that using an unsupported REST method returns an error.""" url = reverse('group-principals', kwargs={'uuid': uuid4()}) client = APIClient() response = client.put(url, {}, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_add_group_principals_success(self, mock_request): """Test that adding a principal to a group returns successfully.""" url = reverse('group-principals', kwargs={'uuid': self.group.uuid}) client = APIClient() new_username = uuid4() test_data = { 'principals': [{ 'username': self.principal.username }, { 'username': new_username }] } response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) url = reverse('group-list') response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data.get('meta').get('count'), 3) self.assertEqual(response.data.get('data')[0].get('principalCount'), 1) self.assertEqual(response.data.get('data')[0].get('policyCount'), None) self.assertEqual(response.data.get('data')[0].get('roleCount'), 1) def test_remove_group_principals_success(self): """Test that removing a principal to a group returns successfully.""" url = reverse('group-principals', kwargs={'uuid': self.group.uuid}) client = APIClient() url = '{}?usernames={}'.format(url, self.principal.username) response = client.delete(url, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_principals_invalid(self): """Test that removing a principal returns an error with invalid data format.""" url = reverse('group-principals', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.delete(url, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [] }) def test_get_group_by_username(self, mock_request): """Test that getting groups for a principalreturns successfully.""" url = reverse('group-principals', kwargs={'uuid': self.group.uuid}) client = APIClient() new_username = uuid4() test_data = { 'principals': [{ 'username': self.principal.username }, { 'username': new_username }] } response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) url = reverse('group-list') url = '{}?username={}'.format(url, self.principal.username) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get('meta').get('count'), 3) url = reverse('group-list') url = '{}?username={}'.format(url, uuid4()) client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.data.get('meta').get('count'), 0) def test_get_group_roles_success(self): """Test that getting roles for a group returns successfully.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.get(url, **self.headers) roles = response.data.get('data') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].get('uuid'), str(self.role.uuid)) self.assertEqual(roles[0].get('name'), self.role.name) self.assertEqual(roles[0].get('description'), self.role.description) def test_add_group_roles_system_policy_create_success(self): """Test that adding a role to a group without a system policy returns successfully.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() test_data = {'roles': [self.roleB.uuid, self.dummy_role_id]} self.assertCountEqual([self.role], list(self.group.roles())) self.assertCountEqual([self.policy], list(self.group.policies.all())) response = client.post(url, test_data, format='json', **self.headers) roles = response.data.get('data') system_policies = Policy.objects.filter(system=True) system_policy = system_policies.get(group=self.group) self.assertEqual(len(system_policies), 1) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.role], list(self.policy.roles.all())) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(len(roles), 2) self.assertEqual(roles[0].get('uuid'), str(self.role.uuid)) self.assertEqual(roles[0].get('name'), self.role.name) self.assertEqual(roles[0].get('description'), self.role.description) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_system_flag_update_on_add(self): """Test that adding a role to a platform_default group flips the system flag.""" url = reverse('group-roles', kwargs={'uuid': self.defGroup.uuid}) client = APIClient() test_data = {'roles': [self.roleB.uuid, self.dummy_role_id]} self.assertTrue(self.defGroup.system) response = client.post(url, test_data, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) self.defGroup.refresh_from_db() self.assertFalse(self.defGroup.system) def test_system_flag_update_on_remove(self): """Test that removing a role from a platform_default group flips the system flag.""" url = reverse('group-roles', kwargs={'uuid': self.defGroup.uuid}) client = APIClient() url = '{}?roles={}'.format(url, self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertTrue(self.defGroup.system) response = client.delete(url, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.defGroup.refresh_from_db() self.assertFalse(self.defGroup.system) def test_add_group_roles_system_policy_create_new_group_success(self): """Test that adding a role to a group without a system policy returns successfully.""" group_url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) groupB_url = reverse('group-roles', kwargs={'uuid': self.groupB.uuid}) client = APIClient() test_data = {'roles': [self.roleB.uuid]} response = client.post(group_url, test_data, format='json', **self.headers) responseB = client.post(groupB_url, test_data, format='json', **self.headers) system_policies = Policy.objects.filter(system=True) system_policy = system_policies.get(group=self.group) system_policyB = system_policies.get(group=self.groupB) self.assertEqual(len(system_policies), 2) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.roleB], list(system_policyB.roles.all())) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(responseB.status_code, status.HTTP_200_OK) def test_add_group_roles_system_policy_get_success(self): """Test that adding a role to a group with existing system policy returns successfully.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() test_data = {'roles': [self.roleB.uuid, self.dummy_role_id]} system_policy_name = 'System Policy for Group {}'.format( self.group.uuid) system_policy = Policy.objects.create(system=True, group=self.group, name=system_policy_name) self.assertCountEqual([self.role], list(self.group.roles())) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) response = client.post(url, test_data, format='json', **self.headers) roles = response.data.get('data') system_policies = Policy.objects.filter(system=True, group=self.group) system_policy = system_policies.first() self.assertEqual(len(system_policies), 1) self.assertCountEqual([system_policy, self.policy], list(self.group.policies.all())) self.assertCountEqual([self.roleB], list(system_policy.roles.all())) self.assertCountEqual([self.role], list(self.policy.roles.all())) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(len(roles), 2) self.assertEqual(roles[0].get('uuid'), str(self.role.uuid)) self.assertEqual(roles[0].get('name'), self.role.name) self.assertEqual(roles[0].get('description'), self.role.description) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_add_group_multiple_roles_success(self): """Test that adding multiple roles to a group returns successfully.""" with tenant_context(self.tenant): groupC = Group.objects.create(name='groupC') url = reverse('group-roles', kwargs={'uuid': groupC.uuid}) client = APIClient() test_data = {'roles': [self.role.uuid, self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format='json', **self.headers) self.assertCountEqual([self.role, self.roleB], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_add_group_multiple_roles_invalid(self): """Test that adding invalid roles to a group fails the request and does not add any.""" with tenant_context(self.tenant): groupC = Group.objects.create(name='groupC') url = reverse('group-roles', kwargs={'uuid': groupC.uuid}) client = APIClient() test_data = {'roles': ['abc123', self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format='json', **self.headers) self.assertCountEqual([], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_add_group_multiple_roles_not_found_success(self): """Test that adding roles to a group skips ids not found, and returns success.""" with tenant_context(self.tenant): groupC = Group.objects.create(name='groupC') url = reverse('group-roles', kwargs={'uuid': groupC.uuid}) client = APIClient() test_data = {'roles': [self.dummy_role_id, self.roleB.uuid]} self.assertCountEqual([], list(groupC.roles())) response = client.post(url, test_data, format='json', **self.headers) self.assertCountEqual([self.roleB], list(groupC.roles())) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_remove_group_roles_success(self): """Test that removing a role from a group returns successfully.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() url = '{}?roles={}'.format(url, self.role.uuid) self.policyB.roles.add(self.role) self.policyB.save() self.assertCountEqual([self.role], list(self.group.roles())) response = client.delete(url, format='json', **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertCountEqual([self.role, self.roleB], list(self.groupB.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_multiple_roles_success(self): """Test that removing multiple roles from a group returns successfully.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() url = '{}?roles={},{}'.format(url, self.role.uuid, self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format='json', **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_multiple_roles_invalid(self): """Test that removing invalid roles from a group fails the request and does not remove any.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() url = '{}?roles={},{}'.format(url, 'abc123', self.roleB.uuid) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format='json', **self.headers) self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_remove_group_multiple_roles_not_found_success(self): """Test that removing roles from a group skips ids not found, and returns success.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() url = '{}?roles={},{},{}'.format(url, self.role.uuid, self.roleB.uuid, self.dummy_role_id) self.policy.roles.add(self.roleB) self.policy.save() self.assertCountEqual([self.role, self.roleB], list(self.group.roles())) response = client.delete(url, format='json', **self.headers) self.assertCountEqual([], list(self.group.roles())) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_remove_group_roles_invalid(self): """Test that removing a role returns an error with invalid data format.""" url = reverse('group-roles', kwargs={'uuid': self.group.uuid}) client = APIClient() response = client.delete(url, format='json', **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
class PrincipalViewsetTests(IdentityRequest): """Test the principal viewset.""" def setUp(self): """Set up the principal viewset tests.""" super().setUp() request = self.request_context['request'] user = User(username=self.user_data['username'], tenant=self.tenant) user.save() request.user = user with tenant_context(self.tenant): self.principal = Principal(username='******') self.principal.save() def tearDown(self): """Tear down principal viewset tests.""" User.objects.all().delete() with tenant_context(self.tenant): Principal.objects.all().delete() @patch('management.principal.proxy.PrincipalProxy.request_principals', return_value={ 'status_code': 200, 'data': [{ 'username': '******' }] }) def test_read_principal_list_success(self, mock_request): """Test that we can read a list of principals.""" url = reverse('principals') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) principal = response.data.get('data')[0] self.assertIsNotNone(principal.get('username')) self.assertEqual(principal.get('username'), self.principal.username) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [{ 'username': '******' }] }) def test_read_principal_filtered_list_success(self, mock_request): """Test that we can read a filtered list of principals.""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) self.assertEqual(len(response.data.get('data')), 1) principal = response.data.get('data')[0] self.assertIsNotNone(principal.get('username')) self.assertEqual(principal.get('username'), 'test_user') def test_bad_query_param(self): """Test handling of bad query params.""" url = f'{reverse("principals")}?limit=foo' client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @patch('management.principal.proxy.PrincipalProxy.request_principals', return_value={ 'status_code': status.HTTP_500_INTERNAL_SERVER_ERROR, 'errors': [{ 'detail': 'error' }] }) def test_read_principal_list_fail(self, mock_request): """Test that we can handle a failure with listing principals.""" url = reverse('principals') client = APIClient() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) error = response.data.get('errors')[0] self.assertIsNotNone(error.get('detail')) @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [{ 'username': '******', 'account_number': '1234' }] }) def test_read_principal_list_account(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) resp = proxy._process_data(response.data.get('data'), account='1234', account_filter=True) self.assertEqual(len(resp), 1) self.assertEqual(resp[0]['username'], 'test_user') @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [{ 'username': '******', 'account_number': '54321' }] }) def test_read_principal_list_account_fail(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) resp = proxy._process_data(response.data.get('data'), account='1234', account_filter=True) self.assertEqual(len(resp), 0) self.assertNotEqual(resp, 'test_user') @patch( 'management.principal.proxy.PrincipalProxy.request_filtered_principals', return_value={ 'status_code': 200, 'data': [{ 'username': '******', 'account_number': '54321' }] }) def test_read_principal_list_account_filter(self, mock_request): """Test that we can handle a request with matching accounts""" url = f'{reverse("principals")}?usernames=test_user&offset=30' client = APIClient() proxy = PrincipalProxy() response = client.get(url, **self.headers) self.assertEqual(response.status_code, status.HTTP_200_OK) for keyname in ['meta', 'links', 'data']: self.assertIn(keyname, response.data) self.assertIsInstance(response.data.get('data'), list) resp = proxy._process_data(response.data.get('data'), account='1234', account_filter=False) self.assertEqual(len(resp), 1) self.assertEqual(resp[0]['username'], 'test_user')