AWSTemplateFormatVersion: "2010-09-09" Description: This template will launch an ECS service (Fargate) for the Modernization Workshop. Parameters: VPCstack: Type: String Description: VPC stack to import values from Default: ModernizationVPC DesiredCount: Type: Number Default: 1 ContrastURL: Type: String Description: TeamServer URL to use for connection. Defaults to Community Edition. Default: https://ce.contrastsecurity.com/Contrast ContrastApiKey: Type: String NoEcho: true Description: Set the API key needed to communicate with the Contrast UI. This sets an environment variable in the Task Definition. ContrastServiceKey: Type: String NoEcho: true Description: Set the service key needed to communicate with the Contrast UI. This sets an environment variable in the Task Definition. ContrastUserName: Type: String NoEcho: true Description: Set the user name used to communicate with the Contrast UI. This sets an environment variable in the Task Definition. Resources: ContrastApiKeySecret: Type: AWS::SecretsManager::Secret Properties: Description: Contrast API Key Name: ContrastApiKeySecret SecretString: Ref: ContrastApiKey ContrastServiceKeySecret: Type: AWS::SecretsManager::Secret Properties: Description: Contrast Service Key Name: ContrastServiceKeySecret SecretString: Ref: ContrastServiceKey ContrastUserNameSecret: Type: AWS::SecretsManager::Secret Properties: Description: Contrast User Name Name: ContrastUserNameSecret SecretString: Ref: ContrastUserName ContrastSecretsManagerPolicy: Type: AWS::IAM::Policy Properties: PolicyName: ContrastSecretsManagerPolicy Roles: - FargateExecutionRole PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: - Ref: ContrastApiKeySecret - Ref: ContrastServiceKeySecret - Ref: ContrastUserNameSecret CloudwatchLogGroup: Type: "AWS::Logs::LogGroup" Properties: LogGroupName: ModernizationWorkshop RetentionInDays: 30 ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: ModernizationCluster TaskExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Action: "sts:AssumeRole" Effect: "Allow" Principal: Service: "ecs-tasks.amazonaws.com" ManagedPolicyArns: - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess" - "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" - "arn:aws:iam::aws:policy/SecretsManagerReadWrite" RoleName: "FargateExecutionRole" TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: modernization-workshop Cpu: 1024 Memory: 2048 NetworkMode: awsvpc ExecutionRoleArn: Ref: TaskExecutionRole TaskRoleArn: FargateExecutionRole RequiresCompatibilities: - "FARGATE" ContainerDefinitions: - Name: modernization-workshop Image: Fn::Sub: '${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/modernization-workshop:latest' Cpu: 1024 Memory: 2048 Environment: - Name: CONTRAST_URL Value: Ref: ContrastURL Secrets: - Name: CONTRAST_API_KEY ValueFrom: Ref: ContrastApiKeySecret - Name: CONTRAST_SERVICE_KEY ValueFrom: Ref: ContrastServiceKeySecret - Name: CONTRAST_USER_NAME ValueFrom: Ref: ContrastUserNameSecret LogConfiguration: LogDriver: awslogs Options: awslogs-region: Ref: AWS::Region awslogs-group: Ref: CloudwatchLogGroup awslogs-stream-prefix: "web" MemoryReservation: 2048 PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp TaskSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: GroupName: ModernSecurityGroup GroupDescription: Security group the the Modern Fargate Task VpcId: Fn::ImportValue: Fn::Sub: ${VPCstack}:VPCId TaskSecurityGroupIngress: Type: "AWS::EC2::SecurityGroupIngress" Properties: GroupId: Ref: TaskSecurityGroup IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: Ref: LBSecurityGroup FargateService: Type: AWS::ECS::Service DependsOn: LoadBalancerListener Properties: Cluster: Ref: ECSCluster DesiredCount: Ref: DesiredCount TaskDefinition: Ref: TaskDefinition LaunchType: FARGATE NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: - Ref: TaskSecurityGroup Subnets: - Fn::ImportValue: Fn::Sub: ${VPCstack}:PublicSubnet1 - Fn::ImportValue: Fn::Sub: ${VPCstack}:PublicSubnet2 LoadBalancers: - ContainerName: modernization-workshop ContainerPort: 80 TargetGroupArn: Ref: TargetGroup ServiceName: ModernService LBSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: GroupName: LbSecurityGroup GroupDescription: Security group the the Modernization Workshop Application Load Balancer SecurityGroupEgress: - CidrIp: "0.0.0.0/0" IpProtocol: TCP FromPort: 80 ToPort: 80 SecurityGroupIngress: - CidrIp: "0.0.0.0/0" IpProtocol: TCP FromPort: 80 ToPort: 80 VpcId: Fn::ImportValue: Fn::Sub: "${VPCstack}:VPCId" LoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: Modernization-Workshop-LB Scheme: internet-facing SecurityGroups: - Ref: LBSecurityGroup Subnets: - Fn::ImportValue: Fn::Sub: "${VPCstack}:PublicSubnet1" - Fn::ImportValue: Fn::Sub: "${VPCstack}:PublicSubnet2" Tags: - Key: Name Value: Modernization-Workshop-LB Type: application IpAddressType: ipv4 LoadBalancerListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: LoadBalancerArn: Ref: LoadBalancer Port: 80 Protocol: HTTP DefaultActions: - Type: forward TargetGroupArn: Ref: TargetGroup TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup DependsOn: LoadBalancer Properties: Name: ecs-modernization-service VpcId: Fn::ImportValue: Fn::Sub: "${VPCstack}:VPCId" Port: 80 Protocol: HTTP HealthCheckEnabled: true HealthCheckIntervalSeconds: 35 HealthCheckPath: /WebGoat/login.mvc HealthCheckPort: 80 HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 30 HealthyThresholdCount: 2 UnhealthyThresholdCount: 10 TargetType: ip Matcher: HttpCode: 200-299 Outputs: Service: Value: Ref: FargateService TargetGroup: Value: Ref: TargetGroup ServiceUrl: Description: URL of the load balancer for the sample service. Value: Fn::Sub: http://${LoadBalancer.DNSName}/WebGoat