// Defines a new lambda resource public CdkWorkshopStack(Construct parent, string id, IStackProps props = null) : base(parent, id, props) { var hello = new Function(this, "HelloHandler", new FunctionProps { Runtime = Runtime.NODEJS_10_X, Code = Code.FromAsset("lambda"), Handler = "hello.handler" }); var helloWithCounter = new HitCounter(this, "HelloHitCounter", new HitCounterProps { Downstream = hello }); var gateway = new LambdaRestApi(this, "Endpoint", new LambdaRestApiProps { Handler = helloWithCounter.Handler }); var tv = new TableViewer(this, "ViewerHitCount", new TableViewerProps { Title = "Hello Hits", Table = helloWithCounter.MyTable }); this.HCViewerUrl = new CfnOutput(this, "TableViewerUrl", new CfnOutputProps { Value = gateway.Url }); this.HCEndpoint = new CfnOutput(this, "GatewayUrl", new CfnOutputProps { Value = gateway.Url }); }
internal CambriaBamDevOpsTalkApiStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { RestApi api = new RestApi(this, "HelloWorldAPI", new RestApiProps { RestApiName = "Hello World API", Description = "This API says hello!", DefaultCorsPreflightOptions = new CorsOptions { AllowMethods = Cors.ALL_METHODS, AllowOrigins = Cors.ALL_ORIGINS } }); Function helloWorldFunction = new Function(this, "hello-world", new FunctionProps { Runtime = Runtime.DOTNET_CORE_2_1, Code = Code.FromAsset("./lambda-src/Cambria.BAM.DevOpsTalk.Api.Lambda/bin/Release/netcoreapp2.1/Cambria.BAM.DevOpsTalk.Api.Lambda.zip"), Handler = "Cambria.BAM.DevOpsTalk.Api.Lambda::Cambria.BAM.DevOpsTalk.Api.Lambda.Function::Get", Timeout = Duration.Seconds(15) }); api.Root.AddMethod("GET", new LambdaIntegration(helloWorldFunction)); var output = new CfnOutput(this, "RootUri", new CfnOutputProps { Description = "The root URI of the API", Value = api.Url }); }
public WorkshopPipelineStage(Construct scope, string id, StageProps props = null) : base(scope, id, props) { var service = new CdkWorkshopStack(this, "WebService"); this.HCEndpoint = service.HCEndpoint; this.HCViewerUrl = service.HCViewerUrl; }
internal MdsiteStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var mdsitebucket = new Bucket(this, "md-site-bucket", new BucketProps { Versioned = true }); new BucketDeployment(this, "DeployFiles", new BucketDeploymentProps() { Sources = new[] { Source.Asset("mycontent/site") }, DestinationBucket = mdsitebucket }); Function cfFunction = new Function(this, "append-index-html", new FunctionProps { Code = FunctionCode.FromFile(new FileCodeOptions() { FilePath = "cloudfrontfunction/append-index-html.js" }) }); var md_distribution = new Distribution(this, "md-site-distribution", new DistributionProps() { DefaultBehavior = new BehaviorOptions { Origin = new S3Origin(mdsitebucket), FunctionAssociations = new FunctionAssociation[] { new FunctionAssociation { Function = cfFunction, EventType = FunctionEventType.VIEWER_REQUEST } } } }); this.MdSiteUrl = new CfnOutput(this, "CloudFront URL", new CfnOutputProps { Value = string.Format("https://{0}", md_distribution.DomainName) }); }
private IRepository CreateECRRepository(EcrRepositoryEntity repo) { var result = new Repository(Scope, repo.RepositoryName, new RepositoryProps { RepositoryName = repo.RepositoryName, RemovalPolicy = repo.RemovalPolicy, ImageTagMutability = repo.ImageTagMutability, ImageScanOnPush = repo.ImageScanOnPush }); var cfnOutput = new CfnOutput(Scope, $"{repo.RepositoryName}Url", new CfnOutputProps { Value = result.RepositoryUri }); TagHandler.LogTag($"{ApplicationName}{EnvironmentName}{repo.RepositoryName}Url", cfnOutput); TagHandler.LogTag(ApplicationName + EnvironmentName + repo.RepositoryName, result); return(result); }
internal LambdaApiSolutionStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { DockerImageCode dockerImageCode = DockerImageCode.FromImageAsset("src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction"); DockerImageFunction dockerImageFunction = new DockerImageFunction(this, "LambdaFunction", new DockerImageFunctionProps() { Code = dockerImageCode, Description = ".NET 5 Docker Lambda function" }); HttpApi httpApi = new HttpApi(this, "APIGatewayForLambda", new HttpApiProps() { ApiName = "APIGatewayForLambda", CreateDefaultStage = true, CorsPreflight = new CorsPreflightOptions() { AllowMethods = new[] { HttpMethod.GET }, AllowOrigins = new[] { "*" }, MaxAge = Duration.Days(10) } }); LambdaProxyIntegration lambdaProxyIntegration = new LambdaProxyIntegration(new LambdaProxyIntegrationProps() { Handler = dockerImageFunction, PayloadFormatVersion = PayloadFormatVersion.VERSION_2_0 }); httpApi.AddRoutes(new AddRoutesOptions() { Path = "/casing", Integration = lambdaProxyIntegration, Methods = new[] { HttpMethod.POST } }); string guid = Guid.NewGuid().ToString(); CfnOutput apiUrl = new CfnOutput(this, "APIGatewayURLOutput", new CfnOutputProps() { ExportName = $"APIGatewayEndpointURL-{guid}", Value = httpApi.ApiEndpoint }); }
private void AddBucket() { var bucket = new Bucket(this, "Bucket"); bucket.ApplyRemovalPolicy(RemovalPolicy.DESTROY); bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "s3:*Object" }, Resources = new[] { bucket.BucketArn, $"{bucket.BucketArn}/*" }, Principals = new[] { new AccountPrincipal(Fn.Ref("AWS::AccountId")), new ArnPrincipal(Fn.ImportValue("cfn-metadata:DevAgentRoleArn")), new ArnPrincipal(Fn.ImportValue("cfn-metadata:ProdAgentRoleArn")), }, })); _ = new CfnOutput(this, "BucketName", new CfnOutputProps { Value = bucket.BucketName, Description = "Name of the Artifacts Bucket for Brighid Discord Adapter.", }); }
internal AuthlambdaStack(Construct scope, string id, AuthlambdaStackProps props = null) : base(scope, id, props) { functionsStack = props.functionsStack; Bucket websiteBucket = new Bucket(this, "websiteBucket", new BucketProps() { BlockPublicAccess = BlockPublicAccess.BLOCK_ALL, PublicReadAccess = false, //WebsiteIndexDocument = "index.html", RemovalPolicy = RemovalPolicy.DESTROY, Cors = new ICorsRule[] { new CorsRule() { AllowedHeaders = new string[] { "Authorization", "Content-Type", "Origin" }, AllowedMethods = new HttpMethods[] { HttpMethods.GET, HttpMethods.HEAD }, AllowedOrigins = new string[] { "*" } } } }); Bucket privateBucket = new Bucket(this, "privateBucket", new BucketProps() { BlockPublicAccess = BlockPublicAccess.BLOCK_ALL, PublicReadAccess = false, RemovalPolicy = RemovalPolicy.DESTROY, Cors = new ICorsRule[] { new CorsRule() { AllowedHeaders = new string[] { "Authorization", "Content-Type", "Origin" }, AllowedMethods = new HttpMethods[] { HttpMethods.GET, HttpMethods.HEAD }, AllowedOrigins = new string[] { "*" } } } }); // The S3 bucket deployment for the website var websiteDeployment = new BucketDeployment(this, "TestStaticWebsiteDeployment", new BucketDeploymentProps() { Sources = new [] { Source.Asset("./src/website") }, DestinationBucket = websiteBucket, RetainOnDelete = false }); var privateDeployment = new BucketDeployment(this, "TestPrivateDeployment", new BucketDeploymentProps() { Sources = new [] { Source.Asset("./src/private") }, DestinationBucket = privateBucket, RetainOnDelete = false }); var cloudfrontOAI = OriginAccessIdentity.FromOriginAccessIdentityName(this, "CloudfrontOAIName", cloudfrontOAIName); websiteBucket.GrantRead(cloudfrontOAI.GrantPrincipal); privateBucket.GrantRead(cloudfrontOAI.GrantPrincipal); var cachePolicy = new CachePolicy(this, "TestCachePolicy", new CachePolicyProps() { CachePolicyName = "TestCachePolicy", Comment = "Cache policy for Testing", DefaultTtl = Duration.Seconds(0), CookieBehavior = CacheCookieBehavior.All(), HeaderBehavior = CacheHeaderBehavior.AllowList( "Authorization", "Content-Type", "Origin" ), QueryStringBehavior = CacheQueryStringBehavior.All(), EnableAcceptEncodingBrotli = false, EnableAcceptEncodingGzip = false }); var websiteOrigin = new S3Origin(websiteBucket, new S3OriginProps() { OriginAccessIdentity = cloudfrontOAI }); var privateOrigin = new S3Origin(privateBucket, new S3OriginProps() { OriginAccessIdentity = cloudfrontOAI }); var dummyOrigin = new HttpOrigin("example.com", new HttpOriginProps() { ProtocolPolicy = OriginProtocolPolicy.HTTPS_ONLY }); // default behavior is for the privateOrigin var defaultPrivateBehavior = new BehaviorOptions { AllowedMethods = AllowedMethods.ALLOW_ALL, CachePolicy = cachePolicy, OriginRequestPolicy = OriginRequestPolicy.CORS_S3_ORIGIN, ViewerProtocolPolicy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS, Origin = privateOrigin, EdgeLambdas = new IEdgeLambda[] { new EdgeLambda() { EventType = LambdaEdgeEventType.VIEWER_REQUEST, FunctionVersion = functionsStack.checkAuthHandler.CurrentVersion, }, new EdgeLambda() { EventType = LambdaEdgeEventType.ORIGIN_RESPONSE, FunctionVersion = functionsStack.httpHeadersHandler.CurrentVersion } } }; // this behavior is for dummy origin var parseAuthBehavior = new BehaviorOptions { AllowedMethods = AllowedMethods.ALLOW_GET_HEAD_OPTIONS, CachePolicy = cachePolicy, OriginRequestPolicy = OriginRequestPolicy.CORS_S3_ORIGIN, ViewerProtocolPolicy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS, Origin = dummyOrigin, EdgeLambdas = new IEdgeLambda[] { new EdgeLambda() { EventType = LambdaEdgeEventType.VIEWER_REQUEST, FunctionVersion = functionsStack.parseAuthHandler.CurrentVersion, } } }; var refreshAuthBehavior = new BehaviorOptions { AllowedMethods = AllowedMethods.ALLOW_GET_HEAD_OPTIONS, CachePolicy = cachePolicy, OriginRequestPolicy = OriginRequestPolicy.CORS_S3_ORIGIN, ViewerProtocolPolicy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS, Origin = dummyOrigin, EdgeLambdas = new IEdgeLambda[] { new EdgeLambda() { EventType = LambdaEdgeEventType.VIEWER_REQUEST, FunctionVersion = functionsStack.refreshAuthHandler.CurrentVersion, } } }; var signOutBehavior = new BehaviorOptions { AllowedMethods = AllowedMethods.ALLOW_GET_HEAD_OPTIONS, CachePolicy = cachePolicy, OriginRequestPolicy = OriginRequestPolicy.CORS_S3_ORIGIN, ViewerProtocolPolicy = ViewerProtocolPolicy.REDIRECT_TO_HTTPS, Origin = dummyOrigin, EdgeLambdas = new IEdgeLambda[] { new EdgeLambda() { EventType = LambdaEdgeEventType.VIEWER_REQUEST, FunctionVersion = functionsStack.signOutHandler.CurrentVersion, } } }; Distribution distribution = new Distribution(this, "TestCloudfrontDistribution", new DistributionProps() { Comment = "Test Website Distribution", DefaultRootObject = "index.html", PriceClass = PriceClass.PRICE_CLASS_ALL, GeoRestriction = GeoRestriction.Whitelist(new [] { "IN" }), DefaultBehavior = defaultPrivateBehavior, }); distribution.AddBehavior("/parseauth", dummyOrigin, parseAuthBehavior); distribution.AddBehavior("/refreshauth", dummyOrigin, refreshAuthBehavior); distribution.AddBehavior("/signout", dummyOrigin, signOutBehavior); var domainNameOutput = new CfnOutput(this, "TestWebsiteDistributionDomainName", new CfnOutputProps() { Value = distribution.DistributionDomainName }); }
internal AppStack(Construct scope, RecipeConfiguration <Configuration> recipeConfiguration, IStackProps props = null) : base(scope, recipeConfiguration.StackName, props) { var settings = recipeConfiguration.Settings; var asset = new Asset(this, "Asset", new AssetProps { Path = recipeConfiguration.DotnetPublishZipPath }); CfnApplication application = null; // Create an app version from the S3 asset defined above // The S3 "putObject" will occur first before CF generates the template var applicationVersion = new CfnApplicationVersion(this, "ApplicationVersion", new CfnApplicationVersionProps { ApplicationName = settings.BeanstalkApplication.ApplicationName, SourceBundle = new CfnApplicationVersion.SourceBundleProperty { S3Bucket = asset.S3BucketName, S3Key = asset.S3ObjectKey } }); if (settings.BeanstalkApplication.CreateNew) { application = new CfnApplication(this, "Application", new CfnApplicationProps { ApplicationName = settings.BeanstalkApplication.ApplicationName }); applicationVersion.AddDependsOn(application); } IRole role; if (settings.ApplicationIAMRole.CreateNew) { role = new Role(this, "Role", new RoleProps { AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/iam-instanceprofile.html ManagedPolicies = new[] { ManagedPolicy.FromAwsManagedPolicyName("AWSElasticBeanstalkWebTier"), ManagedPolicy.FromAwsManagedPolicyName("AWSElasticBeanstalkWorkerTier") } }); } else { role = Role.FromRoleArn(this, "Role", settings.ApplicationIAMRole.RoleArn); } var instanceProfile = new CfnInstanceProfile(this, "InstanceProfile", new CfnInstanceProfileProps { Roles = new[] { role.RoleName } }); var optionSettingProperties = new List <CfnEnvironment.OptionSettingProperty> { new CfnEnvironment.OptionSettingProperty { Namespace = "aws:autoscaling:launchconfiguration", OptionName = "IamInstanceProfile", Value = instanceProfile.AttrArn }, new CfnEnvironment.OptionSettingProperty { Namespace = "aws:elasticbeanstalk:environment", OptionName = "EnvironmentType", Value = settings.EnvironmentType } }; if (!string.IsNullOrEmpty(settings.InstanceType)) { optionSettingProperties.Add(new CfnEnvironment.OptionSettingProperty { Namespace = "aws:autoscaling:launchconfiguration", OptionName = "InstanceType", Value = settings.InstanceType }); } if (settings.EnvironmentType.Equals(ENVIRONMENTTYPE_LOADBALANCED)) { optionSettingProperties.Add( new CfnEnvironment.OptionSettingProperty { Namespace = "aws:elasticbeanstalk:environment", OptionName = "LoadBalancerType", Value = settings.LoadBalancerType } ); } if (!string.IsNullOrEmpty(settings.EC2KeyPair)) { optionSettingProperties.Add( new CfnEnvironment.OptionSettingProperty { Namespace = "aws:autoscaling:launchconfiguration", OptionName = "EC2KeyName", Value = settings.EC2KeyPair } ); } var environment = new CfnEnvironment(this, "Environment", new CfnEnvironmentProps { EnvironmentName = settings.EnvironmentName, ApplicationName = settings.BeanstalkApplication.ApplicationName, PlatformArn = settings.ElasticBeanstalkPlatformArn, OptionSettings = optionSettingProperties.ToArray(), // This line is critical - reference the label created in this same stack VersionLabel = applicationVersion.Ref, }); var output = new CfnOutput(this, "EndpointURL", new CfnOutputProps { Value = $"http://{environment.AttrEndpointUrl}/" }); }
private void AddRepository() { var repository = new Repository(this, "ImageRepository", new RepositoryProps { RepositoryName = "brighid/discord-adapter", ImageScanOnPush = true, LifecycleRules = new[] { new EcrLifecycleRule { Description = "Protect prod-tagged images.", RulePriority = 1, TagStatus = TagStatus.TAGGED, TagPrefixList = new[] { "production" }, MaxImageCount = 1, }, new EcrLifecycleRule { Description = "Protect dev-tagged images.", RulePriority = 2, TagStatus = TagStatus.TAGGED, TagPrefixList = new[] { "development" }, MaxImageCount = 1, }, new EcrLifecycleRule { Description = "Keep last 3 images not tagged with dev or prod", RulePriority = 3, TagStatus = TagStatus.ANY, MaxImageCount = 3, }, }, }); repository.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:ListImages", "ecr:PutImage", // For re-tagging images only }, Principals = new[] { new AccountPrincipal(Fn.Ref("AWS::AccountId")), new AccountPrincipal(Fn.ImportValue("cfn-metadata:DevAccountId")), new AccountPrincipal(Fn.ImportValue("cfn-metadata:ProdAccountId")), }, })); repository.ApplyRemovalPolicy(RemovalPolicy.DESTROY); _ = new CfnOutput(this, "ImageRepositoryUri", new CfnOutputProps { Value = repository.RepositoryUri, Description = "URI of the container image repository for Brighid Discord Adapter.", }); }
public void CreateLogConsumerResources() { //LambdaRole var firehoseLambdaRole = new Role(this, "FirehoseLambdaRole", new RoleProps { AssumedBy = new ServicePrincipal("lambda.amazonaws.com"), Path = "/", }); firehoseLambdaRole.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Resources = new string[] { "arn:aws:logs:*:*:*" }, Actions = new string[] { "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" }, })); //FirehoseDataProcessingFunction var handler = new Function(this, "FirehoseDataProcessorFunction", new FunctionProps { FunctionName = "data-processor-function", Runtime = Runtime.NODEJS_12_X, Code = Code.FromAsset("resources"), Handler = "index.handler", Role = firehoseLambdaRole, Timeout = Duration.Minutes(2) }); //FirehoseDeliveryRole & Policies var firehoseDeliveryRole = new Role(this, "FirehoseDeliveryRole", new RoleProps { AssumedBy = new ServicePrincipal("firehose.amazonaws.com"), Path = "/" }); //S3 permissions firehoseDeliveryRole.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Resources = new string[] { _logsBucket.BucketArn, _logsBucket.BucketArn + "/*" }, Actions = new string[] { "s3:AbortMultipartUpload", "s3:GetBucketLocation", "s3:GetObject" , "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:PutObject" }, })); //Lambda permissions firehoseDeliveryRole.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Resources = new string[] { handler.FunctionArn }, Actions = new string[] { "lambda:GetFunctionConfiguration", "lambda:InvokeFunction" }, })); //Log group for Firehose logs. var firehoseloggroup = new LogGroup(this, "firehoseloggroup", new LogGroupProps { LogGroupName = "central-logs-delivery-group" }); var logstream = new LogStream(this, "logstream", new LogStreamProps { LogStreamName = "central-logs-delivery-stream", LogGroup = firehoseloggroup }); firehoseDeliveryRole.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Resources = new string[] { firehoseloggroup.LogGroupArn }, Actions = new string[] { "logs:PutLogEvents" }, })); //FirehoseLoggingDeliveryStream - Start CfnDeliveryStream.ExtendedS3DestinationConfigurationProperty s3config = new CfnDeliveryStream.ExtendedS3DestinationConfigurationProperty(); s3config.BucketArn = _logsBucket.BucketArn; s3config.BufferingHints = new CfnDeliveryStream.BufferingHintsProperty { SizeInMBs = 50, IntervalInSeconds = 300 }; s3config.CompressionFormat = "UNCOMPRESSED"; s3config.RoleArn = firehoseDeliveryRole.RoleArn; s3config.Prefix = "CentralLogs/AWSLogs/"; s3config.ErrorOutputPrefix = "CentralLogs/AWSLogs/Error/"; var parameters = new CfnDeliveryStream.ProcessorParameterProperty(); parameters.ParameterName = "LambdaArn"; parameters.ParameterValue = handler.FunctionArn; var paramsArray1 = new CfnDeliveryStream.ProcessorParameterProperty[] { parameters }; var processorProperty = new CfnDeliveryStream.ProcessorProperty(); processorProperty.Parameters = paramsArray1; processorProperty.Type = "Lambda"; var paramsArray = new CfnDeliveryStream.ProcessorProperty[] { processorProperty }; s3config.ProcessingConfiguration = new CfnDeliveryStream.ProcessingConfigurationProperty { Enabled = true, Processors = paramsArray }; s3config.CloudWatchLoggingOptions = new CfnDeliveryStream.CloudWatchLoggingOptionsProperty { Enabled = true, LogGroupName = firehoseloggroup.LogGroupName, LogStreamName = logstream.LogStreamName }; CfnDeliveryStream firehoseDeliveryStream = new CfnDeliveryStream(this, "FirehoseLoggingDeliveryStream", new CfnDeliveryStreamProps { DeliveryStreamType = "DirectPut", ExtendedS3DestinationConfiguration = s3config }); //FirehoseLoggingDeliveryStream - End //Policy Statements for LogDestination- start var policyStmt = new PolicyStatement(new PolicyStatementProps() { Actions = new string[] { "firehose:PutRecord" }, Resources = new string[] { "*" }, Effect = Effect.ALLOW }); var policyDoc = new PolicyDocument(); policyDoc.AddStatements(new PolicyStatement[] { policyStmt }); var policyProp = new CfnRole.PolicyProperty(); policyProp.PolicyName = "logDestinationPolicy"; policyProp.PolicyDocument = policyDoc; //Policy Statements - end //AssumeRolePolicyDocument for LogDestination - start var principal = new ServicePrincipal("logs.amazonaws.com"); var assumePolicyStatement = new PolicyStatement(new PolicyStatementProps { Actions = new string[] { "sts:AssumeRole" }, Effect = Effect.ALLOW, Principals = new IPrincipal[] { principal } }); var assumePolicyDoc = new PolicyDocument(); assumePolicyDoc.AddStatements(new PolicyStatement[] { assumePolicyStatement }); //AssumeRolePolicyDocument - end var roleProps = new CfnRoleProps { Path = "/", AssumeRolePolicyDocument = assumePolicyDoc, Policies = new CfnRole.PolicyProperty[] { policyProp } }; CfnRole cfnRole = new CfnRole(this, "CfnRole", roleProps); CfnDestination logDestination = new CfnDestination(this, "LogDestination", new CfnDestinationProps { DestinationName = "Central-Log-Destination", RoleArn = cfnRole.AttrArn, TargetArn = firehoseDeliveryStream.AttrArn, DestinationPolicy = "{\"Version\" : \"2012-10-17\",\"Statement\" : [{\"Effect\" : \"Allow\", \"Principal\" : {\"AWS\" : [\"" + SourceLogAccountId + "\"]},\"Action\" : \"logs:PutSubscriptionFilter\", \"Resource\" : \"arn:aws:logs:" + this.Region + ":" + DestinationAccountId + ":destination:Central-Log-Destination\"}]}" }); logDestination.AddDependsOn(firehoseDeliveryStream); logDestination.AddDependsOn(cfnRole); Console.WriteLine(logDestination.DestinationPolicy); LogDestinationArn = logDestination.AttrArn; CfnOutput output = new CfnOutput(this, "LogDestinationARN", new CfnOutputProps { Description = "LogDestination ARN", Value = logDestination.AttrArn }); }
private void ConfigureAppRunnerService(IRecipeProps <Configuration> props) { if (ServiceAccessRole == null) { throw new InvalidOperationException($"{nameof(ServiceAccessRole)} has not been set. The {nameof(ConfigureIAMRoles)} method should be called before {nameof(ConfigureAppRunnerService)}"); } if (TaskRole == null) { throw new InvalidOperationException($"{nameof(TaskRole)} has not been set. The {nameof(ConfigureIAMRoles)} method should be called before {nameof(ConfigureAppRunnerService)}"); } if (string.IsNullOrEmpty(props.ECRRepositoryName)) { throw new InvalidOrMissingConfigurationException("The provided ECR Repository Name is null or empty."); } var ecrRepository = Repository.FromRepositoryName(this, "ECRRepository", props.ECRRepositoryName); Configuration settings = props.Settings; var appRunnerServiceProp = new CfnServiceProps { ServiceName = settings.ServiceName, SourceConfiguration = new CfnService.SourceConfigurationProperty { AuthenticationConfiguration = new CfnService.AuthenticationConfigurationProperty { AccessRoleArn = ServiceAccessRole.RoleArn }, ImageRepository = new CfnService.ImageRepositoryProperty { ImageRepositoryType = "ECR", ImageIdentifier = ContainerImage.FromEcrRepository(ecrRepository, props.ECRImageTag).ImageName, ImageConfiguration = new CfnService.ImageConfigurationProperty { Port = settings.Port.ToString(), StartCommand = !string.IsNullOrWhiteSpace(settings.StartCommand) ? settings.StartCommand : null } } } }; if (!string.IsNullOrEmpty(settings.EncryptionKmsKey)) { var encryptionConfig = new CfnService.EncryptionConfigurationProperty(); appRunnerServiceProp.EncryptionConfiguration = encryptionConfig; encryptionConfig.KmsKey = settings.EncryptionKmsKey; } var healthCheckConfig = new CfnService.HealthCheckConfigurationProperty(); appRunnerServiceProp.HealthCheckConfiguration = healthCheckConfig; healthCheckConfig.HealthyThreshold = settings.HealthCheckHealthyThreshold; healthCheckConfig.Interval = settings.HealthCheckInterval; healthCheckConfig.Protocol = settings.HealthCheckProtocol; healthCheckConfig.Timeout = settings.HealthCheckTimeout; healthCheckConfig.UnhealthyThreshold = settings.HealthCheckUnhealthyThreshold; if (string.Equals(healthCheckConfig.Protocol, "HTTP")) { healthCheckConfig.Path = string.IsNullOrEmpty(settings.HealthCheckPath) ? "/" : settings.HealthCheckPath; } var instanceConfig = new CfnService.InstanceConfigurationProperty(); appRunnerServiceProp.InstanceConfiguration = instanceConfig; instanceConfig.InstanceRoleArn = TaskRole.RoleArn; instanceConfig.Cpu = settings.Cpu; instanceConfig.Memory = settings.Memory; AppRunnerService = new CfnService(this, nameof(AppRunnerService), InvokeCustomizeCDKPropsEvent(nameof(AppRunnerService), this, appRunnerServiceProp)); var output = new CfnOutput(this, "EndpointURL", new CfnOutputProps { Value = $"https://{AppRunnerService.AttrServiceUrl}/" }); }
public SrcStack(Construct scope, string id, IStackProps props) : base(scope, id, props) { #region VPC, Subnets and Security Groups IVpc batchVpc = new Vpc(this, Constants.VPC_ID, new VpcProps { Cidr = Constants.CIDR_RANGE, MaxAzs = 4 }); var privateSubnetIds = new List <string>(); foreach (Subnet subnet in batchVpc.PrivateSubnets) { privateSubnetIds.Add(subnet.SubnetId); } var batchSecurityGroup = new SecurityGroup(this, Constants.BATCH_SECURITY_GROUP_ID, new SecurityGroupProps { Vpc = batchVpc, SecurityGroupName = Constants.BATCH_SECURITY_GROUP_NAME, Description = Constants.BATCH_SECURITY_GROUP_DESCRIPTION, } ); var batchSecurityGroupIds = new List <string>() { batchSecurityGroup.SecurityGroupId }; #endregion #region S3, DynamoDB, Lambda (to trigger the batch on file drop) s3.Bucket bucket = new s3.Bucket(this, Constants.S3_BUCKET_ID, new s3.BucketProps { BucketName = Constants.S3_BUCKET_NAME + this.Account }); var bucketName = bucket.BucketName; var gsi = new dynamo.GlobalSecondaryIndexProps() { IndexName = "GSI", PartitionKey = new dynamo.Attribute { Name = "CreatedTime", Type = dynamo.AttributeType.STRING }, ProjectionType = dynamo.ProjectionType.KEYS_ONLY }; dynamo.Table table = new dynamo.Table(this, Constants.DynamoDB_TABLE_ID, new dynamo.TableProps { TableName = Constants.DynamoDB_TABLE_ID, PartitionKey = new dynamo.Attribute { Name = "ProductId", Type = dynamo.AttributeType.STRING }, BillingMode = dynamo.BillingMode.PAY_PER_REQUEST }); table.AddGlobalSecondaryIndex(gsi); var lambdaBatchExecutionRoleProvider = new LambdaBatchExecutionRole(this, Constants.LAMBDA_BATCH_EXECUTION_ROLE_ID); #endregion DockerImageAsset imageAsset = new DockerImageAsset(this, "BatchProcessorImage", new DockerImageAssetProps { Directory = Constants.BATCH_PROCESSOR_PYTHON_CODE_PATH, RepositoryName = Constants.ECR_REPOSITORY_NAME }); #region Batch - ComputeEnvironment - Job Queue - Job Definition var batchServiceRole = new BatchServiceRole(this, Constants.BATCH_SERVICE_ROLE_ID); var ecsInstanceRole = new EcsInstanceRole(this, Constants.ECS_INSTANCE_ROLE_ID); var batchInstanceProfile = new InstanceProfile(this, Constants.BATCH_INSTANCE_PROFILE_ID, ecsInstanceRole); var computeEnvironment = new batch.CfnComputeEnvironment(this, Constants.BATCH_COMPUTE_ENVIRONMENT_ID, new batch.CfnComputeEnvironmentProps { ComputeEnvironmentName = Constants.BATCH_COMPUTE_ENVIRONMENT_NAME, Type = Constants.BATCH_COMPUTE_TYPE, ServiceRole = batchServiceRole.Role.RoleName, ComputeResources = new batch.CfnComputeEnvironment.ComputeResourcesProperty { Type = Constants.BATCH_COMPUTE_RESOURCE_TYPE, MinvCpus = 0, MaxvCpus = 32, DesiredvCpus = 0, InstanceRole = ecsInstanceRole.Role.RoleName, InstanceTypes = new string[] { Constants.BATCH_INSTANCE_TYPE }, SecurityGroupIds = batchSecurityGroupIds.ToArray(), Subnets = privateSubnetIds.ToArray() } }); var computeEnvironmentOrders = new List <batch.CfnJobQueue.ComputeEnvironmentOrderProperty>(); var computeEnvironmentOrder = new batch.CfnJobQueue.ComputeEnvironmentOrderProperty() { Order = 1, ComputeEnvironment = computeEnvironment.Ref }; computeEnvironmentOrders.Add(computeEnvironmentOrder); var batchProcessingJobQueue = new batch.CfnJobQueue(this, Constants.BATCH_JOB_QUEUE_ID, new batch.CfnJobQueueProps { JobQueueName = Constants.BATCH_PROCESSING_JOB_QUEUE, Priority = 1, ComputeEnvironmentOrder = computeEnvironmentOrders.ToArray() }); var batchProcessingJobDefinition = new batch.CfnJobDefinition(this, Constants.BATCH_JOB_DEFINITION_ID, new batch.CfnJobDefinitionProps { Type = Constants.CONTAINER, JobDefinitionName = Constants.BATCH_JOB_DEFINITION_NAME, ContainerProperties = new batch.CfnJobDefinition.ContainerPropertiesProperty() { Image = imageAsset.ImageUri, Vcpus = Constants.BATCH_JOB_DEFINITION_VCPU, Memory = Constants.BATCH_JOB_DEFINITION_MemoryLimitMiB, Command = new string[] { "python", "batch_processor.py" } } }); #endregion #region lambda s3 event trigger BatchTriggerLambdaInput batchTriggerLambdaInput = new BatchTriggerLambdaInput { BucketName = bucketName, FileName = "sample.csv", Region = "us-east-1", BatchJobDefinition = batchProcessingJobDefinition.JobDefinitionName, BatchJobName = Constants.BATCH_JOB_NAME, BatchJobQueue = batchProcessingJobQueue.JobQueueName, DBTable = table.TableName }; lambda.Function lambda = BatchTriggerLambda.BatchTriggerLambdaFunction(this, Constants.LAMBDA_NAME, batchTriggerLambdaInput, lambdaBatchExecutionRoleProvider); var batchLambdaFunction = new LambdaFunction( lambda ); var eventPutSource = new eventsources.S3EventSource(bucket, new eventsources.S3EventSourceProps { Events = new s3.EventType[] { s3.EventType.OBJECT_CREATED_PUT } }); lambda.AddEventSource(eventPutSource); #endregion #region OUTPUTS var cfnComputeOutput = new CfnOutput(this, Constants.BATCH_COMPUTE_ENVIRONMENT_NAME_OUTPUT_ID, new CfnOutputProps { Value = computeEnvironment.Ref } ); var cfnS3Output = new CfnOutput(this, Constants.S3_BUCKET_OUTPUT_ID, new CfnOutputProps { Value = bucket.BucketName } ); var cfnEcrRepositoryOutput = new CfnOutput(this, Constants.ECR_REPOSITORY_OUTPUT_ID, new CfnOutputProps { Value = imageAsset.Repository.RepositoryArn } ); var cfnDynamoTableOutput = new CfnOutput(this, Constants.DYNAMO_TABLE_OUTPUT_ID, new CfnOutputProps { Value = table.TableName } ); var cfnLambdaRepositoryOutput = new CfnOutput(this, Constants.LAMBDA_OUTPUT_ID, new CfnOutputProps { Value = lambda.FunctionArn } ); #endregion Tag.Add(this, "Name", Constants.APP_NAME); }