| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | import boto3 | 
					
						
							| 
									
										
										
										
											2021-10-04 13:47:40 +00:00
										 |  |  | import json | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | import yaml | 
					
						
							| 
									
										
										
										
											2022-03-11 20:28:45 -01:00
										 |  |  | import sure  # noqa # pylint: disable=unused-import | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | from botocore.exceptions import ClientError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  | from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | 
					
						
							| 
									
										
										
										
											2021-10-04 13:47:40 +00:00
										 |  |  | from moto import mock_autoscaling, mock_iam, mock_cloudformation, mock_s3, mock_sts | 
					
						
							|  |  |  | from tests import EXAMPLE_AMI_ID | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 11:00:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | TEMPLATE_MINIMAL_ROLE = """
 | 
					
						
							|  |  |  | AWSTemplateFormatVersion: 2010-09-09 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   RootRole: | 
					
						
							|  |  |  |     Type: 'AWS::IAM::Role' | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       AssumeRolePolicyDocument: | 
					
						
							|  |  |  |         Version: 2012-10-17 | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |           - Effect: Allow | 
					
						
							|  |  |  |             Principal: | 
					
						
							|  |  |  |               Service: | 
					
						
							|  |  |  |               - ec2.amazonaws.com | 
					
						
							|  |  |  |             Action: | 
					
						
							|  |  |  |               - 'sts:AssumeRole' | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEMPLATE_ROLE_INSTANCE_PROFILE = """
 | 
					
						
							|  |  |  | AWSTemplateFormatVersion: 2010-09-09 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   RootRole: | 
					
						
							|  |  |  |     Type: 'AWS::IAM::Role' | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       RoleName: {0} | 
					
						
							|  |  |  |       AssumeRolePolicyDocument: | 
					
						
							|  |  |  |         Version: 2012-10-17 | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |           - Effect: Allow | 
					
						
							|  |  |  |             Principal: | 
					
						
							|  |  |  |               Service: | 
					
						
							|  |  |  |               - ec2.amazonaws.com | 
					
						
							|  |  |  |             Action: | 
					
						
							|  |  |  |               - 'sts:AssumeRole' | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       Policies: | 
					
						
							|  |  |  |         - PolicyName: root | 
					
						
							|  |  |  |           PolicyDocument: | 
					
						
							|  |  |  |             Version: 2012-10-17 | 
					
						
							|  |  |  |             Statement: | 
					
						
							|  |  |  |               - Effect: Allow | 
					
						
							|  |  |  |                 Action: '*' | 
					
						
							|  |  |  |                 Resource: '*' | 
					
						
							|  |  |  |   RootInstanceProfile: | 
					
						
							|  |  |  |     Type: 'AWS::IAM::InstanceProfile' | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - !Ref RootRole | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 13:47:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | # AWS::IAM::User Tests | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_user(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: {0} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     provisioned_resource["LogicalResourceId"].should.equal("TheUser") | 
					
						
							|  |  |  |     provisioned_resource["PhysicalResourceId"].should.equal(user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_user_no_interruption(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user = iam_client.get_user(UserName=user_name)["User"] | 
					
						
							|  |  |  |     user["Path"].should.equal("/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     path = "/MyPath/" | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Path: {0} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         path | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     user = iam_client.get_user(UserName=user_name)["User"] | 
					
						
							|  |  |  |     user["Path"].should.equal(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_user_replacement(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     original_user_name = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user = iam_client.get_user(UserName=original_user_name)["User"] | 
					
						
							|  |  |  |     user["Path"].should.equal("/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new_user_name = "MyUser" | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: {0} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         new_user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as e: | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  |         iam_client.get_user(UserName=original_user_name) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     e.value.response["Error"]["Code"].should.equal("NoSuchEntity") | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_user(UserName=new_user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_drop_user(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheFirstUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheSecondUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     first_provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheFirstUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     second_provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheSecondUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     first_user_name = first_provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  |     second_user_name = second_provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     iam_client.get_user(UserName=first_user_name) | 
					
						
							|  |  |  |     iam_client.get_user(UserName=second_user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheSecondUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     len(provisioned_resources).should.equal(1) | 
					
						
							|  |  |  |     second_provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheSecondUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     second_user_name.should.equal(second_provisioned_user["PhysicalResourceId"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_user(UserName=second_user_name) | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as e: | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  |         iam_client.get_user(UserName=first_user_name) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     e.value.response["Error"]["Code"].should.equal("NoSuchEntity") | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_user(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: {} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as e: | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |         iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     e.value.response["Error"]["Code"].should.equal("NoSuchEntity") | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_user_having_generated_name(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     provisioned_resource["LogicalResourceId"].should.equal("TheUser") | 
					
						
							|  |  |  |     user_name = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as e: | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |         iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     e.value.response["Error"]["Code"].should.equal("NoSuchEntity") | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_user_get_attr(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: {0} | 
					
						
							|  |  |  | Outputs: | 
					
						
							|  |  |  |   UserName: | 
					
						
							|  |  |  |     Value: !Ref TheUser | 
					
						
							|  |  |  |   UserArn: | 
					
						
							|  |  |  |     Value: !GetAtt TheUser.Arn | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  |     stack_description = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0] | 
					
						
							|  |  |  |     output_user_name = [ | 
					
						
							|  |  |  |         output["OutputValue"] | 
					
						
							|  |  |  |         for output in stack_description["Outputs"] | 
					
						
							|  |  |  |         if output["OutputKey"] == "UserName" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     output_user_arn = [ | 
					
						
							|  |  |  |         output["OutputValue"] | 
					
						
							|  |  |  |         for output in stack_description["Outputs"] | 
					
						
							|  |  |  |         if output["OutputKey"] == "UserArn" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user_description = iam_client.get_user(UserName=output_user_name)["User"] | 
					
						
							|  |  |  |     output_user_arn.should.equal(user_description["Arn"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  | # AWS::IAM::ManagedPolicy Tests | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_managed_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::ManagedPolicy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: '*' | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy_arn = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  |     policy_arn.should.match( | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |         f"arn:aws:iam::{ACCOUNT_ID}:policy/MyStack-ThePolicy-[A-Z0-9]+" | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     expected_name = policy_arn.split("/")[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response = iam_client.list_entities_for_policy(PolicyArn=policy_arn) | 
					
						
							|  |  |  |     response.should.have.key("PolicyGroups").equal([]) | 
					
						
							|  |  |  |     response.should.have.key("PolicyUsers").equal([]) | 
					
						
							|  |  |  |     response.should.have.key("PolicyRoles").equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy = iam_client.get_policy(PolicyArn=policy_arn)["Policy"] | 
					
						
							|  |  |  |     policy.should.have.key("Arn").equal(policy_arn) | 
					
						
							|  |  |  |     policy.should.have.key("PolicyName").equal(expected_name) | 
					
						
							|  |  |  |     policy.should.have.key("Description").equal("") | 
					
						
							|  |  |  |     policy.should.have.key("Path").equal("/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_managed_policy_with_additional_properties(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     name = "FancyManagedPolicy" | 
					
						
							|  |  |  |     desc = "Custom managed policy with name" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::ManagedPolicy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Description: {0} | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       ManagedPolicyName: {1} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: '*' | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         desc, name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy_arn = provisioned_resource["PhysicalResourceId"] | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     policy_arn.should.equal(f"arn:aws:iam::{ACCOUNT_ID}:policy/{name}") | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     policy = iam_client.get_policy(PolicyArn=policy_arn)["Policy"] | 
					
						
							|  |  |  |     policy.should.have.key("Arn").equal(policy_arn) | 
					
						
							|  |  |  |     policy.should.have.key("Path").equal("/") | 
					
						
							|  |  |  |     policy.should.have.key("Description").equal(desc) | 
					
						
							|  |  |  |     policy.should.have.key("PolicyName").equal(name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_managed_policy_attached_to_a_group(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     group_name = "MyGroup" | 
					
						
							|  |  |  |     iam_client.create_group(GroupName=group_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     desc = "Custom managed policy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::ManagedPolicy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Description: {0} | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: '*' | 
					
						
							|  |  |  |       Groups: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         desc, group_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy_arn = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  |     policy_arn.should.match( | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |         f"rn:aws:iam::{ACCOUNT_ID}:policy/MyStack-ThePolicy-[A-Z0-9]+" | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response = iam_client.list_entities_for_policy(PolicyArn=policy_arn) | 
					
						
							|  |  |  |     response.should.have.key("PolicyUsers").equal([]) | 
					
						
							|  |  |  |     response.should.have.key("PolicyRoles").equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 06:28:42 -05:00
										 |  |  |     response["PolicyGroups"][0]["GroupName"].should.be.equal(group_name) | 
					
						
							|  |  |  |     response["PolicyGroups"][0].should.have.key("GroupId") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_managed_policy_attached_to_a_user(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     desc = "Custom managed policy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::ManagedPolicy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Description: {0} | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: '*' | 
					
						
							|  |  |  |       Users: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         desc, user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy_arn = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  |     policy_arn.should.match( | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |         f"rn:aws:iam::{ACCOUNT_ID}:policy/MyStack-ThePolicy-[A-Z0-9]+" | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response = iam_client.list_entities_for_policy(PolicyArn=policy_arn) | 
					
						
							|  |  |  |     response.should.have.key("PolicyGroups").equal([]) | 
					
						
							|  |  |  |     response.should.have.key("PolicyRoles").equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 06:28:42 -05:00
										 |  |  |     response["PolicyUsers"][0]["UserName"].should.be.equal(user_name) | 
					
						
							|  |  |  |     response["PolicyUsers"][0].should.have.key("UserId") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_managed_policy_attached_to_a_role(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     role_name = "MyRole" | 
					
						
							|  |  |  |     iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="some policy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     desc = "Custom managed policy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::ManagedPolicy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Description: {0} | 
					
						
							|  |  |  |       Path: / | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: '*' | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         desc, role_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     policy_arn = provisioned_resource["PhysicalResourceId"] | 
					
						
							|  |  |  |     policy_arn.should.match( | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |         f"rn:aws:iam::{ACCOUNT_ID}:policy/MyStack-ThePolicy-[A-Z0-9]+" | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response = iam_client.list_entities_for_policy(PolicyArn=policy_arn) | 
					
						
							|  |  |  |     response.should.have.key("PolicyGroups").equal([]) | 
					
						
							|  |  |  |     response.should.have.key("PolicyUsers").equal([]) | 
					
						
							| 
									
										
										
										
											2022-02-25 06:28:42 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response["PolicyRoles"][0]["RoleName"].should.be.equal(role_name) | 
					
						
							|  |  |  |     response["PolicyRoles"][0].should.have.key("RoleId") | 
					
						
							| 
									
										
										
										
											2021-08-28 07:32:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | # AWS::IAM::Policy Tests | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_user_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Users: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_user_policy(UserName=user_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_user_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user_name_1 = "MyUser1" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=user_name_1) | 
					
						
							|  |  |  |     user_name_2 = "MyUser2" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=user_name_2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Users: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, user_name_1 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_user_policy(UserName=user_name_1, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Change template and user | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:ListBuckets | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Users: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, user_name_2 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_user_policy(UserName=user_name_2, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_user_policy.when.called_with( | 
					
						
							|  |  |  |         UserName=user_name_1, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_user_policy_having_generated_name(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user_name = "MyUser" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: MyPolicy | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {0} | 
					
						
							|  |  |  |       Users: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         bucket_arn, user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_user_policy(UserName=user_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  |     iam_client.get_user_policy.when.called_with( | 
					
						
							|  |  |  |         UserName=user_name, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_role_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     role_name = "MyRole" | 
					
						
							|  |  |  |     iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="{}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, role_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_role_policy(RoleName=role_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_role_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     role_name_1 = "MyRole1" | 
					
						
							|  |  |  |     iam_client.create_role(RoleName=role_name_1, AssumeRolePolicyDocument="{}") | 
					
						
							|  |  |  |     role_name_2 = "MyRole2" | 
					
						
							|  |  |  |     iam_client.create_role(RoleName=role_name_2, AssumeRolePolicyDocument="{}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, role_name_1 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_role_policy(RoleName=role_name_1, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Change template and user | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:ListBuckets | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, role_name_2 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_role_policy(RoleName=role_name_2, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_role_policy.when.called_with( | 
					
						
							|  |  |  |         RoleName=role_name_1, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_role_policy_having_generated_name(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     role_name = "MyRole" | 
					
						
							|  |  |  |     iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="{}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: MyPolicy | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {0} | 
					
						
							|  |  |  |       Roles: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         bucket_arn, role_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_role_policy(RoleName=role_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  |     iam_client.get_role_policy.when.called_with( | 
					
						
							|  |  |  |         RoleName=role_name, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_group_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     group_name = "MyGroup" | 
					
						
							|  |  |  |     iam_client.create_group(GroupName=group_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Groups: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, group_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_group_policy(GroupName=group_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_group_policy(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     group_name_1 = "MyGroup1" | 
					
						
							|  |  |  |     iam_client.create_group(GroupName=group_name_1) | 
					
						
							|  |  |  |     group_name_2 = "MyGroup2" | 
					
						
							|  |  |  |     iam_client.create_group(GroupName=group_name_2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Groups: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, group_name_1 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_group_policy(GroupName=group_name_1, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Change template and user | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: {0} | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:ListBuckets | 
					
						
							|  |  |  |           Resource: {1} | 
					
						
							|  |  |  |       Groups: | 
					
						
							|  |  |  |         - {2} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         policy_name, bucket_arn, group_name_2 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_group_policy(GroupName=group_name_2, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_group_policy.when.called_with( | 
					
						
							|  |  |  |         GroupName=group_name_1, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_s3 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_group_policy_having_generated_name(): | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     group_name = "MyGroup" | 
					
						
							|  |  |  |     iam_client.create_group(GroupName=group_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s3_client = boto3.client("s3", region_name="us-east-1") | 
					
						
							|  |  |  |     bucket_name = "my-bucket" | 
					
						
							|  |  |  |     s3_client.create_bucket(Bucket=bucket_name) | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     bucket_arn = f"arn:aws:s3:::{bucket_name}" | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     policy_name = "MyPolicy" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   ThePolicy: | 
					
						
							|  |  |  |     Type: AWS::IAM::Policy | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       PolicyName: MyPolicy | 
					
						
							|  |  |  |       PolicyDocument: | 
					
						
							|  |  |  |         Version: '2012-10-17' | 
					
						
							|  |  |  |         Statement: | 
					
						
							|  |  |  |         - Effect: Allow | 
					
						
							|  |  |  |           Action: s3:* | 
					
						
							|  |  |  |           Resource: {0} | 
					
						
							|  |  |  |       Groups: | 
					
						
							|  |  |  |         - {1} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         bucket_arn, group_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     logical_resource_id = provisioned_resource["LogicalResourceId"] | 
					
						
							|  |  |  |     logical_resource_id.should.equal("ThePolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][ | 
					
						
							|  |  |  |         logical_resource_id | 
					
						
							|  |  |  |     ]["Properties"]["PolicyDocument"] | 
					
						
							|  |  |  |     policy = iam_client.get_group_policy(GroupName=group_name, PolicyName=policy_name) | 
					
						
							|  |  |  |     policy["PolicyDocument"].should.equal(original_policy_document) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  |     iam_client.get_group_policy.when.called_with( | 
					
						
							|  |  |  |         GroupName=group_name, PolicyName=policy_name | 
					
						
							|  |  |  |     ).should.throw(iam_client.exceptions.NoSuchEntityException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # AWS::IAM::User AccessKeys | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_user_with_access_key(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: !Ref TheUser | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_access_keys = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheAccessKey" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     len(provisioned_access_keys).should.equal(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user = iam_client.get_user(UserName=user_name)["User"] | 
					
						
							|  |  |  |     user["UserName"].should.equal(user_name) | 
					
						
							|  |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							|  |  |  |     access_keys["AccessKeyMetadata"][0]["UserName"].should.equal(user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_sts | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_access_key_get_attr(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: !Ref TheUser | 
					
						
							|  |  |  | Outputs: | 
					
						
							|  |  |  |   AccessKeyId: | 
					
						
							|  |  |  |     Value: !Ref TheAccessKey | 
					
						
							|  |  |  |   SecretKey: | 
					
						
							|  |  |  |     Value: !GetAtt TheAccessKey.SecretAccessKey | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_description = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0] | 
					
						
							|  |  |  |     output_access_key_id = [ | 
					
						
							|  |  |  |         output["OutputValue"] | 
					
						
							|  |  |  |         for output in stack_description["Outputs"] | 
					
						
							|  |  |  |         if output["OutputKey"] == "AccessKeyId" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     output_secret_key = [ | 
					
						
							|  |  |  |         output["OutputValue"] | 
					
						
							|  |  |  |         for output in stack_description["Outputs"] | 
					
						
							|  |  |  |         if output["OutputKey"] == "SecretKey" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sts_client = boto3.client( | 
					
						
							|  |  |  |         "sts", | 
					
						
							|  |  |  |         aws_access_key_id=output_access_key_id, | 
					
						
							|  |  |  |         aws_secret_access_key=output_secret_key, | 
					
						
							|  |  |  |         region_name="us-east-1", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     caller_identity = sts_client.get_caller_identity() | 
					
						
							|  |  |  |     caller_identity["Arn"].split("/")[1].should.equal(user_name) | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_delete_users_access_key(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  |     Resources: | 
					
						
							|  |  |  |       TheUser: | 
					
						
							|  |  |  |         Type: AWS::IAM::User | 
					
						
							|  |  |  |       TheAccessKey: | 
					
						
							|  |  |  |         Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |         Properties: | 
					
						
							|  |  |  |           UserName: !Ref TheUser | 
					
						
							|  |  |  |     """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_access_keys = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheAccessKey" | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-02-01 12:37:54 +01:00
										 |  |  |     provisioned_access_keys.should.have.length_of(1) | 
					
						
							|  |  |  |     access_key_id = provisioned_access_keys[0]["PhysicalResourceId"] | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     user = iam_client.get_user(UserName=user_name)["User"] | 
					
						
							|  |  |  |     user["UserName"].should.equal(user_name) | 
					
						
							|  |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2021-08-21 16:33:15 +01:00
										 |  |  |     access_keys["AccessKeyMetadata"][0]["AccessKeyId"].should.equal(access_key_id) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  |     access_keys["AccessKeyMetadata"][0]["UserName"].should.equal(user_name) | 
					
						
							| 
									
										
										
										
											2021-02-01 12:37:54 +01:00
										 |  |  |     access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"]) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.get_user.when.called_with(UserName=user_name).should.throw( | 
					
						
							|  |  |  |         iam_client.exceptions.NoSuchEntityException | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     iam_client.list_access_keys.when.called_with(UserName=user_name).should.throw( | 
					
						
							|  |  |  |         iam_client.exceptions.NoSuchEntityException | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_users_access_key_no_interruption(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: !Ref TheUser | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_access_key = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheAccessKey" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     access_key_id = provisioned_access_key["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							|  |  |  |     access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       Status: Inactive | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							|  |  |  |     access_keys["AccessKeyMetadata"][0]["Status"].should.equal("Inactive") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_update_users_access_key_replacement(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: !Ref TheUser | 
					
						
							|  |  |  | """.strip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_user = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheUser" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     user_name = provisioned_user["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     provisioned_access_key = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in provisioned_resources | 
					
						
							|  |  |  |         if resource["LogicalResourceId"] == "TheAccessKey" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     access_key_id = provisioned_access_key["PhysicalResourceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     iam_client.get_user(UserName=user_name) | 
					
						
							| 
									
										
										
										
											2020-08-27 05:11:47 -04:00
										 |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							|  |  |  |     access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     other_user_name = "MyUser" | 
					
						
							|  |  |  |     iam_client.create_user(UserName=other_user_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = """
 | 
					
						
							|  |  |  | Resources: | 
					
						
							|  |  |  |   TheUser: | 
					
						
							|  |  |  |     Type: AWS::IAM::User | 
					
						
							|  |  |  |   TheAccessKey: | 
					
						
							|  |  |  |     Type: AWS::IAM::AccessKey | 
					
						
							|  |  |  |     Properties: | 
					
						
							|  |  |  |       UserName: {0} | 
					
						
							|  |  |  | """.strip().format(
 | 
					
						
							|  |  |  |         other_user_name | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.update_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     access_keys = iam_client.list_access_keys(UserName=user_name) | 
					
						
							|  |  |  |     len(access_keys["AccessKeyMetadata"]).should.equal(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     access_keys = iam_client.list_access_keys(UserName=other_user_name) | 
					
						
							|  |  |  |     access_key_id.should_not.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"]) | 
					
						
							| 
									
										
										
										
											2021-08-28 11:00:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_role(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = TEMPLATE_MINIMAL_ROLE.strip() | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     role = [res for res in resources if res["ResourceType"] == "AWS::IAM::Role"][0] | 
					
						
							|  |  |  |     role["LogicalResourceId"].should.equal("RootRole") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     iam_client.list_roles()["Roles"].should.have.length_of(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.list_roles()["Roles"].should.have.length_of(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_cloudformation_create_role_and_instance_profile(): | 
					
						
							|  |  |  |     cf_client = boto3.client("cloudformation", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack_name = "MyStack" | 
					
						
							|  |  |  |     role_name = "MyUser" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template = TEMPLATE_ROLE_INSTANCE_PROFILE.strip().format(role_name) | 
					
						
							|  |  |  |     cf_client.create_stack(StackName=stack_name, TemplateBody=template) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resources = cf_client.list_stack_resources(StackName=stack_name)[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     role = [res for res in resources if res["ResourceType"] == "AWS::IAM::Role"][0] | 
					
						
							|  |  |  |     role["LogicalResourceId"].should.equal("RootRole") | 
					
						
							|  |  |  |     role["PhysicalResourceId"].should.equal(role_name) | 
					
						
							|  |  |  |     profile = [ | 
					
						
							|  |  |  |         res for res in resources if res["ResourceType"] == "AWS::IAM::InstanceProfile" | 
					
						
							|  |  |  |     ][0] | 
					
						
							|  |  |  |     profile["LogicalResourceId"].should.equal("RootInstanceProfile") | 
					
						
							|  |  |  |     profile["PhysicalResourceId"].should.contain( | 
					
						
							|  |  |  |         stack_name | 
					
						
							|  |  |  |     )  # e.g. MyStack-RootInstanceProfile-73Y4H4ALFW3N | 
					
						
							|  |  |  |     profile["PhysicalResourceId"].should.contain("RootInstanceProfile") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client = boto3.client("iam", region_name="us-east-1") | 
					
						
							|  |  |  |     iam_client.list_roles()["Roles"].should.have.length_of(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf_client.delete_stack(StackName=stack_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_client.list_roles()["Roles"].should.have.length_of(0) | 
					
						
							| 
									
										
										
										
											2021-10-04 13:47:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_autoscaling | 
					
						
							|  |  |  | @mock_iam | 
					
						
							|  |  |  | @mock_cloudformation | 
					
						
							|  |  |  | def test_iam_roles(): | 
					
						
							|  |  |  |     iam_template = { | 
					
						
							|  |  |  |         "AWSTemplateFormatVersion": "2010-09-09", | 
					
						
							|  |  |  |         "Resources": { | 
					
						
							|  |  |  |             "my-launch-config": { | 
					
						
							|  |  |  |                 "Properties": { | 
					
						
							|  |  |  |                     "IamInstanceProfile": {"Ref": "my-instance-profile-with-path"}, | 
					
						
							|  |  |  |                     "ImageId": EXAMPLE_AMI_ID, | 
					
						
							|  |  |  |                     "InstanceType": "t2.medium", | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 "Type": "AWS::AutoScaling::LaunchConfiguration", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "my-instance-profile-with-path": { | 
					
						
							|  |  |  |                 "Properties": { | 
					
						
							|  |  |  |                     "Path": "my-path", | 
					
						
							|  |  |  |                     "Roles": [{"Ref": "my-role-with-path"}], | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 "Type": "AWS::IAM::InstanceProfile", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "my-instance-profile-no-path": { | 
					
						
							|  |  |  |                 "Properties": {"Roles": [{"Ref": "my-role-no-path"}]}, | 
					
						
							|  |  |  |                 "Type": "AWS::IAM::InstanceProfile", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "my-role-with-path": { | 
					
						
							|  |  |  |                 "Properties": { | 
					
						
							|  |  |  |                     "AssumeRolePolicyDocument": { | 
					
						
							|  |  |  |                         "Statement": [ | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 "Action": ["sts:AssumeRole"], | 
					
						
							|  |  |  |                                 "Effect": "Allow", | 
					
						
							|  |  |  |                                 "Principal": {"Service": ["ec2.amazonaws.com"]}, | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         ] | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                     "Path": "/my-path/", | 
					
						
							|  |  |  |                     "Policies": [ | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             "PolicyDocument": { | 
					
						
							|  |  |  |                                 "Statement": [ | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         "Action": [ | 
					
						
							|  |  |  |                                             "ec2:CreateTags", | 
					
						
							|  |  |  |                                             "ec2:DescribeInstances", | 
					
						
							|  |  |  |                                             "ec2:DescribeTags", | 
					
						
							|  |  |  |                                         ], | 
					
						
							|  |  |  |                                         "Effect": "Allow", | 
					
						
							|  |  |  |                                         "Resource": ["*"], | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 ], | 
					
						
							|  |  |  |                                 "Version": "2012-10-17", | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                             "PolicyName": "EC2_Tags", | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             "PolicyDocument": { | 
					
						
							|  |  |  |                                 "Statement": [ | 
					
						
							|  |  |  |                                     { | 
					
						
							|  |  |  |                                         "Action": ["sqs:*"], | 
					
						
							|  |  |  |                                         "Effect": "Allow", | 
					
						
							|  |  |  |                                         "Resource": ["*"], | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 ], | 
					
						
							|  |  |  |                                 "Version": "2012-10-17", | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                             "PolicyName": "SQS", | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                     ], | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 "Type": "AWS::IAM::Role", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "my-role-no-path": { | 
					
						
							|  |  |  |                 "Properties": { | 
					
						
							|  |  |  |                     "RoleName": "my-role-no-path-name", | 
					
						
							|  |  |  |                     "AssumeRolePolicyDocument": { | 
					
						
							|  |  |  |                         "Statement": [ | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 "Action": ["sts:AssumeRole"], | 
					
						
							|  |  |  |                                 "Effect": "Allow", | 
					
						
							|  |  |  |                                 "Principal": {"Service": ["ec2.amazonaws.com"]}, | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         ] | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 "Type": "AWS::IAM::Role", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam_template_json = json.dumps(iam_template) | 
					
						
							|  |  |  |     cf = boto3.client("cloudformation", region_name="us-west-1") | 
					
						
							|  |  |  |     cf.create_stack(StackName="test_stack", TemplateBody=iam_template_json) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iam = boto3.client("iam", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     role_results = iam.list_roles()["Roles"] | 
					
						
							|  |  |  |     role_name_to_id = {} | 
					
						
							|  |  |  |     role_names = [] | 
					
						
							|  |  |  |     for role_result in role_results: | 
					
						
							|  |  |  |         role = iam.get_role(RoleName=role_result["RoleName"])["Role"] | 
					
						
							|  |  |  |         role_names.append(role["RoleName"]) | 
					
						
							|  |  |  |         # Role name is not specified, so randomly generated - can't check exact name | 
					
						
							|  |  |  |         if "with-path" in role["RoleName"]: | 
					
						
							|  |  |  |             role_name_to_id["with-path"] = role["RoleId"] | 
					
						
							|  |  |  |             role["Path"].should.equal("/my-path/") | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             role_name_to_id["no-path"] = role["RoleId"] | 
					
						
							|  |  |  |             role["RoleName"].should.equal("my-role-no-path-name") | 
					
						
							|  |  |  |             role["Path"].should.equal("/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     instance_profile_responses = iam.list_instance_profiles()["InstanceProfiles"] | 
					
						
							|  |  |  |     instance_profile_responses.should.have.length_of(2) | 
					
						
							|  |  |  |     instance_profile_names = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for instance_profile_response in instance_profile_responses: | 
					
						
							|  |  |  |         instance_profile = iam.get_instance_profile( | 
					
						
							|  |  |  |             InstanceProfileName=instance_profile_response["InstanceProfileName"] | 
					
						
							|  |  |  |         )["InstanceProfile"] | 
					
						
							|  |  |  |         instance_profile_names.append(instance_profile["InstanceProfileName"]) | 
					
						
							|  |  |  |         instance_profile["InstanceProfileName"].should.contain("my-instance-profile") | 
					
						
							|  |  |  |         if "with-path" in instance_profile["InstanceProfileName"]: | 
					
						
							|  |  |  |             instance_profile["Path"].should.equal("my-path") | 
					
						
							|  |  |  |             instance_profile["Roles"][0]["RoleId"].should.equal( | 
					
						
							|  |  |  |                 role_name_to_id["with-path"] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             instance_profile["InstanceProfileName"].should.contain("no-path") | 
					
						
							|  |  |  |             instance_profile["Roles"][0]["RoleId"].should.equal( | 
					
						
							|  |  |  |                 role_name_to_id["no-path"] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             instance_profile["Path"].should.equal("/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     autoscale = boto3.client("autoscaling", region_name="us-west-1") | 
					
						
							|  |  |  |     launch_config = autoscale.describe_launch_configurations()["LaunchConfigurations"][ | 
					
						
							|  |  |  |         0 | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     launch_config.should.have.key("IamInstanceProfile").should.contain( | 
					
						
							|  |  |  |         "my-instance-profile-with-path" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resources = cf.list_stack_resources(StackName="test_stack")[ | 
					
						
							|  |  |  |         "StackResourceSummaries" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     instance_profile_resources = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in resources | 
					
						
							|  |  |  |         if resource["ResourceType"] == "AWS::IAM::InstanceProfile" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     {ip["PhysicalResourceId"] for ip in instance_profile_resources}.should.equal( | 
					
						
							|  |  |  |         set(instance_profile_names) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     role_resources = [ | 
					
						
							|  |  |  |         resource | 
					
						
							|  |  |  |         for resource in resources | 
					
						
							|  |  |  |         if resource["ResourceType"] == "AWS::IAM::Role" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     {r["PhysicalResourceId"] for r in role_resources}.should.equal(set(role_names)) |