示例#1
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;
        }
        internal CdkFargateStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var vpc = new Vpc(this, "SatellytesVpc", new VpcProps
            {
                Cidr   = "10.0.0.0/16",
                MaxAzs = 1,
                SubnetConfiguration = new[] {
                    new SubnetConfiguration()
                    {
                        Name       = "Satellytes/public",
                        SubnetType = SubnetType.PUBLIC,
                    }
                },
            });

            var cluster = new Cluster(this, "SatellytesCluster", new ClusterProps
            {
                Vpc = vpc,
            });

            var taskDefinition = new TaskDefinition(this, "SatellytesWebTask", new TaskDefinitionProps {
                TaskRole = Role.FromRoleArn(this, "taskRole", "arn:aws:iam::576853867587:role/ecsTaskExecutionRole", new FromRoleArnOptions()
                {
                    Mutable = false
                }),
                ExecutionRole = Role.FromRoleArn(this, "taskExecutionRole", "arn:aws:iam::576853867587:role/ecsTaskExecutionRole", new FromRoleArnOptions()
                {
                    Mutable = false
                }),
                Compatibility = Compatibility.FARGATE,
                Cpu           = "256",
                MemoryMiB     = "512",
            });

            var inboundSecurityGrp = new SecurityGroup(this, "satellytesSecurityGrpInboundInet", new SecurityGroupProps {
                Vpc = vpc
            });

            inboundSecurityGrp.AddIngressRule(Peer.AnyIpv4(), Port.Tcp(8080), "inbound http");



            taskDefinition.AddContainer("satellytesWebImage", new ContainerDefinitionProps {
                Image = ContainerImage.FromEcrRepository(Repository.FromRepositoryName(this, "repo", "satellytes-website/backend"), "1cfb651f73fcd20895fc44c06f7bb180ca0e8322"),
            });

            new FargateService(this, "SatellytesWebService", new FargateServiceProps {
                Cluster        = cluster,
                TaskDefinition = taskDefinition,
                VpcSubnets     = new SubnetSelection {
                    SubnetType = SubnetType.PUBLIC
                },
                AssignPublicIp = true,
            });
        }
        public static void AddResourceAccessToRds(SecurityGroup securityGroup, SecurityGroup resource)
        {
            var ports = new Port[]
            {
                new Port(Utils.Ports.GetPortProps(3306, 3306, "MySQL/Auora"))
            };

            foreach (var port in ports)
            {
                securityGroup.AddIngressRule(resource, port);
            }
        }
示例#4
0
        public ISecurityGroup Create(string identification, string groupName, bool allowGroupAllOutbound, IVpc vpc, IPeer ingressPeer, Port ingressPort, IPeer egressPeer, Port egressPort)
        {
            var securityGroup = new SecurityGroup(Scope, identification, new SecurityGroupProps
            {
                AllowAllOutbound  = allowGroupAllOutbound,
                SecurityGroupName = groupName,
                Vpc = vpc
            });

            securityGroup.AddIngressRule(ingressPeer, ingressPort);
            securityGroup.AddEgressRule(egressPeer, egressPort);
            return(securityGroup);
        }
示例#5
0
 public static SecurityGroup WithSecurityGroupRule(this SecurityGroup group, SecurityGroupRule rule)
 {
     if (rule is IngressRule)
     {
         group.AddIngressRule(rule.Peer, rule.Port, rule.Description, rule.RemoteRule);
     }
     else if (rule is EgressRule)
     {
         group.AddEgressRule(rule.Peer, rule.Port, rule.Description, rule.RemoteRule);
     }
     else
     {
         throw new SecurityGroupRuleException(rule);
     }
     return(group);
 }
        internal AuroraDatabaseStack(Construct scope, string id, AuroraDatabaseStackProps props)
            : base(scope, id, props)
        {
            var defaultVpc = Vpc.FromLookup(this, "default", new VpcLookupOptions
            {
                IsDefault = true
            });

            var securityGroup = new SecurityGroup(this, "aurora-sg", new SecurityGroupProps
            {
                AllowAllOutbound = true,
                Description      = "Primary Aurora Serverless SG.  Used by Lambdas",
                Vpc = defaultVpc
            });

            securityGroup.AddIngressRule(securityGroup, Port.AllTraffic());

            new CfnDBCluster(this, "aurora-cluster", new CfnDBClusterProps
            {
                Engine               = "aurora",
                EngineMode           = "serverless",
                Port                 = 3306,
                MasterUsername       = "******",
                MasterUserPassword   = "******",
                DeletionProtection   = false,
                StorageEncrypted     = true,
                VpcSecurityGroupIds  = new string[] { securityGroup.SecurityGroupId },
                ScalingConfiguration = new ScalingConfigurationProperty
                {
                    AutoPause             = true,
                    MinCapacity           = 1,
                    MaxCapacity           = 1,
                    SecondsUntilAutoPause = 300
                }
            });

            new BastionHostLinux(this, "bastion-host", new BastionHostLinuxProps
            {
                Vpc           = defaultVpc,
                SecurityGroup = securityGroup
            });
        }
        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
            });
        }
