public ClassicLoadBalancerStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var vpc = new Vpc(this, "VPC");

            var asg = new AutoScalingGroup(this, "ASG", new AutoScalingGroupProps
            {
                Vpc          = vpc,
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                MachineImage = new AmazonLinuxImage()
            });

            var lb = new LoadBalancer(this, "LB", new LoadBalancerProps
            {
                Vpc            = vpc,
                InternetFacing = true,
                HealthCheck    = new Amazon.CDK.AWS.ElasticLoadBalancing.HealthCheck
                {
                    Port = 80
                }
            });

            lb.AddTarget(asg);
            var listener = lb.AddListener(new LoadBalancerListener {
                ExternalPort = 80
            });

            listener.Connections.AllowDefaultPortFromAnyIpv4("Open to the world");
        }
        /// <summary>
        /// AwsCdkDatabaseHandler
        /// </summary>
        /// <param name="databaseEngineVersion"></param>
        /// <param name="identification"></param>
        /// <param name="clusterIdentifier"></param>
        /// <param name="instanceIdentifierBase"></param>
        /// <param name="databaseName"></param>
        /// <param name="port"></param>
        /// <param name="instances"></param>
        /// <param name="userName"></param>
        /// <param name="secretName"></param>
        /// <param name="vpc"></param>
        /// <param name="instanceClass"></param>
        /// <param name="instanceSize"></param>
        /// <param name="securityId"></param>
        /// <param name="securityGroupId"></param>
        /// <param name="parameterGroupId"></param>
        /// <param name="roles"></param>
        /// <param name="storageEncrypted"></param>
        /// <param name="subnetType"></param>
        /// <param name="defaultSubnetDomainSeparator"></param>
        /// <param name="subnets"></param>
        /// <param name="removalPolicy"></param>
        /// <param name="backupRetentionDays"></param>
        /// <param name="deletionProtection"></param>
        public IDatabaseCluster CreateDatabaseCluster(DeputyBase databaseEngineVersion, string identification, string clusterIdentifier, string instanceIdentifierBase, string databaseName, double?port, double?instances, string userName, string secretName, IVpc vpc, InstanceClass instanceClass, InstanceSize instanceSize, string securityId, string securityGroupId, string parameterGroupId = null, IRole[] roles = null, bool storageEncrypted = true, SubnetType subnetType = SubnetType.PRIVATE_ISOLATED, string defaultSubnetDomainSeparator = ",", string subnets = "", RemovalPolicy removalPolicy = RemovalPolicy.DESTROY, int backupRetentionDays = 1, bool deletionProtection = false)
        {
            BasicDatabaseInfra(vpc, secretName, securityId, securityGroupId, subnetType, defaultSubnetDomainSeparator, subnets, out var securityGroup, out var secret, out var subnetSelection);
            var engine = GetClusterEngine(databaseEngineVersion);

            return(new DatabaseCluster(Scope, identification, new DatabaseClusterProps
            {
                ClusterIdentifier = clusterIdentifier,
                InstanceIdentifierBase = instanceIdentifierBase,
                Engine = engine,
                RemovalPolicy = removalPolicy,
                DeletionProtection = deletionProtection,
                Port = port,
                InstanceProps = new Amazon.CDK.AWS.RDS.InstanceProps
                {
                    InstanceType = InstanceType.Of(instanceClass, instanceSize),
                    VpcSubnets = subnetSelection,
                    Vpc = vpc,
                    SecurityGroups = new[]
                    {
                        securityGroup
                    }
                },
                StorageEncrypted = storageEncrypted,
                Instances = instances,
                Credentials = Credentials.FromPassword(userName, secret.SecretValue),
                DefaultDatabaseName = databaseName,
                ParameterGroup = CreateClusterParameterGroup(parameterGroupId, engine, roles),
                Backup = new BackupProps
                {
                    Retention = Duration.Days(backupRetentionDays)
                }
            }));
        }
        public IDatabaseInstance CreateDatabaseSqlServer(DeputyBase databaseEngineVersion, string identification, string databaseName, string userName, string password, StorageType storageType, InstanceClass instanceClass, string instanceSize, IVpc vpc, ISecurityGroup security, string securityGroupId, string parameterGroupId = null, IRole[] roles = null, double?allocatedStorageGb = 5, RemovalPolicy removalPolicy = RemovalPolicy.DESTROY, bool deleteAutomatedBackups = false, int backupRetentionDays = 1, bool?deletionProtection = false, SubnetType subnetType = SubnetType.PRIVATE_ISOLATED, string defaultSubnetDomainSeparator = ",", string subnets = "", bool multiAZEnabled = true, bool?autoMinorVersionUpgrade = false, bool?storageEncrypted = true, string licenseOption = "LICENSE_INCLUDED", string edition = "ex")
        {
            BasicDatabaseInfraWithHardcodedPassword(vpc, subnetType, defaultSubnetDomainSeparator, subnets, out var subnetSelection);
            var engine = GetInstanceEngine(databaseEngineVersion, edition);

            return(new DatabaseInstance(Scope, identification, new DatabaseInstanceProps
            {
                Engine = engine,
                RemovalPolicy = removalPolicy,
                DeletionProtection = deletionProtection,
                Credentials = Credentials.FromPassword(userName, SecretValue.PlainText(password)),
                StorageType = storageType,
                DatabaseName = licenseOption == LicenseModel.LICENSE_INCLUDED.ToString() ? null : databaseName,
                VpcSubnets = subnetSelection,
                Vpc = vpc,
                SecurityGroups = new[]
                {
                    security
                },
                DeleteAutomatedBackups = deleteAutomatedBackups,
                BackupRetention = Duration.Days(backupRetentionDays),
                AllocatedStorage = allocatedStorageGb,
                InstanceType = InstanceType.Of(instanceClass, GetInstanceSize(instanceSize)),
                ParameterGroup = CreateClusterParameterGroup(parameterGroupId, engine, roles),
                MultiAz = multiAZEnabled,
                AutoMinorVersionUpgrade = autoMinorVersionUpgrade,
                StorageEncrypted = storageEncrypted,
                LicenseModel = GetLicenseModel(licenseOption)
            }));
        }
