def normalise(self, meta, val): result = [] for index, item in enumerate( sb.listof(sb.any_spec()).normalise(meta, val)): s3_spec = s3_specs(item, self.self_type, self.self_name) iam_spec = iam_specs(item, self.self_type, self.self_name) kms_spec = kms_specs(item, self.self_type, self.self_name) arn_spec = arn_specs(item, self.self_type, self.self_name) if isinstance(item, six.string_types): result.append(item) else: types = (("iam", iam_spec), ("kms", kms_spec), ("s3", s3_spec), ("arn", arn_spec)) for typ, spec in types: if typ in item: if self.only and typ not in self.only: raise BadPolicy( "Sorry, don't support this resource type here", wanted=typ, available=self.only, meta=meta) for found in spec.normalise( meta.indexed_at(index).at(typ), item[typ]): result.append(found) return sorted(result)
def normalise(self, meta, val): pairs = [] has_self = False for account_id in self.accounts(meta): users = sb.listof(sb.string_spec()).normalise( meta.at("users"), self.resource.get('users', NotSpecified)) for name in sb.listof(sb.any_spec()).normalise(meta, val): if name == "__self__": if self.self_type != 'role': raise BadPolicy("No __self__ iam role for this policy", meta=meta) else: has_self = True else: pairs.append((name, account_id)) if has_self: pairs.append(("role/{0}".format(self.self_name), self.default_account_id(meta))) for name, account_id in pairs: service = "sts" if name.startswith("assumed-role") else "iam" arn = "arn:aws:{0}::{1}:{2}".format(service, account_id, name) if not users: yield arn else: for user in users: yield "{0}/{1}".format(arn, user)
def normalise(self, meta, val): for bucket_key in sb.listof(sb.string_spec()).normalise(meta, val): if bucket_key == "__self__" or bucket_key.startswith("__self__"): if self.self_type != "bucket": raise BadPolicy("No __self__ bucket for this policy", meta=meta) else: path = "" if "/" in bucket_key: path = bucket_key[bucket_key.find('/'):] bucket_key = "{0}{1}".format(self.self_name, path) yield "arn:aws:s3:::{0}".format(bucket_key) if '/' not in bucket_key: yield "arn:aws:s3:::{0}/*".format(bucket_key)
def normalise(self, meta, val): default_location = "" if "identity" not in self.resource: raise BadPolicy( "Generic arn specified without specifying 'identity'", meta=meta) location = self.location(meta) identities = sb.listof(sb.string_spec()).normalise( meta.at("identity"), self.resource.get("identity")) for account_id in self.accounts(meta): for identity in identities: yield "arn:aws:{0}:{1}:{2}:{3}".format(val, location, account_id, identity)
def accounts(self, meta): accounts = meta.everything["accounts"] default_account_id = self.default_account_id(meta) provided_accounts = sb.listof(sb.string_spec()).normalise( meta.at("account"), self.resource.get("account", [])) if not provided_accounts: yield default_account_id for provided_account in provided_accounts: if provided_account not in accounts: raise BadPolicy("Unknown account specified", account=provided_account, meta=meta) else: account_id = accounts[provided_account] yield account_id
def complain_about_conflicting_args(self, meta, kwargs): found = None conflicting_group = None for group in self.conflicting: found = [ key for key in group if kwargs.get(key, NotSpecified) is not NotSpecified ] if len(found) > 1: conflicting_group = group break if conflicting_group and found: raise BadPolicy( "Statement has conflicting keys, please only choose one", only_one_from=group, found=found, meta=meta)
def complain_about_missing_args(self, meta, kwargs): missing = [] for arg in self.required: if isinstance(arg, six.string_types): arg = (arg, ) available = sorted( list( set( list( chain.from_iterable( [capitalize(thing) for thing in arg]))))) if not any( kwargs.get(option, NotSpecified) is not NotSpecified for option in available): missing.append(" or ".join(available)) if missing: raise BadPolicy("Statement is missing required properties", missing=missing, meta=meta)
def normalise(self, meta, val): accounts = list(self.accounts(meta)) if not accounts: accounts = [self.default_account_id(meta)] for account_id in accounts: string_or_dict = sb.or_spec( sb.string_spec(), sb.dictof(sb.string_choice_spec(["key_id", "alias"]), sb.string_spec())) for key_id in sb.listof(string_or_dict).normalise(meta, val): alias = None if key_id == "__self__" or ( isinstance(key_id, dict) and (key_id.get("alias") == "__self__" or key_id.get("key_id") == "__self__")): if self.self_type != "key": raise BadPolicy("No __self__ key for this policy", meta=meta) else: alias = self.self_name location = self.default_location(meta) else: location = self.location(meta) if not alias: if isinstance(key_id, six.string_types): alias = key_id else: alias = key_id.get("alias") key_id = key_id.get("key_id") if alias: yield "arn:aws:kms:{0}:{1}:alias/{2}".format( location, account_id, alias) else: yield "arn:aws:kms:{0}:{1}:key/{2}".format( location, account_id, key_id)
def normalise(self, meta, val): if isinstance(val, MergedOptions): val = val.as_dict() val = sb.dictionary_spec().normalise(meta, val) if self.principal == "notprincipal": opposite = "principal" else: opposite = ("not", "principal") opposite, cap_opposite = capitalize(opposite) if opposite in val or cap_opposite in val: raise BadPolicy("Specifying opposite principal type in statement", wanted=self.principal, got=opposite, meta=meta) capitalized = self.principal if capitalized in ("principal", "Principal"): arg, capitalized = "principal", "Principal" else: arg, capitalized = "notprincipal", "NotPrincipal" if arg not in val and capitalized not in val: return {self.principal: val} return val