def _get_expected_rules(self, networks, firewall_policy):
        """Builds a FirewallRules object with the rules that should be defined.

        Args:
            networks (list): A list of networks on the project that the
                policy applies to.
            firewall_policy (list): A list of firewall rules that should be
                configured on the project networks.

        Returns:
            fe.FirewallRules: A new FirewallRules object with the expected
                policy.

        Raises:
            EnforcementError: Raised if one or more firewall rules in the policy
                are invalid.
        """
        expected_rules = fe.FirewallRules(self.project_id)
        try:
            for network_name in networks:
                expected_rules.add_rules(
                    firewall_policy, network_name=network_name)
        except fe.InvalidFirewallRuleError as e:
            raise EnforcementError(STATUS_ERROR, 'error adding the expected '
                                   'firewall rules from the policy: %s' % e)
        return expected_rules
Exemplo n.º 2
0
    def _get_current_fw_rules(self, add_rule_callback=None):
        """Create a new FirewallRules object with the current rules.

        Args:
            add_rule_callback (Callable): A callback function that checks
                whether a firewall rule should be applied. If the callback
                returns False, that rule will not be modified.

        Returns:
            fe.FirewallRules: A new FirewallRules object with the current rules
                added to it.

        Raises:
            ProjectDeletedError: Raised if the project has been deleted.
            ComputeApiDisabledError: Raised if the Compute API is not enabled on
                the project.
            EnforcementError: Raised if there are any exceptions raised while
                adding the firewall rules.
        """
        current_rules = fe.FirewallRules(self.project_id,
                                         add_rule_callback=add_rule_callback)
        try:
            current_rules.add_rules_from_api(self.compute_client)
        except api_errors.ApiNotEnabledError as e:
            LOGGER.error('Error getting firewall rules for project %s: %s',
                         self.project_id, e)
            raise ComputeApiDisabledError(e)
        except api_errors.ApiExecutionError as e:
            http_error = e.http_error
            if _is_project_deleted_error(http_error):
                LOGGER.warning('Project %s has been deleted.', self.project_id)
                raise ProjectDeletedError(str(http_error))

            raise EnforcementError(
                STATUS_ERROR,
                'error getting current firewall rules from API: %s' %
                http_error)
        except (fe.DuplicateFirewallRuleNameError,
                fe.InvalidFirewallRuleError) as e:
            raise EnforcementError(
                STATUS_ERROR, 'error getting current firewall '
                'rules from API: %s' % e)
        return current_rules
Exemplo n.º 3
0
    def enforce_firewall_policy(self,
                                firewall_policy,
                                current_rules=None,
                                networks=None,
                                allow_empty_ruleset=False,
                                prechange_callback=None,
                                add_rule_callback=None,
                                retry_on_dry_run=False,
                                maximum_retries=MAX_ENFORCEMENT_RETRIES):
        """Enforces the firewall policy on the project.

        Args:
            firewall_policy (list): A list of firewall rules that should be
                configured on the project networks.
            current_rules (str): A JSON str of firewall rules that specify
                current firewall policies.
            networks (list): A list of networks on the project that the
                policy applies to. If undefined, then the policy will be applied
                to all networks.
            allow_empty_ruleset (bool): If set to true and firewall_policy has
                no rules, all current firewall rules will be deleted from the
                project.
            prechange_callback (Callable): See FirewallEnforcer.apply_firewall()
                docstring for more details.
            add_rule_callback (Callable): A callback function that checks
                whether a firewall rule should be applied. If the callback
                returns False, that rule will not be modified.
            retry_on_dry_run (bool): Set to True to retry applying firewall
                rules when the expected policy does not match the current policy
                when dry_run is enabled.
            maximum_retries (int): The number of times enforce_firewall_policy
                will attempt to set the current firewall policy to the expected
                firewall policy. Set to 0 to disable retry behavior.

        Returns:
            enforcer_log_pb2.ProjectResult: A proto with details on the status
            of the enforcement and an audit log with any changes made.
        """
        try:
            if networks:
                networks = sorted(networks)
            else:
                networks = self._get_project_networks()
                if not networks:
                    self._set_error_status('no networks found for project')
                    return self.result

            expected_rules = self._get_expected_rules(networks,
                                                      firewall_policy)
            if not current_rules:
                rules_before_enforcement = self._get_current_fw_rules(
                    add_rule_callback)
            else:
                rules_before_enforcement = fe.FirewallRules(self.project_id)
                rules_before_enforcement.add_rules_from_json(current_rules)

        except EnforcementError as e:
            self._set_error_status(e.reason())
        except (ComputeApiDisabledError, ProjectDeletedError) as e:
            self._set_deleted_status(e)

        else:

            firewall_enforcer = self._initialize_firewall_enforcer(
                expected_rules, rules_before_enforcement, add_rule_callback)

            rules_after_enforcement = self._apply_firewall_policy(
                firewall_enforcer, expected_rules, networks,
                allow_empty_ruleset, prechange_callback, add_rule_callback,
                retry_on_dry_run, maximum_retries)

            if self.result.status == STATUS_UNSPECIFIED:
                self.result.status = STATUS_SUCCESS

            self._update_fw_results(firewall_enforcer,
                                    rules_before_enforcement,
                                    rules_after_enforcement)

        if not self.result.gce_firewall_enforcement.rules_modified_count:
            LOGGER.info('Firewall policy not changed for %s', self.project_id)

        return self.result