Пример #4
0
        public static InstanceProps InstanceProps(IVpc vpc, ISubnet subnet, IRole role, ISecurityGroup securityGroup, IvrInstanceProps props, string privateIpAddress = null)
        {
            var instanceProps = new InstanceProps
            {
                Vpc        = vpc,
                VpcSubnets = new SubnetSelection
                {
                    //SubnetType = SubnetType.PUBLIC,
                    //SubnetGroupName = subnetGroupName,
                    Subnets = new ISubnet[] { subnet },
                },
                InstanceType = InstanceType.Of(props.InstanceClass, props.InstanceSize),
                MachineImage = new WindowsImage(props.WindowsVersion),
                BlockDevices = new BlockDevice[] {
                    new BlockDevice {
                        DeviceName = "/dev/sda1",
                        Volume     = BlockDeviceVolume.Ebs(props.VolumeSize, new EbsDeviceOptions {
                            VolumeType = props.VolumeType,
                            Encrypted  = true,
                        }),
                    },
                },
                Role          = role,
                SecurityGroup = securityGroup,
            };

            if (!string.IsNullOrWhiteSpace(privateIpAddress))
            {
                instanceProps.PrivateIpAddress = privateIpAddress;
            }
            return(instanceProps);
        }
        public IDatabaseInstance CreateDatabase(DeputyBase databaseEngineVersion, string identification, string databaseName, double?port, string userName, string secretName, StorageType storageType, InstanceClass instanceClass, InstanceSize instanceSize, IVpc vpc, string securityId, string securityGroupId, string parameterGroupId = null, IRole[] roles = null, double?allocatedStorageGb = 5, RemovalPolicy removalPolicy = RemovalPolicy.DESTROY, bool deleteAutomatedBackups = false, int backupRetentionDays = 1, bool deletionProtection = false, SubnetType subnetType = SubnetType.PRIVATE_ISOLATED, string defaultSubnetDomainSeparator = ",", string subnets = "", bool multiAZEnabled = true, bool autoMinorVersionUpgrade = false, bool?storageEncrypted = true)
        {
            BasicDatabaseInfra(vpc, secretName, securityId, securityGroupId, subnetType, defaultSubnetDomainSeparator, subnets, out var securityGroup, out var secret, out var subnetSelection);
            var engine = GetInstanceEngine(databaseEngineVersion);

            return(new DatabaseInstance(Scope, identification, new DatabaseInstanceProps
            {
                Engine = engine,
                RemovalPolicy = removalPolicy,
                DeletionProtection = deletionProtection,
                Credentials = Credentials.FromPassword(userName, secret.SecretValue),
                StorageType = storageType,
                DatabaseName = databaseName,
                Port = port,
                VpcSubnets = subnetSelection,
                Vpc = vpc,
                SecurityGroups = new[]
                {
                    securityGroup
                },
                DeleteAutomatedBackups = deleteAutomatedBackups,
                BackupRetention = Duration.Days(backupRetentionDays),
                AllocatedStorage = allocatedStorageGb,
                InstanceType = InstanceType.Of(instanceClass, instanceSize),
                ParameterGroup = CreateClusterParameterGroup(parameterGroupId, engine, roles),
                MultiAz = multiAZEnabled,
                AutoMinorVersionUpgrade = autoMinorVersionUpgrade,
                StorageEncrypted = storageEncrypted
            }));
        }
Пример #6
0
        internal Database(CdkStack stack, Vpc vpc, SecurityGroup asgSecurityGroup)
        {
            var dbSecurityGroup = new SecurityGroup(vpc, "DBSecurityGroup", new SecurityGroupProps
            {
                Vpc         = vpc,
                Description = "Allows database access to the specified."
            });

            dbSecurityGroup.AddIngressRule(asgSecurityGroup, Port.Tcp(1433), "Allow SQL Server");

            var db = new DatabaseInstance(stack, $"{stack.StackName}-DatabaseCluster", new DatabaseInstanceProps
            {
                Vpc          = vpc,
                VpcPlacement = new SubnetSelection {
                    SubnetType = SubnetType.PRIVATE
                },
                SecurityGroups     = new[] { dbSecurityGroup },
                Engine             = DatabaseInstanceEngine.SQL_SERVER_EX,
                MasterUsername     = "******",
                AllocatedStorage   = 20,
                MultiAz            = false,
                InstanceType       = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.SMALL),
                DeletionProtection = false
            });

            DatabaseResource = db;
            ServerAddress    = db.DbInstanceEndpointAddress;
            Password         = db.Secret;
        }
Пример #7
0
        internal BastionStack(Construct scope, string id, Vpc vpc, string keyPairName, IStackProps props = null) : base(scope, id, props)
        {
            Role = new Role(this, "ec2-bastion-role", new RoleProps {
                AssumedBy = new ServicePrincipal("ec2.amazonaws.com")
            });

            Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("SecretsManagerReadWrite"));

            Bastion = new Instance_(this, id, new InstanceProps
            {
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                MachineImage = new WindowsImage(WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE),
                Vpc          = vpc,
                UserData     = UserData.Custom(Utils.GetResource("bastion_user_data.ps1")),
                KeyName      = keyPairName,
                Role         = Role,
                VpcSubnets   = new SubnetSelection {
                    SubnetType = SubnetType.PUBLIC
                }
            });

            Bastion.Connections.AllowFromAnyIpv4(Port.Tcp(3389), "Internet access RDP");

            new CfnOutput(this, "Bastion Host", new CfnOutputProps {
                Value = Bastion.InstancePublicDnsName
            });
        }
Пример #8
0
        public ApplicationLoadBalancerStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
        {
            var vpc = new Vpc(this, "VPC");

            var asg = new AutoScalingGroup(this, "ASG", new AutoScalingGroupProps {
                Vpc          = vpc,
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                MachineImage = new AmazonLinuxImage()
            });

            var lb = new Amazon.CDK.AWS.ElasticLoadBalancingV2.ApplicationLoadBalancer(this, "LB", new ApplicationLoadBalancerProps {
                Vpc            = vpc,
                InternetFacing = true
            });

            var listener = lb.AddListener("Listener", new BaseApplicationListenerProps {
                Port = 80
            });

            listener.AddTargets("Target", new AddApplicationTargetsProps {
                Port    = 80,
                Targets = new IApplicationLoadBalancerTarget[] { asg }
            });

            listener.Connections.AllowDefaultPortFromAnyIpv4("Open to the world");

            asg.ScaleOnRequestCount("AModestLoad", new RequestCountScalingProps {
                TargetRequestsPerSecond = 1
            });
        }
        public IDatabaseInstance CreateDatabase(DeputyBase databaseEngineVersion, string identification, string databaseName, double?port, string userName, ISecret passwordSecret, StorageType storageType, InstanceClass instanceClass, InstanceSize instanceSize, IVpc vpc, ISecurityGroup securityGroup, ISubnetGroup subnetGroup, IParameterGroup parameterGroup = null, double?allocatedStorageGb = 5, RemovalPolicy removalPolicy = RemovalPolicy.DESTROY, bool deleteAutomatedBackups = false, int backupRetentionDays = 1, bool deletionProtection = false, string[] logTypes = null, bool?storageEncrypted = null, bool?enableIamAuthentication = false, Duration enhancedMonitoringInterval = null, bool multiAZEnabled = true, bool autoMinorVersionUpgrade = false)
        {
            BasicDatabaseInfra(vpc);
            var engine = GetInstanceEngine(databaseEngineVersion);

            return(new DatabaseInstance(Scope, identification, new DatabaseInstanceProps
            {
                Engine = engine,
                RemovalPolicy = removalPolicy,
                DeletionProtection = deletionProtection,
                Credentials = Credentials.FromPassword(userName, passwordSecret.SecretValue),
                StorageType = storageType,
                DatabaseName = databaseName,
                Port = port,
                SubnetGroup = subnetGroup,
                Vpc = vpc,
                SecurityGroups = new[]
                {
                    securityGroup
                },
                DeleteAutomatedBackups = deleteAutomatedBackups,
                BackupRetention = Duration.Days(backupRetentionDays),
                AllocatedStorage = allocatedStorageGb,
                InstanceType = InstanceType.Of(instanceClass, instanceSize),
                ParameterGroup = parameterGroup,
                CloudwatchLogsExports = logTypes,
                StorageEncrypted = storageEncrypted,
                IamAuthentication = enableIamAuthentication,
                MonitoringInterval = enhancedMonitoringInterval,
                MultiAz = multiAZEnabled,
                AutoMinorVersionUpgrade = autoMinorVersionUpgrade
            }));
        }
