def test_delete_expired_service_account_keys_both_user_and_client( cloud_manager, app, db_session, test_user_a, oauth_client): """ Test deleting all expired service account keys """ import fence fence.settings = MagicMock() cloud_manager.return_value.__enter__.return_value.delete_service_account_key.return_value = ( {}) current_time = int(time.time()) service_account = GoogleServiceAccount( google_unique_id="1", user_id=test_user_a["user_id"], google_project_id="test", email="*****@*****.**", ) client_service_account = GoogleServiceAccount( google_unique_id="1", user_id=test_user_a["user_id"], client_id=oauth_client["client_id"], google_project_id="test", email="*****@*****.**", ) db_session.add(service_account) db_session.add(client_service_account) db_session.commit() # Add 2 expired and 1 not expired accounts service_account_key1 = GoogleServiceAccountKey( key_id=1, service_account_id=service_account.id, expires=current_time - 3600) service_account_key2 = GoogleServiceAccountKey( key_id=2, service_account_id=client_service_account.id, expires=current_time - 3600, ) service_account_key3 = GoogleServiceAccountKey( key_id=3, service_account_id=service_account.id, expires=current_time + 3600) db_session.add(service_account_key1) db_session.add(service_account_key2) db_session.add(service_account_key3) db_session.commit() records = db_session.query(GoogleServiceAccountKey).all() assert len(records) == 3 # call function to delete expired service account remove_expired_google_service_account_keys(config["DB"]) # check database. Expect 2 deleted records = db_session.query(GoogleServiceAccountKey).all() assert len(records) == 1 assert records[0].id == service_account_key3.id
def test_google_delete_owned_access_token( app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt ): """ Test ``DELETE /credentials/google``. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_key = "some_key_321" service_account_id = "123456789" path = "/credentials/google/" + service_account_key def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id: # Return two keys, first one is NOT the one we're # requesting to delete return [ {"name": "project/service_accounts/keys/over_9000"}, {"name": "project/service_accounts/keys/" + service_account_key}, ] else: return [] ( cloud_manager.return_value.__enter__.return_value.get_service_account_keys_info.side_effect ) = get_account_keys # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() response = client.delete( path, data={}, headers={"Authorization": "Bearer " + encoded_credentials_jwt} ) # check that the service account id was included in a call to # cloud_manager assert any( [ str(mock_call) for mock_call in cloud_manager.mock_calls if service_account_id in str(mock_call) ] ) assert response.status_code == 204 # check that we actually requested to delete the correct service key ( cloud_manager.return_value.__enter__.return_value.delete_service_account_key ).assert_called_with(service_account_id, service_account_key)
def test_client_delete_error(app, db_session, cloud_manager, test_user_a): """ Test that when Google gives us an error when deleting the service account, we don't remove it from the db. """ client_name = "test123" client = Client(client_id=client_name, client_secret="secret", name=client_name) db_session.add(client) db_session.commit() client_service_account = GoogleServiceAccount( google_unique_id="jf09238ufposijf", client_id=client.client_id, user_id=test_user_a["user_id"], google_project_id="test", email="*****@*****.**", ) db_session.add(client_service_account) db_session.commit() # error when deleting service account ( cloud_manager.return_value.__enter__.return_value.delete_service_account.return_value ) = {"error": "something bad happened"} delete_client_action(config["DB"], client_name) client_after = db_session.query(Client).filter_by(name=client_name).all() client_service_account_after = ( db_session.query(GoogleServiceAccount).filter_by(client_id=client.client_id) ).all() # make sure client is deleted but service account we couldn't delete stays assert len(client_after) == 0 assert len(client_service_account_after) == 1
def test_client_delete(app, db_session, cloud_manager, test_user_a): """ Test that the client delete function correctly cleans up the client's service accounts and the client themself. """ client_name = "test123" client = Client(client_id=client_name, client_secret="secret", name=client_name) db_session.add(client) db_session.commit() client_service_account = GoogleServiceAccount( google_unique_id="jf09238ufposijf", client_id=client.client_id, user_id=test_user_a["user_id"], google_project_id="test", email="*****@*****.**", ) db_session.add(client_service_account) db_session.commit() # empty return means success (cloud_manager.return_value.__enter__.return_value.delete_service_account. return_value) = {} delete_client_action(app.config["DB"], client_name) client_after = db_session.query(Client).filter_by(name=client_name).all() client_service_account_after = ( db_session.query(GoogleServiceAccount).filter_by( client_id=client.client_id)).all() assert len(client_after) == 0 assert len(client_service_account_after) == 0
def test_google_bucket_access_existing_proxy_group( app, google_storage_client_mocker, client, cloud_manager, db_session, encoded_creds_jwt, monkeypatch, ): monkeypatch.setitem(app.config, "MOCK_AUTH", False) user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_id = "123456789" path = "/credentials/google/" proj = Project(id=129, name="test_proj") ap = AccessPrivilege( user_id=user_id, project_id=proj.id, privilege=["write-storage"] ) cloud = CloudProvider(id=129, name="google") bucket = Bucket(id=129, provider_id=cloud.id) gbag = GoogleBucketAccessGroup( id=129, bucket_id=bucket.id, email="*****@*****.**", privileges=["write"] ) ptob = ProjectToBucket(id=129, project_id=proj.id, bucket_id=bucket.id) sa = StorageAccess(project_id=proj.id, provider_id=cloud.id) service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() db_session.add(proj) db_session.add(ap) db_session.add(cloud) db_session.add(bucket) db_session.add(gbag) db_session.add(ptob) db_session.add(sa) db_session.add(service_account) db_session.commit() encoded_credentials_jwt = encoded_creds_jwt["jwt"] path = "/credentials/google/" data = {} response = client.post( path, data=data, headers={"Authorization": "Bearer " + encoded_credentials_jwt} ) assert google_storage_client_mocker.add_bucket_acl.called is False assert response.status_code == 200
def test_google_delete_invalid_access_token(app, client, oauth_client, cloud_manager, db_session): """ Test ``DELETE /credentials/google``. """ client_id = oauth_client["client_id"] service_account_key = "some_key_321" service_account_id = "123456789" proxy_group_id = "proxy_group_0" path = ("/credentials/google/" + service_account_key + "/") def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id: # Return two keys, NEITHER are the key we want to delete return [{ "name": "project/service_accounts/keys/voyager" }, { "name": "project/service_accounts/keys/deep-space-nine" }] else: return [] (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info.side_effect) = get_account_keys with app.test_client() as app_client: # set global client context flask.g.client_id = client_id # get test user info user = (db_session.query(User).filter_by(username="******").first()) user_id = user.id # create a proxy group for user proxy_group = GoogleProxyGroup( id=proxy_group_id, user_id=user_id, ) db_session.add(proxy_group) # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com")) db_session.add(user) db_session.add(service_account) db_session.commit() response = app_client.delete(path, data={}) # check that we didn't try to delete, since the key doesn't exist assert (cloud_manager.return_value.__enter__.return_value. delete_service_account_key).called is False assert response.status_code == 404
def test_google_delete_invalid_access_token( app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt ): """ Test ``DELETE /credentials/google``. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_key = "some_key_321" service_account_id = "123456789" path = "/credentials/google/" + service_account_key + "/" def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id: # Return two keys, NEITHER are the key we want to delete return [ {"name": "project/service_accounts/keys/voyager"}, {"name": "project/service_accounts/keys/deep-space-nine"}, ] else: return [] ( cloud_manager.return_value.__enter__.return_value.get_service_account_keys_info.side_effect ) = get_account_keys # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() response = client.delete( path, data={}, headers={"Authorization": "Bearer " + encoded_credentials_jwt} ) # check that we didn't try to delete, since the key doesn't exist assert ( cloud_manager.return_value.__enter__.return_value.delete_service_account_key ).called is False assert response.status_code == 404
def test_google_attempt_delete_unowned_access_token(app, client, oauth_client, cloud_manager, db_session): """ Test ``DELETE /credentials/google``. """ client_id = oauth_client["client_id"] service_account_key = "some_key_321" proxy_group_id = "proxy_group_0" path = ("/credentials/google/" + service_account_key + "/") with app.test_client() as app_client: # set global client context flask.g.client_id = client_id # get test user info user = (db_session.query(User).filter_by(username="******").first()) user_id = user.id # create a proxy group for user proxy_group = GoogleProxyGroup( id=proxy_group_id, user_id=user_id, ) db_session.add(proxy_group) # create a service account for A DIFFERENT CLIENT client = Client( client_id="NOT_THIS_GUY", client_secret="a0987u23on192y", name="NOT_THIS_GUY", ) service_account = GoogleServiceAccount( google_unique_id="123456789", client_id="NOT_THIS_GUY", user_id=user_id, email=("NOT_THIS_GUY" + "-" + str(user_id) + "@test.com")) db_session.add(user) db_session.add(client) db_session.add(service_account) db_session.commit() response = app_client.delete(path, data={}) # check that we didn't try to get key info or delete, # since the current user/client doesn't have the key assert (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info).called is False assert (cloud_manager.return_value.__enter__.return_value. delete_service_account_key).called is False assert response.status_code == 404
def test_google_attempt_delete_unowned_access_token(app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt): """ Test ``DELETE /credentials/google``. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] service_account_key = "some_key_321" path = "/credentials/google/" + service_account_key + "/" # create a service account for A DIFFERENT CLIENT client_entry = Client(client_id="NOT_THIS_GUY", client_secret="a0987u23on192y", name="NOT_THIS_GUY") service_account = GoogleServiceAccount( google_unique_id="123456789", client_id="NOT_THIS_GUY", user_id=user_id, email=("NOT_THIS_GUY" + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(client_entry) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() response = client.delete( path, data={}, headers={"Authorization": "Bearer " + encoded_credentials_jwt}) # check that we didn't try to get key info or delete, # since the current user/client doesn't have the key assert (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info).called is False assert (cloud_manager.return_value.__enter__.return_value. delete_service_account_key).called is False assert response.status_code == 404
def test_google_create_access_token_post(app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt): """ Test ``POST /credentials/google`` gets a new access key. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_id = "123456789" service_account_email = client_id + "-" + str(user_id) + "@test.com" path = "/credentials/google/" data = {} # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=service_account_email, google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() response = client.post( path, data=data, headers={"Authorization": "Bearer " + encoded_credentials_jwt}) # check that the service account id or email was included in a # call to cloud_manager args, kwargs = (cloud_manager.return_value.__enter__.return_value. get_access_key).call_args combined = [arg for arg in args] + [value for key, value in kwargs.items()] assert service_account_id in combined or service_account_email in combined assert response.status_code == 200
def create_service_account(client_id, user_id, username, proxy_group_id): """ Create a Google Service account for the current client and user. Args: g_cloud_manager (cirrus.GoogleCloudManager): instance of cloud manager to use Returns: fence.models.GoogleServiceAccount: New service account """ if proxy_group_id: if client_id: service_account_id = get_valid_service_account_id_for_client( client_id, user_id) else: service_account_id = get_valid_service_account_id_for_user( user_id, username) with GoogleCloudManager() as g_cloud: new_service_account = g_cloud.create_service_account_for_proxy_group( proxy_group_id, account_id=service_account_id) service_account = GoogleServiceAccount( google_unique_id=new_service_account["uniqueId"], client_id=client_id, user_id=user_id, email=new_service_account["email"], google_project_id=new_service_account["projectId"], ) current_session.add(service_account) current_session.commit() flask.current_app.logger.info( "Created service account {} for proxy group {}.".format( new_service_account["email"], proxy_group_id)) return service_account else: flask.abort( 404, "Could not find Google proxy group for current user in the " "given token.", )
def test_google_create_access_token_post(app, oauth_client, cloud_manager, db_session): """ Test ``POST /credentials/google`` gets a new access key. """ client_id = oauth_client['client_id'] service_account_id = '123456789' proxy_group_id = 'proxy_group_0' path = '/credentials/google/' data = {} with app.test_client() as app_client: # set global client context flask.g.client_id = client_id # get test user info user = (db_session.query(User).filter_by(username='******').first()) user_id = user.id # create a proxy group for user proxy_group = GoogleProxyGroup( id=proxy_group_id, user_id=user_id, ) db_session.add(proxy_group) # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + '-' + str(user_id) + '@test.com')) db_session.add(user) db_session.add(service_account) db_session.commit() response = app_client.post(path, data=data) # check that the service account id was included in a # call to cloud_manager (cloud_manager.return_value.__enter__.return_value.get_access_key ).assert_called_with(service_account_id) assert response.status_code == 200
def load_google_specific_user_data(db_session, test_user_d): """Add Google-specific user data to Fence db.""" gpg = GoogleProxyGroup(id=userd_dict["gpg_id"], email=userd_dict["gpg_email"]) gsak = GoogleServiceAccountKey( id=userd_dict["gsak_id"], key_id=userd_dict["gsak_key_id"], service_account_id=userd_dict["gsa_id"], ) gsa = GoogleServiceAccount( id=userd_dict["gsa_id"], google_unique_id="d_gui", user_id=userd_dict["user_id"], google_project_id="d_gpid", email=userd_dict["gsa_email"], ) bkt = Bucket(id=userd_dict["bucket_id"]) gbag = GoogleBucketAccessGroup( id=userd_dict["gbag_id"], bucket_id=userd_dict["bucket_id"], email=userd_dict["gbag_email"], ) gpg_gbag = GoogleProxyGroupToGoogleBucketAccessGroup( id=userd_dict["gpg_to_gbag_id"], proxy_group_id=userd_dict["gpg_id"], access_group_id=userd_dict["gbag_id"], ) uga = UserGoogleAccount( id=userd_dict["uga_id"], email=userd_dict["uga_email"], user_id=userd_dict["user_id"], ) uga_pg = UserGoogleAccountToProxyGroup( user_google_account_id=userd_dict["uga_id"], proxy_group_id=userd_dict["gpg_id"]) db_session.add_all([gpg, gsak, gsa, bkt, gbag, gpg_gbag, uga, uga_pg]) user = (db_session.query(User).filter_by( username=userd_dict["user_username"]).first()) user.google_proxy_group_id = userd_dict["gpg_id"] db_session.commit()
def _create_google_service_account_for_client(g_cloud_manager): """ Create a Google Service account for the current client and user. Args: g_cloud_manager (cirrus.GoogleCloudManager): instance of cloud manager to use Returns: fence.models.GoogleServiceAccount: New service account """ # create service account, add to db proxy_group = ( current_session .query(GoogleProxyGroup) .filter_by(user_id=flask.g.user.id) .first() ) if proxy_group: client_id = getattr(flask.g, 'client_id', None) new_service_account = ( g_cloud_manager.create_service_account_for_proxy_group(proxy_group.id, account_id=client_id) ) service_account = GoogleServiceAccount( google_unique_id=new_service_account['uniqueId'], client_id=client_id, user_id=flask.g.user.id, email=new_service_account['email'] ) current_session.add(service_account) current_session.commit() else: # TODO Should we create a group here if one doesn't exist for some reason? # These groups *should* get created during dpbap sync flask.abort(404, 'Could not find Google proxy group for current user.') return service_account
def test_google_create_access_token_post( app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt ): """ Test ``POST /credentials/google`` gets a new access key. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_id = "123456789" path = "/credentials/google/" data = {} # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() response = client.post( path, data=data, headers={"Authorization": "Bearer " + encoded_credentials_jwt} ) # check that the service account id was included in a # call to cloud_manager ( cloud_manager.return_value.__enter__.return_value.get_access_key ).assert_called_with(service_account_id) assert response.status_code == 200
def test_google_delete_owned_access_token(app, client, oauth_client, cloud_manager, db_session): """ Test ``DELETE /credentials/google``. """ client_id = oauth_client["client_id"] service_account_key = "some_key_321" service_account_id = "123456789" proxy_group_id = "proxy_group_0" path = ("/credentials/google/" + service_account_key) def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id: # Return two keys, first one is NOT the one we're # requesting to delete return [{ "name": "project/service_accounts/keys/over_9000" }, { "name": "project/service_accounts/keys/" + service_account_key }] else: return [] (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info.side_effect) = get_account_keys with app.test_client() as app_client: # set global client context flask.g.client_id = client_id # get test user info user = (db_session.query(User).filter_by(username="******").first()) user_id = user.id # create a proxy group for user proxy_group = GoogleProxyGroup( id=proxy_group_id, user_id=user_id, ) db_session.add(proxy_group) # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com")) db_session.add(user) db_session.add(service_account) db_session.commit() response = app_client.delete(path, data={}) # check that the service account id was included in a call to # cloud_manager assert any([ str(mock_call) for mock_call in cloud_manager.mock_calls if service_account_id in str(mock_call) ]) assert response.status_code == 204 # check that we actually requested to delete the correct service key (cloud_manager.return_value.__enter__.return_value. delete_service_account_key).assert_called_with( service_account_id, service_account_key)
def test_google_delete_all_owned_access_tokens( app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt, query_arg, valid_arg, ): """ Test ``DELETE /credentials/google/*``. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_key0 = "over_9000" service_account_key1 = "42" service_account_key2 = "one_MILLION_dollars" service_account_id = "123456789" service_account_email = client_id + "-" + str(user_id) + "@test.com" path = "/credentials/google/" + query_arg def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id or args[0] == service_account_email: # Return multiple keys return [ { "name": "project/service_accounts/keys/" + service_account_key0 }, { "name": "project/service_accounts/keys/" + service_account_key1 }, { "name": "project/service_accounts/keys/" + service_account_key2 }, ] else: return [] (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info.side_effect) = get_account_keys # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=service_account_email, google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() response = client.delete( path, data={}, headers={"Authorization": "Bearer " + encoded_credentials_jwt}) if valid_arg: # check that the service account id was included in a call to # cloud_manager assert any([ str(mock_call) for mock_call in cloud_manager.mock_calls if service_account_id in str(mock_call) or service_account_email in str(mock_call) ]) assert response.status_code == 204 valid_calls = [ (service_account_id, service_account_key0), (service_account_id, service_account_key1), (service_account_id, service_account_key2), (service_account_email, service_account_key0), (service_account_email, service_account_key1), (service_account_email, service_account_key2), ] actual_calls = [] # check that we actually requested to delete the correct service key for (call) in (cloud_manager.return_value.__enter__.return_value. delete_service_account_key.call_args_list): args, kwargs = call actual_calls.append(args) assert set(actual_calls).issubset(valid_calls) else: # check that the service account id was NOT included in a call to # cloud_manager assert not any([ str(mock_call) for mock_call in cloud_manager.mock_calls if service_account_id in str(mock_call) or service_account_email in str(mock_call) ]) assert response.status_code != 204
def test_google_delete_owned_access_token(app, client, oauth_client, cloud_manager, db_session, encoded_creds_jwt): """ Test ``DELETE /credentials/google``. """ encoded_credentials_jwt = encoded_creds_jwt["jwt"] user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_key = "some_key_321" service_account_id = "123456789" service_account_email = client_id + "-" + str(user_id) + "@test.com" path = "/credentials/google/" + service_account_key def get_account_keys(*args, **kwargs): # Return the keys only if the correct account is given if args[0] == service_account_id or args[0] == service_account_email: # Return two keys, first one is NOT the one we're # requesting to delete return [ { "name": "project/service_accounts/keys/over_9000" }, { "name": "project/service_accounts/keys/" + service_account_key }, ] else: return [] (cloud_manager.return_value.__enter__.return_value. get_service_account_keys_info.side_effect) = get_account_keys # create a service account for client for user service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=service_account_email, google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() response = client.delete( path, data={}, headers={"Authorization": "Bearer " + encoded_credentials_jwt}) # check that the service account id was included in a call to # cloud_manager assert any([ str(mock_call) for mock_call in cloud_manager.mock_calls if service_account_id in str(mock_call) or service_account_email in str(mock_call) ]) assert response.status_code == 204 # check that we actually requested to delete the correct service key args, kwargs = (cloud_manager.return_value.__enter__.return_value. delete_service_account_key).call_args all_args = [arg for arg in args] + [value for key, value in kwargs.items()] assert service_account_id in all_args or service_account_email in all_args assert service_account_key in all_args
def test_google_bucket_access_existing_proxy_group( app, google_storage_client_mocker, client, cloud_manager, db_session, encoded_creds_jwt, monkeypatch, ): monkeypatch.setitem(config, "MOCK_AUTH", False) user_id = encoded_creds_jwt["user_id"] client_id = encoded_creds_jwt["client_id"] service_account_id = "123456789" path = "/credentials/google/" proj = Project(id=129, name="test_proj") ap = AccessPrivilege(user_id=user_id, project_id=proj.id, privilege=["write-storage"]) cloud = CloudProvider(id=129, name="google") bucket = Bucket(id=129, provider_id=cloud.id) gbag = GoogleBucketAccessGroup(id=129, bucket_id=bucket.id, email="*****@*****.**", privileges=["write"]) ptob = ProjectToBucket(id=129, project_id=proj.id, bucket_id=bucket.id) sa = StorageAccess(project_id=proj.id, provider_id=cloud.id) service_account = GoogleServiceAccount( google_unique_id=service_account_id, client_id=client_id, user_id=user_id, email=(client_id + "-" + str(user_id) + "@test.com"), google_project_id="projectId-0", ) db_session.add(service_account) db_session.commit() db_session.add(proj) db_session.add(ap) db_session.add(cloud) db_session.add(bucket) db_session.add(gbag) db_session.add(ptob) db_session.add(sa) db_session.add(service_account) db_session.commit() # make function return the service account we created and don't try to update db # since we already did it in the test mock = MagicMock() mock.return_value = service_account patch("fence.resources.google.utils.get_or_create_service_account", mock).start() patch("fence.resources.google.utils._update_service_account_db_entry", mock).start() encoded_credentials_jwt = encoded_creds_jwt["jwt"] path = "/credentials/google/" data = {} response = client.post( path, data=data, headers={"Authorization": "Bearer " + encoded_credentials_jwt}) assert google_storage_client_mocker.add_bucket_acl.called is False assert response.status_code == 200
def _update_service_account_db_entry( client_id, user_id, proxy_group_id, new_service_account ): """ Now that SA exists in Google so lets check our db and update/add as necessary """ # if we're now using a prefix for SAs, cleanup the db if config["GOOGLE_SERVICE_ACCOUNT_PREFIX"]: # - if using the old naming convention without a prefix, # remove that SA from the db b/c we'll be using the new one from now on # - construct old email using account id provided and # domain from new email to find the db entry old_service_account_id = get_valid_service_account_id_for_client( client_id, user_id ) old_sa_email = "@".join( (old_service_account_id, new_service_account["email"].split("@")[-1]) ) # clear out old SA and keys if there is one old_service_account_db_entry = ( current_session.query(GoogleServiceAccount) .filter(GoogleServiceAccount.email == old_sa_email) .first() ) if old_service_account_db_entry: logger.info( "Found Google Service Account using old naming convention without a prefix: " "{}. Removing from db. Keys should still have access in Google until " "cronjob removes them (e.g. fence-create google-manage-keys). NOTE: " "the SA will still exist in Google but fence will use new SA {} for " "new keys.".format(old_sa_email, new_service_account["email"]) ) old_service_account_keys_db_entries = ( current_session.query(GoogleServiceAccountKey) .filter( GoogleServiceAccountKey.service_account_id == old_service_account_db_entry.id ) .all() ) # remove the keys then the sa itself from db for old_key in old_service_account_keys_db_entries: current_session.delete(old_key) current_session.commit() current_session.delete(old_service_account_db_entry) service_account_db_entry = ( current_session.query(GoogleServiceAccount) .filter(GoogleServiceAccount.email == new_service_account["email"]) .first() ) if not service_account_db_entry: service_account_db_entry = GoogleServiceAccount( google_unique_id=new_service_account["uniqueId"], client_id=client_id, user_id=user_id, email=new_service_account["email"], google_project_id=new_service_account["projectId"], ) current_session.add(service_account_db_entry) else: service_account_db_entry.google_unique_id = new_service_account["uniqueId"] service_account_db_entry.email = new_service_account["email"] service_account_db_entry.google_project_id = (new_service_account["projectId"],) current_session.commit() logger.info( "Created service account {} for proxy group {}.".format( new_service_account["email"], proxy_group_id ) ) return service_account_db_entry