public FrontendStack(Construct scope, string name, string url, StackProps props = null) : base(scope, $"frontend-{name}", props) { // pricing - hosted zone // 0,50 USD por zona hospedada/mês para as primeiras 25 zonas hospedadas // 0,10 USD por zona hospedada/mês para zonas hospedadas adicionais // Consultas padrão // 0,40 USD por milhão de consultas – primeiro 1 bilhão de consultas/mês // 0,20 USD por milhão de consultas – mais de 1 bilhão de consultas/mês // Consultas de roteamento baseado em latência // 0,60 USD por milhão de consultas – primeiro 1 bilhão de consultas/mês // 0,30 USD por milhão de consultas – mais de 1 bilhão de consultas/mês // Consultas de Geo DNS e geoproximidade // 0,70 USD por milhão de consultas -- primeiro 1 bilhão de consultas/mês // 0,35 USD por milhão de consultas -- mais de 1 bilhão de consultas/mês _bucket = new Bucket(this, $"frontend-{name}-bucket", new BucketProps() { BucketName = name + "72b302bf297a228a75730123efef7c41", WebsiteIndexDocument = "index.html", PublicReadAccess = true, RemovalPolicy = RemovalPolicy.DESTROY }); _bucketDeployment = new BucketDeployment(this, $"frontend-{name}-deployment", new BucketDeploymentProps() { Sources = new[] { Source.Asset("../tools/frontend/") }, DestinationBucket = _bucket, RetainOnDelete = false }); _hostedZone = new HostedZone(this, $"frontend-{name}-hostedzone", new HostedZoneProps { ZoneName = url }); _certificate = new Certificate(this, $"frontend-{name}-certificate", new CertificateProps { DomainName = url, Validation = CertificateValidation.FromDns(_hostedZone) }); _distribution = new Distribution(this, $"frontend-{name}-distribution", new DistributionProps { DefaultBehavior = new BehaviorOptions { Origin = new S3Origin(_bucket), ViewerProtocolPolicy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS }, DomainNames = new[] { url }, Certificate = _certificate, DefaultRootObject = "index.html" }); _aRecord = new ARecord(this, $"frontend-{name}-arecord", new ARecordProps { Zone = _hostedZone, RecordName = url, Target = RecordTarget.FromAlias(new CloudFrontTarget(_distribution)) }); }
public static void Main(string[] args) { var app = new App(); var props = new StackProps() { Env = new Environment() { Account = "353697730469", Region = "us-east-1" } }; var network = new NetworkStack(app, "companies", props); new FrontendStack(app, "companies", "zro17.com"); new DatabaseStack(app, "companies", network.GetVpc(), props); new SchedulerStack(app, "regulatory-sec-update", 128, new CronOptions() { Minute = "*/5", Hour = "*", Day = "*", Month = "*", Year = "*" }, network.GetVpc(), props); new ConsumerStack(app, "regulatory-sec-reader", 128, network.GetVpc(), props); new ConsumerStack(app, "regulatory-sec-parser", 128, network.GetVpc(), props); new ConsumerStack(app, "calculations-indexes", 128, network.GetVpc(), props); app.Synth(); }
public static void Main(string[] args) { var app = new App(); var props = new StackProps { Env = makeEnv() }; new CdkWorkshopStack(app, "CdkWorkshopStack", props); app.Synth(); }
public DatabaseStack(Construct scope, string name, Vpc vpc, StackProps props = null) : base(scope, $"database-{name}", props) { // pricing - rds // 750 horas de uso de instâncias db.t2.micro Single-AZ do Amazon RDS para execução de // MySQL, MariaDB, PostgreSQL, Oracle BYOL ou SQL Server(executando SQL Server Express Edition) // // 20 GB de armazenamento de banco de dados de SSD // // 20 GB de armazenamento de backup para seus backups de banco de dados automatizados e // quaisquer snapshots de banco de dados iniciados por usuário // // pricing - secret manager // 0,40 USD por segredo por mês. No caso de segredos armazenados por menos de um mês, // o preço é pro-rata (com base no número de horas). // 0,05 USD por 10.000 chamadas de API. var secret = new Secret(this, $"database-{name}-secret", new SecretProps() { Description = $"Database {name} password", SecretName = $"database-{name}-secret" }); var databaseSecret = new DatabaseSecret(this, $"database-{name}-databasesecret", new DatabaseSecretProps() { Username = "******", MasterSecret = secret, ExcludeCharacters = "{}[]()'\"/\\" }); _databaseInstance = new DatabaseInstance(this, $"database-{name}-cluster", new DatabaseInstanceProps() { InstanceIdentifier = name + "-instance", DatabaseName = name, Credentials = Credentials.FromSecret(databaseSecret), Engine = DatabaseInstanceEngine.Mysql(new MySqlInstanceEngineProps() { Version = MysqlEngineVersion.VER_8_0_21 }), InstanceType = new InstanceType("t2.micro"), Vpc = vpc, VpcSubnets = new SubnetSelection() { SubnetType = SubnetType.ISOLATED } }); _databaseInstance.AddRotationSingleUser(new RotationSingleUserOptions() { AutomaticallyAfter = Duration.Days(7), ExcludeCharacters = "!@#$%^&*" }); }
public ConsumerStack(Construct scope, string name, double memory, Vpc vpc, StackProps props = null) : base(scope, $"consumer-{name}", props) { // pricing - lambda // 1 milhão de solicitações gratuitas por mês e // 400.000 GB/segundos de tempo de computação por mês. // // pricing - sqs // Primeiro milhão de solicitações/mês - padrao: Gratuito - fifo: Gratuito // De 1 milhão a 100 bilhões de solicitações mês - padrão: 0,40 USD - fifo: 0,50 USD // De 100 milhões a 200 bilhões de solicitações/mês - padrão: 0,30 USD - fifo: 0,40 USD // Mais de 200 bilhões de solicitações/mês - padrão: 0,24 USD - fifo: 0,35 USD _function = new Function(this, $"consumer-{name}-lambda", new FunctionProps() { FunctionName = name, MemorySize = memory, Runtime = Runtime.DOTNET_CORE_3_1, Handler = "Lambda::Lambda.Function::Handler", Code = Code.FromAsset("../tools/consumer"), Timeout = Duration.Seconds(20), LogRetention = RetentionDays.ONE_DAY, Vpc = vpc, VpcSubnets = new SubnetSelection() { SubnetType = SubnetType.PRIVATE } }); _deadletter = new Queue(this, $"consumer-{name}-deadletter", new QueueProps() { QueueName = name + "-deadletter", VisibilityTimeout = Duration.Seconds(30), RetentionPeriod = Duration.Days(10) }); ; _queue = new Queue(this, $"consumer-{name}-queue", new QueueProps() { QueueName = name, VisibilityTimeout = Duration.Seconds(30), RetentionPeriod = Duration.Days(10), DeadLetterQueue = new DeadLetterQueue() { MaxReceiveCount = 3, Queue = _deadletter } }); _function.AddEventSource(new SqsEventSource(_queue)); }
public static void Main(string[] args) { var app = new App(); var stackProps = new StackProps { Env = new Environment { Region = "eu-west-1" } }; new AwsCdkDotnetStack(app, "AwsCdkDotnetStack", stackProps); app.Synth(); }
public static void Main(string[] args) { var app = new App(); var defaultAccount = System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"); var stackProps = new StackProps { Env = new Amazon.CDK.Environment { Region = "eu-central-1", Account = defaultAccount } }; var networkStack = new NetworkStack(app, "iac-demo-network-stack", stackProps); var webAppStack = new WebAppStack(app, "iac-demo-web-app-stack", networkStack.VpcRef, stackProps); var workflowStack = new WorkflowStack(app, "iac-demo-workflow-stack", networkStack.VpcRef, networkStack.L1Vpc, stackProps); app.Synth(); }
public static void Main(string[] args) { var app = new App(); var stackProps = new StackProps { Env = new Environment { Account = System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), Region = System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") } }; new LambdaStack(app, "LambdaFunctionOne", stackProps); new LambdaStack(app, "LambdaFunctionTwo", stackProps); new WebsiteStack(app, "WebsiteOne", stackProps); new ApiGatewayStack(app, "HelloApiGateway", stackProps); app.Synth(); }
public static void Main(string[] args) { var app = new App(); var props = new StackProps() { Env = new Environment() { Account = "277944362602", Region = "us-east-1" } }; var network = new NetworkStack(app, "player2", props); new FrontendStack(app, "player2", "player2.store"); app.Synth(); }
public static void Main(string[] args) { var app = new App(); var props = new StackProps() { Env = GetEnvironment() }; // weird syntax, but a good way to grab Zone / Certificate from one place, otherwise // you get errors like // "Failed to create resource. Error: you have reached your limit of 20 certificates in the last year" var networkStack = new Stack(app, "NetworkStack", props); var config = GetNetworkConfig(networkStack); new LandingStack(app, "LandingStack", baseDomainName, config, props); new WorkSplitCalculatorStack(app, "WorkSplitCalculatorStack", baseDomainName, config, props); app.Synth(); }
public NetworkStack(Construct scope, string name, StackProps props = null) : base(scope, $"network-{name}", props) { _natInstanceProvider = NatProvider.Instance(new NatInstanceProps { InstanceType = new InstanceType("t2.micro") }); _vpc = new Vpc(this, $"network-{name}-vpc", new VpcProps() { Cidr = "10.0.0.0/20", MaxAzs = 2, NatGateways = 1, NatGatewayProvider = _natInstanceProvider, SubnetConfiguration = new ISubnetConfiguration[] { new SubnetConfiguration { CidrMask = 23, Name = "PUBLIC", SubnetType = SubnetType.PUBLIC }, new SubnetConfiguration { CidrMask = 23, Name = "PRIVATE", SubnetType = SubnetType.PRIVATE }, new SubnetConfiguration { CidrMask = 23, Name = "ISOLATED", SubnetType = SubnetType.ISOLATED } } }); }
internal ColdStartSimulatorStack(Construct scope, string id, StackProps props = null) : base(scope, id, props) { var coldStartSimulatorLambdaPolicy = new Amazon.CDK.AWS.IAM.PolicyStatement { Effect = Amazon.CDK.AWS.IAM.Effect.ALLOW }; coldStartSimulatorLambdaPolicy.AddResources("*"); coldStartSimulatorLambdaPolicy.AddActions("lambda:*"); coldStartSimulatorLambdaPolicy.AddActions("xray:*"); var coldStartSimulatorSetupFunction = new Function(this, "coldstartsimulator-setup", new FunctionProps { FunctionName = "coldstartsimulator-setup", Runtime = Runtime.DOTNET_CORE_3_1, Code = Code.FromAsset("../lambdas/coldstartsimulator/bin/Release/netcoreapp3.1/publish"), Handler = "ColdStartSimulator::ColdStartSimulator.StepFunctionTasks::Setup", Timeout = Duration.Seconds(31), MemorySize = 512 }); var coldStartSimulatorInvokeLambdaFunction = new Function(this, "coldstartsimulator-invokelambda", new FunctionProps { FunctionName = "coldstartsimulator-invokelambda", Runtime = Runtime.DOTNET_CORE_3_1, Code = Code.FromAsset("../lambdas/coldstartsimulator/bin/Release/netcoreapp3.1/publish"), Handler = "ColdStartSimulator::ColdStartSimulator.StepFunctionTasks::InvokeLambda", Timeout = Duration.Seconds(31), MemorySize = 512 }); coldStartSimulatorInvokeLambdaFunction.AddToRolePolicy(coldStartSimulatorLambdaPolicy); var coldStartSimulatorTouchLambdaFunction = new Function(this, "coldstartsimulator-touchlambda", new FunctionProps { FunctionName = "coldstartsimulator-touchlambda", Runtime = Runtime.DOTNET_CORE_3_1, Code = Code.FromAsset("../lambdas/coldstartsimulator/bin/Release/netcoreapp3.1/publish"), Handler = "ColdStartSimulator::ColdStartSimulator.StepFunctionTasks::TouchLambda", Timeout = Duration.Seconds(31), MemorySize = 512 }); coldStartSimulatorTouchLambdaFunction.AddToRolePolicy(coldStartSimulatorLambdaPolicy); var metricS3Bucket = new Bucket(this, "metric-bucket", new BucketProps { BucketName = "coldstart-metric-bucket", }); var coldStartSimulatorCollectMetricsFunction = new Function(this, "coldstartsimulator-collectmetrics", new FunctionProps { FunctionName = "coldstartsimulator-collectmetrics", Runtime = Runtime.DOTNET_CORE_3_1, Code = Code.FromAsset("../lambdas/coldstartsimulator/bin/Release/netcoreapp3.1/publish"), Handler = "ColdStartSimulator::ColdStartSimulator.StepFunctionTasks::CollectMetrics", Timeout = Duration.Seconds(31), MemorySize = 512 }); metricS3Bucket.GrantPut(coldStartSimulatorCollectMetricsFunction); coldStartSimulatorCollectMetricsFunction.AddEnvironment("MetricS3BucketName", metricS3Bucket.BucketName); coldStartSimulatorCollectMetricsFunction.AddToRolePolicy(coldStartSimulatorLambdaPolicy); var setup = new LambdaInvoke(this, "Setup", new LambdaInvokeProps { LambdaFunction = coldStartSimulatorSetupFunction, OutputPath = "$.Payload" }); var touch = new LambdaInvoke(this, "Touch", new LambdaInvokeProps { LambdaFunction = coldStartSimulatorTouchLambdaFunction, OutputPath = "$.Payload" }); var invoke = new LambdaInvoke(this, "Invoke", new LambdaInvokeProps { LambdaFunction = coldStartSimulatorInvokeLambdaFunction, OutputPath = "$.Payload" }); var collectMetrics = new LambdaInvoke(this, "Collect Metrics", new LambdaInvokeProps { LambdaFunction = coldStartSimulatorCollectMetricsFunction, OutputPath = "$.Payload" }); var wait3Seconds = new Wait(this, "Wait 3 seconds", new WaitProps { Time = WaitTime.Duration(Duration.Seconds(3)) }); var wait30Seconds = new Wait(this, "Wait 30 seconds", new WaitProps { Time = WaitTime.Duration(Duration.Seconds(30)) }); var invokeAgainChoice = new Choice(this, "Invoke again?"); invokeAgainChoice.When(Condition.BooleanEquals("$.Continue", true), touch); invokeAgainChoice.Otherwise(wait30Seconds); wait30Seconds .Next(collectMetrics); var definition = setup .Next(touch) .Next(wait3Seconds) .Next(invoke) .Next(invokeAgainChoice); new StateMachine(this, "ColdStartSimulatorStateMachine", new StateMachineProps { Definition = definition, Timeout = Duration.Minutes(10) }); }
public SchedulerStack(Construct scope, string name, double memory, CronOptions cron, Vpc vpc, StackProps props = null) : base(scope, $"scheduler-{name}", props) { // pricing - lambda // 1 milhão de solicitações gratuitas por mês e // 400.000 GB/segundos de tempo de computação por mês. // // pricing - event bridge // Eventos de serviços da AWS: Gratuito // Eventos personalizados: 1,00 USD / milhões de eventos personalizados publicados // Eventos de terceiros(SaaS): 1,00 USD / milhões de eventos publicados // Eventos entre contas: 1,00 USD / milhões de eventos entre contas publicados _function = new Function(this, $"scheduler-{name}-lambda", new FunctionProps() { FunctionName = name, MemorySize = memory, Runtime = Runtime.DOTNET_CORE_3_1, Handler = "Lambda::Lambda.Function::Handler", Code = Code.FromAsset("../tools/scheduler"), Timeout = Duration.Seconds(20), LogRetention = RetentionDays.ONE_DAY, Vpc = vpc, VpcSubnets = new SubnetSelection() { SubnetType = SubnetType.PRIVATE } }); _rule = new Rule(this, $"scheduler-{name}-rule", new RuleProps { RuleName = name, Schedule = Schedule.Cron(cron), Targets = new[] { new LambdaFunction(_function) } }); }
public IvrStack(Construct scope, string stackId, StackProps stackProps, IvrSiteSchema schema, IEnumerable <SecurityGroupRule> securityGroupRules) : base(scope, stackId, stackProps) { IVpc vpc = null; var MaxIpsPerSubnet = IvrVpcProps.MaxIpsPerSubnet; if (!string.IsNullOrWhiteSpace(schema.VpcName)) { vpc = Vpc.FromLookup(this, "$VPC", new VpcLookupOptions { VpcName = schema.VpcName, }); // will error if not found //MaxIpsPerSubnet = ???; } else if (!string.IsNullOrWhiteSpace(schema.VpcId)) { vpc = Vpc.FromLookup(this, "$VPC", new VpcLookupOptions { VpcId = schema.VpcId, }); // will error if not found //MaxIpsPerSubnet = ???; } else if (null != schema.VpcProps) { // use provided props to create brand new VPC vpc = new IvrVpc(this, $"VPC", schema.VpcProps); } if (schema.AddVpcS3Gateway) { var s3gw = new GatewayVpcEndpoint(this, $"S3GW", new GatewayVpcEndpointProps { Vpc = vpc, Service = GatewayVpcEndpointAwsService.S3, Subnets = new SubnetSelection[] { new SubnetSelection { SubnetType = SubnetType.PUBLIC, } }, }); } var role = new Role(this, "IVR", new RoleProps { AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), InlinePolicies = new IvrInlinePolicies(stackProps.Env.Account, stackId, schema), }); // Configure inbound security for RDP (and more?) var securityGroup = new SecurityGroup(this, $"Ingress", new SecurityGroupProps { Vpc = vpc, AllowAllOutbound = schema.AllowAllOutbound, }); securityGroupRules.ForEach(rule => securityGroup.WithSecurityGroupRule(rule)); if (schema.AllowAllIntranet) { securityGroup.WithSecurityGroupRule(new IngressRule(Peer.Ipv4($"{vpc.VpcCidrBlock}"), Port.AllTraffic()).WithDescription($"All intranet traffic")); } // Finally - create our instances! var hosts = new List <HostInstance>(); for (var subnetIndex = 0; ++subnetIndex <= Math.Min(vpc.PublicSubnets.Length, schema.MaxSubnets);) { var hostIndexInSubnet = 0; foreach (var group in schema.HostGroups) { var numberOfHosts = Math.Min(group.HostCount, MaxIpsPerSubnet); if (numberOfHosts != group.HostCount) { Console.WriteLine($"Group({group.Name}) host count changed from {group.HostCount} to {numberOfHosts}"); group.HostCount = numberOfHosts; } var instanceProps = IvrInstanceProps.InstanceProps(vpc, vpc.PublicSubnets[subnetIndex - 1], role, securityGroup, group.InstanceProps); for (var hostCount = 0; ++hostCount <= numberOfHosts; ++hostIndexInSubnet) { var hostName = $"{schema.HostNamePrefix}{subnetIndex}{hostIndexInSubnet:00}"; var hostPrimingProps = new HostPrimingProps { HostName = hostName.AsWindowsComputerName(), // must fit into 15 chars WorkingFolder = $"{stackId}".AsWindowsFolder(), AwsAccount = stackProps.Env.Account, AwsRoleName = role.RoleName, RdpProps = schema.RdpProps, EC2Users = schema.EC2Users, DownloadAndInstall = group.DownloadAndInstall, S3iArgs = $"{group.InstallS3i} --verbose", }; var hostCommands = HostPriming.PrimeForS3i(hostPrimingProps) .WithFirewallAllowInbound($"{vpc.VpcCidrBlock}"); hostCommands.WithRenameAndRestart(hostPrimingProps.HostName); instanceProps.KeyName = schema.KeyPairName; instanceProps.UserData = hostCommands.UserData; hosts.Add(new HostInstance { Group = group, Instance = new Instance_(this, hostName.AsCloudFormationId(), instanceProps), }); } } } // associate pre-allocated EIPs var preAllocatedEIPs = schema.PreAllocatedElasticIPs?.SelectMany(s => s.Csv()).ToList() ?? new List <string> { }; var hostsThatRequireEIP = hosts.Where(h => h.Group.UsePreAllocatedElasticIPs).ToList(); if (preAllocatedEIPs.Count < hostsThatRequireEIP.Count) { throw new ArgumentException($"Pre-Allocated Elastic IPs needed: {hostsThatRequireEIP.Count()}, but only {preAllocatedEIPs.Count()} configured in schema.{nameof(IvrSiteSchema.PreAllocatedElasticIPs)}"); } var elasticIPAssociations = hostsThatRequireEIP.Zip(preAllocatedEIPs, (h, a) => { return(new CfnEIPAssociation(this, $"EIPA{h.Instance.InstancePrivateIp}".AsCloudFormationId(), new CfnEIPAssociationProps { AllocationId = a, InstanceId = h.Instance.InstanceId, })); }).ToList(); // execute LINQ now // We have schema.Domain registered in advance if (!string.IsNullOrWhiteSpace(schema.HostedZoneDomain)) { var theZone = HostedZone.FromLookup(this, $"{stackId}_Zone_", new HostedZoneProviderProps { DomainName = schema.HostedZoneDomain, //Comment = "HostedZone created by Route53 Registrar", }); // assign new Elastic IPs as needed if (!string.IsNullOrWhiteSpace(schema.SubdomainEIPs)) { var newElasticIPs = hosts.Where(h => h.Group.AllocateNewElasticIPs).Select(h => { return(new CfnEIP(this, $"EIP{h.Instance.InstancePrivateIp}".AsCloudFormationId(), new CfnEIPProps { // 'standard' or 'vpc': https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-eip.html#cfn-ec2-eip-domain Domain = "vpc", InstanceId = h.Instance.InstanceId, })); }).ToList(); // collect them now to prevent LINQ side effects if (newElasticIPs.Any()) { // Register public Elastic IPs var arNewPublic = new ARecord(this, $"ARecord_Public_NewAlloc".AsCloudFormationId(), new ARecordProps { Zone = theZone, RecordName = $"{schema.SubdomainEIPs}.{theZone.ZoneName}", Target = RecordTarget.FromValues(newElasticIPs.Select(eip => eip.Ref).ToArray()), Ttl = Duration.Seconds(300), }); } else if (elasticIPAssociations.Any()) { // Register public Elastic IPs /* * var arPrePublic = new ARecord(this, $"ARecord_Public_PreAlloc".AsCloudFormationId(), new ARecordProps * { * Zone = theZone, * RecordName = $"{schema.SubdomainEIPs}.{theZone.ZoneName}", * Target = RecordTarget.FromValues(elasticIPAssociations.Select(eipa => eipa.Ref).ToArray()), // ***** how to do that? * Ttl = Duration.Seconds(300), * }); */ foreach (var a in elasticIPAssociations) { Console.WriteLine($"Pre-Allocated Elastic IP Associations: {a.AllocationId}/{a.InstanceId}, {a.Eip}/{a.PrivateIpAddress}, {a.Ref} - please put it to {schema.SubdomainEIPs}.{theZone.ZoneName} ARecord manually"); } } } if (0 < hosts.Count && !string.IsNullOrWhiteSpace(schema.SubdomainHosts)) { // Register private IPs (never changing, as opposed to public - which change on stop/start) addresses of all hosts var arPrivate = new ARecord(this, $"ARecord_Private_".AsCloudFormationId(), new ARecordProps { Zone = theZone, RecordName = $"{schema.SubdomainHosts}.{theZone.ZoneName}", Target = RecordTarget.FromIpAddresses(hosts.Select(h => h.Instance.InstancePrivateIp).ToArray()), Ttl = Duration.Seconds(300), }); } //throw new Exception(); } }
public PostgresStack(Construct scope, string id, DatabaseInstanceProps props, StackProps stackProps) : base(scope, id, stackProps) { Instance = new DatabaseInstance(this, id, props); Instance.Connections.AllowFrom(Peer.Ipv4(props.Vpc.VpcCidrBlock), Port.Tcp(5432)); //fix secret issues - invalid connection string can be generate without excluding these chars. var dbSecret = Instance.Node.TryFindChild("Secret") as DatabaseSecret; var cfnSecret = dbSecret.Node.DefaultChild as CfnSecret; cfnSecret.AddPropertyOverride("GenerateSecretString.ExcludeCharacters", "'\\;@$\"`!/"); }