def test_invalid_google_project_membership(valid_google_project_patcher): """ Test that when the Google Project is invalid, the resulting GoogleProjectValidity is False-y and contains the expected information. Here we're testing when the Google Project has invalid membership. """ patcher = valid_google_project_patcher patcher[ "get_google_project_valid_users_and_service_accounts"].side_effect = Exception( ) google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to false since invalid assert not google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert not google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert not google_project_validity["members_exist_in_fence"]
def test_valid_google_project(valid_google_project_patcher): """ Test that when everything is valid, the GoogleProjectValidity is valid and has the expected information. """ google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to true since all checks should result in valid project assert google_project_validity # test that it contains the default error information and it's true assert "valid_parent_org" in google_project_validity assert google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert "access" in google_project_validity
def test_invalid_google_project_no_monitor(valid_google_project_patcher): """ Test that when we can't determine the project number, we determine that the project is invalid. This happens when the monitoring service account does not have access on the project """ patcher = valid_google_project_patcher patcher["get_google_project_number"].return_value = None google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to false since invalid assert not google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert not google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert not google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert not google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert "access" in google_project_validity
def test_invalid_google_project_parent_org(app, valid_google_project_patcher): """ Test that when the Google Project is invalid, the resulting GoogleProjectValidity is False-y and contains the expected information. Here we're testing when the Google Project has a parent org (which is invalid). """ patcher = valid_google_project_patcher patcher["get_google_project_parent_org"].return_value = "some-parent-org" google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to false since invalid assert not google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert not google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert "access" in google_project_validity
def test_valid_google_project_access(valid_google_project_patcher, valid_service_account_patcher, db_session): """ Test that when everything is valid and there are access to data through projects (access is all valid), the GoogleProjectValidity is valid and has the expected information. """ patcher = valid_google_project_patcher project1 = Project(auth_id="some-project-auth-id") project2 = Project(auth_id="some-other-project-auth-id") db_session.add(project1) db_session.add(project2) db_session.commit() patcher["get_project_access_from_service_accounts"].return_value = [ project1, project2, ] google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to true since it's valid assert google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert "access" in google_project_validity assert hasattr(google_project_validity["access"], "__iter__") assert "some-project-auth-id" in (google_project_validity["access"]) assert "some-other-project-auth-id" in (google_project_validity["access"])
def test_invalid_google_project_access(valid_google_project_patcher, db_session): """ Test that when the Google Project is invalid, the resulting GoogleProjectValidity is False-y and contains the expected information. Here we're testing when the Google Project's members have invalid access. """ patcher = valid_google_project_patcher project = Project(auth_id="some-project-auth-id") db_session.add(project) db_session.commit() patcher["get_project_access_from_service_accounts"].return_value = [ project ] patcher["get_users_from_google_members"].return_value = ["test-user"] patcher["do_all_users_have_access_to_project"].return_value = False google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to false since invalid assert not google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert "access" in google_project_validity assert hasattr(google_project_validity["access"], "__iter__") assert "some-project-auth-id" in (google_project_validity["access"]) assert not google_project_validity["access"]["some-project-auth-id"]
def _is_valid_google_project(google_project_id, db=None, config=None): """ Validate the given google project id and remove all registered service accounts under that project if invalid. """ try: project_validity = GoogleProjectValidity(google_project_id) project_validity.check_validity(early_return=True, db=db, config=config) except Exception: # any issues, assume invalid # TODO not sure if this is the right way to handle this... print("Project determined invalid due to unhandled exception:") traceback.print_exc() project_validity = None return project_validity
def _is_valid_google_project(google_project_id, db=None): """ Validate the given google project id and remove all registered service accounts under that project if invalid. """ try: project_validity = GoogleProjectValidity(google_project_id) project_validity.check_validity(early_return=True, db=db) except Exception as exc: # any issues, assume invalid # TODO not sure if this is the right way to handle this... logger.warning( "Project {} determined invalid due to unhandled exception: {}. " "Assuming project is invalid.".format(google_project_id, str(exc))) traceback.print_exc() project_validity = None return project_validity
def test_valid_google_project_service_accounts(app, valid_google_project_patcher, valid_service_account_patcher): """ Test that when everything is valid and there are service accounts (which are also all valid), the GoogleProjectValidity is valid and has the expected information. """ patcher = valid_google_project_patcher patcher["get_service_account_ids_from_google_members"].return_value = [ "some-account-id", "some-other-account-id", ] google_project_validity = GoogleProjectValidity("some-project-id") # should evaluate to true by default before checking validity assert google_project_validity google_project_validity.check_validity(early_return=False) # should evaluate to true since it's valid assert google_project_validity # test that it contains the correct error information assert "valid_parent_org" in google_project_validity assert google_project_validity["valid_parent_org"] assert "valid_member_types" in google_project_validity assert google_project_validity["valid_member_types"] assert "members_exist_in_fence" in google_project_validity assert google_project_validity["members_exist_in_fence"] assert "new_service_account" in google_project_validity assert "service_accounts" in google_project_validity assert hasattr(google_project_validity["service_accounts"], "__iter__") assert "some-account-id" in (google_project_validity["service_accounts"]) assert "some-other-account-id" in ( google_project_validity["service_accounts"]) assert "access" in google_project_validity
def _get_service_account_error_status(sa): """ Get a dictionary describing any errors that will occur if attempting to give service account specified permissions fails. Args: sa ( fence.resources.google.service_account.GoogleServiceAccountRegistration ): the service account object with its email, project_access, a google project, and optionally a user who is attempting to modify/add Returns: dict: error information if unsuccessful, { "success": True } otherwise Example: { "success": False, "errors": { "service_account_email": { "status": 200, "error": None, "error_description": None }, "google_project_id": { "status": 200, "error": None, "error_description": None }, "project_access": { "projectA": { "status": 200, "error": None, "error_description": None }, "projectB": { "status": 403, "error": "unauthorized", "error_description": "Not all users have access requested" } }, "expires_in": { "status": 400, "error": "user_error", "error_description": "expires_in must be a positive integer" } } } """ response = { "success": False, "errors": { "service_account_email": None, "google_project_id": None, "project_access": None, "expires_in": { "status": 200, "error": None, "error_description": None }, }, } try: get_valid_expiration_from_request() except UserError as e: response["errors"]["expires_in"] = { "status": e.code, "error": "user_error", "error_description": e.message, } project_validity = GoogleProjectValidity( google_project_id=sa.google_project_id, new_service_account=sa.email, new_service_account_access=sa.project_access, user_id=sa.user_id, ) project_validity.check_validity(early_return=False) response["errors"][ "google_project_id"] = _get_google_project_id_error_status( project_validity) response["errors"][ "service_account_email"] = _get_service_account_email_error_status( project_validity) response["errors"]["project_access"] = _get_project_access_error_status( project_validity) # if we cannot find the monitoring service account, the other checks statuses should # not be 200 and should be populated with relevant information if (response["errors"]["google_project_id"]["error"] == ValidationErrors.MONITOR_NOT_FOUND): if response["errors"]["service_account_email"].get("status") == 200: response["errors"]["service_account_email"]["status"] = 400 response["errors"]["service_account_email"][ "error"] = ValidationErrors.MONITOR_NOT_FOUND response["errors"]["service_account_email"]["error_description"] = ( "Fence's monitoring service account was not found on the project so we " "were unable to complete the necessary validation checks.") if response["errors"]["project_access"].get("status") == 200: response["errors"]["project_access"]["status"] = 400 response["errors"]["project_access"][ "error"] = ValidationErrors.MONITOR_NOT_FOUND response["errors"]["project_access"]["error_description"] = ( "Fence's monitoring service account was not found on the project so we " "were unable to complete the necessary validation checks.") # all statuses must be 200 to be successful if (response["errors"]["service_account_email"].get("status") == 200 and response["errors"]["google_project_id"].get("status") == 200 and response["errors"]["project_access"].get("status") == 200 and response["errors"]["expires_in"].get("status") == 200): response["success"] = True return response
def _get_service_account_error_status(sa): """ Get a dictionary describing any errors that will occur if attempting to give service account specified permissions fails. Args: sa ( fence.resources.google.service_account.GoogleServiceAccountRegistration ): the service account object with its email, project_access, a google project, and optionally a user who is attempting to modify/add Returns: dict: error information if unsuccessful, { "success": True } otherwise Example: { "success": False, "errors": { "service_account_email": { "status": 200, "error": None, "error_description": None }, "google_project_id": { "status": 200, "error": None, "error_description": None }, "project_access": { "projectA": { "status": 200, "error": None, "error_description": None }, "projectB": { "status": 403, "error": "unauthorized", "error_description": "Not all users have access requested" } } } } """ response = { "success": False, "errors": { "service_account_email": None, "google_project_id": None, "project_access": None, }, } project_validity = GoogleProjectValidity( google_project_id=sa.google_project_id, new_service_account=sa.email, new_service_account_access=sa.project_access, user_id=sa.user_id, ) project_validity.check_validity(early_return=False) response["errors"][ "service_account_email"] = _get_service_account_email_error_status( project_validity) response["errors"][ "google_project_id"] = _get_google_project_id_error_status( project_validity) response["errors"]["project_access"] = _get_project_access_error_status( project_validity) # all statuses must be 200 to be successful if (response["errors"]["service_account_email"].get("status") == 200 and response["errors"]["google_project_id"].get("status") == 200 and response["errors"]["project_access"].get("status") == 200): response["success"] = True return response