def resource_vocabulary(cloud_name=None, qualify_name=True): vocabulary = {} resources = {} for cname, ctype in clouds.items(): if cloud_name is not None and cloud_name != cname: continue for rname, rtype in ctype.resources.items(): if qualify_name: resources['%s.%s' % (cname, rname)] = rtype else: resources[rname] = rtype for type_name, resource_type in resources.items(): classes = {'actions': {}, 'filters': {}} actions = [] for action_name, cls in resource_type.action_registry.items(): actions.append(action_name) classes['actions'][action_name] = cls filters = [] for filter_name, cls in resource_type.filter_registry.items(): filters.append(filter_name) classes['filters'][filter_name] = cls vocabulary[type_name] = { 'filters': sorted(filters), 'actions': sorted(actions), 'classes': classes, } return vocabulary
def resource_outline(provider=None): outline = {} for cname, ctype in sorted(clouds.items()): if provider and provider != cname: continue cresources = outline[cname] = {} for rname, rtype in sorted(ctype.resources.items()): cresources['%s.%s' % (cname, rname)] = rinfo = {} rinfo['filters'] = sorted(rtype.filter_registry.keys()) rinfo['actions'] = sorted(rtype.action_registry.keys()) return outline
def resource_vocabulary(cloud_name=None, qualify_name=True, aliases=True): vocabulary = {} resources = {} if aliases: vocabulary['aliases'] = {} for cname, ctype in clouds.items(): if cloud_name is not None and cloud_name != cname: continue for rname, rtype in ctype.resources.items(): if qualify_name: resources['%s.%s' % (cname, rname)] = rtype else: resources[rname] = rtype for type_name, resource_type in resources.items(): classes = {'actions': {}, 'filters': {}, 'resource': resource_type} actions = [] for cls in ElementSchema.elements(resource_type.action_registry): action_name = ElementSchema.name(cls) actions.append(action_name) classes['actions'][action_name] = cls filters = [] for cls in ElementSchema.elements(resource_type.filter_registry): filter_name = ElementSchema.name(cls) filters.append(filter_name) classes['filters'][filter_name] = cls vocabulary[type_name] = { 'filters': sorted(filters), 'actions': sorted(actions), 'classes': classes, } if aliases and resource_type.type_aliases: provider = type_name.split('.', 1)[0] for type_alias in resource_type.type_aliases: vocabulary['aliases']["{}.{}".format( provider, type_alias)] = vocabulary[type_name] if provider == 'aws': vocabulary['aliases'][type_alias] = vocabulary[type_name] vocabulary[type_name]['resource_type'] = type_name vocabulary["mode"] = {} for mode_name, cls in execution.items(): vocabulary["mode"][mode_name] = cls return vocabulary
def _visit_filters_and_actions(self, visitor): names = [] for cloud_name, cloud in clouds.items(): for resource_name, resource in cloud.resources.items(): for fname, f in resource.filter_registry.items(): if fname in ('and', 'or', 'not'): continue if visitor(f): names.append("%s.%s.filters.%s" % (cloud_name, resource_name, fname)) for aname, a in resource.action_registry.items(): if visitor(a): names.append('%s.%s.actions.%s' % (cloud_name, resource_name, aname)) return names
def load_resources(resource_types=('*',)): pmap = {} for r in resource_types: parts = r.split('.', 1) pmap.setdefault(parts[0], []).append(r) load_providers(set(pmap)) missing = [] for pname, p in clouds.items(): if '*' in pmap: p.get_resource_types(('*',)) elif pname in pmap: _, not_found = p.get_resource_types(pmap[pname]) missing.extend(not_found) return missing
def resource_vocabulary(cloud_name=None, qualify_name=True): vocabulary = {} resources = {} for cname, ctype in clouds.items(): if cloud_name is not None and cloud_name != cname: continue for rname, rtype in ctype.resources.items(): if qualify_name: resources['%s.%s' % (cname, rname)] = rtype else: resources[rname] = rtype for type_name, resource_type in resources.items(): classes = {'actions': {}, 'filters': {}, 'resource': resource_type} actions = [] for cls in ElementSchema.elements(resource_type.action_registry): action_name = ElementSchema.name(cls) actions.append(action_name) classes['actions'][action_name] = cls filters = [] for cls in ElementSchema.elements(resource_type.filter_registry): filter_name = ElementSchema.name(cls) filters.append(filter_name) classes['filters'][filter_name] = cls vocabulary[type_name] = { 'filters': sorted(filters), 'actions': sorted(actions), 'classes': classes, } vocabulary["mode"] = {} for mode_name, cls in execution.items(): vocabulary["mode"][mode_name] = cls return vocabulary
def generate(resource_types=()): resource_defs = {} definitions = { 'resources': resource_defs, 'iam-statement': { 'additionalProperties': False, 'type': 'object', 'properties': { 'Sid': { 'type': 'string' }, 'Effect': { 'type': 'string', 'enum': ['Allow', 'Deny'] }, 'Principal': { 'anyOf': [{ 'type': 'string' }, { 'type': 'object' }, { 'type': 'array' }] }, 'NotPrincipal': { 'anyOf': [{ 'type': 'object' }, { 'type': 'array' }] }, 'Action': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'NotAction': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'Resource': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'NotResource': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'Condition': { 'type': 'object' } }, 'required': ['Sid', 'Effect'], 'oneOf': [{ 'required': ['Principal', 'Action', 'Resource'] }, { 'required': ['NotPrincipal', 'Action', 'Resource'] }, { 'required': ['Principal', 'NotAction', 'Resource'] }, { 'required': ['NotPrincipal', 'NotAction', 'Resource'] }, { 'required': ['Principal', 'Action', 'NotResource'] }, { 'required': ['NotPrincipal', 'Action', 'NotResource'] }, { 'required': ['Principal', 'NotAction', 'NotResource'] }, { 'required': ['NotPrincipal', 'NotAction', 'NotResource'] }] }, 'actions': {}, 'filters': { 'value': ValueFilter.schema, 'event': EventFilter.schema, 'age': AgeFilter.schema, # Shortcut form of value filter as k=v 'valuekv': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1 }, }, 'policy': { 'type': 'object', 'required': ['name', 'resource'], 'additionalProperties': False, 'properties': { 'name': { 'type': 'string', 'pattern': "^[A-z][A-z0-9]*(-[A-z0-9]+)*$" }, 'region': { 'type': 'string' }, 'tz': { 'type': 'string' }, 'start': { 'format': 'date-time' }, 'end': { 'format': 'date-time' }, 'resource': { 'type': 'string' }, 'max-resources': { 'type': 'integer', 'minimum': 1 }, 'max-resources-percent': { 'type': 'number', 'minimum': 0, 'maximum': 100 }, 'comment': { 'type': 'string' }, 'comments': { 'type': 'string' }, 'description': { 'type': 'string' }, 'tags': { 'type': 'array', 'items': { 'type': 'string' } }, 'mode': { '$ref': '#/definitions/policy-mode' }, 'source': { 'enum': ['describe', 'config'] }, 'actions': { 'type': 'array', }, 'filters': { 'type': 'array' }, # # unclear if this should be allowed, it kills resource # cache coherency between policies, and we need to # generalize server side query mechanisms, currently # this only for ec2 instance queries. limitations # in json schema inheritance prevent us from doing this # on a type specific basis # https://stackoverflow.com/questions/22689900/json-schema-allof-with-additionalproperties 'query': { 'type': 'array', 'items': { 'type': 'object' } } }, }, 'policy-mode': { 'anyOf': [e.schema for _, e in execution.items()], } } resource_refs = [] for cloud_name, cloud_type in clouds.items(): for type_name, resource_type in cloud_type.resources.items(): if resource_types and type_name not in resource_types: continue alias_name = None r_type_name = "%s.%s" % (cloud_name, type_name) if cloud_name == 'aws': alias_name = type_name resource_refs.append( process_resource(r_type_name, resource_type, resource_defs, alias_name, definitions)) schema = { '$schema': 'http://json-schema.org/schema#', 'id': 'http://schema.cloudcustodian.io/v0/custodian.json', 'definitions': definitions, 'type': 'object', 'required': ['policies'], 'additionalProperties': False, 'properties': { 'vars': { 'type': 'object' }, 'policies': { 'type': 'array', 'additionalItems': False, 'items': { 'anyOf': resource_refs } } } } return schema
def generate(resource_types=()): resource_defs = {} definitions = { 'resources': resource_defs, 'iam-statement': { 'additionalProperties': False, 'type': 'object', 'properties': { 'Sid': {'type': 'string'}, 'Effect': {'type': 'string', 'enum': ['Allow', 'Deny']}, 'Principal': {'anyOf': [ {'type': 'string'}, {'type': 'object'}, {'type': 'array'}]}, 'NotPrincipal': {'anyOf': [{'type': 'object'}, {'type': 'array'}]}, 'Action': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'NotAction': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'Resource': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'NotResource': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'Condition': {'type': 'object'} }, 'required': ['Sid', 'Effect'], 'oneOf': [ {'required': ['Principal', 'Action', 'Resource']}, {'required': ['NotPrincipal', 'Action', 'Resource']}, {'required': ['Principal', 'NotAction', 'Resource']}, {'required': ['NotPrincipal', 'NotAction', 'Resource']}, {'required': ['Principal', 'Action', 'NotResource']}, {'required': ['NotPrincipal', 'Action', 'NotResource']}, {'required': ['Principal', 'NotAction', 'NotResource']}, {'required': ['NotPrincipal', 'NotAction', 'NotResource']} ] }, 'actions': {}, 'filters': { 'value': ValueFilter.schema, 'event': EventFilter.schema, 'age': AgeFilter.schema, # Shortcut form of value filter as k=v 'valuekv': { 'type': 'object', 'additionalProperties': {'oneOf': [{'type': 'number'}, {'type': 'null'}, {'type': 'array', 'maxItems': 0}, {'type': 'string'}, {'type': 'boolean'}]}, 'minProperties': 1, 'maxProperties': 1}, }, 'filters_common': { 'comparison_operators': { 'enum': list(OPERATORS.keys())}, 'value_types': {'enum': VALUE_TYPES}, 'value_from': ValuesFrom.schema, 'value': {'oneOf': [ {'type': 'array'}, {'type': 'string'}, {'type': 'boolean'}, {'type': 'number'}, {'type': 'null'}]}, }, 'policy': { 'type': 'object', 'required': ['name', 'resource'], 'additionalProperties': False, 'properties': { 'name': { 'type': 'string', 'pattern': "^[A-z][A-z0-9]*(-[A-z0-9]+)*$"}, 'region': {'type': 'string'}, 'tz': {'type': 'string'}, 'start': {'format': 'date-time'}, 'end': {'format': 'date-time'}, 'resource': {'type': 'string'}, 'max-resources': {'anyOf': [ {'type': 'integer', 'minimum': 1}, {'$ref': '#/definitions/max-resources-properties'} ]}, 'max-resources-percent': {'type': 'number', 'minimum': 0, 'maximum': 100}, 'comment': {'type': 'string'}, 'comments': {'type': 'string'}, 'description': {'type': 'string'}, 'tags': {'type': 'array', 'items': {'type': 'string'}}, 'mode': {'$ref': '#/definitions/policy-mode'}, 'source': {'enum': ['describe', 'config', 'resource-graph']}, 'actions': { 'type': 'array', }, 'filters': { 'type': 'array' }, # # TODO: source queries should really move under # source. This was initially used for describe sources # to expose server side query mechanisms, however its # important to note it also prevents resource cache # utilization between policies that have different # queries. 'query': { 'type': 'array', 'items': {'type': 'object'}} }, }, 'policy-mode': { 'anyOf': [e.schema for _, e in execution.items()], }, 'max-resources-properties': { 'type': 'object', 'additionalProperties': False, 'properties': { 'amount': {"type": 'integer', 'minimum': 1}, 'op': {'enum': ['or', 'and']}, 'percent': {'type': 'number', 'minimum': 0, 'maximum': 100} } } } resource_refs = [] for cloud_name, cloud_type in clouds.items(): for type_name, resource_type in cloud_type.resources.items(): r_type_name = "%s.%s" % (cloud_name, type_name) if resource_types and r_type_name not in resource_types: if not resource_type.type_aliases: continue # atm only azure is using type aliases. elif not set([ "%s.%s" % (cloud_name, ralias) for ralias in resource_type.type_aliases]).intersection( resource_types): continue aliases = [] if resource_type.type_aliases: aliases.extend(["%s.%s" % (cloud_name, a) for a in resource_type.type_aliases]) # aws gets legacy aliases with no cloud prefix if cloud_name == 'aws': aliases.extend(resource_type.type_aliases) # aws gets additional alias for default name if cloud_name == 'aws': aliases.append(type_name) resource_refs.append( process_resource( r_type_name, resource_type, resource_defs, aliases, definitions, cloud_name )) schema = { "$schema": "http://json-schema.org/draft-07/schema#", 'id': 'http://schema.cloudcustodian.io/v0/custodian.json', 'definitions': definitions, 'type': 'object', 'required': ['policies'], 'additionalProperties': False, 'properties': { 'vars': {'type': 'object'}, 'policies': { 'type': 'array', 'additionalItems': False, 'items': {'anyOf': resource_refs} } } } return schema
skip_condition = not ( # Okay slightly gross, basically if we're explicitly told via # env var to run doc tests do it. (os.environ.get("C7N_TEST_DOC") in ('yes', 'true') or # Or for ci to avoid some tox pain, we'll auto configure here # to run on the py3.6 test runner, as its the only one # without additional responsibilities. (os.environ.get('C7N_TEST_RUN') and sys.version_info.major == 2 and sys.version_info.minor == 7))) @pytest.mark.skipif(skip_condition, reason="Doc tests must be explicitly enabled with C7N_DOC_TEST") @pytest.mark.parametrize("provider_name,provider", list(clouds.items())) def test_doc_examples(provider_name, provider): policies, duplicate_names = get_doc_policies(provider.resources) with tempfile.NamedTemporaryFile(suffix='.json', delete=False) as fh: atexit.register(os.unlink, fh.name) fh.write(json.dumps({'policies': list(policies.values())}).encode('utf8')) fh.flush() collection = load(Config.empty(), fh.name) assert isinstance(collection, PolicyCollection) assert not duplicate_names for p in policies.values():
def generate(resource_types=()): resource_defs = {} definitions = { 'resources': resource_defs, 'iam-statement': { 'additionalProperties': False, 'type': 'object', 'properties': { 'Sid': { 'type': 'string' }, 'Effect': { 'type': 'string', 'enum': ['Allow', 'Deny'] }, 'Principal': { 'anyOf': [{ 'type': 'string' }, { 'type': 'object' }, { 'type': 'array' }] }, 'NotPrincipal': { 'anyOf': [{ 'type': 'object' }, { 'type': 'array' }] }, 'Action': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'NotAction': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'Resource': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'NotResource': { 'anyOf': [{ 'type': 'string' }, { 'type': 'array' }] }, 'Condition': { 'type': 'object' } }, 'required': ['Sid', 'Effect'], 'oneOf': [{ 'required': ['Principal', 'Action', 'Resource'] }, { 'required': ['NotPrincipal', 'Action', 'Resource'] }, { 'required': ['Principal', 'NotAction', 'Resource'] }, { 'required': ['NotPrincipal', 'NotAction', 'Resource'] }, { 'required': ['Principal', 'Action', 'NotResource'] }, { 'required': ['NotPrincipal', 'Action', 'NotResource'] }, { 'required': ['Principal', 'NotAction', 'NotResource'] }, { 'required': ['NotPrincipal', 'NotAction', 'NotResource'] }] }, 'filters': { 'value': ValueFilter.schema, 'event': EventFilter.schema, 'age': AgeFilter.schema, # Shortcut form of value filter as k=v 'valuekv': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1 }, }, 'policy': { 'type': 'object', 'required': ['name', 'resource'], 'additionalProperties': False, 'properties': { 'name': { 'type': 'string', 'pattern': "^[A-z][A-z0-9]*(-[A-z0-9]+)*$" }, 'region': { 'type': 'string' }, 'resource': { 'type': 'string' }, 'max-resources': { 'type': 'integer' }, 'comment': { 'type': 'string' }, 'comments': { 'type': 'string' }, 'description': { 'type': 'string' }, 'tags': { 'type': 'array', 'items': { 'type': 'string' } }, 'mode': { '$ref': '#/definitions/policy-mode' }, 'source': { 'enum': ['describe', 'config'] }, 'actions': { 'type': 'array', }, 'filters': { 'type': 'array' }, # # unclear if this should be allowed, it kills resource # cache coherency between policies, and we need to # generalize server side query mechanisms, currently # this only for ec2 instance queries. limitations # in json schema inheritance prevent us from doing this # on a type specific basis http://goo.gl/8UyRvQ 'query': { 'type': 'array', 'items': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1 } } }, }, 'policy-mode': { 'type': 'object', 'required': ['type'], 'additionalProperties': False, 'properties': { 'type': { 'enum': [ 'cloudtrail', 'ec2-instance-state', 'asg-instance-state', 'config-rule', 'guard-duty', 'periodic' ] }, 'events': { 'type': 'array', 'items': { 'oneOf': [{ 'type': 'string' }, { 'type': 'object', 'required': ['event', 'source', 'ids'], 'properties': { 'source': { 'type': 'string' }, 'ids': { 'type': 'string' }, 'event': { 'type': 'string' } } }], } }, 'execution-options': { 'type': 'object' }, 'role': { 'type': 'string' }, 'runtime': { 'enum': ['python2.7', 'python3.6'] }, 'memory': { 'type': 'number' }, 'timeout': { 'type': 'number' }, 'schedule': { 'type': 'string' }, 'function-prefix': { 'type': 'string' }, 'dead_letter_config': { 'type': 'object' }, 'environment': { 'type': 'object' }, 'kms_key_arn': { 'type': 'string' }, 'tracing_config': { 'type': 'object' }, 'tags': { 'type': 'object' }, 'packages': { 'type': 'array' }, 'subnets': { 'type': 'array' }, 'security_groups': { 'type': 'array' }, # specific to guard duty 'member-role': { 'type': 'string' }, }, }, } resource_refs = [] for cloud_name, cloud_type in clouds.items(): for type_name, resource_type in cloud_type.resources.items(): if resource_types and type_name not in resource_types: continue alias_name = None r_type_name = "%s.%s" % (cloud_name, type_name) if cloud_name == 'aws': alias_name = type_name resource_refs.append( process_resource(r_type_name, resource_type, resource_defs, alias_name)) schema = { '$schema': 'http://json-schema.org/schema#', 'id': 'http://schema.cloudcustodian.io/v0/custodian.json', 'definitions': definitions, 'type': 'object', 'required': ['policies'], 'additionalProperties': False, 'properties': { 'vars': { 'type': 'object' }, 'policies': { 'type': 'array', 'additionalItems': False, 'items': { 'anyOf': resource_refs } } } } return schema
def generate(resource_types=()): resource_defs = {} definitions = { 'resources': resource_defs, 'filters': { 'value': ValueFilter.schema, 'event': EventFilter.schema, 'age': AgeFilter.schema, # Shortcut form of value filter as k=v 'valuekv': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1}, }, 'policy': { 'type': 'object', 'required': ['name', 'resource'], 'additionalProperties': False, 'properties': { 'name': { 'type': 'string', 'pattern': "^[A-z][A-z0-9]*(-[A-z0-9]+)*$"}, 'region': {'type': 'string'}, 'resource': {'type': 'string'}, 'max-resources': {'type': 'integer'}, 'comment': {'type': 'string'}, 'comments': {'type': 'string'}, 'description': {'type': 'string'}, 'tags': {'type': 'array', 'items': {'type': 'string'}}, 'mode': {'$ref': '#/definitions/policy-mode'}, 'source': {'enum': ['describe', 'config']}, 'actions': { 'type': 'array', }, 'filters': { 'type': 'array' }, # # unclear if this should be allowed, it kills resource # cache coherency between policies, and we need to # generalize server side query mechanisms, currently # this only for ec2 instance queries. limitations # in json schema inheritance prevent us from doing this # on a type specific basis http://goo.gl/8UyRvQ 'query': { 'type': 'array', 'items': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1}} }, }, 'policy-mode': { 'type': 'object', 'required': ['type'], 'additionalProperties': False, 'properties': { 'type': { 'enum': [ 'cloudtrail', 'ec2-instance-state', 'asg-instance-state', 'config-rule', 'guard-duty', 'periodic' ]}, 'events': {'type': 'array', 'items': { 'oneOf': [ {'type': 'string'}, {'type': 'object', 'required': ['event', 'source', 'ids'], 'properties': { 'source': {'type': 'string'}, 'ids': {'type': 'string'}, 'event': {'type': 'string'}}}], }}, 'execution-options': {'type': 'object'}, 'role': {'type': 'string'}, 'runtime': {'enum': ['python2.7', 'python3.6']}, 'memory': {'type': 'number'}, 'timeout': {'type': 'number'}, 'schedule': {'type': 'string'}, 'function-prefix': {'type': 'string'}, 'dead_letter_config': {'type': 'object'}, 'environment': {'type': 'object'}, 'kms_key_arn': {'type': 'string'}, 'tracing_config': {'type': 'object'}, 'tags': {'type': 'object'}, 'packages': {'type': 'array'}, 'subnets': {'type': 'array'}, 'security_groups': {'type': 'array'}, # specific to guard duty 'member-role': {'type': 'string'}, }, }, } resource_refs = [] for cloud_name, cloud_type in clouds.items(): for type_name, resource_type in cloud_type.resources.items(): if resource_types and type_name not in resource_types: continue alias_name = None r_type_name = "%s.%s" % (cloud_name, type_name) if cloud_name == 'aws': alias_name = type_name resource_refs.append( process_resource(r_type_name, resource_type, resource_defs, alias_name)) schema = { '$schema': 'http://json-schema.org/schema#', 'id': 'http://schema.cloudcustodian.io/v0/custodian.json', 'definitions': definitions, 'type': 'object', 'required': ['policies'], 'additionalProperties': False, 'properties': { 'vars': {'type': 'object'}, 'policies': { 'type': 'array', 'additionalItems': False, 'items': {'anyOf': resource_refs} } } } return schema
def generate(resource_types=()): resource_defs = {} definitions = { 'resources': resource_defs, 'iam-statement': { 'additionalProperties': False, 'type': 'object', 'properties': { 'Sid': {'type': 'string'}, 'Effect': {'type': 'string', 'enum': ['Allow', 'Deny']}, 'Principal': {'anyOf': [ {'type': 'string'}, {'type': 'object'}, {'type': 'array'}]}, 'NotPrincipal': {'anyOf': [{'type': 'object'}, {'type': 'array'}]}, 'Action': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'NotAction': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'Resource': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'NotResource': {'anyOf': [{'type': 'string'}, {'type': 'array'}]}, 'Condition': {'type': 'object'} }, 'required': ['Sid', 'Effect'], 'oneOf': [ {'required': ['Principal', 'Action', 'Resource']}, {'required': ['NotPrincipal', 'Action', 'Resource']}, {'required': ['Principal', 'NotAction', 'Resource']}, {'required': ['NotPrincipal', 'NotAction', 'Resource']}, {'required': ['Principal', 'Action', 'NotResource']}, {'required': ['NotPrincipal', 'Action', 'NotResource']}, {'required': ['Principal', 'NotAction', 'NotResource']}, {'required': ['NotPrincipal', 'NotAction', 'NotResource']} ] }, 'actions': {}, 'filters': { 'value': ValueFilter.schema, 'event': EventFilter.schema, 'age': AgeFilter.schema, # Shortcut form of value filter as k=v 'valuekv': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1}, }, 'policy': { 'type': 'object', 'required': ['name', 'resource'], 'additionalProperties': False, 'properties': { 'name': { 'type': 'string', 'pattern': "^[A-z][A-z0-9]*(-[A-z0-9]+)*$"}, 'region': {'type': 'string'}, 'tz': {'type': 'string'}, 'start': {'format': 'date-time'}, 'end': {'format': 'date-time'}, 'resource': {'type': 'string'}, 'max-resources': {'type': 'integer', 'minimum': 1}, 'max-resources-percent': {'type': 'number', 'minimum': 0, 'maximum': 100}, 'comment': {'type': 'string'}, 'comments': {'type': 'string'}, 'description': {'type': 'string'}, 'tags': {'type': 'array', 'items': {'type': 'string'}}, 'mode': {'$ref': '#/definitions/policy-mode'}, 'source': {'enum': ['describe', 'config']}, 'actions': { 'type': 'array', }, 'filters': { 'type': 'array' }, # # unclear if this should be allowed, it kills resource # cache coherency between policies, and we need to # generalize server side query mechanisms, currently # this only for ec2 instance queries. limitations # in json schema inheritance prevent us from doing this # on a type specific basis http://goo.gl/8UyRvQ 'query': { 'type': 'array', 'items': { 'type': 'object', 'minProperties': 1, 'maxProperties': 1}} }, }, 'policy-mode': { 'anyOf': [e.schema for _, e in execution.items()], } } resource_refs = [] for cloud_name, cloud_type in clouds.items(): for type_name, resource_type in cloud_type.resources.items(): if resource_types and type_name not in resource_types: continue alias_name = None r_type_name = "%s.%s" % (cloud_name, type_name) if cloud_name == 'aws': alias_name = type_name resource_refs.append( process_resource( r_type_name, resource_type, resource_defs, alias_name, definitions )) schema = { '$schema': 'http://json-schema.org/schema#', 'id': 'http://schema.cloudcustodian.io/v0/custodian.json', 'definitions': definitions, 'type': 'object', 'required': ['policies'], 'additionalProperties': False, 'properties': { 'vars': {'type': 'object'}, 'policies': { 'type': 'array', 'additionalItems': False, 'items': {'anyOf': resource_refs} } } } return schema