Exemplo n.º 1
0
 def test_empty_statements(self):
     """If there are no statements, it should not break."""
     empty_statements = {"Version": "2012-10-17", "Statement": []}
     empty_statements_document = PolicyDocument(
         policy=empty_statements,
         service="iam",
     )
     results = json.loads(empty_statements_document.__str__())
     print(json.dumps(results, indent=4))
     self.assertDictEqual(results, empty_statements)
Exemplo n.º 2
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     # If you do not know the names of the policies that are attached to the identity, you can use ListIdentityPolicies
     logger.debug("Getting resource policy for %s" % self.arn)
     # When there is no policy, let's return an empty policy to avoid breaking things
     policy = constants.get_empty_policy()
     try:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses.html#SES.Client.list_identity_policies
         response = self.client.list_identity_policies(Identity=self.name)
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses.html#SES.Client.get_identity_policies
         policy_names = response.get("PolicyNames")
         if policy_names:
             response = self.client.get_identity_policies(Identity=self.name, PolicyNames=policy_names)
             policies = response.get("Policies")
             if constants.SID_SIGNATURE in policies:
                 policy = json.loads(policies.get(constants.SID_SIGNATURE))
             success = True
         else:
             policy = constants.get_empty_policy()
             success = True
     except botocore.exceptions.ClientError:
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document, success=success)
     return response
Exemplo n.º 3
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     # When there is no policy, let's return an empty policy to avoid breaking things
     policy = constants.get_empty_policy()
     try:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/glacier.html#Glacier.Client.get_vault_access_policy
         response = self.client.get_vault_access_policy(vaultName=self.name)
         policy = json.loads(response.get("policy").get("Policy"))
         success = True
     # This is silly. If there is no access policy set on the vault, then it returns the same error as if the vault didn't exist.
     except self.client.exceptions.ResourceNotFoundException as error:
         logger.debug(error)
         success = True
     except botocore.exceptions.ClientError:
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 4
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     try:
         response = self.client.get_role(RoleName=self.name)
         policy = response.get("Role").get("AssumeRolePolicyDocument")
         success = True
     except self.client.exceptions.NoSuchEntityException:
         logger.critical(f"There is no resource with the name {self.name}")
         policy = constants.get_empty_policy()
         success = False
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         policy = constants.get_empty_policy()
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 5
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     policy = constants.get_empty_policy()
     try:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecr.html#ECR.Client.get_repository_policy
         response = self.client.get_repository_policy(
             repositoryName=self.name)
         policy = json.loads(response.get("policyText"))
         success = True
     except self.client.exceptions.RepositoryPolicyNotFoundException:
         logger.debug("Policy not found. Setting policy document to empty.")
         success = True
     except self.client.exceptions.RepositoryNotFoundException:
         logger.critical("Repository does not exist")
         success = False
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 6
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     # When there is no policy, let's return an empty policy to avoid breaking things
     policy = constants.get_empty_policy()
     try:
         response = self.client.get_topic_attributes(TopicArn=self.arn)
         attributes = response.get("Attributes")
         if attributes.get("Policy"):
             policy = constants.get_empty_policy()
             policy["Statement"].extend(
                 json.loads(attributes.get("Policy")).get("Statement"))
         else:
             policy = constants.get_empty_policy()
         success = True
     except self.client.exceptions.ResourceNotFoundException as error:
         logger.critical(error)
         success = False
     except botocore.exceptions.ClientError as error:
         logger.critical(error)
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 7
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     policy = constants.get_empty_policy()
     try:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/acm-pca.html#ACMPCA.Client.get_policy
         response = self.client.get_policy(ResourceArn=self.arn)
         policy = json.loads(response.get("Policy"))
         success = True
     # This is dumb. "If either the private CA resource or the policy cannot be found, this action returns a ResourceNotFoundException."
     # That means we have to set it to true, even when the resource doesn't exist. smh.
     # That will only affect the expose command and not the smash command.
     except self.client.exceptions.ResourceNotFoundException:
         logger.debug(f"Resource {self.name} not found")
         success = True
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 8
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     policy = constants.get_empty_policy()
     try:
         response = self.client.get_bucket_policy(Bucket=self.name)
         policy = json.loads(response.get("Policy"))
         message = "200: Successfully obtained bucket policy for %s" % self.arn
         success = True
     except botocore.exceptions.ClientError as error:
         error_code = error.response['Error']['Code']
         message = f"{error_code}: {error.response.get('Error').get('Message')} for {error.response.get('Error').get('BucketName')}"
         if error.response['Error']['Code'] == "AccessDenied":
             success = False
         elif error.response['Error']['Code'] == "NoSuchBucketPolicy":
             success = True
         else:
             # This occurs when there is no resource policy attached
             success = True
     except Exception as error:
         message = error
         success = False
     logger.debug(message)
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 9
0
 def _get_rbp(self) -> ResponseGetRbp:
     logger.debug("Getting resource policy for %s" % self.arn)
     # When there is no policy, let's return an empty policy to avoid breaking things
     policy = constants.get_empty_policy()
     try:
         response = self.client.get_layer_version_policy(
             LayerName=self.name, VersionNumber=self.version)
         policy = json.loads(response.get("Policy"))
         success = True
     except self.client.exceptions.ResourceNotFoundException as error:
         logger.debug("The Policy does not exist. We will have to add it.")
         success = True
     except botocore.exceptions.ClientError as error:
         logger.critical(error)
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 10
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kms.html#KMS.Client.get_key_policy
     logger.debug("Getting resource policy for %s" % self.arn)
     try:
         response = self.client.get_key_policy(KeyId=self.arn,
                                               PolicyName="default")
         if response.get("Policy"):
             policy = constants.get_empty_policy()
             policy["Statement"].extend(
                 json.loads(response.get("Policy")).get("Statement"))
         else:
             policy = constants.get_empty_policy()
         success = True
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         policy = constants.get_empty_policy()
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 11
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     try:
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses.html#SES.Client.list_identity_policies
         response = self.client.describe_elasticsearch_domain_config(DomainName=self.name)
         domain_config = response.get("DomainConfig")
         policy = domain_config.get("AccessPolicies").get("Options")
         if policy:
             policy = json.loads(policy)
         else:
             policy = constants.get_empty_policy()
         success = True
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         policy = constants.get_empty_policy()
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document, success=success)
     return response
