Exemplo n.º 1
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        self.location = self.definition.get("location")
        self.description = self.definition.get("description")

        self.connection = self.amazon.kms_connection_for(self.location)
        if not self.description:
            raise BadPolicy("Please define a description", key=self.name)

        if "admin_users" in self.definition:
            policy = {
                "principal": self.definition["admin_users"],
                "action": "kms:*",
                "resource": {
                    "kms": "__self__"
                },
                "Sid": ""
            }
            for statement in self.statements.make_permission_statements(
                    policy, allow=True):
                self.permission.append(statement)

        for key, default_allow in (("permission", None), ("allow_permission",
                                                          True),
                                   ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(
                        policy, allow=default_allow):
                    self.permission.append(statement)

        for policy in listified(self.definition, "grant"):
            if not isinstance(policy, dict):
                raise BadPolicy(
                    "Grant must be a dictionary of atleast {grantee, operations}",
                    got=policy,
                    key=self.name)

            if "grantee" not in policy and "operations" not in policy:
                raise BadPolicy(
                    "Grant must be a dictionary of atleast {grantee, operations}",
                    got=list(policy.keys()),
                    key=self.name)

            policy['grantee'] = list(
                self.statements.iam_arns_from_specification(policy['grantee']))
            if 'retiree' in policy:
                policy['retiree'] = list(
                    self.statements.iam_arns_from_specification(
                        policy['retiree']))

            for thing in ('grantee', 'retiree'):
                if thing in policy:
                    if len(policy[thing]) > 1:
                        raise BadPolicy("Can only have one {0}".format(thing),
                                        got=len(policy[thing]),
                                        key=self.name)
                    policy[thing] = policy[thing][0]

            self.grant.append(policy)
Exemplo n.º 2
0
    def make_permission_statements(self, policy, allow=None):
        """
        Make zero or more permissions statements from a policy definition

        If allow is None and no allow or Effect is specified, an error is raised
        Otherwise we assume the truthiness of allow
        """
        result = dict((key, val) for key, val in policy.items() if key[0].isupper())

        if allow is None and "Effect" not in policy:
            if not isinstance(policy.get("allow"), bool):
                raise BadPolicy("Need to specify whether we allow this policy or not", policy=policy, **{self.self_type:self.name})
            result["Effect"] = ["Deny", "Allow"][policy["allow"]]
        elif allow is not None:
            result["Effect"] = ["Deny", "Allow"][allow]

        for key, dest in (("action", "Action"), ("notaction", "NotAction")):
            for specified in listified(policy, key):
                listify(result, dest).append(specified)

        for key, dest in (("resource", "Resource"), ("notresource", "NotResource")):
            for specified in listified(policy, key):
                listify(result, dest).extend(self.fill_out_resources(specified))

        self.expand_principal(policy, result)

        if "Resource" not in result and "NotResource" not in result:
            raise BadPolicy("No Resource or NotResource was defined for policy", policy=policy, **{self.self_type:self.name})

        if "Action" not in result and "NotAction" not in result:
            raise BadPolicy("No Action or NotAction defined for this policy", policy=policy, **{self.self_type:self.name})

        if "Sid" not in result and self.self_type == "bucket":
            result["Sid"] = ""

        # Amazon gets rid of the lists if only one item
        # And this mucks around with the diffing....
        for thing in ("Action", "NotAction", "Resource", "NotResource"):
            if thing in result:
                if len(listify(result, thing)) == 1:
                    result[thing] = result[thing][0]
                else:
                    result[thing] = sorted(result[thing])

        yield result
Exemplo n.º 3
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        self.tags = self.definition.get("tags", {})
        if type(self.tags) != dict or any(not isinstance(tag_name, six.string_types) or not isinstance(tag_val, six.string_types) for tag_name, tag_val in self.tags.items()):
            raise SyncrError("Bucket tags should be a dictionary of {<string> : <string>}", got=self.tags)

        self.location = self.definition.get("location", "ap-southeast-2")
        for key, default_allow in (("permission", None), ("allow_permission", True), ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(policy, allow=default_allow):
                    self.permission.append(statement)
Exemplo n.º 4
0
    def expand_principal(self, statement, result):
        """Expand out Principal and NotPrincipal"""
        for principal, capd in [("principal", "Principal"), ("notprincipal", "NotPrincipal")]:
            if principal in statement:
                if capd not in result:
                    result[capd] = {}

                looking_at = statement[principal]
                if not isinstance(looking_at, list):
                    looking_at = [looking_at]

                for instruction in looking_at:
                    principal = result[capd]

                    for specified in listified(instruction, "service"):
                        if specified == "ec2":
                            specified = "ec2.amazonaws.com"
                        listify(principal, "Service").append(specified)

                    for specified in listified(instruction, "federated"):
                        listify(principal, "Federated").extend(self.iam_arns_from_specification(specified))
                        if "Action" not in result:
                            result["Action"] = "sts:AssumeRoleWithSAML"

                    if "iam" in instruction:
                        listify(principal, "AWS").extend(self.iam_arns_from_specification(instruction))

        # Amazon gets rid of the lists if only one item
        # And this mucks around with the diffing....
        for princ in (result.get("Principal"), result.get("NotPrincipal")):
            if princ:
                for principal_type in ("AWS", "Federated", "Service"):
                    if principal_type in princ:
                        if len(listify(princ, principal_type)) == 1:
                            princ[principal_type] = princ[principal_type][0]
                        else:
                            princ[principal_type] = sorted(princ[principal_type])
Exemplo n.º 5
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        self.location = self.definition.get("location")
        self.description = self.definition.get("description")

        self.connection = self.amazon.kms_connection_for(self.location)
        if not self.description:
            raise BadPolicy("Please define a description", key=self.name)

        if "admin_users" in self.definition:
            policy = {"principal": self.definition["admin_users"], "action": "kms:*", "resource": { "kms": "__self__" }, "Sid": ""}
            for statement in self.statements.make_permission_statements(policy, allow=True):
                self.permission.append(statement)

        for key, default_allow in (("permission", None), ("allow_permission", True), ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(policy, allow=default_allow):
                    self.permission.append(statement)

        for policy in listified(self.definition, "grant"):
            if not isinstance(policy, dict):
                raise BadPolicy("Grant must be a dictionary of atleast {grantee, operations}", got=policy, key=self.name)

            if "grantee" not in policy and "operations" not in policy:
                raise BadPolicy("Grant must be a dictionary of atleast {grantee, operations}", got=list(policy.keys()), key=self.name)

            policy['grantee'] = list(self.statements.iam_arns_from_specification(policy['grantee']))
            if 'retiree' in policy:
                policy['retiree'] = list(self.statements.iam_arns_from_specification(policy['retiree']))

            for thing in ('grantee', 'retiree'):
                if thing in policy:
                    if len(policy[thing]) > 1:
                        raise BadPolicy("Can only have one {0}".format(thing), got=len(policy[thing]), key=self.name)
                    policy[thing] = policy[thing][0]

            self.grant.append(policy)
Exemplo n.º 6
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        if "use" in self.definition:
            template = self.definition["use"]
            if not self.templates:
                raise NoTemplates(name=self.name, looking_for_template=template, available=self.templates.keys())

            if template not in self.templates:
                raise CantFindTemplate(name=self.name, looking_for_template=template, available=self.templates.keys())

            self.definition = MergedOptions.using(self.templates[template], self.definition)

        self.description = self.definition.get("description", "No description provided!")

        for statement in listified(self.definition, "allow_to_assume_me"):
            self.trust.extend(self.statements.expand_trust_statement(statement, allow=True))

        for statement in listified(self.definition, "disallow_to_assume_me"):
            self.distrust.extend(self.statements.expand_trust_statement(statement, allow=False))

        for key, default_allow in (("permission", None), ("allow_permission", True), ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(policy, allow=default_allow):
                    self.permission.append(statement)
Exemplo n.º 7
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        self.tags = self.definition.get("tags", {})
        if type(self.tags) != dict or any(
                not isinstance(tag_name, six.string_types)
                or not isinstance(tag_val, six.string_types)
                for tag_name, tag_val in self.tags.items()):
            raise SyncrError(
                "Bucket tags should be a dictionary of {<string> : <string>}",
                got=self.tags)

        self.location = self.definition.get("location", "ap-southeast-2")
        for key, default_allow in (("permission", None), ("allow_permission",
                                                          True),
                                   ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(
                        policy, allow=default_allow):
                    self.permission.append(statement)
Exemplo n.º 8
0
    def iam_arns_from_specification(self, specification):
        """Get us an iam arn from this specification"""
        if not isinstance(specification, list):
            specification = [specification]

        for spec in specification:
            if isinstance(spec, six.string_types):
                yield spec
            else:
                provided_accounts = spec.get("account", "")
                if not isinstance(provided_accounts, list):
                    provided_accounts = [provided_accounts]

                for provided_account in provided_accounts:
                    if provided_account:
                        if provided_account not in self.accounts:
                            raise BadPolicy("Unknown account specified", account=provided_account, specification=spec)
                        else:
                            account_id = self.accounts[provided_account]
                    else:
                        account_id = self.account_id

                    users = spec.get("users", [])
                    for name in listified(spec, "iam"):
                        if name == "__self__":
                            if self.self_type == 'bucket':
                                raise BadPolicy("Bucket policy has no __self__ iam role", bucket=self.name)

                            account_id = self.account_id
                            name = "role/{0}".format(self.name)

                        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)
Exemplo n.º 9
0
    it "returns the key as is if already a list":
        lst = [1, 2]
        dct = {"blah": lst}
        self.assertIs(listify(dct, "blah"), lst)
        self.assertEqual(dct, {"blah": lst})

    it "makes the key a list and returns if in there but not a list already":
        for val in (0, 1, None, True, False, "", "adf", lambda: 1, mock.Mock(name="blah")):
            dct = {"blah": val}
            lst = listify(dct, "blah")
            self.assertEqual(lst, [val])
            self.assertEqual(dct, {"blah": lst})

describe TestCase, "listified":
    it "yields nothing if the key isn't in the dict":
        self.assertEqual(list(listified({"meh": 1}, "blah")), [])

    it "yields the thing if the thing is not a list":
        for val in (0, 1, None, True, False, "", "adf", lambda: 1, mock.Mock(name="blah")):
            self.assertEqual(list(listified({"blah": val}, "blah")), [val])

    it "yields the items in the thing if the thing is a list":
        item1 = 3
        item2 = 1
        item3 = 2
        lst = [item1, item2, item3]
        self.assertEqual(list(listified({"blah": lst}, "blah")), [item1, item2, item3])

describe TestCase, "as_list":
    it "yields the things in the thing if it's a list":
        lst = [1, 2]