From c953d3772d089980f1e28a61fd6d16dc2e615363 Mon Sep 17 00:00:00 2001 From: BinamB Date: Mon, 3 Aug 2020 16:35:04 -0500 Subject: [PATCH 1/2] Fix: Limit service account to six projects per account --- fence/blueprints/google.py | 17 ++++- tests/google/test_service_accounts.py | 104 ++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/fence/blueprints/google.py b/fence/blueprints/google.py index e220f7f941..ba5a2d6bfc 100644 --- a/fence/blueprints/google.py +++ b/fence/blueprints/google.py @@ -127,9 +127,14 @@ def post(self): user_id = current_token["sub"] payload = flask.request.get_json(silent=True) or {} + project_access = payload.get("project_access") + + if len(project_access) > 6: + raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + sa = GoogleServiceAccountRegistration( email=payload.get("service_account_email"), - project_access=payload.get("project_access"), + project_access=project_access, google_project_id=payload.get("google_project_id"), user_id=user_id, ) @@ -352,9 +357,14 @@ def post(self, id_): user_id = current_token["sub"] payload = flask.request.get_json(silent=True) or {} + project_access = payload.get("project_access") + + if len(project_access) > 6: + raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + sa = GoogleServiceAccountRegistration( email=payload.get("service_account_email"), - project_access=payload.get("project_access"), + project_access=project_access, google_project_id=payload.get("google_project_id"), user_id=user_id, ) @@ -587,6 +597,9 @@ def _get_service_account_for_patch(id_): for access_privilege in registered_service_account.access_privileges ] + if len(project_access) > 6: + raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + google_project_id = registered_service_account.google_project_id return GoogleServiceAccountRegistration( diff --git a/tests/google/test_service_accounts.py b/tests/google/test_service_accounts.py index a5d31bd17f..65291fefe1 100644 --- a/tests/google/test_service_accounts.py +++ b/tests/google/test_service_accounts.py @@ -1027,6 +1027,110 @@ def test_register_service_account_already_exists( assert len(db_session.query(ServiceAccountAccessPrivilege).all()) == 1 assert len(db_session.query(ServiceAccountToGoogleBucketAccessGroup).all()) == 1 +def test_post_service_account_limit( + app, + db_session, + client, + encoded_jwt_service_accounts_access, + cloud_manager, + valid_google_project_patcher, + valid_service_account_patcher, +): + """ + Test that adding more than 6 service accounts returns a 400. + """ + + proj_patcher = valid_google_project_patcher + project_access = [] + n_projects = 8 + for i in range(n_projects): + project = Project(id=i, auth_id="auth_id_{}".format(i)) + + bucket = Bucket(id=i) + + db_session.add(project) + db_session.add(bucket) + db_session.commit() + + project_to_bucket = ProjectToBucket(project_id=i, bucket_id=i) + + db_session.add(project_to_bucket) + db_session.commit() + + gbag = GoogleBucketAccessGroup(id=i, bucket_id=i, email="gbag@gmail.com") + + db_session.add(gbag) + db_session.commit() + + project_access.append("auth_id_{}".format(i)) + + + google_project_id = "project-id" + encoded_creds_jwt = encoded_jwt_service_accounts_access["jwt"] + proj_patcher["get_service_account_ids_from_google_members"].return_value = [ + "test-{}@test.com".format(google_project_id), + "{}@compute-system.iam.gserviceaccount.com".format(google_project_id), + ] + valid_service_account = { + "service_account_email": "sa@gmail.com", + "google_project_id": google_project_id, + "project_access": project_access, + } + + ( + cloud_manager.return_value.__enter__.return_value.get_service_account.return_value + ) = {"uniqueId": "sa_unique_id", "email": "sa@gmail.com"} + + ( + cloud_manager.return_value.__enter__.return_value.add_member_to_group.return_value + ) = {"email": "sa@gmail.com"} + + assert len(db_session.query(UserServiceAccount).all()) == 0 + assert len(db_session.query(ServiceAccountAccessPrivilege).all()) == 0 + assert len(db_session.query(ServiceAccountToGoogleBucketAccessGroup).all()) == 0 + + response = client.post( + "/google/service_accounts", + headers={"Authorization": "Bearer " + encoded_creds_jwt}, + data=json.dumps(valid_service_account), + content_type="application/json", + ) + + assert response.status_code == 400 + + +def test_patch_service_account_limit( + client, + app, + db_session, + encoded_jwt_service_accounts_access, + register_user_service_account, + user_can_manage_service_account_mock, + valid_user_service_account_mock, + revoke_user_service_account_from_google_mock, + add_user_service_account_to_google_mock, +): + """ + Test that patching with new project_access against _dry_run returns 400 + when more than 6 projects are trying to be registered. + """ + encoded_creds_jwt = encoded_jwt_service_accounts_access["jwt"] + service_account = register_user_service_account["service_account"] + n_projects = 8 + project_access = [] + for i in range(n_projects): + project_access.append("valid-project-{}".format(i)) + valid_service_account = { + "project_access": project_access, + } + response = client.patch( + "/google/service_accounts/_dry_run/{}".format(quote(service_account.email)), + headers={"Authorization": "Bearer " + encoded_creds_jwt}, + content_type="application/json", + data=json.dumps(valid_service_account), + ) + assert response.status_code == 400 + def _assert_expected_service_account_response_structure(data): assert "service_account_email" in data From 52cc836b02f9df4160e3fea5ca3e4948a1e9578e Mon Sep 17 00:00:00 2001 From: BinamB Date: Mon, 3 Aug 2020 17:00:20 -0500 Subject: [PATCH 2/2] black --- fence/blueprints/google.py | 12 +++++++++--- tests/google/test_service_accounts.py | 8 ++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/fence/blueprints/google.py b/fence/blueprints/google.py index ba5a2d6bfc..e243ee49c7 100644 --- a/fence/blueprints/google.py +++ b/fence/blueprints/google.py @@ -130,7 +130,9 @@ def post(self): project_access = payload.get("project_access") if len(project_access) > 6: - raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + raise UserError( + "Project access limited to 6. You added {}".format(len(project_access)) + ) sa = GoogleServiceAccountRegistration( email=payload.get("service_account_email"), @@ -360,7 +362,9 @@ def post(self, id_): project_access = payload.get("project_access") if len(project_access) > 6: - raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + raise UserError( + "Project access limited to 6. You added {}".format(len(project_access)) + ) sa = GoogleServiceAccountRegistration( email=payload.get("service_account_email"), @@ -598,7 +602,9 @@ def _get_service_account_for_patch(id_): ] if len(project_access) > 6: - raise UserError("Project access limited to 6. You added {}".format(len(project_access))) + raise UserError( + "Project access limited to 6. You added {}".format(len(project_access)) + ) google_project_id = registered_service_account.google_project_id diff --git a/tests/google/test_service_accounts.py b/tests/google/test_service_accounts.py index 65291fefe1..57928d3835 100644 --- a/tests/google/test_service_accounts.py +++ b/tests/google/test_service_accounts.py @@ -1027,6 +1027,7 @@ def test_register_service_account_already_exists( assert len(db_session.query(ServiceAccountAccessPrivilege).all()) == 1 assert len(db_session.query(ServiceAccountToGoogleBucketAccessGroup).all()) == 1 + def test_post_service_account_limit( app, db_session, @@ -1061,9 +1062,8 @@ def test_post_service_account_limit( db_session.add(gbag) db_session.commit() - - project_access.append("auth_id_{}".format(i)) + project_access.append("auth_id_{}".format(i)) google_project_id = "project-id" encoded_creds_jwt = encoded_jwt_service_accounts_access["jwt"] @@ -1117,7 +1117,7 @@ def test_patch_service_account_limit( encoded_creds_jwt = encoded_jwt_service_accounts_access["jwt"] service_account = register_user_service_account["service_account"] n_projects = 8 - project_access = [] + project_access = [] for i in range(n_projects): project_access.append("valid-project-{}".format(i)) valid_service_account = { @@ -1129,7 +1129,7 @@ def test_patch_service_account_limit( content_type="application/json", data=json.dumps(valid_service_account), ) - assert response.status_code == 400 + assert response.status_code == 400 def _assert_expected_service_account_response_structure(data):