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 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, } 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}, }, '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']}, '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', '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(): 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, 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
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': { '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)) 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, 'string_dict': { "type": "object", "patternProperties": { "*": { "type": "string" }, }, }, 'basic_dict': { "type": "object", "patternProperties": { "*": { 'oneOf': [ { "type": "string" }, { "type": "boolean" }, { "type": "number" }, ], } }, }, '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]+)*$" }, 'conditions': { 'type': 'array', 'items': { 'anyOf': [{ 'type': 'object', 'additionalProperties': False, 'properties': { 'or': { '$ref': '#/definitions/policy/properties/conditions' } } }, { 'type': 'object', 'additionalProperties': False, 'properties': { 'not': { '$ref': '#/definitions/policy/properties/conditions' } } }, { 'type': 'object', 'additionalProperties': False, 'properties': { 'and': { '$ref': '#/definitions/policy/properties/conditions' } } }, { '$ref': '#/definitions/filters/value' }, { '$ref': '#/definitions/filters/event' }, { '$ref': '#/definitions/filters/valuekv' }] } }, # these should be deprecated for conditions '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', 'inventory', 'resource-graph', 'disk', 'static' ] }, '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 sorted(clouds.items()): for type_name, resource_type in sorted(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 elif not { "%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 } } } } # allow empty policies with lazy load if not resource_refs: schema['properties']['policies']['items'] = {'type': 'object'} 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
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 }, }, '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'] }, '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()], }, 'max-resources-properties': { 'type': 'object', '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(): 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/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