AWSTemplateFormatVersion: "2010-09-09" Description: Deploy a CoreOS Clair on ECS Fargate Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "Network Configuration if Stack doesn't exist" Parameters: - VpcId - PublicSubnets - PrivateSubnets - Label: default: "Amazon ECS and ECR Configuration" Parameters: - ECSClusterName - ECRRepositoryUri Parameters: VpcId: Type: AWS::EC2::VPC::Id Description: VPC ID in which resources will be deployed. PublicSubnets: Type: List Description: Public Subnet IDs PrivateSubnets: Type: List Description: Private Subnet IDs ECSClusterName: Type: String Description: ECS Cluster to deploy the Containers. Default: clair-demo-cluster ECRRepositoryUri: Type: String Description: ECR Repository URI e.g. .dkr.ecr..amazonaws.com/. Resources: ClairALBSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: VpcId: !Ref VpcId GroupDescription: "CoreOS Clair ALB Security Group" SecurityGroupIngress: - IpProtocol: tcp FromPort: 6060 ToPort: 6060 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: Clair-ALB-SG ClairContainerSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: VpcId: !Ref VpcId GroupDescription: "CoreOS Clair Container Security Group" SecurityGroupIngress: - IpProtocol: tcp FromPort: 6060 ToPort: 6061 SourceSecurityGroupId: Fn::GetAtt: [ClairALBSecurityGroup, GroupId] Tags: - Key: Name Value: Clair-Container-SG ClairDbSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: VpcId: !Ref VpcId GroupDescription: "CoreOS Clair RDS Cluster Security Group" SecurityGroupIngress: - IpProtocol: tcp FromPort: 5432 ToPort: 5432 SourceSecurityGroupId: Fn::GetAtt: [ClairContainerSecurityGroup, GroupId] Tags: - Key: Name Value: Clair-DB-SG ClairDbSubnetGroup: Type: "AWS::RDS::DBSubnetGroup" Properties: DBSubnetGroupDescription: Subnet Group for Clair DB Cluster SubnetIds: !Ref PrivateSubnets ClairDbCluster: Type: "AWS::RDS::DBCluster" DeletionPolicy: Delete Properties: DBSubnetGroupName: !Ref ClairDbSubnetGroup Engine: aurora-postgresql EngineVersion: "9.6.8" MasterUsername: postgres MasterUserPassword: password DatabaseName: postgres DBClusterParameterGroupName: "default.aurora-postgresql9.6" Port: 5432 VpcSecurityGroupIds: [!Ref ClairDbSecurityGroup] Tags: - Key: Name Value: ClairDBCluster ClairDbPrimaryInstance: Type: "AWS::RDS::DBInstance" Properties: Engine: aurora-postgresql EngineVersion: "9.6.8" DBClusterIdentifier: !Ref ClairDbCluster DBInstanceClass: "db.r4.large" DBSubnetGroupName: !Ref ClairDbSubnetGroup Tags: - Key: Name Value: ClairDB-Instance-01 ClairALB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing SecurityGroups: [!Ref ClairALBSecurityGroup] Subnets: !Ref PublicSubnets Type: application ClairALBTargetGroup: Type: "AWS::ElasticLoadBalancingV2::TargetGroup" Properties: Protocol: "HTTP" Port: 6060 TargetType: "ip" VpcId: !Ref VpcId HealthCheckProtocol: "HTTP" HealthCheckPort: 6061 HealthCheckPath: "/health" HealthyThresholdCount: 5 UnhealthyThresholdCount: 2 HealthCheckTimeoutSeconds: 5 HealthCheckIntervalSeconds: 30 Matcher: HttpCode: '200' ClairALBListener: Type: "AWS::ElasticLoadBalancingV2::Listener" Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref ClairALBTargetGroup LoadBalancerArn: !Ref ClairALB Port: 6060 Protocol: "HTTP" ClairContainerCloudWatchLogGroup: Type: "AWS::Logs::LogGroup" ClairEcsTaskExecutionRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "sts:AssumeRole" Principal: Service: "ecs-tasks.amazonaws.com" ClairEcsTaskExecutionRolePolicy: Type: "AWS::IAM::Policy" Properties: PolicyName: "fargate-execution" Roles: - Ref: "ClairEcsTaskExecutionRole" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "ecr:GetAuthorizationToken" - "ecr:BatchGetImage" - "ecr:GetDownloadUrlForLayer" - "ecr:BatchCheckLayerAvailability" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "*" ClairEcsTaskRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "sts:AssumeRole" Principal: Service: "ecs-tasks.amazonaws.com" ClairECSCluster: Type: "AWS::ECS::Cluster" Properties: ClusterName: !Ref ECSClusterName ClairTaskDefinition: Type: "AWS::ECS::TaskDefinition" Properties: Family: coreos-clair Cpu: "1024" Memory: "2GB" NetworkMode: "awsvpc" RequiresCompatibilities: ["FARGATE"] ExecutionRoleArn: !Ref ClairEcsTaskExecutionRole TaskRoleArn: !Ref ClairEcsTaskRole ContainerDefinitions: - Name: "clair" Image: !Ref ECRRepositoryUri Essential: "true" Environment: - Name: DB_HOST Value: !GetAtt [ClairDbCluster, Endpoint.Address] PortMappings: - ContainerPort: 6060 Protocol: tcp - ContainerPort: 6061 Protocol: tcp LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref ClairContainerCloudWatchLogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: "clair" ClairECSService: Type: "AWS::ECS::Service" DependsOn: ClairDbPrimaryInstance Properties: Cluster: !Ref ClairECSCluster LaunchType: "FARGATE" DesiredCount: 1 TaskDefinition: !Ref ClairTaskDefinition LoadBalancers: - ContainerName: clair ContainerPort: 6060 TargetGroupArn: !Ref ClairALBTargetGroup NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: [!Ref ClairContainerSecurityGroup] Subnets: !Ref PrivateSubnets Outputs: ClairAlbDnsName: Description: Clair ALB DNS Name Value: !GetAtt [ClairALB, DNSName] ClairAlbUrl: Description: URL of the Clair ALB Value: Fn::Join: ["", ["http://", !GetAtt [ClairALB, DNSName],":6060"]] ECSClusterName: Description: ECS Cluster Name Value: !Ref ClairECSCluster ECSClusterArn: Description: ECS Cluster ARN Value: !GetAtt [ClairECSCluster, Arn] ClairECSServiceName: Description: ECS Service Name Value: !Ref ClairECSService