Beispiel #1
0
def validate(options):
    load_resources()
    if len(options.configs) < 1:
        log.error('no config files specified')
        sys.exit(1)

    used_policy_names = set()
    schm = schema.generate()
    errors = []
    for config_file in options.configs:
        config_file = os.path.expanduser(config_file)
        if not os.path.exists(config_file):
            raise ValueError("Invalid path for config %r" % config_file)

        options.dryrun = True
        fmt = config_file.rsplit('.', 1)[-1]
        with open(config_file) as fh:
            if fmt in ('yml', 'yaml'):
                data = yaml.safe_load(fh.read())
            elif fmt in ('json', ):
                data = json.load(fh)
            else:
                log.error("The config file must end in .json, .yml or .yaml.")
                raise ValueError(
                    "The config file must end in .json, .yml or .yaml.")

        errors += schema.validate(data, schm)
        conf_policy_names = {
            p.get('name', 'unknown')
            for p in data.get('policies', ())
        }
        dupes = conf_policy_names.intersection(used_policy_names)
        if len(dupes) >= 1:
            errors.append(
                ValueError(
                    "Only one policy with a given name allowed, duplicates: %s"
                    % (", ".join(dupes))))
        used_policy_names = used_policy_names.union(conf_policy_names)
        if not errors:
            null_config = Bag(dryrun=True,
                              log_group=None,
                              cache=None,
                              assume_role="na")
            for p in data.get('policies', ()):
                try:
                    policy = Policy(p, null_config, Bag())
                    policy.validate()
                except Exception as e:
                    msg = "Policy: %s is invalid: %s" % (p.get(
                        'name', 'unknown'), e)
                    errors.append(msg)
        if not errors:
            log.info("Configuration valid: {}".format(config_file))
            continue

        log.error("Configuration invalid: {}".format(config_file))
        for e in errors:
            log.error("%s" % e)
    if errors:
        sys.exit(1)
Beispiel #2
0
class Missing(Filter):
    """Assert the absence of a particular resource.

    Intended for use at a logical account/subscription/project level

    This works as an effectively an embedded policy thats evaluated.
    """
    schema = type_schema('missing',
                         policy={'type': 'object'},
                         required=['policy'])

    def __init__(self, data, manager):
        super(Missing, self).__init__(data, manager)
        self.data['policy']['name'] = self.manager.ctx.policy.name
        self.embedded_policy = Policy(self.data['policy'], self.manager.config,
                                      self.manager.session_factory)

    def validate(self):
        if 'mode' in self.data['policy']:
            raise PolicyValidationError("Execution mode can't be specified in "
                                        "embedded policy %s" % self.data)
        if 'actions' in self.data['policy']:
            raise PolicyValidationError("Actions can't be specified in "
                                        "embedded policy %s" % self.data)

        self.embedded_policy.validate()
        return self

    def get_permissions(self):
        return self.embedded_policy.get_permissions()

    def process(self, resources, event=None):

        provider = clouds[self.manager.ctx.policy.provider_name]()

        # if the embedded policy only specifies one region, or only
        # being executed on a single region.
        if self.embedded_policy.region or len(
                self.manager.config.regions) <= 1:
            if (self.embedded_policy.region and
                    self.embedded_policy.region != self.manager.config.region):
                return []
            self.embedded_policy.expand_variables(
                self.embedded_policy.get_variables())
            return not self.embedded_policy.poll() and resources or []

        # For regional resources and multi-region execution, the policy matches if
        # the resource is missing in any region.
        found = {}
        for p in provider.initialize_policies(
                PolicyCollection([self.embedded_policy], self.manager.config),
                self.manager.config):
            p.expand_variables(p.get_variables())
            p.validate()
            found[p.options.region] = p.poll()
        if not all(found.values()):
            return resources
        return []
