Ejemplo n.º 1
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()
Ejemplo n.º 2
0
def test_service_account_does_not_exist(cloud_manager):
    (cloud_manager.get_service_account_policy.return_value) = MockResponse({},
                                                                           404)

    with pytest.raises(NotFound):
        get_service_account_policy("test", cloud_manager)