Пример #10
0
        public static Header Read(StandardBusinessDocumentHeader sbdh) // throws SbdhException
        {
            Header header = Header.NewInstance();

            // Sender
            PartnerIdentification senderIdentifier = sbdh.Sender[0].Identifier;

            header = header.SetSender(
                ParticipantIdentifier.Of(senderIdentifier.Value, Scheme.Of(senderIdentifier.Authority)));

            // Receiver
            PartnerIdentification receiverIdentifier = sbdh.Receiver[0].Identifier;

            header = header.SetReceiver(
                ParticipantIdentifier.Of(receiverIdentifier.Value, Scheme.Of(receiverIdentifier.Authority)));

            // Identifier
            header = header.SetIdentifier(InstanceIdentifier.Of(sbdh.DocumentIdentification.InstanceIdentifier));

            // InstanceType
            header = header.SetInstanceType(
                InstanceType.Of(
                    sbdh.DocumentIdentification.Standard,
                    sbdh.DocumentIdentification.Type,
                    sbdh.DocumentIdentification.TypeVersion));

            // CreationTimestamp
            if (sbdh.DocumentIdentification.CreationDateAndTime == null)
            {
                throw new SbdhException("Element 'CreationDateAndTime' is not set or contains invalid value.");
            }

            header = header.SetCreationTimestamp(sbdh.DocumentIdentification.CreationDateAndTime);

            // Scope
            foreach (Scope scope in sbdh.BusinessScope)
            {
                if (scope.Type.Equals("DOCUMENTID"))
                {
                    Scheme scheme = scope.Identifier != null
                                        ? Scheme.Of(scope.Identifier)
                                        : DocumentTypeIdentifier.DefaultScheme;

                    header = header.SetDocumentType(DocumentTypeIdentifier.Of(scope.InstanceIdentifier, scheme));
                }
                else if (scope.Type.Equals("PROCESSID"))
                {
                    Scheme scheme = scope.Identifier != null
                                        ? Scheme.Of(scope.Identifier)
                                        : ProcessIdentifier.DefaultScheme;

                    header = header.SetProcess(ProcessIdentifier.Of(scope.InstanceIdentifier, scheme));
                }
            }

            return(header);
        }
        public Amazon.CDK.AWS.AutoScaling.AutoScalingGroup Create(Amazon.CDK.AWS.EC2.Vpc vpc, SecurityGroup sg)
        {
            // todo define roles in config
            var role      = new Security.Roles.IamRole().Create(this, _config, "asg-ec2-role");
            var selection = new SubnetSelection
            {
                SubnetType = SubnetType.PUBLIC
            };

            var healchCheck = HealthCheck.Elb(new ElbHealthCheckOptions
            {
                Grace = Duration.Minutes(5)
            });

            var asg = new Amazon.CDK.AWS.AutoScaling.AutoScalingGroup(this, _config.Asg.Name, new AutoScalingGroupProps
            {
                AutoScalingGroupName = _config.Asg.Name,
                Vpc = vpc,
                // todo parse enums and pull from config
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                // get the linux two type otherwise it defaults to the older image
                // todo parse enums and pull from config
                MachineImage = new AmazonLinuxImage(new AmazonLinuxImageProps {
                    Generation = AmazonLinuxGeneration.AMAZON_LINUX_2
                }),
                AllowAllOutbound = _config.Asg.AllowAllOutbound,
                DesiredCapacity  = _config.Asg.DesiredCapacity,
                MinCapacity      = _config.Asg.MinCapacity,
                MaxCapacity      = _config.Asg.MaxCapacity,

                KeyName = _config.Asg.KeyName,
                AssociatePublicIpAddress = _config.Asg.AssociatePublicIpAddress,
                VpcSubnets    = selection,
                Role          = role,
                UserData      = GetUserData(_config.Asg.UserDataPath),
                HealthCheck   = healchCheck,
                SecurityGroup = sg
            });

            Utilities.Tagging.Tag(asg, _config, _config.Asg.Tags);
            Utilities.Tagging.Tag(asg, _config, _config.Tags);

            //asg.ScaleOnCpuUtilization()


            return(asg);
        }
        public Header ToVefa()
        {
            PeppolDocumentTypeId documentTypeId = PeppolDocumentTypeId.ValueOf(this.DocumentTypeIdentifier.Identifier);

            return(Header.Of(
                       this.SenderId,
                       this.RecipientId,
                       this.ProfileTypeIdentifier,
                       this.DocumentTypeIdentifier,
                       this.InstanceId == null ? InstanceIdentifier.GenerateUuid() : this.InstanceId.ToVefa(),
                       InstanceType.Of(
                           documentTypeId.RootNameSpace,
                           documentTypeId.LocalName,
                           documentTypeId.Version),
                       this.CreationDateAndTime
                       ));
        }
