# This template is used to create the resources required for the AML .NET Modernization workshop. # The template can be executed standalone by providing network configurations or can be run as a nested template using the Event Engine driver template. --- AWSTemplateFormatVersion: "2010-09-09" Description: .NET modernization workshop template. Creates resources required for the AML Unicorn Workshop. Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "Network configurations. These are required parameters." Parameters: - "VPCId" - "SubnetIdList" - Label: default: "MSSQL Instance configurations." Parameters: - "InstanceIdentifier" - "MasterUsername" - "MasterUserPassword" - Label: default: "Elastic Beanstalk configurations." Parameters: - "ApplicationName" - "EnvironmentName" - Label: default: "Elastic Beanstalk Locust App configurations." Parameters: - "LocustApplicationName" - "LocustEnvironmentName" - Label: default: "Elastic Container Service configurations." Parameters: - "ClusterName" - Label: default: "Hosted Zone configurations." Parameters: - "HostedZone" Parameters: InstanceIdentifier: Type: String Description: "Name of the MSSQL Instance" Default: "unishop" MasterUsername: Type: String Description: "MSSQL connection user name" Default: "admin" MasterUserPassword: NoEcho: True Type: String Description: "MSSQL connection user password" Default: "dMdLgX6sZoXmOU2rnWTS" # ----------------------------------- ApplicationName: Type: String Description: "Elastic Beanstalk Application Name" Default: "LegacyApplication" EnvironmentName: Type: String Description: "Elastic Beanstalk Environment name" Default: "LegacyApplication" LocustApplicationName: Type: String Description: "Elastic Beanstalk Application Name" Default: "LoadGenerator" LocustEnvironmentName: Type: String Description: "Elastic Beanstalk Environment name" Default: "LoadGenerator" # ----------------------------------- ClusterName: Type: String Description: "Elastic Container Service cluster name" Default: "UnishopCluster" # ----------------------------------- # ----------------------------------- HostedZone: Type: String Description: "Domain name for the hosted resources" Default: "unishop.local" # ----------------------------------- VpcId: Type: String Description: "VPC to deploy the resources" Default: "" SubnetIdList: Type: CommaDelimitedList Description: "Subnet Id to deploy the instance" Default: "" # ----------------------------------- StaticHostingBucketName: Type: String Description: "Name of the bucket used to host static UI content" Default: "unishopui" Resources: # Elastic Beanstalk resources. # Deploy the monolithic application in a Windows Server instance. # Securtiy groups for resource. EBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security Group to allow EB aplication to accept HTTP requests" SecurityGroupIngress: - IpProtocol: 'tcp' FromPort: 80 ToPort: 80 CidrIp: '0.0.0.0/0' SecurityGroupEgress: - IpProtocol: -1 CidrIp: '0.0.0.0/0' VpcId: !Ref VpcId # IAM roles to provide permissions. EBEC2Role: Type: AWS::IAM::Role Properties: RoleName: 'elastic-beanstalk-ec2-modernization-workshop-role' Description: "This role enables EC2 configuration" Path: '/' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier' - 'arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker' - 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier' AssumeRolePolicyDocument: Version: "2008-10-17" Statement: - Effect: "Allow" Principal: Service: - 'ec2.amazonaws.com' Action: "sts:AssumeRole" # Service role to provide permissions. EBServiceRole: Type: AWS::IAM::Role Properties: RoleName: 'elastic-beanstalk-service-modernization-workshop-role' Description: "This role enables EB Service configuration" Path: '/' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth' - 'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService' AssumeRolePolicyDocument: Version: "2008-10-17" Statement: - Effect: "Allow" Principal: Service: - 'elasticbeanstalk.amazonaws.com' Action: "sts:AssumeRole" #Instance profile for the EB role. EBInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - Ref: EBEC2Role # Elastic Beanstalk Application. EBApp: Type: AWS::ElasticBeanstalk::Application Properties: ApplicationName: !Ref ApplicationName Description: "AWS Elastic Beanstalk Legacy .NET Framework application" # Elastic Beanstalk Application config template. Specifies the platform. EBConfig: Type: AWS::ElasticBeanstalk::ConfigurationTemplate Properties: ApplicationName: Ref: "EBApp" Description: "AWS Elastic Beanstalk Legacy .NET Framework configuration template" PlatformArn: !Join [':', ["arn:aws:elasticbeanstalk", !Ref 'AWS::Region', ":platform/IIS 10.0 running on 64bit Windows Server 2019"]] # Elastic Beanstalk Monolithic Application environment. EBEnvironment: Type: AWS::ElasticBeanstalk::Environment DependsOn: - MSSQLDatabaseInstance - RDSDNSRecord Properties: ApplicationName: Ref: "EBApp" Description: "AWS Elastic Beanstalk Environment running Legacy .NET Framework" EnvironmentName: !Ref EnvironmentName TemplateName: Ref: "EBConfig" OptionSettings: - Namespace: 'aws:elasticbeanstalk:environment' OptionName: 'EnvironmentType' Value: 'SingleInstance' - Namespace: 'aws:elasticbeanstalk:environment' OptionName: 'ServiceRole' Value: !Ref EBServiceRole - Namespace: 'aws:autoscaling:launchconfiguration' OptionName: "IamInstanceProfile" Value: !Ref EBInstanceProfile - Namespace: 'aws:ec2:vpc' OptionName: "AssociatePublicIpAddress" Value: true - Namespace: 'aws:ec2:vpc' OptionName: 'VpcId' Value: !Ref VpcId - Namespace: 'aws:ec2:vpc' OptionName: 'Subnets' Value: !Select [0, !Ref SubnetIdList] - Namespace: 'aws:autoscaling:launchconfiguration' OptionName: "SecurityGroups" Value: !GetAtt EBSecurityGroup.GroupId Tier: Name: "WebServer" Type: "Standard" #VersionLabel: #Ref : "EBAppVersion" # Deploy Locust load testing application in Amazon Linux instance with Docker support. # Elastic Beanstalk Application. EBLocustApp: Type: AWS::ElasticBeanstalk::Application Properties: ApplicationName: !Ref LocustApplicationName Description: "AWS Elastic Beanstalk Docker Locust application" # Elastic Beanstalk Application config template. Specifies the platform. EBLocustConfig: Type: AWS::ElasticBeanstalk::ConfigurationTemplate Properties: ApplicationName: Ref: "EBLocustApp" Description: "AWS Elastic Beanstalk Docker Locust configuration template" PlatformArn: !Join [':', ["arn:aws:elasticbeanstalk", !Ref 'AWS::Region', ":platform/Docker running on 64bit Amazon Linux"]] # Elastic Beanstalk locust application environment. EBLocustEnvironment: Type: AWS::ElasticBeanstalk::Environment Properties: ApplicationName: Ref: "EBLocustApp" Description: "AWS Elastic Beanstalk Environment running Docker Locust" EnvironmentName: !Ref LocustEnvironmentName TemplateName: Ref: "EBLocustConfig" OptionSettings: - Namespace: 'aws:elasticbeanstalk:environment' OptionName: 'EnvironmentType' Value: 'SingleInstance' - Namespace: 'aws:elasticbeanstalk:environment' OptionName: 'ServiceRole' Value: !Ref EBServiceRole - Namespace: 'aws:autoscaling:launchconfiguration' OptionName: "IamInstanceProfile" Value: !Ref EBInstanceProfile - Namespace: 'aws:ec2:vpc' OptionName: "AssociatePublicIpAddress" Value: false - Namespace: 'aws:ec2:vpc' OptionName: 'VpcId' Value: !Ref VpcId - Namespace: 'aws:ec2:vpc' OptionName: 'Subnets' Value: !Select [0, !Ref SubnetIdList] Tier: Name: "WebServer" Type: "Standard" #VersionLabel: #Ref : "EBLocustAppVersion" # Database resources. # RDS MSSQL Database to store Legacy application data. # MSSQL Database security group. Allow connections from the Monolithic application, VS Dev instance and DMS resources. MSSQLVPCSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security Group to allow applications to connect to RDS Instance" SecurityGroupIngress: - IpProtocol: 'tcp' FromPort: 1433 ToPort: 1433 SourceSecurityGroupId: !GetAtt EBSecurityGroup.GroupId - IpProtocol: 'tcp' FromPort: 1433 ToPort: 1433 SourceSecurityGroupId: !Ref ECSContainerSecurityGroup SecurityGroupEgress: - IpProtocol: -1 CidrIp: '0.0.0.0/0' VpcId: !Ref VpcId # MSSQL Database subnet. MSSQLDBSubnet: Type: 'AWS::RDS::DBSubnetGroup' Properties: DBSubnetGroupDescription: "DB Subnet Group to create RDS in a VPC" DBSubnetGroupName: "UnishopRDSSubnetGroup" SubnetIds: !Ref SubnetIdList # MSSQL Database. SQL Express server hosted in the specified subnet. MSSQLDatabaseInstance: Type: 'AWS::RDS::DBInstance' Properties: DBInstanceIdentifier: !Ref InstanceIdentifier DBInstanceClass: db.t2.micro AllocatedStorage: 20 Engine: sqlserver-ex EngineVersion: 14.00.3281.6.v1 LicenseModel: license-included MasterUsername: !Ref MasterUsername MasterUserPassword: !Ref MasterUserPassword PubliclyAccessible: true DBSubnetGroupName: !Ref MSSQLDBSubnet VPCSecurityGroups: - !GetAtt MSSQLVPCSecurityGroup.GroupId # Container resources. # These include resources that are required to deploy and run containers on Amazon ECS. # ECR Repository to store the microservice images. ECRRepository: Type: 'AWS::ECR::Repository' Properties: RepositoryName: "unishop-repository" # ECS Cluster to run services and tasks. ECSCluster: Type: 'AWS::ECS::Cluster' Properties: ClusterName: !Ref ClusterName ClusterSettings: - Name: containerInsights Value: enabled # ECS TaskExecution role, allow ECS to pull image and store logs. ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: RoleName: 'ecs-task-execution-modernization-workshop-role' AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - "ecs-tasks.amazonaws.com" Action: - "sts:AssumeRole" ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy' # ECS Task role (an empty role, user can attach policies if needed). # The role used by the task itself to use other services. ECSTaskRole: Type: AWS::IAM::Role Properties: RoleName: 'ecs-task-modernization-workshop-role' AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - "ecs-tasks.amazonaws.com" - "rekognition.amazonaws.com" - "s3.amazonaws.com" Action: - "sts:AssumeRole" # Security group for ECS tasks/service. ECSContainerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VpcId GroupDescription: Security group for ECS tasks/service GroupName: ECSClusterSecurityGroup # DMS related resources. # Database migration is done from MS SQL to Aurora postgressql server. # IAM role to provide permissions for DMS. # Lambda function resources. # IAM Role for Lambda function DynamoDB acess DynamoDBAccessRole: Type: 'AWS::IAM::Role' Properties: RoleName: 'dynamodb-access-modernization-workshop-role' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: FullAccessToDDB PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "dynamodb:List*" - "dynamodb:DescribeReservedCapacity*" - "dynamodb:DescribeLimits" - "dynamodb:DescribeTimeToLive" Resource: '*' - Effect: Allow Action: - "dynamodb:BatchGet*" - "dynamodb:DescribeStream" - "dynamodb:DescribeTable" - "dynamodb:Get*" - "dynamodb:Query" - "dynamodb:Scan" - "dynamodb:BatchWrite*" - "dynamodb:CreateTable" - "dynamodb:Delete*" - "dynamodb:Update*" - "dynamodb:PutItem" Resource: "arn:aws:dynamodb:*:*:table/UnicornBasket" # Route 53 hosted zone. # A hosted zone to map a DNS with the created resource endpoints. # Private hosted zone in the specified VPC. AppHostedZone: Type: AWS::Route53::HostedZone Properties: HostedZoneConfig: Comment: "Hosted zone to route resource endpoints" Name: !Ref HostedZone VPCs: - VPCId: !Ref VpcId VPCRegion: !Ref 'AWS::Region' # DNS name attached to the locust load tester. LocustDNSRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneId: !Ref AppHostedZone Comment: "DNS for locust load testing service" Name: !Join [ '.',['locust', !Ref HostedZone ]] Type: A TTL: '900' ResourceRecords: - !GetAtt EBLocustEnvironment.EndpointURL # DNS name attached to Monolithic application. EBAppDNSRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneId: !Ref AppHostedZone Comment: "DNS for legacy application" Name: !Join [ '.',['app', !Ref HostedZone ]] Type: A TTL: '900' ResourceRecords: - !GetAtt EBEnvironment.EndpointURL # DNS name attached to the MSSQL RDS instance. RDSDNSRecord: Type: AWS::Route53::RecordSet DependsOn: - MSSQLDatabaseInstance Properties: HostedZoneId: !Ref AppHostedZone Comment: "DNS for locust load testing service" Name: !Join [ '.',['db', !Ref HostedZone ]] Type: CNAME TTL: '900' ResourceRecords: - !GetAtt MSSQLDatabaseInstance.Endpoint.Address # S3 resources # S3 bucket with public objects enabled. # Enables static website hosting. StaticHostingBucket: Type: AWS::S3::Bucket DeletionPolicy: Delete Properties: BucketName: !Join - '-' - - !Ref 'StaticHostingBucketName' - !Ref 'AWS::AccountId' PublicAccessBlockConfiguration: IgnorePublicAcls: false BlockPublicAcls: false BlockPublicPolicy: true RestrictPublicBuckets: true Outputs: EBLegacyEnvironmentName: Description: "Environment name of EB that hosts the legacy app." Value: !Ref EBEnvironment EBLegacyApplicationName: Description: "Application name of EB that hosts the legacy app." Value: !Ref EBApp EBLocustEnvironmentName: Description: "Environment name of EB that hosts locust." Value: !Ref EBLocustEnvironment EBLocustApplicationName: Description: "Application name of EB that hosts locust." Value: !Ref EBLocustApp ECSClusterName: Description: "Name of the ECS cluster hosting inventory service." Value: !Ref ECSCluster DynamoDBAccessRoleARN: Description: "The arn of the dynamodb-access-modernization-workshop-role." Value: !GetAtt DynamoDBAccessRole.Arn UnishopFrontendBucket: Description: "The name of the UnishopFrontEnd Bucket" Value: !Ref StaticHostingBucket