Beispiel #3
0
class Missing(Filter):
    """Assert the absence of a particular resource.

    Intended for use at a logical account/subscription/project level

    This works as an effectively an embedded policy thats evaluated.
    """
    schema = type_schema(
        'missing', policy={'type': 'object'},
        required=['policy'])

    def __init__(self, data, manager):
        super(Missing, self).__init__(data, manager)
        self.data['policy']['name'] = self.manager.ctx.policy.name
        self.embedded_policy = Policy(
            self.data['policy'], self.manager.config, self.manager.session_factory)

    def validate(self):
        if 'mode' in self.data['policy']:
            raise PolicyValidationError(
                "Execution mode can't be specified in "
                "embedded policy %s" % self.data)
        if 'actions' in self.data['policy']:
            raise PolicyValidationError(
                "Actions can't be specified in "
                "embedded policy %s" % self.data)

        self.embedded_policy.validate()
        return self

    def get_permissions(self):
        return self.embedded_policy.get_permissions()

    def process(self, resources, event=None):

        provider = clouds[self.manager.ctx.policy.provider_name]()

        # if the embedded policy only specifies one region, or only
        # being executed on a single region.
        if self.embedded_policy.region or len(self.manager.config.regions) <= 1:
            if (self.embedded_policy.region and
                    self.embedded_policy.region != self.manager.config.region):
                return []
            self.embedded_policy.expand_variables(self.embedded_policy.get_variables())
            return not self.embedded_policy.poll() and resources or []

        # For regional resources and multi-region execution, the policy matches if
        # the resource is missing in any region.
        found = {}
        for p in provider.initialize_policies(
                PolicyCollection([self.embedded_policy], self.manager.config),
                self.manager.config):
            p.expand_variables(p.get_variables())
            p.validate()
            found[p.options.region] = p.poll()
        if not all(found.values()):
            return resources
        return []
def validate(options):
    load_resources()
    if len(options.configs) < 1:
        log.error('no config files specified')
        sys.exit(1)

    used_policy_names = set()
    schm = schema.generate()
    errors = []

    for config_file in options.configs:
        config_file = os.path.expanduser(config_file)
        if not os.path.exists(config_file):
            raise ValueError("Invalid path for config %r" % config_file)

        options.dryrun = True
        fmt = config_file.rsplit('.', 1)[-1]
        with open(config_file) as fh:
            if fmt in ('yml', 'yaml'):
                data = yaml.safe_load(fh.read())
            elif fmt in ('json',):
                data = json.load(fh)
            else:
                log.error("The config file must end in .json, .yml or .yaml.")
                raise ValueError("The config file must end in .json, .yml or .yaml.")

        errors += schema.validate(data, schm)
        conf_policy_names = {
            p.get('name', 'unknown') for p in data.get('policies', ())}
        dupes = conf_policy_names.intersection(used_policy_names)
        if len(dupes) >= 1:
            errors.append(ValueError(
                "Only one policy with a given name allowed, duplicates: %s" % (
                    ", ".join(dupes)
                )
            ))
        used_policy_names = used_policy_names.union(conf_policy_names)
        if not errors:
            null_config = Config.empty(dryrun=True, account_id='na', region='na')
            for p in data.get('policies', ()):
                try:
                    policy = Policy(p, null_config, Bag())
                    policy.validate()
                except Exception as e:
                    msg = "Policy: %s is invalid: %s" % (
                        p.get('name', 'unknown'), e)
                    errors.append(msg)
        if not errors:
            log.info("Configuration valid: {}".format(config_file))
            continue

        log.error("Configuration invalid: {}".format(config_file))
        for e in errors:
            log.error("%s" % e)
    if errors:
        sys.exit(1)
Beispiel #5
0
def validate(options):
    from c7n import schema

    if len(options.configs) < 1:
        log.error('no config files specified')
        sys.exit(1)

    used_policy_names = set()
    structure = StructureParser()
    errors = []

    for config_file in options.configs:

        config_file = os.path.expanduser(config_file)
        if not os.path.exists(config_file):
            raise ValueError("Invalid path for config %r" % config_file)

        options.dryrun = True
        fmt = config_file.rsplit('.', 1)[-1]

        with open(config_file) as fh:
            if fmt in ('yml', 'yaml', 'json'):
                data = yaml.load(fh.read(), Loader=DuplicateKeyCheckLoader)
            else:
                log.error("The config file must end in .json, .yml or .yaml.")
                raise ValueError("The config file must end in .json, .yml or .yaml.")

        try:
            structure.validate(data)
        except PolicyValidationError as e:
            log.error("Configuration invalid: {}".format(config_file))
            log.error("%s" % e)
            errors.append(e)
            continue

        load_resources(structure.get_resource_types(data))
        schm = schema.generate()
        errors += schema.validate(data, schm)
        conf_policy_names = {
            p.get('name', 'unknown') for p in data.get('policies', ())}
        dupes = conf_policy_names.intersection(used_policy_names)
        if len(dupes) >= 1:
            errors.append(ValueError(
                "Only one policy with a given name allowed, duplicates: %s" % (
                    ", ".join(dupes)
                )
            ))
        used_policy_names = used_policy_names.union(conf_policy_names)
        if not errors:
            null_config = Config.empty(dryrun=True, account_id='na', region='na')
            for p in data.get('policies', ()):
                try:
                    policy = Policy(p, null_config, Bag())
                    policy.validate()
                except Exception as e:
                    msg = "Policy: %s is invalid: %s" % (
                        p.get('name', 'unknown'), e)
                    errors.append(msg)
        if not errors:
            log.info("Configuration valid: {}".format(config_file))
            continue

        log.error("Configuration invalid: {}".format(config_file))
        for e in errors:
            log.error("%s" % e)
    if errors:
        sys.exit(1)