示例#8
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)
            });
        }
示例#9
0
        internal InfraStack(Construct scope, string id, CustomStackProps props = null)
            : base(scope, id, props)
        {
            var vpc = props.Vpc;

            var cluster = new Cluster(this, "Cluster",
                                      new ClusterProps
            {
                Vpc         = vpc,
                ClusterName = Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("Cluster")
            });

            var albSecurityGroup = new SecurityGroup(this, "AlbSecurityGroup",
                                                     new SecurityGroupProps
            {
                Vpc = vpc,
                AllowAllOutbound = true
            });

            albSecurityGroup.AddIngressRule(Peer.AnyIpv4(), Port.Tcp(80));

            var alb = new ApplicationLoadBalancer(this, "ALB",
                                                  new ApplicationLoadBalancerProps
            {
                Vpc            = vpc,
                InternetFacing = true,
                Http2Enabled   = true,
                IdleTimeout    = Duration.Seconds(60),
                IpAddressType  = IpAddressType.IPV4,
                SecurityGroup  = albSecurityGroup
            });

            var webApiServiceSecurityGroup = new SecurityGroup(this, "WebApiServiceSecurityGroup",
                                                               new SecurityGroupProps
            {
                Vpc = vpc,
                AllowAllOutbound = true
            });

            webApiServiceSecurityGroup.AddIngressRule(albSecurityGroup, Port.Tcp(80));

            var appListener = alb.AddListener("AppListener",
                                              new BaseApplicationListenerProps
            {
                Port          = 80,
                Protocol      = ApplicationProtocol.HTTP,
                DefaultAction = ListenerAction.FixedResponse(404,
                                                             new FixedResponseOptions
                {
                    ContentType = "text/plain",
                    MessageBody = "This is not here..."
                })
            });

            new CfnOutput(this, "ClusterName",
                          new CfnOutputProps
            {
                ExportName = Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("ClusterName"),
                Value      = cluster.ClusterName
            });

            new CfnOutput(this, "WebApiServiceSecurityGroupId",
                          new CfnOutputProps
            {
                ExportName = Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("WebApiServiceSecurityGroupId"),
                Value      = albSecurityGroup.SecurityGroupId
            });

            new CfnOutput(this, "AppListenerArn",
                          new CfnOutputProps
            {
                ExportName = Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("AppListenerArn"),
                Value      = appListener.ListenerArn
            });
        }