Пример #13
0
        public DatabaseInstance Create(Amazon.CDK.AWS.EC2.Vpc vpc, IConfigSettings configSettings, SecurityGroup[] securityGroups)
        {
            var db = new DatabaseInstance(this, $"{configSettings.Rds.Name}", new DatabaseInstanceProps
            {
                // todo change all properties based on config settings
                Engine = DatabaseInstanceEngine.Mysql(new MySqlInstanceEngineProps
                {
                    //todo change based on config settings
                    Version = MysqlEngineVersion.VER_5_7,
                }),

                Credentials  = GetCredentials(configSettings),
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE2, InstanceSize.SMALL),
                VpcSubnets   = new SubnetSelection
                {
                    SubnetType = SubnetType.ISOLATED
                },
                Vpc                     = vpc,
                MultiAz                 = configSettings.Rds.MultiAz,
                BackupRetention         = Duration.Days(configSettings.Rds.BackupRetentionInDays),
                StorageEncrypted        = configSettings.Rds.StorageEncrypted,
                AutoMinorVersionUpgrade = configSettings.Rds.AutoMinorVersionUpgrade,
                // todo
                StorageType        = StorageType.GP2,
                SecurityGroups     = securityGroups,
                InstanceIdentifier = configSettings.Rds.Name,
                DeletionProtection = configSettings.Rds.DeletionProtection,
            });


            // rotate the master password (use this when storing it in secrets manager)
            //db.AddRotationSingleUser();

            //EaSdRDpAgGjGKd0AL-uI2fwSJ,znW5

            DBInstance = db;

            return(db);
        }
        internal TargetInstanceStack(Construct scope, string id, Vpc vpc, string keyPairName, IStackProps props = null) : base(scope, id, props)
        {
            SecurityGroup = new SecurityGroup(this, "TargetInstance-Security-Group", new SecurityGroupProps
            {
                Vpc = vpc,
                AllowAllOutbound  = true,
                Description       = "TargetInstance-Security-Group",
                SecurityGroupName = "secgroup-" + id
            });


            Role = new Role(this, "ec2-targetinstance-role", new RoleProps
            {
                AssumedBy = new ServicePrincipal("ec2.amazonaws.com")
            });

            Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("SecretsManagerReadWrite"));

            TargetInstance = new Instance_(this, id, new InstanceProps
            {
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                MachineImage = new WindowsImage(WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE),
                Vpc          = vpc,
                UserData     = UserData.Custom(Utils.GetResource("target_instance_user_data.ps1")),
                KeyName      = keyPairName,
                Role         = Role,
                VpcSubnets   = new SubnetSelection {
                    SubnetType = SubnetType.PRIVATE
                },
                SecurityGroup = SecurityGroup
            });

            SecurityGroup.AddIngressRule(Peer.AnyIpv4(), Port.AllTraffic(), "Allow all trafic in. In production - change this!");

            new CfnOutput(this, "target-instance", new CfnOutputProps {
                Value = TargetInstance.InstancePrivateIp
            });
        }
Пример #15
0
        public static void Main(string[] args)
        {
            var app = new App();

            new CdkStack(app, "MagicOnionBenchmarkCdkStack", new ReportStackProps
            {
                BenchmarkEndpoint              = BenchmarkEndpoint.ServiceDiscoveryWithHttp,
                AlbDomain                      = ("dev.cysharp.io", "Z075519318R3LY1VXMWII"),
                ForceRecreateMagicOnion        = false,
                EnableMagicOnionScaleInCron    = true,
                AutomaticScaleInAfterHour      = 1,
                UseEc2CloudWatchAgentProfiler  = true,
                UseEc2DatadogAgentProfiler     = false,
                UseFargateDatadogAgentProfiler = true,
                MagicOnionInstanceType         = InstanceType.Of(InstanceClass.COMPUTE5_AMD, InstanceSize.LARGE),
                MasterFargate                  = new Fargate(Fargate.CpuSpec.Half, Fargate.MemorySpec.Low),
                WorkerFargate                  = new Fargate(Fargate.CpuSpec.Double, Fargate.MemorySpec.Low),
                Tags = new Dictionary <string, string>()
                {
                    { "environment", "bench" },
                    { "cf-stack", "MagicOnionBenchmarkCdkStack" },
                },
            });
Пример #16
0
        internal NorthwindCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var vpc = new Vpc(this, "LabVpc", new VpcProps
            {
                MaxAzs = 2
            });



            // SQL Server

            var sg = new SecurityGroup(this, "NorthwindDatabaseSecurityGroup", new SecurityGroupProps
            {
                Vpc = vpc,

                SecurityGroupName = "Northwind-DB-SG",
                AllowAllOutbound  = false
            });

            // !!!!!!!!!! replace IP according to the instructions above
            sg.AddIngressRule(Peer.Ipv4("35.171.193.180/32"), Port.Tcp(1433)); // SQL Server
            // !!!!!!!!!!

            var sql = new DatabaseInstance(this, "NorthwindSQLServer", new DatabaseInstanceProps
            {
                Vpc = vpc,

                InstanceIdentifier = "northwind-sqlserver",
                Engine             = DatabaseInstanceEngine.SqlServerEx(new SqlServerExInstanceEngineProps {
                    Version = SqlServerEngineVersion.VER_14
                }),                                                                                                                          // SQL Server Express

                Credentials = Credentials.FromUsername("adminuser", new CredentialsFromUsernameOptions()
                {
                    Password = new SecretValue("Admin12345?")
                }),


                //MasterUsername = "******",
                //MasterUserPassword = new SecretValue("Admin12345?"),

                InstanceType   = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.SMALL), // t3.small
                SecurityGroups = new ISecurityGroup[] { sg },
                MultiAz        = false,
                VpcSubnets     = new SubnetSelection()
                {
                    SubnetType = SubnetType.PUBLIC
                },                              // public subnet

                DeletionProtection     = false, // you need to be able to delete database
                DeleteAutomatedBackups = true,
                BackupRetention        = Duration.Days(0),
                RemovalPolicy          = RemovalPolicy.DESTROY // you need to be able to delete database
            });;

            new CfnOutput(this, "SQLServerEndpointAddress", new CfnOutputProps
            {
                Value = sql.DbInstanceEndpointAddress
            });

            // SQL Server connection string in Systems Manager Parameter Store

            new StringParameter(this, "NorthwindDatabaseConnectionString", new StringParameterProps
            {
                ParameterName = "/Northwind/ConnectionStrings/NorthwindDatabase",
                Type          = ParameterType.STRING,
                Description   = "SQL Server connection string",
                StringValue   = string.Format("Server={0},1433;Integrated Security=false;User ID=adminuser;Password=Admin12345?;Initial Catalog=NorthwindTraders;", sql.DbInstanceEndpointAddress)
            });



            // PostgreSQL setup

            // !!!!!!!!!! add 2 rules when you use provided VM, add 1 rule when you use your computer
            sg.AddIngressRule(Peer.Ipv4("35.171.193.180/32"), Port.Tcp(5432)); // PostgreSQL
            sg.AddIngressRule(Peer.Ipv4("3.238.53.13/32"), Port.Tcp(5432));    // PostgreSQL
            // !!!!!!!!!!

            var postgreSql = new DatabaseCluster(this, "NorthwindPostgreSQL", new DatabaseClusterProps
            {
                InstanceProps = new Amazon.CDK.AWS.RDS.InstanceProps
                {
                    Vpc            = vpc,
                    InstanceType   = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MEDIUM), // t3.medium
                    SecurityGroups = new ISecurityGroup[] { sg },
                    VpcSubnets     = new SubnetSelection()
                    {
                        SubnetType = SubnetType.PUBLIC
                    },                                                                     // you need to access database from your developer PC
                    ParameterGroup = ParameterGroup.FromParameterGroupName(this, "DBInstanceParameterGroup", "default.aurora-postgresql11"),
                },
                ParameterGroup    = ParameterGroup.FromParameterGroupName(this, "DBClusterParameterGroup", "default.aurora-postgresql11"),
                ClusterIdentifier = "northwind-postgresql",
                Engine            = DatabaseClusterEngine.AuroraPostgres(new AuroraPostgresClusterEngineProps
                {
                    Version = AuroraPostgresEngineVersion.VER_11_6
                }),                                                  // Aurora PostgreSQL
                Credentials = Credentials.FromUsername("adminuser", new CredentialsFromUsernameOptions
                {
                    Password = new SecretValue("Admin12345?")
                }),
                //MasterUser = new Login
                //{
                //    Username = "******",
                //    Password = new SecretValue("Admin12345?")
                //},
                Instances = 1,
                Port      = 5432,

                Backup = new BackupProps
                {
                    Retention = Duration.Days(1) // minimum is 1
                },

                DefaultDatabaseName    = "NorthwindTraders",
                InstanceIdentifierBase = "northwind-postgresql-instance",

                RemovalPolicy = RemovalPolicy.DESTROY // you need to be able to delete database,
            });;

            new CfnOutput(this, "PostgreSQLEndpointAddress", new CfnOutputProps
            {
                Value = postgreSql.ClusterEndpoint.Hostname
            });


            // Aurora PostgreSQL connection string in Systems Manager Parameter Store

            new StringParameter(this, "NorthwindPostgreSQLDatabaseConnectionString", new StringParameterProps
            {
                ParameterName = "/Northwind/ConnectionStrings/NorthwindPostgreDatabase",
                Type          = ParameterType.STRING,
                Description   = "PostgreSQL connection string",
                StringValue   = string.Format("Server={0};Database=NorthwindTraders;Username=adminuser;Password=Admin12345?", postgreSql.ClusterEndpoint.Hostname)
            });
        }
