Beispiel #1
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_is_valid_service_account_type_user_managed(cloud_manager):
    """
    Test that USER_MANAGED is a valid service account type
    for service account registration
    """
    (cloud_manager.get_service_account_type.return_value) = "iam.gserviceaccount.com"
    assert is_valid_service_account_type(1, cloud_manager)
Beispiel #3
0
def test_not_valid_service_account_type_compute_engine_api(cloud_manager):
    """
    Test that COMPUTE_ENGINE_API is not a valid service account type
    for service account registration
    """
    (cloud_manager.get_service_account_type.return_value
     ) = "compute-system.iam.gserviceaccount.com"
    assert not is_valid_service_account_type(1, cloud_manager)
Beispiel #4
0
def test_not_valid_service_account_type_google_api(cloud_manager):
    """
    Test that GOOGLE_API is not a valid service account type
    for service account registration
    """
    (cloud_manager.get_service_account_type.return_value
     ) = "cloudservices.gserviceaccount.com"
    assert not is_valid_service_account_type(1, cloud_manager)
Beispiel #5
0
def test_is_valid_service_account_type_compute_engine_default(cloud_manager):
    """
    Test that COMPUTE_ENGINE_DEFAULT is a valid service account type
    for service account registration
    """
    (cloud_manager.get_service_account_type.return_value
     ) = "developer.gserviceaccount.com"
    assert is_valid_service_account_type(1, cloud_manager)
Beispiel #6
0
def test_is_valid_service_account_type_user_managed(cloud_manager):
    """
    Test that USER_MANAGED is a valid service account type
    for service account registration
    """
    (cloud_manager.return_value.__enter__.return_value.
     get_service_account_type.return_value) = USER_MANAGED_SERVICE_ACCOUNT
    assert is_valid_service_account_type(cloud_manager.project_id, 1)
Beispiel #7
0
def test_not_valid_service_account_type_compute_engine_api(cloud_manager):
    """
    Test that COMPUTE_ENGINE_API is not a valid service account type
    for service account registration
    """
    (cloud_manager.return_value.__enter__.return_value.get_service_account_type
     .return_value) = COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT
    assert not is_valid_service_account_type(cloud_manager.project_id, 1)
Beispiel #8
0
def test_not_valid_service_account_type_google_api(cloud_manager):
    """
    Test that GOOGLE_API is not a valid service account type
    for service account registration
    """
    (cloud_manager.return_value.__enter__.return_value.
     get_service_account_type.return_value) = GOOGLE_API_SERVICE_ACCOUNT
    assert not is_valid_service_account_type(cloud_manager.project_id, 1)
Beispiel #9
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()