示例#10
0
        private (FargateService, Amazon.CDK.AWS.ServiceDiscovery.IService) CreateService(string id,
                                                                                         string serviceName,
                                                                                         string branch,
                                                                                         IVpc vpc,
                                                                                         Cluster cluster,
                                                                                         PrivateDnsNamespace cloudMapNamespace,
                                                                                         string appMeshVirtualNodeName,
                                                                                         Mesh mesh,
                                                                                         IRole taskExecutionRole,
                                                                                         RepositoryImage envoyImage,
                                                                                         ContainerImage containerImage)
        {
            var taskDefinition = new TaskDefinition(this, $"{id}_{serviceName}-{branch}-task-definiton", new TaskDefinitionProps
            {
                Compatibility      = Compatibility.FARGATE,
                MemoryMiB          = "512",
                Cpu                = "256",
                ProxyConfiguration = new AppMeshProxyConfiguration(new AppMeshProxyConfigurationConfigProps()
                {
                    ContainerName = "envoy",
                    Properties    = new AppMeshProxyConfigurationProps()
                    {
                        AppPorts = new double[1] {
                            5000
                        },
                        ProxyIngressPort = 15000,
                        ProxyEgressPort  = 15001,
                        IgnoredUID       = 1337,
                        EgressIgnoredIPs = new string[2] {
                            "169.254.170.2", "169.254.169.254"
                        }
                    }
                }),
                Family        = $"{id}_{serviceName}-task-definition",
                ExecutionRole = taskExecutionRole
            });
            var envoyContainer = taskDefinition.AddContainer("envoy", new ContainerDefinitionOptions
            {
                User        = "******",
                Image       = envoyImage,
                Essential   = true,
                Environment = new Dictionary <string, string>
                {
                    { "APPMESH_VIRTUAL_NODE_NAME", $"mesh/{mesh.MeshName}/virtualNode/{appMeshVirtualNodeName}" }
                },
                HealthCheck = new Amazon.CDK.AWS.ECS.HealthCheck()
                {
                    Command     = new string[] { "CMD-SHELL", "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE" },
                    Interval    = Duration.Seconds(5),
                    Timeout     = Duration.Seconds(2),
                    StartPeriod = Duration.Seconds(10),
                    Retries     = 3
                },
                MemoryLimitMiB = 500,
                Logging        = new AwsLogDriver(new AwsLogDriverProps()
                {
                    StreamPrefix = $"{id}_{serviceName}-{branch}-envoy",
                    LogRetention = RetentionDays.ONE_DAY
                }),
            });
            var container = taskDefinition.AddContainer($"{serviceName}-container", new ContainerDefinitionOptions()
            {
                Image   = containerImage,
                Logging = new AwsLogDriver(new AwsLogDriverProps()
                {
                    StreamPrefix = $"{id}_{serviceName}-{branch}-service",
                    LogRetention = RetentionDays.ONE_DAY
                }),
                Essential   = true,
                Environment = new Dictionary <string, string>
                {
                    { "BRANCH", branch },
                    { "APPMESH_NAMESPACE", cloudMapNamespace.PrivateDnsNamespaceName }
                }
            });

            container.AddPortMappings(new Amazon.CDK.AWS.ECS.PortMapping()
            {
                ContainerPort = 5000
            });
            container.AddContainerDependencies(new ContainerDependency()
            {
                Condition = ContainerDependencyCondition.HEALTHY,
                Container = envoyContainer
            });
            // Cloudmap will append the namespace to the dns entry in R53.
            // We're explicitly checking for master here because for service to service lookups to go via the envoy proxy, the DNS name must resolve.
            // see https://github.com/aws/aws-app-mesh-roadmap/issues/65
            // i.e I want the ping service to call http://pong-service.{namespace}:5000/ and for this to be routed correctly by the proxy.
            // If you create the fargate task with cloudmap service integration with a more specific (branched) DNS name then pong-service.{namespace} r53 entry will never be created
            // and routing doesn't work through envoy.
            var dnsName = $"{serviceName}-service{(branch == "master" ? "" : "-" + branch)}";
            var sg      = new SecurityGroup(this, $"{id}_{serviceName}-{branch}-sg", new SecurityGroupProps()
            {
                AllowAllOutbound  = true,
                SecurityGroupName = $"{id}_{serviceName}-{branch}-sg",
                Vpc = vpc,
            });

            sg.AddIngressRule(Peer.AnyIpv4(), new Port(new PortProps()
            {
                Protocol = Amazon.CDK.AWS.EC2.Protocol.TCP, FromPort = 5000, ToPort = 5000, StringRepresentation = "tcp:5000:5000"
            }), "allow access from outside.");
            var fargateService = new Amazon.CDK.AWS.ECS.FargateService(this, $"{serviceName}-{branch}-service", new FargateServiceProps
            {
                ServiceName    = $"{serviceName}-{branch}-service",
                AssignPublicIp = true,
                Cluster        = cluster,
                TaskDefinition = taskDefinition,
                VpcSubnets     = new SubnetSelection()
                {
                    Subnets = vpc.PublicSubnets
                },
                CloudMapOptions = new CloudMapOptions()
                {
                    Name              = dnsName,
                    DnsRecordType     = DnsRecordType.A,
                    CloudMapNamespace = cloudMapNamespace
                },
                SecurityGroup = sg
            });

            return(fargateService, fargateService.CloudMapService);
        }