Пример #17
0
        internal AutoScaledInstances(
            CdkStack stack,
            CfnParameter targetPlatform,
            Vpc vpc,
            bool publicAccess,
            SecurityGroup albSecurityGroup,
            SecurityGroup instanceSecurityGroup,
            Database database = null,
            Policy policy     = null,
            ApplicationLoadBalancer restApiLoadBalancer = null)
        {
            IMachineImage selectedImage;

            bool targetWindows = false;

            if (targetWindows)
            {
                var userData = UserData.ForWindows();
                userData.AddCommands(
                    "New-Item -Path c:\\temp -ItemType Directory -Force",
                    $"Read-S3Object -BucketName aws-codedeploy-{stack.Region}/latest -Key codedeploy-agent.msi -File c:\\temp\\codedeploy-agent.msi",
                    "Start-Process -Wait -FilePath c:\\temp\\codedeploy-agent.msi -WindowStyle Hidden"
                    );
                selectedImage = new WindowsImage(
                    WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_CORE_BASE,
                    new WindowsImageProps
                {
                    UserData = userData
                }
                    );
            }
            else
            {
                var userData = UserData.ForLinux(new LinuxUserDataOptions {
                    Shebang = "#!/bin/bash -xe"
                });
                userData.AddCommands(
                    "exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1",
                    "yum install -y aws-cli ruby jq",
                    "yum -y update",
                    "cd /tmp/",
                    $"curl -O https://aws-codedeploy-{stack.Region}.s3.amazonaws.com/latest/install",
                    "chmod +x ./install",
                    "if ./install auto; then",
                    "    echo \"CodeDeploy Agent installation completed successfully!\"",
                    "    exit 0",
                    "else",
                    "    echo \"CodeDeploy Agent installation failed, please investigate.\"",
                    "    rm -f /tmp/install",
                    "    exit 1",
                    "fi",
                    "rm -rf /tmp/*"
                    );
                selectedImage = new AmazonLinuxImage(new AmazonLinuxImageProps
                {
                    Edition        = AmazonLinuxEdition.STANDARD,
                    Virtualization = AmazonLinuxVirt.HVM,
                    Generation     = AmazonLinuxGeneration.AMAZON_LINUX_2,
                    Storage        = AmazonLinuxStorage.EBS,
                    UserData       = userData
                });
            };

            var alb = new ApplicationLoadBalancer(stack, $"ApplicationLoadBalancer-{(publicAccess ? "public" : "private")}", new ApplicationLoadBalancerProps
            {
                InternetFacing = publicAccess,
                Vpc            = vpc,
                VpcSubnets     = new SubnetSelection {
                    SubnetType = publicAccess ? SubnetType.PUBLIC : SubnetType.PRIVATE
                },
                SecurityGroup = albSecurityGroup,
                IpAddressType = IpAddressType.IPV4,
                Http2Enabled  = true
            });

            var albTargetGroup = new ApplicationTargetGroup(stack, $"ApplicationTargetGroup-{(publicAccess ? "public" : "private")}", new ApplicationTargetGroupProps
            {
                Vpc         = vpc,
                Port        = 80,
                Protocol    = ApplicationProtocol.HTTP,
                TargetType  = TargetType.INSTANCE,
                HealthCheck = new Amazon.CDK.AWS.ElasticLoadBalancingV2.HealthCheck
                {
                    Timeout  = Duration.Seconds(5),
                    Interval = Duration.Seconds(10),
                    HealthyThresholdCount = 2
                }
            });
            var albListener = new ApplicationListener(stack, $"ApplicationListener-{(publicAccess ? "public" : "private")}", new ApplicationListenerProps
            {
                Port          = 80,
                Protocol      = ApplicationProtocol.HTTP,
                DefaultAction = ListenerAction.Forward(new[] { albTargetGroup }),
                LoadBalancer  = alb
            });

            var asg = new AutoScalingGroup(stack, $"ASG-{(publicAccess ? "public" : "private")}", new AutoScalingGroupProps
            {
                Vpc          = vpc,
                MinCapacity  = 2,
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MEDIUM),
                MachineImage = selectedImage,
                BlockDevices = new[] {
                    new Amazon.CDK.AWS.AutoScaling.BlockDevice()
                    {
                        DeviceName = "/dev/xvda",
                        Volume     = Amazon.CDK.AWS.AutoScaling.BlockDeviceVolume.Ebs(
                            targetWindows ? 30: 8,
                            new Amazon.CDK.AWS.AutoScaling.EbsDeviceOptions {
                            VolumeType          = Amazon.CDK.AWS.AutoScaling.EbsDeviceVolumeType.GP2,
                            DeleteOnTermination = true
                        }
                            )
                    }
                },
                AssociatePublicIpAddress = false,
                VpcSubnets = new SubnetSelection {
                    SubnetType = SubnetType.PRIVATE
                }
            });

            if (policy != null)
            {
                asg.Role.AttachInlinePolicy(policy);
            }
            asg.Role.AddToPrincipalPolicy(
                new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new[] { "ec2:DescribeTags" },
                Resources = new[] { "*" }
            })
                );
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"));
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("AWSXRayDaemonWriteAccess"));
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("CloudWatchAgentServerPolicy"));

            Tag.Add(asg, "Application", stack.StackName);
            if (publicAccess)
            {
                Tag.Add(asg, "ApplicationRole", "Front End");
                Tag.Add(asg, "RESTAPIAddress", restApiLoadBalancer.LoadBalancerDnsName);
            }
            else
            {
                Tag.Add(asg, "ApplicationRole", "REST API");
            }
            if (database != null)
            {
                asg.Node.AddDependency(database.DatabaseResource);
                Tag.Add(asg, "DBSecretArn", database.Password.SecretArn);
            }

            // Enable access from the ALB
            asg.AddSecurityGroup(instanceSecurityGroup);
            Result = new LoadBalancedInstancesResult
            {
                AutoScalingGroup = asg,
                TargetGroup      = albTargetGroup,
                LoadBalancer     = alb
            };
        }