Beispiel #6
0
def validate(options):
    from c7n import schema

    if len(options.configs) < 1:
        log.error('no config files specified')
        sys.exit(1)

    used_policy_names = set()
    structure = StructureParser()
    errors = []
    found_deprecations = False
    footnotes = deprecated.Footnotes()

    for config_file in options.configs:

        config_file = os.path.expanduser(config_file)
        if not os.path.exists(config_file):
            raise ValueError("Invalid path for config %r" % config_file)

        options.dryrun = True
        fmt = config_file.rsplit('.', 1)[-1]

        with open(config_file) as fh:
            if fmt in ('yml', 'yaml', 'json'):
                # our loader is safe loader derived.
                data = yaml.load(
                    fh.read(),
                    Loader=DuplicateKeyCheckLoader)  # nosec nosemgrep
            else:
                log.error("The config file must end in .json, .yml or .yaml.")
                raise ValueError(
                    "The config file must end in .json, .yml or .yaml.")

        try:
            structure.validate(data)
        except PolicyValidationError as e:
            log.error("Configuration invalid: {}".format(config_file))
            log.error("%s" % e)
            errors.append(e)
            continue

        load_resources(structure.get_resource_types(data))
        schm = schema.generate()
        errors += schema.validate(data, schm)
        conf_policy_names = {
            p.get('name', 'unknown')
            for p in data.get('policies', ())
        }
        dupes = conf_policy_names.intersection(used_policy_names)
        if len(dupes) >= 1:
            errors.append(
                ValueError(
                    "Only one policy with a given name allowed, duplicates: %s"
                    % (", ".join(dupes))))
        used_policy_names = used_policy_names.union(conf_policy_names)
        source_locator = None
        if fmt in ('yml', 'yaml'):
            # For yaml files there is at least the expectation that the policy
            # name is on a line by itself. With JSON, the file could be one big
            # line. At this stage we are only attempting to find line number for
            # policies in yaml files.
            source_locator = SourceLocator(config_file)
        if not errors:
            null_config = Config.empty(dryrun=True,
                                       account_id='na',
                                       region='na')
            for p in data.get('policies', ()):
                try:
                    policy = Policy(p, null_config, Bag())
                    policy.validate()
                    # If the policy is invalid, there isn't much point checking
                    # for deprecated usage as there is no guarantee as to the
                    # state of the policy.
                    if options.check_deprecations != deprecated.SKIP:
                        report = deprecated.report(policy)
                        if report:
                            found_deprecations = True
                            log.warning(
                                "deprecated usage found in policy\n" +
                                report.format(source_locator=source_locator,
                                              footnotes=footnotes))

                except Exception as e:
                    msg = "Policy: %s is invalid: %s" % (p.get(
                        'name', 'unknown'), e)
                    errors.append(msg)
        if not errors:
            log.info("Configuration valid: {}".format(config_file))
            continue

        log.error("Configuration invalid: {}".format(config_file))
        for e in errors:
            log.error("%s" % e)
    if found_deprecations:
        notes = footnotes()
        if notes:
            log.warning("deprecation footnotes:\n" + notes)
        if options.check_deprecations == deprecated.STRICT:
            sys.exit(1)
    if errors:
        sys.exit(1)