示例#11
0
        internal EksCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var clusterAdmin = new Role(this, Constants.ADMIN_ROLE, new RoleProps {
                AssumedBy = new AccountRootPrincipal()
            });

            IVpc vpc = new Vpc(this, Constants.VPC_ID, new VpcProps {
                Cidr = Constants.VPC_CIDR
            });

            var cluster = new Cluster(this, Constants.CLUSTER_ID, new ClusterProps {
                MastersRole     = clusterAdmin,
                Version         = KubernetesVersion.V1_16,
                KubectlEnabled  = true,
                DefaultCapacity = 0,
                Vpc             = vpc
            });

            var tags = new Dictionary <string, string>();

            tags.Add("name", Constants.CDK8s);

            var eksEC2sNodeGroup = cluster.AddNodegroup(Constants.CLUSTER_NODE_GRP_ID, new NodegroupOptions {
                InstanceType = new InstanceType(Constants.EC2_INSTANCE_TYPE),
                MinSize      = 2,
                Subnets      = new SubnetSelection {
                    Subnets = vpc.PrivateSubnets
                },
                Tags = tags
            });

            string[] ManagedPolicyArns = GetNodeRoleManagedPolicyARNs();
            foreach (string arn in ManagedPolicyArns)
            {
                eksEC2sNodeGroup.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName(arn));
            }

            var repository = new ecr.Repository(this, Constants.ECR_REPOSITORY_ID, new ecr.RepositoryProps {
                RepositoryName = Constants.ECR_REPOSITORY_NAME
            });

            #region Aurora Database

            var secGrp = new SecurityGroup(this, Constants.DATABASE_SECURITY_GRP, new SecurityGroupProps {
                Vpc = vpc
            });
            var eksSecGrp = ec2.SecurityGroup.FromSecurityGroupId(this, Constants.EKS_SECURITY_GRP, cluster.ClusterSecurityGroupId);
            secGrp.AddIngressRule(eksSecGrp, ec2.Port.Tcp(3306), description: Constants.EC2_INGRESS_DESCRIPTION);

            var privateSubnets = new List <string>();
            foreach (Subnet subnet in vpc.PrivateSubnets)
            {
                privateSubnets.Add(subnet.SubnetId);
            }

            var dbsubnetGroup = new rds.CfnDBSubnetGroup(this, Constants.AURORA_DB_SUBNET_ID, new rds.CfnDBSubnetGroupProps {
                DbSubnetGroupDescription = Constants.AURORA_DB_SUBNET_DESCRIPTION,
                DbSubnetGroupName        = Constants.AURORA_DB_SUBNET_GROUP_NAME,
                SubnetIds = privateSubnets.ToArray()
            });

            List <CfnTag> cfnDbSecurityGroupTag = new List <CfnTag>();
            CfnTag        tagName = new CfnTag()
            {
                Key = "Name", Value = Constants.APP_NAME
            };
            cfnDbSecurityGroupTag.Add(tagName);

            var dbSecurityGroup = new CfnSecurityGroup(this, Constants.AURORA_CFN_SG_ID,
                                                       new CfnSecurityGroupProps {
                VpcId            = vpc.VpcId,
                GroupName        = Constants.AURORA_GROUP_NAME,
                GroupDescription = "Access to the RDS",
                Tags             = cfnDbSecurityGroupTag.ToArray()
            }
                                                       );

            var cfnSecurityGroupIngress = new ec2.CfnSecurityGroupIngress(
                this, Constants.AURORA_SG_INGRESS, new ec2.CfnSecurityGroupIngressProps {
                Description           = Constants.AURORA_SG_INGRESS_DESCRIPTION,
                FromPort              = Constants.AURORA_PORT,
                ToPort                = Constants.AURORA_PORT,
                IpProtocol            = Constants.CONTAINER_PROTOCOL,
                SourceSecurityGroupId = eksSecGrp.SecurityGroupId,
                GroupId               = dbSecurityGroup.AttrGroupId
            });

            var dbcluster = new rds.CfnDBCluster(this, Constants.AURORA_TODO_DATABASE,
                                                 new rds.CfnDBClusterProps {
                Engine              = Constants.AURORA_DB_ENGINE,
                EngineMode          = Constants.AURORA_ENGINE_MODE,
                Port                = Constants.AURORA_PORT,
                MasterUsername      = Constants.DB_USER_VALUE,
                MasterUserPassword  = Constants.DB_PASSWORD_VALUE,
                DbSubnetGroupName   = Constants.AURORA_DB_SUBNET_GROUP_NAME,
                DatabaseName        = Constants.DB_NAME_VALUE,
                VpcSecurityGroupIds = new string[] {
                    dbSecurityGroup.AttrGroupId
                }
            });
            dbcluster.DbClusterIdentifier = Constants.AURORA_TODO_DATABASE;
            dbcluster.AddDependsOn(dbsubnetGroup);
            dbcluster.CfnOptions.DeletionPolicy = CfnDeletionPolicy.DELETE;
            #endregion

            #region  SSM

            StringBuilder connString = new StringBuilder();
            connString.AppendFormat("server={0}", dbcluster.AttrEndpointAddress);
            connString.AppendFormat(";port={0}", Constants.AURORA_PORT);
            connString.AppendFormat(";database={0}", Constants.DB_NAME_VALUE);
            connString.AppendFormat(";user={0}", Constants.DB_USER_VALUE);
            connString.AppendFormat(";password={0}", Constants.DB_PASSWORD_VALUE);

            new ssm.StringParameter(this, "Parameter", new ssm.StringParameterProps {
                Description   = "Maintains the Aurora Database Connection String",
                ParameterName = Constants.SSM_DB_CONN_STRING,
                StringValue   = connString.ToString(),
                Tier          = ssm.ParameterTier.ADVANCED
            });

            #endregion
        }
