--- AWSTemplateFormatVersion: "2010-09-09" Description: This AWS CloudFormation Template configures an environment with the necessary resources to support the Serverless Round of the Identity Round-Robin Workshop. Parameters: ResourcePrefix: Type: String Default: identity-wksp-permissionsboundary AllowedValues: - identity-wksp-permissionsboundary Description: Prefix of resources created for this workshop. Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "Resource Configuration" Parameters: - ResourcePrefix - TeamName # Mappings: Resources: # Website Bucket Resources WebsiteBucket: Type: 'AWS::S3::Bucket' Properties: BucketName: Fn::Join: - '-' - ["shared-logging", !Ref "AWS::AccountId", !Ref "AWS::Region","data"] # Resources to copy website content WebsiteContent: DependsOn: - WebsiteBucket Type: "Custom::S3Objects" Properties: ServiceToken: !GetAtt WebsiteContentLambda.Arn Bucket: !Ref WebsiteBucket WebsiteContentLambdaRole: Type: AWS::IAM::Role Properties: RoleName: Fn::Join: - '-' - [!Ref ResourcePrefix, 'lambda-content'] AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: S3Access PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowLogging Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "*" - Sid: DestBucketWriteAccess Effect: Allow Action: - "s3:ListBucket" - "s3:GetObject" - "s3:PutObject" - "s3:PutObjectAcl" - "s3:PutObjectVersionAcl" - "s3:DeleteObject" - "s3:DeleteObjectVersion" - "s3:CopyObject" Resource: - !Sub "arn:aws:s3:::${WebsiteBucket}" - !Sub "arn:aws:s3:::${WebsiteBucket}/*" WebsiteContentLambda: Type: AWS::Lambda::Function Properties: FunctionName: Fn::Join: - '-' - [!Ref ResourcePrefix, 'content'] Description: Copies objects from a source S3 bucket to a destination S3 bucket. Handler: index.handler Runtime: python3.7 Role: !GetAtt WebsiteContentLambdaRole.Arn Timeout: 30 Code: ZipFile: | from botocore.exceptions import ClientError import json import cfnresponse import boto3 import logging # Create S3 clinet s3 = boto3.client('s3') # Set Logging logger = logging.getLogger() logger.setLevel(logging.INFO) def handler(event, context): logger.info("Received event: %s" % json.dumps(event)) # Set Variables bucket = event['ResourceProperties']['Bucket'] prefix = event['ResourceProperties'].get('Prefix') or '' # Set Initial CFN Response result = cfnresponse.SUCCESS try: # Create or Update Event if event['RequestType'] == 'Create' or event['RequestType'] == 'Update': # Create files locally and copy them to s3 f= open("/tmp/you-should-NOT-SEE-this-file-appadmins_logging1","w+") response = s3.upload_file("/tmp/you-should-NOT-SEE-this-file-appadmins_logging1", bucket, "appadmins/you-should-NOT-SEE-this-file-appadmins_logging1") f= open("/tmp/you-should-NOT-SEE-this-file-appadmins_logging2","w+") response = s3.upload_file("/tmp/you-should-NOT-SEE-this-file-appadmins_logging2", bucket, "appadmins/you-should-NOT-SEE-this-file-appadmins_logging2") f= open("/tmp/you-should-NOT-SEE-this-file-appadmins_logging3","w+") response = s3.upload_file("/tmp/you-should-NOT-SEE-this-file-appadmins_logging3", bucket, "appadmins/you-should-NOT-SEE-this-file-appadmins_logging3") f= open("/tmp/you-should-NOT-SEE-this-file-appadmins_logging4","w+") response = s3.upload_file("/tmp/you-should-NOT-SEE-this-file-appadmins_logging4", bucket, "appadmins/you-should-NOT-SEE-this-file-appadmins_logging4") f= open("/tmp/you-should-SEE-this-file--webadmins_logging1","w+") response = s3.upload_file("/tmp/you-should-SEE-this-file--webadmins_logging1", bucket, "webadmins/you-should-SEE-this-file--webadmins_logging1") f= open("/tmp/you-should-SEE-this-file--webadmins_logging2","w+") response = s3.upload_file("/tmp/you-should-SEE-this-file--webadmins_logging2", bucket, "webadmins/you-should-SEE-this-file--webadmins_logging2") f= open("/tmp/you-should-SEE-this-file--webadmins_logging3","w+") response = s3.upload_file("/tmp/you-should-SEE-this-file--webadmins_logging3", bucket, "webadmins/you-should-SEE-this-file--webadmins_logging3") f= open("/tmp/you-should-SEE-this-file--webadmins_logging4","w+") response = s3.upload_file("/tmp/you-should-SEE-this-file--webadmins_logging4", bucket, "webadmins/you-should-SEE-this-file--webadmins_logging4") # Send signal to cloudformation result = cfnresponse.SUCCESS # Delete Event elif event['RequestType'] == 'Delete': paginator = s3.get_paginator('list_objects_v2') page_iterator = paginator.paginate(Bucket=bucket, Prefix=prefix) objects = [{'Key': x['Key']} for page in page_iterator for x in page['Contents']] s3.delete_objects(Bucket=bucket, Delete={'Objects': objects}) # Send signal to cloudformation result = cfnresponse.SUCCESS except ClientError as e: logger.error('Error: %s', e) # Send signal to cloudformation result = cfnresponse.FAILED cfnresponse.send(event, context, result, {}) # Cloud9 Environment pbcloudnineenv: Type : AWS::Cloud9::EnvironmentEC2 Properties: Description: "Cloud9 environment for the permissions boundary advanced workshop" AutomaticStopTimeMinutes: 120 #InstanceType: !Ref InstanceType InstanceType: t2.micro Name: "workshop-environment" SubnetId: !Ref Subnet # VPC for Cloud9 SystemVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 192.168.0.0/16 EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Created-for Value: PB-Workshop InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Ref ResourcePrefix GatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: Ref: InternetGateway VpcId: !Ref SystemVPC RouteTable: DependsOn: - SystemVPC Type: AWS::EC2::RouteTable Properties: Tags: - Key: Name Value: !Ref ResourcePrefix VpcId: !Ref SystemVPC PublicRoute: DependsOn: - RouteTable - GatewayAttachment Type: AWS::EC2::Route Properties: DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway RouteTableId: !Ref RouteTable Subnet: Type: AWS::EC2::Subnet Properties: CidrBlock: 192.168.0.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Ref ResourcePrefix VpcId: !Ref SystemVPC AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: "" SubnetAssoc: DependsOn: - Subnet - RouteTable Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref Subnet SubnetTwo: Type: AWS::EC2::Subnet Properties: CidrBlock: 192.168.128.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Ref ResourcePrefix VpcId: !Ref SystemVPC AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: "" SubnetTwoAssoc: DependsOn: - SubnetTwo - RouteTable Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetTwo PublicNACL: Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref SystemVPC Tags: - Key: Network Value: Public InboundPublicNACLEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref PublicNACL RuleNumber: 100 Protocol: -1 RuleAction: allow Egress: false CidrBlock: '0.0.0.0/0' PortRange: From: 0 To: 65535 OutboundPublicNACLEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref PublicNACL RuleNumber: 100 Protocol: -1 RuleAction: allow Egress: true CidrBlock: 0.0.0.0/0 PortRange: From: 0 To: 65535 SubnetNACLAssociation: Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref Subnet NetworkAclId: !Ref PublicNACL SubnetTwoNACLAssociation: Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref SubnetTwo NetworkAclId: !Ref PublicNACL # Outputs: