diff --git a/docs/source/specs/openapi.json b/docs/source/specs/openapi.json index ccd690c6c..5f4b88896 100644 --- a/docs/source/specs/openapi.json +++ b/docs/source/specs/openapi.json @@ -3305,7 +3305,7 @@ }, "ServiceAccount": { "required": [ - "clientID", + "clientId", "username", "type" ], @@ -3320,7 +3320,7 @@ "service-account" ] }, - "clientID": { + "clientId": { "type": "string", "example": "fe593ba0-9c62-013c-1dc2-6aa2427b506a" }, @@ -3345,7 +3345,7 @@ "ServiceAccountIn": { "required": [ "type", - "clientID" + "clientId" ], "properties": { "type": { @@ -3354,7 +3354,7 @@ "service-account" ] }, - "clientID": { + "clientId": { "type": "string", "example": "fe593ba0-9c62-013c-1dc2-6aa2427b506a" } diff --git a/rbac/internal/specs/openapi.json b/rbac/internal/specs/openapi.json index f38451580..aa41ec3e3 100644 --- a/rbac/internal/specs/openapi.json +++ b/rbac/internal/specs/openapi.json @@ -1495,7 +1495,7 @@ }, "ServiceAccount": { "required": [ - "clientID", + "clientId", "username", "type" ], @@ -1510,7 +1510,7 @@ "service-account" ] }, - "clientID": { + "clientId": { "type": "string", "example": "fe593ba0-9c62-013c-1dc2-6aa2427b506a" }, @@ -1535,7 +1535,7 @@ "ServiceAccountIn": { "required": [ "type", - "clientID" + "clientId" ], "properties": { "type": { @@ -1544,7 +1544,7 @@ "service-account" ] }, - "clientID": { + "clientId": { "type": "string", "example": "fe593ba0-9c62-013c-1dc2-6aa2427b506a" } diff --git a/rbac/management/group/view.py b/rbac/management/group/view.py index d588c00e4..814d32cf4 100644 --- a/rbac/management/group/view.py +++ b/rbac/management/group/view.py @@ -82,7 +82,7 @@ SERVICE_ACCOUNT_CLIENT_IDS_KEY = "service_account_client_ids" SERVICE_ACCOUNT_DESCRIPTION_KEY = "service_account_description" SERVICE_ACCOUNT_NAME_KEY = "service_account_name" -SERVICE_ACCOUNT_USERNAME_FORMAT = "service-account-{clientID}" +SERVICE_ACCOUNT_USERNAME_FORMAT = "service-account-{clientId}" TYPE_SERVICE_ACCOUNT = "service-account" VALID_EXCLUDE_VALUES = ["true", "false"] VALID_GROUP_ROLE_FILTERS = ["role_name", "role_description", "role_display_name", "role_system"] @@ -442,14 +442,14 @@ def add_service_accounts( # Organize them by their client ID. it_service_accounts_by_client_ids: dict[str, dict] = {} for it_sa in it_service_accounts: - it_service_accounts_by_client_ids[it_sa["clientID"]] = it_sa + it_service_accounts_by_client_ids[it_sa["clientId"]] = it_sa # Make sure that the service accounts the user specified are visible by them. it_sa_client_ids = it_service_accounts_by_client_ids.keys() invalid_service_accounts: set = set() for specified_sa in service_accounts: - if specified_sa["clientID"] not in it_sa_client_ids: - invalid_service_accounts.add(specified_sa["clientID"]) + if specified_sa["clientId"] not in it_sa_client_ids: + invalid_service_accounts.add(specified_sa["clientId"]) # If we have any invalid service accounts, notify the user. if len(invalid_service_accounts) > 0: @@ -461,15 +461,15 @@ def add_service_accounts( # Fetch the service account from our database to add it to the group. If it doesn't exist, we create # it. for specified_sa in service_accounts: - client_id = specified_sa["clientID"] + client_id = specified_sa["clientId"] try: principal = Principal.objects.get( - username__iexact=SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientID=client_id), + username__iexact=SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientId=client_id), tenant=tenant, ) except Principal.DoesNotExist: principal = Principal.objects.create( - username=SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientID=client_id), + username=SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientId=client_id), service_account_id=client_id, type=TYPE_SERVICE_ACCOUNT, tenant=tenant, @@ -481,7 +481,7 @@ def add_service_accounts( group_principal_change_notification_handler( self.request.user, group, - SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientID=client_id), + SERVICE_ACCOUNT_USERNAME_FORMAT.format(clientId=client_id), "added", ) diff --git a/rbac/management/principal/it_service.py b/rbac/management/principal/it_service.py index cd312547a..0dca2f55c 100644 --- a/rbac/management/principal/it_service.py +++ b/rbac/management/principal/it_service.py @@ -222,7 +222,7 @@ def _is_service_account_valid(self, user: User, client_id: str) -> bool: service_accounts: list[dict] = self.request_service_accounts(bearer_token=user.bearer_token) for sa in service_accounts: - if client_id == sa.get("clientID"): + if client_id == sa.get("clientId"): return True return False @@ -451,7 +451,7 @@ def _transform_incoming_payload(self, service_account_from_it_service: dict) -> created_at = service_account_from_it_service.get("createdAt") if client_id: - service_account["clientID"] = client_id + service_account["clientId"] = client_id if name: service_account["name"] = name @@ -484,7 +484,7 @@ def _merge_principals_it_service_accounts( for it_service_account in it_service_accounts: try: - sa_principal = service_account_principals[it_service_account["clientID"]] + sa_principal = service_account_principals[it_service_account["clientId"]] if username_only and username_only == "true": service_accounts.append({"username": sa_principal.username}) # type: ignore diff --git a/rbac/management/principal/serializer.py b/rbac/management/principal/serializer.py index e9e2edb06..510da5cd9 100644 --- a/rbac/management/principal/serializer.py +++ b/rbac/management/principal/serializer.py @@ -39,14 +39,14 @@ class PrincipalInputSerializer(serializers.Serializer): """Serializer for the Principal model.""" username = serializers.CharField(required=False, max_length=150) - clientID = serializers.UUIDField(required=False, source="service_account_id") + clientId = serializers.UUIDField(required=False, source="service_account_id") type = serializers.CharField(required=False) def validate(self, data: OrderedDict): """ Assert that the correct fields are specified. - Assert that when the specified type is 'service-account', the corresponding 'clientID' field + Assert that when the specified type is 'service-account', the corresponding 'clientId' field has been specified. """ # If the "type" has not been specified, we assume it is a user principal. @@ -57,7 +57,7 @@ def validate(self, data: OrderedDict): return data elif data["type"] == "service-account": if "service_account_id" not in data: - raise ValidationError(code="missing", message="the clientID field is required for service accounts") + raise ValidationError(code="missing", message="the clientId field is required for service accounts") return data else: @@ -68,13 +68,13 @@ def validate(self, data: OrderedDict): class Meta: """Metadata for the serializer.""" - fields = ("username", "clientID", "type") + fields = ("username", "clientId", "type") class ServiceAccountSerializer(serializers.Serializer): """Serializer for Service Account.""" - clientID = serializers.UUIDField() + clientId = serializers.UUIDField() name = serializers.CharField() description = serializers.CharField(allow_null=True, required=False) owner = serializers.CharField() diff --git a/tests/management/group/test_view.py b/tests/management/group/test_view.py index 2f1abc214..4e849ed0f 100644 --- a/tests/management/group/test_view.py +++ b/tests/management/group/test_view.py @@ -392,7 +392,7 @@ def test_read_group_list_success(self): "management.principal.it_service.ITService.request_service_accounts", return_value=[ { - "clientID": "b7a82f30-bcef-013c-2452-6aa2427b506c", + "clientId": "b7a82f30-bcef-013c-2452-6aa2427b506c", "name": f"service_account_name", "description": f"Service Account description", "owner": "jsmith", @@ -2105,7 +2105,7 @@ def test_get_group_service_account_success(self, mock_request): for uuid in self.sa_client_ids: mocked_values.append( { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith", @@ -2129,11 +2129,11 @@ def test_get_group_service_account_success(self, mock_request): sa = response.data.get("data")[0] self.assertCountEqual( list(sa.keys()), - ["clientID", "name", "description", "owner", "time_created", "type", "username"], + ["clientId", "name", "description", "owner", "time_created", "type", "username"], ) for mock_sa in mocked_values: - if mock_sa["clientID"] == sa.get("clientID"): + if mock_sa["clientId"] == sa.get("clientId"): self.assertEqual(sa.get("name"), mock_sa["name"]) self.assertEqual(sa.get("description"), mock_sa["description"]) self.assertEqual(sa.get("owner"), mock_sa["owner"]) @@ -2147,7 +2147,7 @@ def test_get_group_service_account_empty_response(self, mock_request): uuid = self.sa_client_ids[0] mock_request.return_value = [ { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith", @@ -2174,7 +2174,7 @@ def test_get_group_service_account_valid_limit_offset(self, mock_request): for uuid in self.sa_client_ids: mocked_values.append( { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith", @@ -2220,7 +2220,7 @@ def test_get_group_service_account_invalid_limit_offset(self, mock_request): for uuid in self.sa_client_ids: mocked_values.append( { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith", @@ -2577,7 +2577,7 @@ def test_get_group_service_account_filter_by_username_success(self, mock_request for uuid in [uuid1, uuid2]: mocked_values.append( { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith", @@ -2615,7 +2615,7 @@ def test_get_group_service_account_filter_by_username_success(self, mock_request self.assertEqual(len(response.data.get("data")), 1) sa = response.data.get("data")[0] - self.assertEqual(sa.get("clientID"), uuid2) + self.assertEqual(sa.get("clientId"), uuid2) self.assertEqual(sa.get("username"), "service-account-" + uuid2) # Test that 0 SA is returned for SA with "r" in username @@ -2890,7 +2890,7 @@ def test_group_service_account_with_user_administrator_role_add_principals( # Create the test data to add a service account and a regular user to the group. test_data = { "principals": [ - {"clientID": new_sa_principal.service_account_id, "type": "service-account"}, + {"clientId": new_sa_principal.service_account_id, "type": "service-account"}, {"username": new_principal.username}, ] } @@ -3184,7 +3184,7 @@ def test_group_user_with_user_administrator_role_add_principals(self, request_fi # Create the test data to add a service account and a regular user to the group. test_data = { "principals": [ - {"clientID": new_sa_principal.service_account_id, "type": "service-account"}, + {"clientId": new_sa_principal.service_account_id, "type": "service-account"}, {"username": new_principal.username}, ] } @@ -3718,7 +3718,7 @@ def test_list_service_account_principals_in_group_with_User_Access_Admin_success sa_uuid = sa_principal.service_account_id mocked_values = [ { - "clientID": sa_uuid, + "clientId": sa_uuid, "name": f"Service Account name", "description": f"Service Account description", "owner": "jsmith", @@ -3798,7 +3798,7 @@ def test_add_service_account_principal_in_group_without_User_Access_Admin_fail(s sa_uuid = sa_principal.service_account_id mocked_values = [ { - "clientID": sa_uuid, + "clientId": sa_uuid, "name": f"Service Account name", "description": f"Service Account description", "owner": "jsmith", @@ -3812,7 +3812,7 @@ def test_add_service_account_principal_in_group_without_User_Access_Admin_fail(s url = reverse("group-principals", kwargs={"uuid": test_group.uuid}) client = APIClient() - request_body = {"principals": [{"clientID": sa_uuid, "type": "service-account"}]} + request_body = {"principals": [{"clientId": sa_uuid, "type": "service-account"}]} response = client.post(url, request_body, format="json", **self.headers_user_based_principal) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) @@ -3888,7 +3888,7 @@ def test_add_service_account_principal_in_group_with_User_Access_Admin_success(s sa_uuid = sa_principal.service_account_id mocked_values = [ { - "clientID": sa_uuid, + "clientId": sa_uuid, "name": f"Service Account name", "description": f"Service Account description", "owner": "jsmith", @@ -3902,7 +3902,7 @@ def test_add_service_account_principal_in_group_with_User_Access_Admin_success(s url = reverse("group-principals", kwargs={"uuid": test_group.uuid}) client = APIClient() - request_body = {"principals": [{"clientID": sa_uuid, "type": "service-account"}]} + request_body = {"principals": [{"clientId": sa_uuid, "type": "service-account"}]} response = client.post(url, request_body, format="json", **self.headers_user_based_principal) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -3995,7 +3995,7 @@ def test_add_service_account_principal_in_group_with_User_Access_Admin_fail(self sa_uuid = sa_principal.service_account_id mocked_values = [ { - "clientID": sa_uuid, + "clientId": sa_uuid, "name": f"Service Account name", "description": f"Service Account description", "owner": "jsmith", @@ -4009,7 +4009,7 @@ def test_add_service_account_principal_in_group_with_User_Access_Admin_fail(self url = reverse("group-principals", kwargs={"uuid": test_group.uuid}) client = APIClient() - request_body = {"principals": [{"clientID": sa_uuid, "type": "service-account"}]} + request_body = {"principals": [{"clientId": sa_uuid, "type": "service-account"}]} response = client.post(url, request_body, format="json", **self.headers_user_based_principal) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/tests/management/principal/test_it_service.py b/tests/management/principal/test_it_service.py index 2f2c38d70..cd3559199 100644 --- a/tests/management/principal/test_it_service.py +++ b/tests/management/principal/test_it_service.py @@ -166,7 +166,7 @@ def _assert_created_sa_and_result_are_same( # Make it easier to find the service accounts by their client ID. result_sas_by_client_id: dict[str[dict, str]] = {} for sa in function_result: - result_sas_by_client_id[sa["clientID"]] = sa + result_sas_by_client_id[sa["clientId"]] = sa # Assert that the only service accounts in the result are the ones from the tenant associated to the user # that was passed to the function under test. @@ -180,7 +180,7 @@ def _assert_created_sa_and_result_are_same( self.assertEqual( sa_principal.service_account_id, - sa["clientID"], + sa["clientId"], "the mocked service account's client ID should be the service account principal's ID", ) @@ -221,9 +221,9 @@ def _assert_IT_to_RBAC_model_transformations( # Rearrange RBAC's service accounts by client ID for an easier search later on. rbac_service_accounts_by_cid: dict[str, dict[str, str]] = {} for rbac_sa in rbac_service_accounts: - rbac_sa_cid = rbac_sa.get("clientID") + rbac_sa_cid = rbac_sa.get("clientId") if not rbac_sa_cid: - self.fail(f'the transformed service account does not have the "clientID" property: {rbac_sa}') + self.fail(f'the transformed service account does not have the "clientId" property: {rbac_sa}') rbac_service_accounts_by_cid[rbac_sa_cid] = rbac_sa @@ -241,9 +241,9 @@ def _assert_IT_to_RBAC_model_transformations( ) # Assert that the client IDs are the same. - rbac_sa_client_id = rbac_sa.get("clientID") + rbac_sa_client_id = rbac_sa.get("clientId") if not rbac_sa_client_id: - self.fail(f'the transformed RBAC service account does not contain the "clientID" property: {rbac_sa}') + self.fail(f'the transformed RBAC service account does not contain the "clientId" property: {rbac_sa}') self.assertEqual(rbac_sa_client_id, client_id, "the client IDs for the RBAC and IT models do not match") @@ -593,7 +593,7 @@ def test_is_service_account_valid(self, request_service_accounts: mock.Mock): user.bearer_token = "mocked-bt" expected_client_id = str(uuid.uuid4()) - request_service_accounts.return_value = [{"clientID": expected_client_id}] + request_service_accounts.return_value = [{"clientId": expected_client_id}] self.assertEqual( True, @@ -602,9 +602,9 @@ def test_is_service_account_valid(self, request_service_accounts: mock.Mock): ) request_service_accounts.return_value = [ - {"clientID": str(uuid.uuid4())}, - {"clientID": str(uuid.uuid4())}, - {"clientID": expected_client_id}, + {"clientId": str(uuid.uuid4())}, + {"clientId": str(uuid.uuid4())}, + {"clientId": expected_client_id}, ] self.assertEqual( @@ -629,9 +629,9 @@ def test_is_service_account_invalid(self, request_service_accounts: mock.Mock): ) request_service_accounts.return_value = [ - {"clientID": str(uuid.uuid4())}, - {"clientID": str(uuid.uuid4())}, - {"clientID": str(uuid.uuid4())}, + {"clientId": str(uuid.uuid4())}, + {"clientId": str(uuid.uuid4())}, + {"clientId": str(uuid.uuid4())}, ] self.assertEqual( @@ -657,7 +657,7 @@ def test_is_service_account_valid_zero_results_from_it(self, request_service_acc def test_is_service_account_valid_one_matching_result_from_it(self, request_service_accounts: mock.Mock): """Test that the function under test positively validates the given service account if IT responds with that service account.""" client_id = "client-id-123" - request_service_accounts.return_value = [{"clientID": client_id}] + request_service_accounts.return_value = [{"clientId": client_id}] user = User() user.bearer_token = "mocked-bt" @@ -671,7 +671,7 @@ def test_is_service_account_valid_one_matching_result_from_it(self, request_serv def test_is_service_account_valid_not_matching_result_from_it(self, request_service_accounts: mock.Mock): """Test that the function under test does not validate the given service account if IT does not return a response with a proper service account.""" client_id = "client-id-123" - request_service_accounts.return_value = [{"clientID": "different-client-id"}] + request_service_accounts.return_value = [{"clientId": "different-client-id"}] user = User() user.bearer_token = "mocked-bt" @@ -1426,11 +1426,11 @@ def test_transform_incoming_payload(self) -> None: result = self.it_service._transform_incoming_payload(service_account_from_it_service=it_service_account) # Assert that the transformation was correct. - result_client_id = result["clientID"] + result_client_id = result["clientId"] if not result_client_id: - self.fail('the "clientID" field is not present in the resulting model') + self.fail('the "clientId" field is not present in the resulting model') - self.assertEqual(client_id, result_client_id, 'the "clientID" field was not correctly transformed') + self.assertEqual(client_id, result_client_id, 'the "clientId" field was not correctly transformed') result_name = result["name"] if not result_name: @@ -1474,9 +1474,9 @@ def test_merge_principals_it_service_accounts(self) -> None: expected_first_username = f"{sa_client_id}-username" expected_second_username = f"{sa_two_client_id}-username" it_service_accounts = [ - {"clientID": sa_client_id, "username": expected_first_username, "made_up_key": "made_up_value"}, - {"clientID": sa_two_client_id, "username": expected_second_username, "made_up_key": "made_up_value"}, - {"clientID": str(uuid.uuid4()), "username": "should-not-be-picked", "made_up_key": "made_up_value"}, + {"clientId": sa_client_id, "username": expected_first_username, "made_up_key": "made_up_value"}, + {"clientId": sa_two_client_id, "username": expected_second_username, "made_up_key": "made_up_value"}, + {"clientId": str(uuid.uuid4()), "username": "should-not-be-picked", "made_up_key": "made_up_value"}, ] # Call the function under test. diff --git a/tests/management/principal/test_view.py b/tests/management/principal/test_view.py index 98d0bec57..716f62675 100644 --- a/tests/management/principal/test_view.py +++ b/tests/management/principal/test_view.py @@ -816,7 +816,7 @@ def test_read_principal_service_account_list_success(self, mock_request): mock_request.return_value = [ { - "clientID": sa_client_id, + "clientId": sa_client_id, "name": "service_account_name", "description": "Service Account description", "owner": "jsmith", @@ -838,9 +838,9 @@ def test_read_principal_service_account_list_success(self, mock_request): sa = response.data.get("data")[0] self.assertCountEqual( list(sa.keys()), - ["clientID", "name", "description", "owner", "time_created", "type", "username"], + ["clientId", "name", "description", "owner", "time_created", "type", "username"], ) - self.assertEqual(sa.get("clientID"), sa_client_id) + self.assertEqual(sa.get("clientId"), sa_client_id) self.assertEqual(sa.get("name"), "service_account_name") self.assertEqual(sa.get("description"), "Service Account description") self.assertEqual(sa.get("owner"), "jsmith") @@ -855,7 +855,7 @@ def test_read_principal_service_account_list_empty_response(self, mock_request): sa_client_id = "026f5290-a3d3-013c-b93f-6aa2427b506c" mock_request.return_value = [ { - "clientID": sa_client_id, + "clientId": sa_client_id, "name": "service_account_name", "description": "Service Account description", "owner": "jsmith", @@ -897,7 +897,7 @@ def test_read_principal_service_account_valid_limit_offset(self, mock_request): for uuid in sa_client_ids: mocked_values.append( { - "clientID": uuid, + "clientId": uuid, "name": f"service_account_name_{uuid.split('-')[0]}", "description": f"Service Account description {uuid.split('-')[0]}", "owner": "jsmith",