示例#12
0
        internal CdkStack(Construct scope, string id, IStackProps props = null) :
            base(scope, id, props)
        {
            var targetPlatform = new CfnParameter(this, "TargetPlatform", new CfnParameterProps
            {
                AllowedValues = new[] { "Linux", "Windows" },
                Type          = "String",
                Default       = "Linux"
            });

            var vpc = new Vpc(this, "VPC", new VpcProps
            {
                Cidr               = "10.0.0.0/16",
                MaxAzs             = 2,
                NatGatewayProvider = NatProvider.Gateway(),
                NatGateways        = 2,
                NatGatewaySubnets  = new SubnetSelection {
                    SubnetType = SubnetType.PUBLIC, OnePerAz = true
                },
                SubnetConfiguration = new[]
                {
                    new SubnetConfiguration {
                        CidrMask = 24, Name = "PublicSubnet", SubnetType = SubnetType.PUBLIC
                    },
                    new SubnetConfiguration {
                        CidrMask = 24, Name = "PrivateSubnet", SubnetType = SubnetType.PRIVATE
                    },
                }
            });

            var externalLoadBalancerSecurityGroup = new SecurityGroup(vpc, "ExternalLoadBalancerSecurityGroup", new SecurityGroupProps
            {
                Vpc         = vpc,
                Description = "Allows HTTP access to the application."
            });

            externalLoadBalancerSecurityGroup.AddIngressRule(externalLoadBalancerSecurityGroup, Port.Tcp(80), "Allow HTTP");
            var frontEndSecurityGroup = new SecurityGroup(vpc, "UISecurityGroup", new SecurityGroupProps
            {
                Vpc         = vpc,
                Description = "Allows HTTP access to the UI."
            });

            frontEndSecurityGroup.AddIngressRule(externalLoadBalancerSecurityGroup, Port.Tcp(80), "Allow HTTP");
            var internalLoadBalancerSecurityGroup = new SecurityGroup(vpc, "InternalLoadBalancerSecurityGroup", new SecurityGroupProps
            {
                Vpc         = vpc,
                Description = "Allows HTTP access to the REST API."
            });

            internalLoadBalancerSecurityGroup.AddIngressRule(frontEndSecurityGroup, Port.Tcp(80));
            var restApiSecurityGroup = new SecurityGroup(vpc, "ApiSecurityGroup", new SecurityGroupProps
            {
                Vpc         = vpc,
                Description = "Allows HTTP access to the Rest API."
            });

            restApiSecurityGroup.AddIngressRule(internalLoadBalancerSecurityGroup, Port.Tcp(80));

            var db = new Database(this, vpc, restApiSecurityGroup);

            var policy = new Amazon.CDK.AWS.IAM.Policy(this,
                                                       "DBPasswordSecretAccess",
                                                       new Amazon.CDK.AWS.IAM.PolicyProps
            {
                PolicyName = "AllowPasswordAccess",
                Statements = new[] {
                    new Amazon.CDK.AWS.IAM.PolicyStatement(new Amazon.CDK.AWS.IAM.PolicyStatementProps {
                        Effect  = Amazon.CDK.AWS.IAM.Effect.ALLOW,
                        Actions = new [] {
                            "secretsmanager:GetSecretValue"
                        },
                        Resources = new [] { db.Password.SecretArn }
                    })
                }
            });
            var restApiInstances  = new AutoScaledInstances(this, targetPlatform, vpc, false, internalLoadBalancerSecurityGroup, restApiSecurityGroup, db, policy: policy);
            var frontEndInstances = new AutoScaledInstances(this, targetPlatform, vpc, true, externalLoadBalancerSecurityGroup, frontEndSecurityGroup, restApiLoadBalancer: restApiInstances.Result.LoadBalancer);

            //var instances = new AutoScaledInstances(this, targetPlatform, vpc, appSecurityGroup);
            new CICD(this, targetPlatform, frontEndInstances.Result, restApiInstances.Result);
        }
