예제 #1
0
    def __init__(
        self,
        account_id,
        google_project_id,
        google_cloud_manager=None,
        google_project_number=None,
        *args,
        **kwargs
    ):
        self.account_id = account_id
        self.google_project_id = google_project_id

        # default to the given project id if not provided
        self.google_project_number = google_project_number or google_project_id
        self.google_cloud_manager = google_cloud_manager or GoogleCloudManager(
            google_project_id
        )
        super(GoogleServiceAccountValidity, self).__init__(*args, **kwargs)

        # setup default values for error information, will get updated in
        # check_validity
        self._info["owned_by_project"] = None
        self._info["valid_type"] = None
        self._info["no_external_access"] = None
        self._info["policy_accessible"] = None
예제 #2
0
    def __init__(
        self,
        google_project_id,
        new_service_account=None,
        new_service_account_access=None,
        user_id=None,
        google_cloud_manager=None,
        *args,
        **kwargs
    ):
        """
        Initialize

        Args:
            google_project_id (str): Google project identifier
            new_service_account (str, optional): an additional service account
                identifier (ex: email) to include when checking access. You can
                provide this without actually giving it access to check if
                access will be valid
            new_service_account_access (List(str), optional): List of
                Project.auth_ids to attempt to provide the new service account
                access to
            user_id (None, optional): User requesting validation. ONLY pass this if you
                want to check if the user is a member of this project.
        """
        self.google_project_id = google_project_id
        self.new_service_account = new_service_account
        self.new_service_account_access = new_service_account_access or []
        self.user_id = user_id
        self.google_cloud_manager = google_cloud_manager or GoogleCloudManager(
            google_project_id
        )

        super(GoogleProjectValidity, self).__init__(*args, **kwargs)

        # setup default values for error information, will get updated in
        # check_validity
        self._info["user_has_access"] = None
        self._info["monitor_has_access"] = None
        self._info["valid_parent_org"] = None
        self._info["valid_member_types"] = None
        self._info["members_exist_in_fence"] = None
        self._info["new_service_account"] = {}
        self._info["service_accounts"] = {}
        self._info["access"] = {}
예제 #3
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()