Пример #18
0
        internal AppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // 面倒くさいのでスタックは分けない。
            var vpc = new Vpc(this, "Vpc");
            var efs = new EFS.FileSystem(this, "Efs", new EFS.FileSystemProps()
            {
                Vpc = vpc,
            });
            var efsUser = new PosixUser()
            {
                Gid = "1001",
                Uid = "1001",
            };
            var efsCreateAcl = new Acl()
            {
                OwnerGid    = "1001",
                OwnerUid    = "1001",
                Permissions = "755",
            };
            var efsAccessPoint = new EFS.AccessPoint(this, "EfsAccessPoint", new EFS.AccessPointProps()
            {
                FileSystem = efs,
                // 他の設定そのままで "/" では書き込み権限が得られていなかった。
                // CDK上ではなく、NFSマウント後にルートユーザーで権限を操作すればよい。
                // (ルートディレクトリは既定でルートユーザーが所有している状態)
                // See. https://docs.aws.amazon.com/ja_jp/efs/latest/ug/using-fs.html
                //      https://docs.aws.amazon.com/ja_jp/efs/latest/ug/accessing-fs-nfs-permissions-per-user-subdirs.html
                Path = "/",
                // ファイルIOに用いるユーザーとディレクトリ作成時権限の設定は必須である様子。
                // CDKが既定のユーザーを構成してくれるようなことはない。
                // -> ↑嘘。必要がなければ構成しなくても問題ない。所詮はNFSなので、権限が他のユーザーに解放されているディレクトリは操作できる。はず。
                PosixUser = efsUser,
                CreateAcl = efsCreateAcl,
            });

            // Assets
            // https://docs.aws.amazon.com/cdk/api/latest/docs/aws-s3-assets-readme.html
            // vs
            // https://docs.aws.amazon.com/cdk/api/latest/docs/aws-s3-deployment-readme.html
            // 静的にS3にファイルを残し、スタックのデプロイ後にDataSyncでEFSに転送するのでDeployment。
            var assetBucket = new Bucket(this, "AssetBucket", new BucketProps()
            {
            });

            new BucketDeployment(this, "AssetBucketDeployment", new BucketDeploymentProps()
            {
                Sources           = new ISource[] { Source.Asset("assets") },
                DestinationBucket = assetBucket,
            });

            // https://github.com/shelfio/chrome-aws-lambda-layer
            var chromeLayer = new LayerVersion(this, "ChromeLayer", new LayerVersionProps()
            {
                Code = AssetCode.FromAsset("chrome_aws_lambda.zip"),
                CompatibleRuntimes = new Runtime[] { Runtime.NODEJS_12_X }
            });

            var renderImageBucket = new Bucket(this, "RenderImageBucket", new BucketProps()
            {
            });

            var renderHtmlToS3Function = new Function(this, "RenderHtmlToS3Function", new FunctionProps()
            {
                Vpc         = vpc,
                Runtime     = Runtime.NODEJS_12_X,
                MemorySize  = 1024,
                Timeout     = Duration.Seconds(10),
                Code        = Code.FromAsset("handlers"),
                Handler     = "render-html-to-s3.handler",
                Environment = new Dictionary <string, string>()
                {
                    ["BucketName"]   = renderImageBucket.BucketName,
                    ["EfsMountPath"] = "/mnt/efs",
                },
                Layers     = new ILayerVersion[] { chromeLayer },
                Filesystem = Lambda.FileSystem.FromEfsAccessPoint(efsAccessPoint, "/mnt/efs"),
            });

            // VPCやEFSに関してはCDK上の関連から
            // セキュリティグループや既定のロールへのインラインポリシーが構成される。
            // S3バケットはCDK上の関連はないため明に権限を付与する。
            renderImageBucket.GrantReadWrite(renderHtmlToS3Function);

            // 踏み台
            var bastion = new BastionHostLinux(this, "Bastion", new BastionHostLinuxProps()
            {
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.NANO),
                Vpc          = vpc,
            });

            assetBucket.GrantRead(bastion);
            // https://docs.aws.amazon.com/cdk/api/latest/docs/aws-efs-readme.html
            efs.Connections.AllowDefaultPortFrom(bastion);
            bastion.Instance.UserData.AddCommands(
                "yum check-update -y",                          // Ubuntu: apt-get -y update
                "yum upgrade -y",                               // Ubuntu: apt-get -y upgrade
                "yum install -y amazon-efs-utils",              // Ubuntu: apt-get -y install amazon-efs-utils
                "yum install -y nfs-utils",                     // Ubuntu: apt-get -y install nfs-common
                "file_system_id_1=" + efs.FileSystemId,
                "efs_mount_point_1=/mnt/efs/fs1",
                "mkdir -p \"${efs_mount_point_1}\"",
                "test -f \"/sbin/mount.efs\" && echo \"${file_system_id_1}:/ ${efs_mount_point_1} efs defaults,_netdev\" >> /etc/fstab || " +
                "echo \"${file_system_id_1}.efs." + Stack.Of(this).Region + ".amazonaws.com:/ ${efs_mount_point_1} nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev 0 0\" >> /etc/fstab",
                "mount -a -t efs,nfs4 defaults",
                "chmod go+rw /mnt/efs/fs1"
                );

            new CfnOutput(this, "BastionInstanceId", new CfnOutputProps()
            {
                ExportName = "BastionInstanceId",
                Value      = bastion.InstanceId,
            });
            new CfnOutput(this, "AssetBucketName", new CfnOutputProps()
            {
                ExportName = "AssetBucketName",
                Value      = assetBucket.BucketName,
            });
        }