示例#13
0
        internal CdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var stackProps                = ReportStackProps.ParseOrDefault(props);
            var dframeWorkerLogGroup      = "MagicOnionBenchWorkerLogGroup";
            var dframeMasterLogGroup      = "MagicOnionBenchMasterLogGroup";
            var benchNetwork              = stackProps.GetBenchNetwork();
            var recreateMagicOnionTrigger = stackProps.GetBenchmarkServerBinariesHash();

            // s3
            var s3 = new Bucket(this, "Bucket", new BucketProps
            {
                AutoDeleteObjects = true,
                RemovalPolicy     = RemovalPolicy.DESTROY,
                AccessControl     = BucketAccessControl.PRIVATE,
            });
            var lifecycleRule = new LifecycleRule
            {
                Enabled    = true,
                Prefix     = "reports/",
                Expiration = Duration.Days(stackProps.DaysKeepReports),
                AbortIncompleteMultipartUploadAfter = Duration.Days(1),
            };

            s3.AddLifecycleRule(lifecycleRule);
            s3.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Sid        = "AllowPublicRead",
                Effect     = Effect.ALLOW,
                Principals = new[] { new AnyPrincipal() },
                Actions    = new[] { "s3:GetObject*" },
                Resources  = new[] { $"{s3.BucketArn}/html/*" },
            }));
            s3.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Sid        = "AllowAwsAccountAccess",
                Effect     = Effect.ALLOW,
                Principals = new[] { new AccountRootPrincipal() },
                Actions    = new[] { "s3:*" },
                Resources  = new[] { $"{s3.BucketArn}/*" },
            }));

            // s3 deploy
            var masterDllDeployment = new BucketDeployment(this, "DeployMasterDll", new BucketDeploymentProps
            {
                DestinationBucket    = s3,
                Sources              = new[] { Source.Asset(Path.Combine(Directory.GetCurrentDirectory(), $"out/linux/server")) },
                DestinationKeyPrefix = $"assembly/linux/server"
            });
            var userdataDeployment = new BucketDeployment(this, "UserData", new BucketDeploymentProps
            {
                DestinationBucket    = s3,
                Sources              = new[] { Source.Asset(Path.Combine(Directory.GetCurrentDirectory(), "userdata/")) },
                DestinationKeyPrefix = "userdata/"
            });

            // docker deploy
            var dockerImage = new DockerImageAsset(this, "dframeWorkerImage", new DockerImageAssetProps
            {
                Directory = Path.Combine(Directory.GetCurrentDirectory(), "app"),
                File      = "ConsoleAppEcs/Dockerfile.Ecs",
            });
            var dframeImage = ContainerImage.FromDockerImageAsset(dockerImage);

            // network
            var vpc = new Vpc(this, "Vpc", new VpcProps
            {
                MaxAzs              = 2,
                NatGateways         = 0,
                SubnetConfiguration = new[] { new SubnetConfiguration {
                                                  Name = "public", SubnetType = SubnetType.PUBLIC
                                              } },
            });
            var allsubnets = new SubnetSelection {
                Subnets = vpc.PublicSubnets
            };
            var singleSubnets = new SubnetSelection {
                Subnets = new[] { vpc.PublicSubnets.First() }
            };
            var sg = new SecurityGroup(this, "MasterSg", new SecurityGroupProps
            {
                AllowAllOutbound = true,
                Vpc = vpc,
            });

            foreach (var subnet in vpc.PublicSubnets)
            {
                sg.AddIngressRule(Peer.Ipv4(vpc.VpcCidrBlock), Port.AllTcp(), "VPC", true);
            }

            // service discovery
            var serviceDiscoveryDomain = "local";
            var serverMapName          = "server";
            var dframeMapName          = "dframe-master";
            var ns = new PrivateDnsNamespace(this, "Namespace", new PrivateDnsNamespaceProps
            {
                Vpc  = vpc,
                Name = serviceDiscoveryDomain,
            });
            var serviceDiscoveryServer = ns.CreateService("server", new DnsServiceProps
            {
                Name          = serverMapName,
                DnsRecordType = DnsRecordType.A,
                RoutingPolicy = RoutingPolicy.MULTIVALUE,
            });

            // alb
            var albDnsName = "benchmark-alb";
            var benchToMagicOnionDnsName = benchNetwork.RequireAlb
                ? $"{benchNetwork.EndpointScheme}://{albDnsName}.{stackProps.AlbDomain.domain}"
                : $"{benchNetwork.EndpointScheme}://{serverMapName}.{serviceDiscoveryDomain}";
            IApplicationTargetGroup grpcTargetGroup  = null;
            IApplicationTargetGroup httpsTargetGroup = null;

            if (benchNetwork.RequireAlb)
            {
                // route53
                var hostedZone = HostedZone.FromHostedZoneAttributes(this, "HostedZone", new HostedZoneAttributes
                {
                    HostedZoneId = stackProps.AlbDomain.zoneId,
                    ZoneName     = stackProps.AlbDomain.domain,
                });

                // acm
                var certificate = new DnsValidatedCertificate(this, "certificate", new DnsValidatedCertificateProps
                {
                    DomainName = $"{albDnsName}.{hostedZone.ZoneName}",
                    HostedZone = hostedZone,
                });
                // alb
                var lb = new ApplicationLoadBalancer(this, "LB", new ApplicationLoadBalancerProps
                {
                    Vpc           = vpc,
                    VpcSubnets    = allsubnets,
                    SecurityGroup = new SecurityGroup(this, "AlbSg", new SecurityGroupProps
                    {
                        AllowAllOutbound = true,
                        Vpc = vpc,
                    }),
                    InternetFacing = false,
                    Http2Enabled   = true,
                });
                grpcTargetGroup  = AddGrpcTargetGroup(benchNetwork, vpc, certificate, lb);
                httpsTargetGroup = AddHttpsTargetGroup(benchNetwork, vpc, certificate, lb);

                // Dns Record
                _ = new CnameRecord(this, "alb-alias-record", new CnameRecordProps
                {
                    RecordName = $"{albDnsName}.{stackProps.AlbDomain.domain}",
                    Ttl        = Duration.Seconds(60),
                    Zone       = hostedZone,
                    DomainName = lb.LoadBalancerDnsName,
                });
            }

            // iam
            var iamEc2MagicOnionRole  = GetIamEc2MagicOnionRole(s3, serviceDiscoveryServer);
            var iamEcsTaskExecuteRole = GetIamEcsTaskExecuteRole(new[] { dframeWorkerLogGroup, dframeMasterLogGroup });
            var iamDFrameTaskDefRole  = GetIamEcsDframeTaskDefRole(s3);
            var iamWorkerTaskDefRole  = GetIamEcsWorkerTaskDefRole(s3);

            // secrets
            var ddToken = stackProps.UseEc2DatadogAgentProfiler || stackProps.UseFargateDatadogAgentProfiler
                ? Amazon.CDK.AWS.SecretsManager.Secret.FromSecretNameV2(this, "dd-token", "magiconion-benchmark-datadog-token")
                : null;

            // MagicOnion
            var asg = new AutoScalingGroup(this, "MagicOnionAsg", new AutoScalingGroupProps
            {
                // Monitoring is default DETAILED.
                SpotPrice                = "1.0", // 0.0096 for spot price average for m3.medium
                Vpc                      = vpc,
                SecurityGroup            = sg,
                VpcSubnets               = singleSubnets,
                InstanceType             = stackProps.MagicOnionInstanceType,
                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             = iamEc2MagicOnionRole,
                UpdatePolicy     = UpdatePolicy.ReplacingUpdate(),
                Signals          = Signals.WaitForCount(1, new SignalsOptions
                {
                    Timeout = Duration.Minutes(10),
                }),
            });

            asg.AddSecretsReadGrant(ddToken, () => stackProps.UseEc2DatadogAgentProfiler);
            var userdata = GetUserData(recreateMagicOnionTrigger, s3.BucketName, stackProps.BenchmarkBinaryNames, serviceDiscoveryServer.ServiceId, stackProps.UseEc2CloudWatchAgentProfiler, stackProps.UseEc2DatadogAgentProfiler);

            asg.AddUserData(userdata);
            asg.UserData.AddSignalOnExitCommand(asg);
            asg.Node.AddDependency(masterDllDeployment);
            asg.Node.AddDependency(userdataDeployment);
            if (stackProps.EnableMagicOnionScaleInCron)
            {
                asg.ScaleOnSchedule("ScheduleOut", new BasicScheduledActionProps
                {
                    DesiredCapacity = 1,
                    MaxCapacity     = 1,
                    // AM9:00 (JST+9) on Monday to Wednesday
                    Schedule = Schedule.Expression("0 0 * 1-3 *"),
                });
                asg.ScaleOnSchedule("ScheduleIn", new BasicScheduledActionProps
                {
                    DesiredCapacity = 0,
                    MaxCapacity     = 0,
                    // PM9:00 (JST+9) on Everyday
                    Schedule = Schedule.Expression("0 12 * 1-7 *"),
                });
            }
            if (benchNetwork.RequireAlb)
            {
                asg.AttachToApplicationTargetGroup(grpcTargetGroup);
                asg.AttachToApplicationTargetGroup(httpsTargetGroup);
            }

            // ECS
            var cluster = new Cluster(this, "WorkerCluster", new ClusterProps
            {
                Vpc = vpc,
            });

            cluster.Node.AddDependency(asg); // wait until asg is up

            // dframe-worker
            var dframeWorkerContainerName = "worker";
            var dframeWorkerTaskDef       = new FargateTaskDefinition(this, "DFrameWorkerTaskDef", new FargateTaskDefinitionProps
            {
                ExecutionRole  = iamEcsTaskExecuteRole,
                TaskRole       = iamWorkerTaskDefRole,
                Cpu            = stackProps.WorkerFargate.CpuSize,
                MemoryLimitMiB = stackProps.WorkerFargate.MemorySize,
            });

            dframeWorkerTaskDef.AddContainer(dframeWorkerContainerName, new ContainerDefinitionOptions
            {
                Image       = dframeImage,
                Command     = new[] { "--worker-flag" },
                Environment = new Dictionary <string, string>
                {
                    { "DFRAME_MASTER_CONNECT_TO_HOST", $"{dframeMapName}.{serviceDiscoveryDomain}" },
                    { "DFRAME_MASTER_CONNECT_TO_PORT", "12345" },
                    { "BENCH_SERVER_HOST", benchToMagicOnionDnsName },
                    { "BENCH_REPORTID", stackProps.ReportId },
                    { "BENCH_S3BUCKET", s3.BucketName },
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "WorkerLogGroup", new LogGroupProps
                    {
                        LogGroupName  = dframeWorkerLogGroup,
                        RemovalPolicy = RemovalPolicy.DESTROY,
                        Retention     = RetentionDays.TWO_WEEKS,
                    }),
                    StreamPrefix = dframeWorkerLogGroup,
                }),
            });
            dframeWorkerTaskDef.AddDatadogContainer($"{dframeWorkerContainerName}-datadog", ddToken, () => stackProps.UseFargateDatadogAgentProfiler);
            var dframeWorkerService = new FargateService(this, "DFrameWorkerService", new FargateServiceProps
            {
                ServiceName       = "DFrameWorkerService",
                DesiredCount      = 0,
                Cluster           = cluster,
                TaskDefinition    = dframeWorkerTaskDef,
                VpcSubnets        = singleSubnets,
                SecurityGroups    = new[] { sg },
                PlatformVersion   = FargatePlatformVersion.VERSION1_4,
                MinHealthyPercent = 0,
                AssignPublicIp    = true,
            });

            // dframe-master
            var dframeMasterTaskDef = new FargateTaskDefinition(this, "DFrameMasterTaskDef", new FargateTaskDefinitionProps
            {
                ExecutionRole  = iamEcsTaskExecuteRole,
                TaskRole       = iamDFrameTaskDefRole,
                Cpu            = stackProps.MasterFargate.CpuSize,
                MemoryLimitMiB = stackProps.MasterFargate.MemorySize,
            });

            dframeMasterTaskDef.AddContainer("dframe", new ContainerDefinitionOptions
            {
                Image       = dframeImage,
                Environment = new Dictionary <string, string>
                {
                    { "DFRAME_CLUSTER_NAME", cluster.ClusterName },
                    { "DFRAME_MASTER_SERVICE_NAME", "DFrameMasterService" },
                    { "DFRAME_WORKER_CONTAINER_NAME", dframeWorkerContainerName },
                    { "DFRAME_WORKER_SERVICE_NAME", dframeWorkerService.ServiceName },
                    { "DFRAME_WORKER_TASK_NAME", Fn.Select(1, Fn.Split("/", dframeWorkerTaskDef.TaskDefinitionArn)) },
                    { "DFRAME_WORKER_IMAGE", dockerImage.ImageUri },
                    { "BENCH_REPORTID", stackProps.ReportId },
                    { "BENCH_S3BUCKET", s3.BucketName },
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "MasterLogGroup", new LogGroupProps
                    {
                        LogGroupName  = dframeMasterLogGroup,
                        RemovalPolicy = RemovalPolicy.DESTROY,
                        Retention     = RetentionDays.TWO_WEEKS,
                    }),
                    StreamPrefix = dframeMasterLogGroup,
                }),
            });
            dframeMasterTaskDef.AddDatadogContainer($"dframe-datadog", ddToken, () => stackProps.UseFargateDatadogAgentProfiler);
            var dframeMasterService = new FargateService(this, "DFrameMasterService", new FargateServiceProps
            {
                ServiceName       = "DFrameMasterService",
                DesiredCount      = 1,
                Cluster           = cluster,
                TaskDefinition    = dframeMasterTaskDef,
                VpcSubnets        = singleSubnets,
                SecurityGroups    = new[] { sg },
                PlatformVersion   = FargatePlatformVersion.VERSION1_4,
                MinHealthyPercent = 0,
                AssignPublicIp    = true,
            });

            dframeMasterService.EnableCloudMap(new CloudMapOptions
            {
                CloudMapNamespace = ns,
                Name          = dframeMapName,
                DnsRecordType = DnsRecordType.A,
                DnsTtl        = Duration.Seconds(300),
            });

            // output
            new CfnOutput(this, "ReportUrl", new CfnOutputProps {
                Value = $"https://{s3.BucketRegionalDomainName}/html/{stackProps.ReportId}/index.html"
            });
            new CfnOutput(this, "EndPointStyle", new CfnOutputProps {
                Value = stackProps.BenchmarkEndpoint.ToString()
            });
            new CfnOutput(this, "AsgName", new CfnOutputProps {
                Value = asg.AutoScalingGroupName
            });
            new CfnOutput(this, "EcsClusterName", new CfnOutputProps {
                Value = cluster.ClusterName
            });
            new CfnOutput(this, "DFrameWorkerEcsTaskdefImage", new CfnOutputProps {
                Value = dockerImage.ImageUri
            });
        }