示例#1
0
def test_service_account_has_role_in_service_policy(cloud_manager):
    """
    Test service account has roles in its policy
    """
    faked_json = {
        "bindings": [
            {
                "role":
                "roles/owner",
                "members": [
                    "user:[email protected]",
                    "group:[email protected]",
                    "domain:google.com",
                    "serviceAccount:[email protected]",
                ],
            },
            {
                "role": "roles/viewer",
                "members": ["user:[email protected]"]
            },
        ]
    }

    (cloud_manager.get_service_account_policy.return_value) = MockResponse(
        faked_json, 200)

    assert service_account_has_external_access("test_service_account",
                                               cloud_manager)
示例#2
0
    def check_validity(self,
                       early_return=True,
                       check_type_and_access=True,
                       config=None):
        google_managed_sa_domains = (
            config["GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS"]
            if config else None)

        is_owned_by_google_project = is_service_account_from_google_project(
            self.account_id,
            self.google_project_id,
            self.google_project_number,
            google_managed_sa_domains=google_managed_sa_domains,
        )
        self.set("owned_by_project", is_owned_by_google_project)
        if not is_owned_by_google_project:
            # we cannot determine further information if the account isn't
            # owned by the project
            return

        if check_type_and_access:
            valid_type = is_valid_service_account_type(self.google_project_id,
                                                       self.account_id)

            self.set("valid_type", valid_type)
            if not valid_type and early_return:
                return

            no_external_access = not (service_account_has_external_access(
                self.account_id, self.google_project_id))
            self.set("no_external_access", no_external_access)
            if not no_external_access and early_return:
                return
def test_service_account_has_external_access_no_authorization(cloud_manager):
    """
    In the case that a exception is raised when there is no access to the service account policy
    """
    (cloud_manager.get_service_account_policy.return_value) = MockResponse({}, 403)

    assert service_account_has_external_access("test_service_account", cloud_manager)
示例#4
0
def test_service_account_has_external_access_raise_exception(cloud_manager):
    """
    In the case that a exception is raised when there is no access to the service account policy
    """
    (cloud_manager.get_service_account_policy.return_value
     ) = Exception("exception")

    with pytest.raises(Exception):
        assert service_account_has_external_access("test_service_account",
                                                   cloud_manager)
示例#5
0
def test_service_account_does_not_have_external_access(cloud_manager):
    """
    Test that service account does not have any role or user managed key in its policy
    """
    faked_json = {"etag": "ACAB"}

    (cloud_manager.get_service_account_policy.return_value) = MockResponse(
        faked_json, 200)

    (cloud_manager.get_service_account_keys_info.return_value) = []
    assert not service_account_has_external_access("test_service_account",
                                                   cloud_manager)
def test_service_account_has_user_managed_key_in_service_policy(cloud_manager):
    """
    Test that service account has user managed keys in its policy
    """
    faked_json = {"etag": "ACAB"}

    (cloud_manager.get_service_account_policy.return_value) = MockResponse(
        faked_json, 200
    )

    (cloud_manager.get_service_account_keys_info.return_value) = ["key1", "key2"]

    assert service_account_has_external_access("test_service_account", cloud_manager)
示例#7
0
    def check_validity(
        self,
        early_return=True,
        check_type=True,
        check_external_access=True,
        check_policy_accessible=True,
    ):
        logger.debug(
            "Validating Google Service Account {} for Google Project {}.".format(
                self.account_id, self.google_project_id
            )
        )

        self.google_cloud_manager.open()

        # check ownership
        logger.debug(
            "Determining if {} is owned by the Google Project.".format(self.account_id)
        )

        is_owned_by_google_project = is_service_account_from_google_project(
            self.account_id, self.google_project_id, self.google_project_number
        )
        self.set("owned_by_project", is_owned_by_google_project)
        if not is_owned_by_google_project:
            logger.warning(
                "INVALID SA {}, it is NOT owned by the Google Project {}.".format(
                    self.account_id, self.google_project_id
                )
            )
            if early_return:
                self.google_cloud_manager.close()
                return

        # select the GCM to use for the remainder of the checks
        # if the account is not owned by the google project then
        # it is invalid, however, if Fence has access to the SA's
        # project, we can still check the other conditions

        if is_owned_by_google_project:
            gcm = self.google_cloud_manager
        else:
            self.google_cloud_manager.close()
            try:
                # check to see if we can access the project the SA belongs to
                project_id = self.account_id.split("@")[-1].split(".")[0]
                gcm = GoogleCloudManager(project_id)
                gcm.open()
            except Exception:
                logger.debug(
                    "Could not access the Google Project for Service "
                    "Account {}. Unable to continue validity "
                    "checkingwithout access to the project, "
                    "early exit.".format(self.account_id)
                )
                return

        # check if the SA's policy is accessible
        policy_accessible = None
        sa_policy = None
        if check_policy_accessible:
            try:
                policy_accessible = True
                sa_policy = get_service_account_policy(self.account_id, gcm)
            except Exception:
                policy_accessible = False
                gcm.close()
                return
            finally:
                self.set("policy_accessible", policy_accessible)

        if check_external_access:

            if not policy_accessible:
                logger.warning(
                    "Invalid function use. External Access check requires "
                    "Service Account Policy & may fail if policy is not "
                    "accessible. If you want to check external access, make "
                    "sure you are also checking policy_accessible. "
                )
                gcm.close()
                return

            no_external_access = not (
                service_account_has_external_access(self.account_id, gcm, sa_policy)
            )
            self.set("no_external_access", no_external_access)
            if not no_external_access:
                logger.warning(
                    "INVALID SA {}, it has external access "
                    "(keys generated or roles on it).".format(self.account_id)
                )
                if early_return:
                    gcm.close()
                    return

        # check if the SA is an allowed type
        if check_type:

            if not policy_accessible:
                logger.warning(
                    "Policy access was not checked. If the service account's "
                    "policy is not accessible or the service account does not "
                    "exist, this check may fail."
                )
                # don't return early, we can still check type without checking
                # policy, however, if the SA doesn't exist, this will fail

            valid_type = is_valid_service_account_type(self.account_id, gcm)

            self.set("valid_type", valid_type)
            if not valid_type:
                logger.warning(
                    "INVALID SA {}, it is not a valid SA type.".format(self.account_id)
                )
                if early_return:
                    gcm.close()
                    return

        gcm.close()