def validate(self): super(PHDMode, self).validate() if self.policy.resource_type == 'account': return if 'health-event' not in self.policy.resource_manager.filter_registry: raise PolicyValidationError( "policy:%s phd event mode not supported for resource:%s" % (self.policy.name, self.policy.resource_type))
def validate(self): if self.data.get('encrypted', True): key = self.data.get('target_key') if not key: raise PolicyValidationError( "Encrypted snapshot copy requires kms key on %s" % (self.manager.data, )) return self
def factory(self, data, manager): if isinstance(data, dict): action_type = data.get('type') if action_type is None: raise PolicyValidationError("Invalid action type found in %s" % (data)) else: action_type = data data = {} action_class = self.get(action_type) if action_class is None: raise PolicyValidationError( "Invalid action type %s, valid actions %s" % (action_type, list(self.keys()))) # Construct a ResourceManager return action_class(data, manager).validate()
def parse(cls, data): results = [] for d in data: if not isinstance(d, dict): raise PolicyValidationError( "Health Query Filter Invalid structure %s" % d) results.append(cls(d).validate()) return results
def validate(self): attrs = dict(self.data['attributes']) if 'DBClusterIdentifier' in attrs: raise PolicyValidationError( "Can't include DBClusterIdentifier in modify-db-cluster action" ) attrs['DBClusterIdentifier'] = 'PolicyValidation' return shape_validate(attrs, self.shape, 'rds')
def validate(self): for finding_type in self.data["types"]: if finding_type.count('/') > 2 or finding_type.split( '/')[0] not in FindingTypes: raise PolicyValidationError( "Finding types must be in the format 'namespace/category/classifier'." " Found {}. Valid namespace values are: {}.".format( finding_type, " | ".join([ns for ns in FindingTypes])))
def validate(self): attrs = dict(self.data['attributes']) if 'Name' in attrs: raise PolicyValidationError( "Can't include Name in update-trail action") attrs['Name'] = 'PolicyValidation' return shape_validate(attrs, self.shape, self.manager.resource_type.service)
def validate(self): if self.data.get('state') == 'enabled': if 'bucket' not in self.data: raise PolicyValidationError( ("redshift logging enablement requires `bucket` " "and `prefix` specification on %s" % (self.manager.data, ))) return self
def validate(self): for f in self.manager.iter_filters(): if isinstance(f, RedshiftSnapshotCrossAccount): return self raise PolicyValidationError( '`revoke-access` may only be used in ' 'conjunction with `cross-account` filter on %s' % (self.manager.data, ))
def validate(self): region = self.manager.data.get('region', '') if len(self.global_services.intersection(self.data.get('services', []))): if region != 'us-east-1': raise PolicyValidationError( "Global services: %s must be targeted in us-east-1 on the policy" % ', '.join(self.global_services)) return self
def _validate_event_matches_resource(self): resource_type = self.policy.resource_manager.resource_type.resource_type if resource_type != 'armresource': for event in self.subscribed_events: if resource_type.lower() not in event.lower(): raise PolicyValidationError( 'The policy resource, {}, can not be triggered by the event, {}.' .format(resource_type, event))
def shape_validate(params, shape_name, service): session = fake_session()._session model = session.get_service_model(service) shape = model.shape_for(shape_name) validator = ParamValidator() report = validator.validate(params, shape) if report.has_errors(): raise PolicyValidationError(report.generate_report())
def validate_policy(self, p): if not isinstance(p, dict): raise PolicyValidationError( ('policy must be a dictionary/mapping found:%s policy:\n %s' % (type(p).__name__, json.dumps(p, indent=2)))) pkeys = set(p) if self.required_policy_keys.difference(pkeys): raise PolicyValidationError( 'policy missing required keys (name, resource) data:\n %s' % (json.dumps(p, indent=2))) if pkeys.difference(self.allowed_policy_keys): raise PolicyValidationError( 'policy:%s has unknown keys: %s' % (p['name'], ','.join( pkeys.difference(self.allowed_policy_keys)))) if not isinstance(p.get('filters', []), (list, type(None))): raise PolicyValidationError( ('policy:%s must use a list for filters found:%s' % (p['name'], type(p['filters']).__name__))) element_types = (dict, str) for f in p.get('filters', ()): if not isinstance(f, element_types): raise PolicyValidationError( ('policy:%s filter must be a mapping/dict found:%s' % (p.get('name', 'unknown'), type(f).__name__))) if not isinstance(p.get('actions', []), (list, type(None))): raise PolicyValidationError( ('policy:%s must use a list for actions found:%s' % (p.get('name', 'unknown'), type(p['actions']).__name__))) for a in p.get('actions', ()): if not isinstance(a, element_types): raise PolicyValidationError( ('policy:%s action must be a mapping/dict found:%s' % (p.get('name', 'unknown'), type(a).__name__)))
def validate(self): super().validate() if not self.policy.data['mode'].get('schedule'): raise PolicyValidationError( "policy:%s config-poll-rule schedule required" % (self.policy.name)) if self.policy.resource_manager.resource_type.config_type: raise PolicyValidationError( "resource:%s fully supported by config and should use mode: config-rule" % (self.policy.resource_type)) if self.policy.data['mode'].get('pattern'): raise PolicyValidationError( "policy:%s AWS Config does not support event pattern filtering" % (self.policy.name)) if not self.policy.resource_manager.resource_type.cfn_type: raise PolicyValidationError( ('policy:%s resource:%s does not have a cloudformation type' ' and is there-fore not supported by config-poll-rule'))
def validate(self): if not len(list(self.data.keys())) == 1: raise PolicyValidationError("EMR Query Filter Invalid %s" % self.data) self.key = list(self.data.keys())[0] self.value = list(self.data.values())[0] if self.key not in EMR_VALID_FILTERS and not self.key.startswith( 'tag:'): raise PolicyValidationError( "EMR Query Filter invalid filter name %s" % (self.data)) if self.value is None: raise PolicyValidationError( "EMR Query Filters must have a value, use tag-key" " w/ tag name as value for tag present checks" " %s" % self.data) return self
def validate(self): delta = set(self.data.keys()).difference(self.multi_attrs) delta.remove('type') if 'match-operator' in delta: delta.remove('match-operator') if delta: raise PolicyValidationError( "filter:{} unknown keys {} on {}".format( self.type, ", ".join(delta), self.manager.data))
def lifecycle_rule_validate(policy, rule): # This is a non exhaustive list of lifecycle validation rules # see this for a more comprehensive list # # https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html#lp_evaluation_rules if (rule['selection']['tagStatus'] == 'tagged' and 'tagPrefixList' not in rule['selection']): raise PolicyValidationError( ("{} has invalid lifecycle rule {} tagprefixlist " "required for tagStatus: tagged").format( policy.name, rule)) if (rule['selection']['countType'] == 'sinceImagePushed' and 'countUnit' not in rule['selection']): raise PolicyValidationError( ("{} has invalid lifecycle rule {} countUnit " "required for countType: sinceImagePushed").format( policy.name, rule))
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) collection = PolicyLoader(self.manager.config).load_data( {'policies': [self.data['policy']]}, "memory://", session_factory=self.manager.session_factory) if not collection: raise PolicyValidationError( "policy %s missing filter empty embedded policy" % (self.manager.ctx.policy.name)) self.embedded_policy = list(collection).pop() self.embedded_policy.validate() return self
def validate(self): if not self.data.get('state', True): return self key = self.data.get('kms-key', '') if not key: raise ValueError('Must specify either a KMS key ARN or Alias') if 'alias/' not in key and ':key/' not in key: raise PolicyValidationError("Invalid kms key format %s" % key) return self
def parse(cls, data): filters = [] if not isinstance(data, (tuple, list)): raise PolicyValidationError( "%s Query invalid format, must be array of dicts %s" % ( cls.type_name, data)) for d in data: if not isinstance(d, dict): raise PolicyValidationError( "%s Query Filter Invalid %s" % (cls.type_name, data)) if "Name" not in d or cls.value_key not in d: raise PolicyValidationError( "%s Query Filter Invalid: Missing Key or Values in %s" % ( cls.type_name, data)) key = d['Name'] values = d[cls.value_key] if not cls.multi_value and isinstance(values, list): raise PolicyValidationError( "%s Query Filter Invalid Key: Value:%s Must be single valued" % ( cls.type_name, key)) elif not cls.multi_value: values = [values] if key not in cls.QuerySchema and not key.startswith('tag:'): raise PolicyValidationError( "%s Query Filter Invalid Key:%s Valid: %s" % ( cls.type_name, key, ", ".join(cls.QuerySchema.keys()))) vtype = cls.QuerySchema.get(key) if vtype is None and key.startswith('tag'): vtype = str if not isinstance(values, list): raise PolicyValidationError( "%s Query Filter Invalid Values, must be array %s" % ( cls.type_name, data,)) for v in values: if isinstance(vtype, tuple): if v not in vtype: raise PolicyValidationError( "%s Query Filter Invalid Value: %s Valid: %s" % ( cls.type_name, v, ", ".join(vtype))) elif not isinstance(v, vtype): raise PolicyValidationError( "%s Query Filter Invalid Value Type %s" % ( cls.type_name, data,)) filters.append(d) return filters
def _validate_value_regex(self, regex): """Specific validation for `value_regex` type The `value_regex` type works a little differently. In particular it doesn't support OPERATORS that perform operations on a list of values, specifically 'intersect', 'contains', 'difference', 'in' and 'not-in' """ # Sanity check that we can compile try: pattern = re.compile(regex) if pattern.groups != 1: raise PolicyValidationError( "value_regex must have a single capturing group: %s" % self.data) except re.error as e: raise PolicyValidationError( "Invalid value_regex: %s %s" % (e, self.data)) return self
def _handle_missing_resources(self, policy_data, missing): # for an invalid resource type catch and try to associate # it to the policy by name. for p in policy_data.get('policies', ()): pr = p['resource'] if '.' not in pr: pr = "aws.%s" % pr if pr in missing: raise PolicyValidationError( "Policy:%s references an unknown resource:%s" % (p['name'], p['resource']))
def resource_query(self): filters = [] for q in self.data.get('query', ()): if (not isinstance(q, dict) or not set(q.keys()) == set( ('Key', 'Values', 'Operator')) or q['Key'] not in self.QueryKeys or q['Operator'] not in self.QueryOperators): raise PolicyValidationError("invalid ops-item query %s" % self.data['query']) filters.append(q) return {'OpsItemFilters': filters}
def validate(self): if 'accounts' in self.data and self.data['accounts'] == 'matched': found = False for f in self.manager.iter_filters(): if isinstance(f, AmiCrossAccountFilter): found = True break if not found: raise PolicyValidationError( "policy:%s filter:%s with matched requires cross-account filter" % (self.manager.ctx.policy.name, self.type))
def validate(self): m = self.get_execution_mode() if m is None: raise PolicyValidationError( "Invalid Execution mode in policy %s" % (self.data,)) m.validate() self.validate_policy_start_stop() for f in self.resource_manager.filters: f.validate() for a in self.resource_manager.actions: a.validate()
def validate(self): mode = self.policy.data['mode'] if 'tz' in mode: error = PolicyValidationError( "policy:%s gcp-periodic invalid tz:%s" % (self.policy.name, mode['tz'])) # We can't catch all errors statically, our local tz retrieval # then the form gcp is using, ie. not all the same aliases are # defined. tzinfo = tz.gettz(mode['tz']) if tzinfo is None: raise error
def validate(self): if self.data['accounts'] != 'matched': return found = False for f in self.manager.iter_filters(): if isinstance(f, CatalogPortfolioCrossAccount): found = True break if not found: raise PolicyValidationError( "policy:%s action:%s with matched requires cross-account filter" % (self.manager.ctx.policy.name, self.type))
def validate(self): if self.manager.data.get('mode', {}).get('type') == 'azure-event-grid' \ and self.data.get('days') is not None: raise PolicyValidationError( "Auto tag actions in event mode does not use days.") if (self.data.get('days') is not None and (self.data.get('days') < 1 or self.data.get('days') > 90)): raise FilterValidationError("Days must be between 1 and 90") return self
def validate(self): found = False for f in self.manager.iter_filters(): if isinstance(f, WafEnabled): found = True break if not found: # try to ensure idempotent usage raise PolicyValidationError( "set-waf should be used in conjunction with waf-enabled filter on %s" % (self.manager.data, )) return self
def validate(self): sg_filter = self.manager.filter_registry.get('security-group') if not sg_filter or not sg_filter.RelatedIdsExpression: raise PolicyValidationError(self._format_error(( "policy:{policy} resource:{resource_type} does " "not support {action_type} action"))) if self.get_action_group_names(): vpc_filter = self.manager.filter_registry.get('vpc') if not vpc_filter or not vpc_filter.RelatedIdsExpression: raise PolicyValidationError(self._format_error(( "policy:{policy} resource:{resource_type} does not support " "security-group names only ids in action:{action_type}"))) self.vpc_expr = jmespath.compile(vpc_filter.RelatedIdsExpression) if self.sg_expr is None: self.sg_expr = jmespath.compile( self.manager.filter_registry.get('security-group').RelatedIdsExpression) if 'all' in self._get_array('remove') and not self._get_array('isolation-group'): raise PolicyValidationError(self._format_error(( "policy:{policy} use of action:{action_type} with " "remove: all requires specifying isolation-group"))) return self