Пример #19
0
        internal GrpcBenchmarkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var vpc = new Vpc(this, "vpc", new VpcProps
            {
                MaxAzs              = 1,
                NatGateways         = 0,
                SubnetConfiguration = new[] { new SubnetConfiguration {
                                                  Name = "public", SubnetType = SubnetType.PUBLIC
                                              } },
            });
            var subnets = new SubnetSelection {
                Subnets = vpc.PublicSubnets
            };
            var sg = new SecurityGroup(this, "MasterSg", new SecurityGroupProps
            {
                AllowAllOutbound = true,
                Vpc = vpc,
            });
            var role = new Role(this, "MasterRole", new RoleProps
            {
                AssumedBy = new ServicePrincipal("ec2.amazonaws.com"),
            });

            role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"));

            var spot = new AutoScalingGroup(this, "instances", new AutoScalingGroupProps
            {
                // Monitoring is default DETAILED.
                SpotPrice                = "1.0", // 0.0096 for spot price average for m3.medium
                Vpc                      = vpc,
                SecurityGroup            = sg,
                VpcSubnets               = subnets,
                InstanceType             = InstanceType.Of(InstanceClass.COMPUTE5_AMD, InstanceSize.XLARGE4),
                DesiredCapacity          = 1,
                MaxCapacity              = 1,
                MinCapacity              = 0,
                AssociatePublicIpAddress = true,
                MachineImage             = new AmazonLinuxImage(new AmazonLinuxImageProps
                {
                    CpuType        = AmazonLinuxCpuType.X86_64,
                    Generation     = AmazonLinuxGeneration.AMAZON_LINUX_2,
                    Storage        = AmazonLinuxStorage.GENERAL_PURPOSE,
                    Virtualization = AmazonLinuxVirt.HVM,
                }),
                AllowAllOutbound = true,
                GroupMetrics     = new[] { GroupMetrics.All() },
                Role             = role,
                UpdatePolicy     = UpdatePolicy.ReplacingUpdate(),
            });

            // https://gist.github.com/npearce/6f3c7826c7499587f00957fee62f8ee9
            spot.AddUserData(new[]
            {
                "amazon-linux-extras install docker -y",
                "service docker start",
                "chkconfig docker on",
                "usermod -a -G docker ec2-user",
                "curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose",
                "chmod +x /usr/local/bin/docker-compose",
                "yum install -y git",
                "reboot",
            });
        }
Пример #20
0
        public CdkExampleStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
        {
            var vpc = new Vpc(this, "MainVPC", new VpcProps
            {
                Cidr = "192.168.0.0/16"
            });

            var loadBalancer = new ApplicationLoadBalancer(this, "PublicALB", new ApplicationLoadBalancerProps
            {
                InternetFacing = true,
                Vpc            = vpc
            });

            var listener = loadBalancer.AddListener("MyListener", new ApplicationListenerProps
            {
                Port = 80
            });

            var userData = UserData.ForLinux(new LinuxUserDataOptions
            {
                Shebang = "#!/bin/bash"
            });

            userData.AddCommands(
                "yum update -y",
                "yum install httpd -y",
                "echo \"Hello World\" >> /var/www/html/index.html",
                "service httpd start",
                "chkconfig httpd on");


            var ec2SG = new SecurityGroup(this, "Ec2SecurityGroup", new SecurityGroupProps
            {
                Vpc = vpc,
                SecurityGroupName = "Ec2SG"
            });

            ec2SG.Connections.AllowFrom(loadBalancer, Port.Tcp(80), "FROM ALB");

            var instanceIds = new List <string>();

            for (var ix = 0; ix < vpc.PrivateSubnets.Length; ix++)
            {
                var instance = new Instance_(this, $"Instance-{ix}", new InstanceProps
                {
                    InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
                    VpcSubnets   = new SubnetSelection()
                    {
                        SubnetType = SubnetType.PRIVATE
                    },
                    AvailabilityZone = vpc.PrivateSubnets[ix].AvailabilityZone,
                    Vpc           = vpc,
                    MachineImage  = new AmazonLinuxImage(),
                    UserData      = userData,
                    KeyName       = "test-cdk",
                    SecurityGroup = ec2SG
                });

                instanceIds.Add(instance.InstanceId);
            }

            listener.AddTargets("Targets", new AddApplicationTargetsProps
            {
                Port    = 80,
                Targets = instanceIds.Select(i => new InstanceIdTarget(i, 80)).ToArray()
            });
        }
