def ecs_task_execution_role(self) -> Role: """Return ecs task execution role, see role description for details.""" return Role( name="ECSTaskExecutionRole", description="grants the Amazon ECS container agent permission to make " "AWS API calls on your behalf.", trust=Trust(services=["ecs-tasks"]), managed_policy_arns=[ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ], )
def create_stack(self) -> list[Stack]: """Return MyCFNProject stack.""" self.add( ( Role( name="TestRole", description="TestRole description", trust={"Service": "test"}, ) ) ) return self.stack
def ecs_events_role(self) -> Role: """Return ecs events role, see role description for details.""" return Role( name="ECSEventsRole", description="Allow CloudWatch Events service to run Amazon ECS tasks", trust=Trust(services=["events"]), managed_policy_arns=[ "arn:aws:iam::aws:policy/service-role/" "AmazonEC2ContainerServiceEventsRole", Ref(name_to_id("ECSPassExecutionRolePolicy")), ], )
def test_role(stack: Stack) -> None: """Test IAM role creation. Creating a Role also tests PolicyDocument and Policystatement classes. """ stack.add( Role( name="TestRole", description="TestRole description", principal={"Service": "test"}, ) ) assert stack.export()["Resources"] == EXPECTED_ROLE
def test_role(stack: Stack) -> None: """Test IAM role creation. Creating a Role also tests PolicyDocument and Policystatement classes. """ stack.add( Role( name="TestRole", description="TestRole description", max_session_duration=7200, trust={"Service": "test"}, tags={"TestTagKey": "TestTagValue"}, )) assert stack.export()["Resources"] == EXPECTED_ROLE
def ecs_task_execution_role(self) -> Role: """Return ecs task execution role, see role description for details.""" # For unknown reason if path is provided for this role it cannot be # use by ECS task definitions. return Role( name="ECSTaskExecutionRole", description= "grants the Amazon ECS container agent permission to make " "AWS API calls on your behalf.", trust=Trust(services=["ecs-tasks"]), managed_policy_arns=[ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ], )
def test_stackset(stack: Stack) -> None: """test Cloudformation stack set creation.""" stack.s3_bucket = "cfn_bucket" stack.s3_key = "templates/" stack_set = StackSet( name="stack-set-test", description="this is a test", regions=["eu-west-1"], ous=["test-ou"], ) stack_set.add( Role( name="TestRole", description="TestRole description", trust={"Service": "test"}, ) ) stack_set.add_condition("", Equals(AccountId, "test_account_id")) stack.add(stack_set) assert stack.export()["Resources"] == EXPECTED_TEMPLATE
def build_and_deploy_tstacks() -> None: """Build and deploy two simple troposphere stacks. Two stacks in two different regions are deployed. An us stack define only a secure bucket. An eu stack define secure s3 buckets, a role to add object to the eu bucket and a AWSConfig recorder with rules that check s3 buckets security configurations across both regions. """ sessions = { "eu": Session(regions=["eu-west-1"]), "us": Session(regions=["us-east-1"]), } stack = {} for region in ("eu", "us"): stack[region] = Stack( f"e3-example-{region}", sessions[region], opts={"Capabilities": ["CAPABILITY_NAMED_IAM"]}, ) # Add a s3 secure bucket in each region stack["eu"].add_construct([Bucket(name="e3-l1-example")]) stack["us"].add_construct([Bucket(name="e3-l2-example")]) # Define a new IAM-Roles that will be used to acces e3-l1-example bucket stack["eu"].add_construct( [ Role( name="L1WriteRole", description="Role to write to l1 buckets", principal={"Service": "ecs-tasks.amazonaws.com"}, ) ] ) # Define a new IAM-Policy to putObject in e3-l1-example bucket # and attach the L1WriteRole role to it stack["eu"].add_construct( [ S3AccessManagedPolicy( name="S3WriteAccess", buckets=["e3-l1-example"], action=["s3:PutObject"], roles=[Ref(stack["eu"]["L1WriteRole"])], ) ] ) # Add AWS config rules to check S3 buckets security configuration. # This should only be defined in one region for region in ("eu",): stack[region].add_construct( [ConfigurationRecorder(bucket_name="config-bucket-example")] ) for region in ("eu",): stack[region].add_construct( [ S3BucketPublicWriteProhibited, S3BucketPublicReadProhibited, S3BucketServerSideEncryptionEnabled, S3BucketSSLRequestsOnly, IAMUserNoPoliciesCheck, ] ) # Deploy stacks for region in ("eu", "us"): stack[region].deploy()
def add_cache_invalidation(self, stack: Stack) -> list[AWSObject]: """Return resources invalidating cache when objects are pushed to s3. A lambda is called at each s3 object update to invalidate cloudformation cache for the updated object. """ lambda_name = f"{self.name}-cache-invalidation-lambda" lambda_policy = ManagedPolicy( name=f"{lambda_name}-policy", description=f"managed policy used by {lambda_name}", path=f"/{stack.name}/", statements=[ Allow( action=["cloudfront:CreateInvalidation"], resource=Join( "", [ "arn:aws:cloudfront::", AccountId, ":distribution ", self.id ], ), ) ], ) lambda_role = Role( name=f"{lambda_name}-role", description=f"role assumed by {lambda_name}", path=f"/{stack.name}/", trust=Trust(services=["lambda"]), managed_policy_arns=[lambda_policy.arn], ) # Get first part of invalidation lambda code from a file with open( os.path.join( os.path.dirname(os.path.abspath(__file__)), "data", "lambda_invalidate_head.py", )) as lf: lambda_code = lf.read().splitlines() # Complete it with the part depending on the distribution id lambda_code.extend([ " client.create_invalidation(", Sub( " DistributionId='${distribution_id}',", distribution_id=self.id, ), " InvalidationBatch={", " 'Paths': {'Quantity': 1, 'Items': path},", " 'CallerReference': str(time.time()),", " },", " )", ]) lambda_function = Function( name_to_id(lambda_name), description=(f"lambda invalidating cloudfront cache when " f"{self.bucket.name} objects are updated"), handler="invalidate.handler", role=lambda_role, code_zipfile=Join("\n", lambda_code), runtime="python3.9", ) sns_topic = Topic(name=f"{self.name}-invalidation-topic") sns_topic.add_lambda_subscription( function=lambda_function, delivery_policy={"throttlePolicy": { "maxReceivesPerSecond": 10 }}, ) # Trigger the invalidation when a file is updated self.bucket.add_notification_configuration(event="s3:ObjectCreated:*", target=sns_topic, permission_suffix=self.name) result = [ resource for construct in (lambda_policy, lambda_role, lambda_function, sns_topic) for resource in construct.resources(stack) ] return result