Exemplo n.º 12
0
 def _get_rbp(self) -> ResponseGetRbp:
     """Get the resource based policy for this resource and store it"""
     logger.debug("Getting resource policy for %s" % self.arn)
     try:
         response = self.client.get_resource_policy(SecretId=self.name)
         if response.get("ResourcePolicy"):
             policy = json.loads(response.get("ResourcePolicy"))
         else:
             policy = constants.get_empty_policy()
         success = True
     except botocore.exceptions.ClientError:
         # When there is no policy, let's return an empty policy to avoid breaking things
         policy = constants.get_empty_policy()
         success = False
     policy_document = PolicyDocument(
         policy=policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     response = ResponseGetRbp(policy_document=policy_document,
                               success=success)
     return response
Exemplo n.º 13
0
 def test_policy_plus_evil_principal(self):
     empty_statements = {"Version": "2012-10-17", "Statement": []}
     empty_statements_document = PolicyDocument(
         policy=empty_statements,
         service="iam",
         override_resource_block="*",
     )
     policy = empty_statements_document.policy_plus_evil_principal(
         victim_account_id="111122223333",
         evil_principal="arn:aws:iam::999988887777:user/mwahahaha")
     print(json.dumps(policy, indent=4))
     self.assertEqual(policy["Statement"][0]["Sid"], "AllowCurrentAccount")
     self.assertEqual(policy["Statement"][0]["Principal"]["AWS"][0],
                      "arn:aws:iam::111122223333:root")
     self.assertEqual(policy["Statement"][1]["Sid"], "Endgame")
     self.assertEqual(policy["Statement"][1]["Principal"]["AWS"][0],
                      "arn:aws:iam::999988887777:user/mwahahaha")
Exemplo n.º 14
0
 def set_rbp(self, evil_policy: dict) -> ResponseMessage:
     logger.debug("Setting resource policy for %s" % self.arn)
     new_policy_document = PolicyDocument(
         policy=evil_policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     new_policy_json = {"Version": "2012-10-17", "Statement": []}
     current_sids = get_sid_names_with_error_handling(self.original_policy)
     success = True
     try:
         for statement in new_policy_document.statements:
             if statement.sid not in current_sids:
                 if ":" in statement.aws_principals[0]:
                     account_id = get_account_from_arn(
                         statement.aws_principals[0])
                     principal = f"arn:aws:iam::{account_id}:root"
                 elif "*" == statement.aws_principals[0]:
                     principal = "*"
                 else:
                     principal = statement.aws_principals[0]
                 try:
                     self.client.add_layer_version_permission(
                         LayerName=self.arn_without_version,
                         VersionNumber=self.version,
                         StatementId=statement.sid,
                         Action="lambda:GetLayerVersion",
                         Principal=principal,
                     )
                 except botocore.exceptions.ClientError as error:
                     success = False
                     logger.critical(
                         f"Operation was not successful for {self.service} {self.resource_type} "
                         f"{self.name}. %s" % error)
             new_policy_json["Statement"].append(
                 json.loads(statement.__str__()))
         message = "success"
     except botocore.exceptions.ClientError as error:
         message = str(error)
         success = False
     policy_document = self._get_rbp().policy_document
     response_message = ResponseMessage(
         message=message,
         operation="set_rbp",
         success=success,
         evil_principal="",
         victim_resource_arn=self.arn,
         original_policy=self.original_policy,
         updated_policy=policy_document.json,
         resource_type=self.resource_type,
         resource_name=self.name,
         service=self.service)
     return response_message
Exemplo n.º 15
0
 def test_get_allow_current_account_id(self):
     """Allow Current account ID"""
     empty_statements = {"Version": "2012-10-17", "Statement": []}
     empty_statements_document = PolicyDocument(policy=empty_statements,
                                                service="iam",
                                                override_resource_block="*")
     statement = empty_statements_document.statement_allow_account_id(
         "999988887777", "*")
     # results = json.loads(empty_statements_document.__str__())
     print(json.dumps(statement, indent=4))
     # self.assertDictEqual(results, empty_statements)
     expected_result = {
         "Sid": "AllowCurrentAccount",
         "Effect": "Allow",
         "Principal": {
             "AWS": ["arn:aws:iam::999988887777:root"]
         },
         "Resource": ["*"],
         "Action": ["iam:*"]
     }
     self.assertEqual(statement["Resource"][0], "*")
     self.assertDictEqual(statement, expected_result)
Exemplo n.º 16
0
 def set_rbp(self, evil_policy: dict) -> ResponseMessage:
     logger.debug("Setting resource policy for %s" % self.arn)
     new_policy_document = PolicyDocument(
         policy=evil_policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     new_policy_json = {"Version": "2012-10-17", "Statement": []}
     current_sids = get_sid_names_with_error_handling(self.original_policy)
     try:
         for statement in new_policy_document.statements:
             if statement.sid not in current_sids:
                 account_ids = []
                 for principal in statement.aws_principals:
                     if ":" in principal:
                         account_ids.append(get_account_from_arn(principal))
                 self.client.add_permission(
                     QueueUrl=self.queue_url,
                     Label=statement.sid,
                     AWSAccountIds=account_ids,
                     Actions=self.sqs_actions_without_prefixes(
                         statement.actions))
             else:
                 new_policy_json["Statement"].append(
                     json.loads(statement.__str__()))
         message = "success"
         success = True
     except botocore.exceptions.ClientError as error:
         message = str(error)
         success = False
     get_rbp_response = self._get_rbp()
     response_message = ResponseMessage(
         message=message,
         operation="set_rbp",
         success=success,
         evil_principal="",
         victim_resource_arn=self.arn,
         original_policy=self.original_policy,
         updated_policy=get_rbp_response.policy_document.json,
         resource_type=self.resource_type,
         resource_name=self.name,
         service=self.service)
     return response_message
Exemplo n.º 17
0
 def set_rbp(self, evil_policy: dict) -> ResponseMessage:
     logger.debug("Setting resource policy for %s" % self.arn)
     new_policy_document = PolicyDocument(
         policy=evil_policy,
         service=self.service,
         override_action=self.override_action,
         include_resource_block=self.include_resource_block,
         override_resource_block=self.override_resource_block,
         override_account_id_instead_of_principal=self.
         override_account_id_instead_of_principal,
     )
     new_policy_json = {"Version": "2012-10-17", "Statement": []}
     current_sids = get_sid_names_with_error_handling(self.original_policy)
     try:
         for statement in new_policy_document.statements:
             if statement.sid not in current_sids:
                 self.client.add_permission(
                     TopicArn=self.arn,
                     Label=statement.sid,
                     ActionName=self.sns_actions_without_prefixes(
                         statement.actions),
                     AWSAccountId=statement.aws_principals,
                 )
             new_policy_json["Statement"].append(
                 json.loads(statement.__str__()))
         message = "success"
         success = True
     except botocore.exceptions.ClientError as error:
         message = str(error)
         success = False
         logger.critical(
             f"Operation was not successful for {self.service} {self.resource_type} "
             f"{self.name}. %s" % error)
     get_rbp_response = self._get_rbp()
     response_message = ResponseMessage(
         message=message,
         operation="set_rbp",
         success=success,
         evil_principal="",
         victim_resource_arn=self.arn,
         original_policy=self.original_policy,
         updated_policy=get_rbp_response.policy_document.json,
         resource_type=self.resource_type,
         resource_name=self.name,
         service=self.service)
     return response_message
Exemplo n.º 18
0
 def setUp(self):
     self.override_account_id_document = PolicyDocument(
         policy=kms_policy,
         service="kms",
         override_account_id_instead_of_principal=True,
         override_resource_block="*")
     self.policy_with_principal_service = PolicyDocument(
         policy=ec2_assume_role_policy,
         service="iam",
         override_action="sts:AssumeRole",
         override_account_id_instead_of_principal=False,
         include_resource_block=False)
     self.override_action_policy = PolicyDocument(
         policy=ec2_assume_role_policy,
         service="iam",
         override_action="sts:Yolo",
         override_account_id_instead_of_principal=False,
         include_resource_block=False)
Exemplo n.º 19
0
class PolicyDocumentTestCase(unittest.TestCase):
    def setUp(self):
        self.override_account_id_document = PolicyDocument(
            policy=kms_policy,
            service="kms",
            override_account_id_instead_of_principal=True,
            override_resource_block="*")
        self.policy_with_principal_service = PolicyDocument(
            policy=ec2_assume_role_policy,
            service="iam",
            override_action="sts:AssumeRole",
            override_account_id_instead_of_principal=False,
            include_resource_block=False)
        self.override_action_policy = PolicyDocument(
            policy=ec2_assume_role_policy,
            service="iam",
            override_action="sts:Yolo",
            override_account_id_instead_of_principal=False,
            include_resource_block=False)

    def test_override_account_id_instead_of_principal(self):

        results = json.loads(self.override_account_id_document.__str__())
        allow_current_account_id = results['Statement'][0]['Principal']['AWS'][
            0]
        self.assertEqual(allow_current_account_id, "123456789012")
        evil_current_account_id = results['Statement'][1]['Principal']['AWS'][
            0]
        self.assertEqual(evil_current_account_id, "999988887777")
        # print(json.dumps(results, indent=4))

    def test_statement_with_principal_service(self):
        results = json.loads(self.policy_with_principal_service.__str__())
        print(json.dumps(results, indent=4))
        expected_results = {
            "Version":
            "2012-10-17",
            "Statement": [{
                "Sid": "",
                "Effect": "Allow",
                "Principal": {
                    "Service": "ec2.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }]
        }
        self.assertDictEqual(results, expected_results)

    def test_override_action(self):
        results = json.loads(self.override_action_policy.__str__())
        print(json.dumps(results, indent=4))
        expected_results = {
            "Version":
            "2012-10-17",
            "Statement": [{
                "Sid": "",
                "Effect": "Allow",
                "Principal": {
                    "Service": "ec2.amazonaws.com"
                },
                "Action": "sts:Yolo"
            }]
        }
        self.assertDictEqual(results, expected_results)

    def test_empty_statements(self):
        """If there are no statements, it should not break."""
        empty_statements = {"Version": "2012-10-17", "Statement": []}
        empty_statements_document = PolicyDocument(
            policy=empty_statements,
            service="iam",
        )
        results = json.loads(empty_statements_document.__str__())
        print(json.dumps(results, indent=4))
        self.assertDictEqual(results, empty_statements)

    def test_get_allow_current_account_id(self):
        """Allow Current account ID"""
        empty_statements = {"Version": "2012-10-17", "Statement": []}
        empty_statements_document = PolicyDocument(policy=empty_statements,
                                                   service="iam",
                                                   override_resource_block="*")
        statement = empty_statements_document.statement_allow_account_id(
            "999988887777", "*")
        # results = json.loads(empty_statements_document.__str__())
        print(json.dumps(statement, indent=4))
        # self.assertDictEqual(results, empty_statements)
        expected_result = {
            "Sid": "AllowCurrentAccount",
            "Effect": "Allow",
            "Principal": {
                "AWS": ["arn:aws:iam::999988887777:root"]
            },
            "Resource": ["*"],
            "Action": ["iam:*"]
        }
        self.assertEqual(statement["Resource"][0], "*")
        self.assertDictEqual(statement, expected_result)

    def test_policy_plus_evil_principal(self):
        empty_statements = {"Version": "2012-10-17", "Statement": []}
        empty_statements_document = PolicyDocument(
            policy=empty_statements,
            service="iam",
            override_resource_block="*",
        )
        policy = empty_statements_document.policy_plus_evil_principal(
            victim_account_id="111122223333",
            evil_principal="arn:aws:iam::999988887777:user/mwahahaha")
        print(json.dumps(policy, indent=4))
        self.assertEqual(policy["Statement"][0]["Sid"], "AllowCurrentAccount")
        self.assertEqual(policy["Statement"][0]["Principal"]["AWS"][0],
                         "arn:aws:iam::111122223333:root")
        self.assertEqual(policy["Statement"][1]["Sid"], "Endgame")
        self.assertEqual(policy["Statement"][1]["Principal"]["AWS"][0],
                         "arn:aws:iam::999988887777:user/mwahahaha")