Пример #21
0
        public QaStage(Construct scope, string id, QaStageProps props) : base(scope, id, props)
        {
            var mainStack = new Stack(this, "main-stack", new StackProps
            {
                Env = Constants.DefaultEnv
            });

            var credentials = new GitHubSourceCredentials(mainStack, "github-source-credentials", new GitHubSourceCredentialsProps
            {
                AccessToken = SecretValue.SecretsManager("github/oauth/token")
            });

            var vpc = new Vpc(mainStack, "main-vpc", new VpcProps
            {
                Cidr = "10.0.0.0/16"
            });

            //should change this to Aurora Serverless!!!
            //https://dev.to/cjjenkinson/how-to-create-an-aurora-serverless-rds-instance-on-aws-with-cdk-5bb0

            var db = new PostgresStack(this, "postgres-db-stack", new DatabaseInstanceProps
            {
                Vpc    = vpc,
                Engine = DatabaseInstanceEngine.Postgres(new PostgresInstanceEngineProps
                {
                    Version = PostgresEngineVersion.VER_12_3
                }),
                AllocatedStorage         = 5,
                BackupRetention          = Duration.Days(0),
                DeletionProtection       = false,
                InstanceType             = InstanceType.Of(InstanceClass.BURSTABLE2, InstanceSize.MICRO),
                MasterUsername           = "******",
                MultiAz                  = false,
                DatabaseName             = "postgres",
                RemovalPolicy            = RemovalPolicy.DESTROY,
                AllowMajorVersionUpgrade = false
            }, new StackProps
            {
                Env = Constants.DefaultEnv
            });

            var containerEnvVars = new Dictionary <string, string>
            {
                { "DB__ADDRESS", db.Instance.InstanceEndpoint.SocketAddress }
            };
            var containerSecrets = new Dictionary <string, Secret>
            {
                { "DatabaseConnection", Secret.FromSecretsManager(db.Instance.Secret) }
            };

            var accountMetadataTable = new Table(mainStack, "AccountMetadata", new TableProps
            {
                TableName    = "AccountMetadata",
                PartitionKey = new Attribute
                {
                    Name = "UserId",
                    Type = AttributeType.NUMBER
                },
                SortKey = new Attribute
                {
                    Name = "AccountId",
                    Type = AttributeType.NUMBER
                },
                Stream = StreamViewType.NEW_IMAGE
            });

            var ecsCluster = new Cluster(mainStack, "app-cluster", new ClusterProps
            {
                Vpc               = vpc,
                ClusterName       = "app-cluster",
                ContainerInsights = true
            });

            var fargateSslCertArn = SecretValue.SecretsManager("fargateSslCertArn").ToString();
            var albCert           = Certificate.FromCertificateArn(mainStack, "alb-cert", fargateSslCertArn);

            var sandbankBuildInfra = this.CreateApiBuildStack("SandBank", vpc);
            var sandbankApi        = this.CreateApiStack("SandBank",
                                                         ecsCluster,
                                                         vpc,
                                                         sandbankBuildInfra.EcrRepository,
                                                         "sandbank-api",
                                                         props.HostedZoneName,
                                                         props.HostedZoneId,
                                                         albCert,
                                                         containerEnvVars,
                                                         containerSecrets);

            accountMetadataTable.GrantFullAccess(sandbankApi.FargateService.TaskDefinition.TaskRole);

            var cloudfrontCertArn = SecretValue.SecretsManager("cloudfrontcertarn").ToString();
            var cert = Certificate.FromCertificateArn(mainStack, "cloudfront-cert", cloudfrontCertArn);

            var sandbankSpa = new SpaStack(this, "sandbank-spa-stack", new SpaStackProps
            {
                Env               = Constants.DefaultEnv,
                Vpc               = vpc,
                ServiceName       = "sandbank-spa",
                SubDomain         = "sandbank",
                HostedZoneName    = props.HostedZoneName,
                HostedZoneId      = props.HostedZoneId,
                CloudFrontCert    = cert,
                GitHubSourceProps = Constants.GithubRepo,
                BuildSpecFile     = Constants.NpmBuildSpec,
                SpaDirectory      = "App/FrontEnd/sandbank.spa",
                ApiUrl            = $"{sandbankApi.ApiUrl}/api" //maybe should use CfnOutput instead
            });

            //lambda
            //SandBank.Lambda.ConfigAuditTrail::SandBank.Lambda.ConfigAuditTrail.Function::FunctionHandler
        }
        internal AppdeploymentStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            #region Application hosting resources

            var vpc = new Vpc(this, "appVpc", new VpcProps
            {
                MaxAzs = 3
            });

            var image = new LookupMachineImage(new LookupMachineImageProps
            {
                // maps to "Amazon Linux 2 with .NET Core 3.0 and Mono 5.18"
                Name   = "amzn2-ami-hvm-2.0.*-x86_64-gp2-mono-*",
                Owners = new [] { "amazon" }
            });

            var userData = UserData.ForLinux();
            userData.AddCommands(new string[]
            {
                "sudo yum install -y httpd",
                "sudo systemctl start httpd",
                "sudo systemctl enable httpd"
            });

            var scalingGroup = new AutoScalingGroup(this, "appASG", new AutoScalingGroupProps
            {
                Vpc              = vpc,
                InstanceType     = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MEDIUM),
                MachineImage     = image,
                MinCapacity      = 1,
                MaxCapacity      = 4,
                AllowAllOutbound = true,
                UserData         = userData
            });

            var alb = new ApplicationLoadBalancer(this, "appLB", new ApplicationLoadBalancerProps
            {
                Vpc            = vpc,
                InternetFacing = true
            });

            var albListener = alb.AddListener("Port80Listener", new BaseApplicationListenerProps
            {
                Port = 80
            });

            albListener.AddTargets("Port80ListenerTargets", new AddApplicationTargetsProps
            {
                Port    = 80,
                Targets = new [] { scalingGroup }
            });

            albListener.Connections.AllowDefaultPortFromAnyIpv4("Open access to port 80");

            scalingGroup.ScaleOnRequestCount("ScaleOnModestLoad", new RequestCountScalingProps
            {
                TargetRequestsPerSecond = 1
            });

            #endregion

            #region CI/CD resources

            var _sourceOutput = new Artifact_("Source");
            var _buildOutput  = new Artifact_("Build");

            var build = new PipelineProject(this, "CodeBuild", new PipelineProjectProps
            {
                // relative path to sample app's file (single html page for now)
                BuildSpec   = BuildSpec.FromSourceFilename("talk-demos/appdeployment/SimplePage/buildspec.yml"),
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.AMAZON_LINUX_2_2
                },
            });

            var appDeployment = new ServerApplication(this, "appDeployment");
            // we will use CodeDeploy's default one-at-a-time deployment mode as we are
            // not specifying a deployment config
            var deploymentGroup = new ServerDeploymentGroup(this, "appDeploymentGroup", new ServerDeploymentGroupProps
            {
                Application  = appDeployment,
                InstallAgent = true,
                AutoRollback = new AutoRollbackConfig
                {
                    FailedDeployment = true
                },
                AutoScalingGroups = new [] { scalingGroup }
            });

            // SecretValue.SsmSecure is not currently supported for setting OauthToken,
            // and haven't gotten the SecretsManager approach to work either so
            // resorting to keeping my token in an environment var for now!
            var oauthToken = SecretValue.PlainText(System.Environment.GetEnvironmentVariable("GitHubPersonalToken"));

            var pipeline = new Pipeline(this, "sampleappPipeline", new PipelineProps
            {
                Stages = new StageProps[]
                {
                    new StageProps
                    {
                        StageName = "Source",
                        Actions   = new IAction[]
                        {
                            new GitHubSourceAction(new GitHubSourceActionProps
                            {
                                ActionName = "GitHubSource",
                                Branch     = "master",
                                Repo       = this.Node.TryGetContext("repo-name").ToString(),
                                Owner      = this.Node.TryGetContext("repo-owner").ToString(),
                                OauthToken = oauthToken,
                                Output     = _sourceOutput
                            })
                        }
                    },

                    new StageProps
                    {
                        StageName = "Build",
                        Actions   = new IAction[]
                        {
                            new CodeBuildAction(new CodeBuildActionProps
                            {
                                ActionName = "Build-app",
                                Project    = build,
                                Input      = _sourceOutput,
                                Outputs    = new Artifact_[] { _buildOutput },
                                RunOrder   = 1
                            })
                        }
                    },

                    new StageProps
                    {
                        StageName = "Deploy",
                        Actions   = new IAction[]
                        {
                            new CodeDeployServerDeployAction(new CodeDeployServerDeployActionProps
                            {
                                ActionName      = "Deploy-app",
                                Input           = _buildOutput,
                                RunOrder        = 2,
                                DeploymentGroup = deploymentGroup
                            })
                        }
                    }
                }
            });

            #endregion
        }