Пример #1
0
        public HelloStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
        {
            var topic = new Topic(this, "HelloCdkTopic", new TopicProps
            {
                TopicName   = "HelloCdkTopic",
                DisplayName = "My First Topic From HelloCdk"
            });

            var queue = new Queue(this, "HelloCdkQueue", new QueueProps
            {
                QueueName = "HelloCdkQueue"
            });

            topic.AddSubscription(new SqsSubscription(queue, new SqsSubscriptionProps
            {
                RawMessageDelivery = true
            }));

            var functionType = typeof(HelloCdkConsumerLambda.Function);
            var function     = new Function(this, nameof(HelloCdkConsumerLambda), new FunctionProps
            {
                Code       = Code.FromAsset($"./src/{nameof(HelloCdkConsumerLambda)}/bin/Release/netcoreapp2.1/publish"),
                Runtime    = Runtime.DOTNET_CORE_2_1,
                Tracing    = Tracing.ACTIVE,
                Handler    = $"{functionType.Assembly.GetName().Name}::{functionType}::{nameof(HelloCdkConsumerLambda.Function.FunctionHandler)}",
                MemorySize = 256,
                Timeout    = Duration.Seconds(10)
            });

            function.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Actions   = new[] { "sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes", "sqs:ChangeMessageVisibility" },
                Resources = new[] { queue.QueueArn }
            }));

            _ = new EventSourceMapping(this, $"{nameof(HelloCdkConsumerLambda)}Trigger", new EventSourceMappingProps
            {
                EventSourceArn = queue.QueueArn,
                BatchSize      = 10,
                Enabled        = true,
                Target         = function
            });
        }
Пример #2
0
        internal LoadTesterStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // The code that defines your stack goes here

            var fn = new Function(this, "loadtester", new FunctionProps
            {
                FunctionName = "loadtester",
                Runtime      = Runtime.NODEJS_12_X,
                Code         = Code.FromAsset("src/EdgyRegions/resources/loadtest"),
                Handler      = "index.handler",
                Timeout      = Duration.Minutes(15)
            });
            var poly = new Amazon.CDK.AWS.IAM.PolicyStatement
            {
                Effect = Amazon.CDK.AWS.IAM.Effect.ALLOW,
            };

            poly.AddActions(new string[] { "cloudwatch:PutMetricData" });
            poly.AddAllResources();
            fn.AddToRolePolicy(poly);
        }
        public TheEventbridgeAtmStack(Construct scope, string id, IStackProps props = null)
            : base(scope, id, props)
        {
            //Producer Lambda
            var atmProducerLambda = new Function(this, "atmProducerLambda", new FunctionProps
            {
                Runtime = Runtime.NODEJS_12_X,
                Code    = Code.FromAsset("lambda-fns/atmProducer"),
                Handler = "handler.lambdaHandler"
            });

            var eventPolicy = new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Resources = new[] { "*" },
                Actions   = new[] { "events:PutEvents" }
            });

            atmProducerLambda.AddToRolePolicy(eventPolicy);

            //Approved Transaction Consumer
            var atmConsumer1Lambda = new Function(this, "atmConsumer1Lambda", new FunctionProps
            {
                Runtime = Runtime.NODEJS_12_X,
                Code    = Code.FromAsset("lambda-fns/atmConsumer"),
                Handler = "handler.case1Handler"
            });

            var atmConsumer1LambdaRule = new Rule(this, "atmConsumer1LambdaRule", new RuleProps
            {
                Description  = "Approved transactions",
                EventPattern = new EventPattern
                {
                    Source     = new[] { "custom.myATMapp" },
                    DetailType = new[] { "transaction" },
                    Detail     = new Dictionary <string, object>
                    {
                        ["result"] = new[] { "approved" }
                    }
                }
            });

            atmConsumer1LambdaRule.AddTarget(new LambdaFunction(atmConsumer1Lambda));

            //NY Prefix Consumer
            var atmConsumer2Lambda = new Function(this, "atmConsumer2Lambda", new FunctionProps
            {
                Runtime = Runtime.NODEJS_12_X,
                Code    = Code.FromAsset("lambda-fns/atmConsumer"),
                Handler = "handler.case2Handler"
            });

            var atmConsumer2LambdaRule = new Rule(this, "atmConsumer2LambdaRule", new RuleProps
            {
                Description  = "Transactions with NY- prefix",
                EventPattern = new EventPattern
                {
                    Source     = new[] { "custom.myATMapp" },
                    DetailType = new[] { "transaction" },
                    Detail     = new Dictionary <string, object>
                    {
                        ["location"] = new []
                        {
                            new Dictionary <string, string>
                            {
                                ["prefix"] = "NY-"
                            }
                        }
                    }
                }
            });

            atmConsumer2LambdaRule.AddTarget(new LambdaFunction(atmConsumer2Lambda));

            //Not Approved Consumer
            var atmConsumer3Lambda = new Function(this, "atmConsumer3Lambda", new FunctionProps
            {
                Runtime = Runtime.NODEJS_12_X,
                Code    = Code.FromAsset("lambda-fns/atmConsumer"),
                Handler = "handler.case3Handler"
            });

            var atmConsumer3LambdaRule = new Rule(this, "atmConsumer3LambdaRule", new RuleProps
            {
                Description  = "Not approved transactions",
                EventPattern = new EventPattern
                {
                    Source     = new[] { "custom.myATMapp" },
                    DetailType = new[] { "transaction" },
                    Detail     = new Dictionary <string, object>
                    {
                        ["result"] = new[]
                        {
                            new Dictionary <string, object>
                            {
                                ["anything-but"] = "approved"
                            }
                        }
                    }
                }
            });

            atmConsumer3LambdaRule.AddTarget(new LambdaFunction(atmConsumer3Lambda));

            //API Gateway proxy integration
            // defines an API Gateway REST API resource backed by our "atmProducerLambda" function.
            new LambdaRestApi(this, "Endpoint", new LambdaRestApiProps
            {
                Handler = atmProducerLambda
            });
        }
Пример #4
0
        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)
            });
        }
        internal TranscriptionStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var inputBucket  = new Bucket(this, "Input");
            var outputBucket = new Bucket(this, "Output");

            var languageCode = this.Node.TryGetContext("LanguageCode")?.ToString();

            if (string.IsNullOrEmpty(languageCode))
            {
                languageCode = "en-us";
            }

            var startJobFunction = new Function(this, "StartJobFunction", new FunctionProps
            {
                Tracing     = Tracing.ACTIVE,
                Runtime     = Runtime.DOTNET_CORE_2_1,
                Timeout     = Duration.Seconds(30),
                MemorySize  = 256,
                Environment = new Dictionary <string, string>()
                {
                    { "TRANSCRIBE_OUTPUT_BUCKET", outputBucket.BucketName },
                    { "TRANSCRIBE_LANGUAGE_CODE", languageCode }
                },
                FunctionName = "StartTranscriptionJob",
                Code         = Code.FromAsset("./assets/StartTranscriptionJob.zip"),
                Handler      = "StartTranscriptionJob::StartTranscriptionJob.Function::FunctionHandler",
                Events       = new[]
                {
                    new S3EventSource(inputBucket, new S3EventSourceProps
                    {
                        Events = new [] { EventType.OBJECT_CREATED }
                    })
                }
            });

            startJobFunction.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Actions   = new[] { "transcribe:StartTranscriptionJob" },
                Effect    = Effect.ALLOW,
                Resources = new[] { "*" }
            }));
            // this is passed onto Transcribe so it can write to the output bucket
            startJobFunction.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Actions   = new[] { "s3:Put*" },
                Effect    = Effect.ALLOW,
                Resources = new[] { outputBucket.ArnForObjects("*") }
            }));

            inputBucket.GrantRead(startJobFunction);

            var notificationTopic = new Topic(this, "TranscriptionNotificationTopic", new TopicProps
            {
                TopicName = "TranscriptionCompletedTopic",
            });

            var subscriberEmail = this.Node.TryGetContext("SubscriberEmail")?.ToString();

            if (!string.IsNullOrEmpty(subscriberEmail))
            {
                notificationTopic.AddSubscription(new EmailSubscription(subscriberEmail));
            }

            var notifyCompletionFunction = new Function(this, "NotifyCompleteFunction", new FunctionProps
            {
                Tracing     = Tracing.ACTIVE,
                Runtime     = Runtime.DOTNET_CORE_2_1,
                Timeout     = Duration.Seconds(30),
                MemorySize  = 256,
                Environment = new Dictionary <string, string>()
                {
                    { "TRANSCRIBE_TOPIC_ARN", notificationTopic.TopicArn }
                },
                FunctionName = "NotifyTranscriptionJobComplete",
                Code         = Code.FromAsset("./assets/NotifyTranscriptionJobComplete.zip"),
                Handler      = "NotifyTranscriptionJobComplete::NotifyTranscriptionJobComplete.Function::FunctionHandler",
                Events       = new[]
                {
                    new S3EventSource(outputBucket, new S3EventSourceProps
                    {
                        Events = new [] { EventType.OBJECT_CREATED }
                    })
                }
            });

            notifyCompletionFunction.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Actions   = new[] { "sns:Publish" },
                Effect    = Effect.ALLOW,
                Resources = new[] { notificationTopic.TopicArn }
            }));
            notifyCompletionFunction.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                // this permission is needed so that when the user clicks the presigned url
                // that the Lambda generates, S3 will permit access to the object content and
                // not otherwise return an access-denied error
                Actions   = new[] { "s3:GetObject" },
                Effect    = Effect.ALLOW,
                Resources = new[] { outputBucket.ArnForObjects("*") }
            }));

            outputBucket.GrantWrite(notifyCompletionFunction);

            // emit the name of the input bucket so we know where to upload content!
            new CfnOutput(this, "InputBucket", new CfnOutputProps
            {
                Value = inputBucket.BucketName
            });
        }
Пример #6
0
        internal MackerelAlertLampStack(Construct scope, string id, MackerelAlertLampProps props) : base(scope, id, props)
        {
            System.Console.Out.WriteLine(string.Join(",", props.ThingCerts));

            // MackerelのEventBridge通知チャンネル先のパートナーイベントソース名
            // リソース名に使用するのでここで構築しておく。
            var eventSourceName = $"aws.partner/mackerel.io/{props.OrganizationName}/{props.EventName}";

            var thingPolicy = new Amazon.CDK.AWS.IoT.CfnPolicy(this, "MackerelAlertLampThingPoilcy", new Amazon.CDK.AWS.IoT.CfnPolicyProps()
            {
                PolicyName     = "MackerelAlertLampThingPoilcy",
                PolicyDocument = new Dictionary <string, object>
                {
                    ["Version"]   = "2012-10-17",
                    ["Statement"] = new object[] {
                        new Dictionary <string, object>
                        {
                            ["Effect"] = "Allow",
                            ["Action"] = new string[] {
                                "iot:*",
                                "greengrass:*",
                            },
                            ["Resource"] = new string[] {
                                "*"
                            },
                        }
                    }
                }
            });

            // IDなどに使うために証明書のARNを加工しておく。
            var certs = props.ThingCerts
                        .Select(x => new
            {
                Arn  = x,
                Hash = Utils.ToHash(x),
            }).ToList();
            var certAttaches = certs.Select(x =>
            {
                var attach = new CfnPolicyPrincipalAttachment(this, "MackerelAlertLampCertAttach-" + x.Hash, new CfnPolicyPrincipalAttachmentProps()
                {
                    PolicyName = thingPolicy.PolicyName,
                    Principal  = x.Arn,
                });
                attach.AddDependsOn(thingPolicy);
                return(attach);
            }).ToList();

            var things = certs.Select(x => new
            {
                CertArn = x.Arn,
                Thing   = new CfnThing(this, "MackerelAlertLampThing-" + x.Hash, new CfnThingProps()
                {
                    ThingName = "MackerelAlertLamp-" + x.Hash,
                })
            }).ToList();
            var thingAttaches = things.Select(x =>
            {
                var attach = new CfnThingPrincipalAttachment(this, x.Thing.ThingName + "Attach", new CfnThingPrincipalAttachmentProps()
                {
                    ThingName = x.Thing.ThingName,
                    Principal = x.CertArn,
                });
                attach.AddDependsOn(x.Thing);
                return(attach);
            }).ToList();

            var cloudReceiveAlertFunction = new Function(this, "CloudReceiveAlert", new FunctionProps()
            {
                Runtime     = Runtime.PYTHON_3_7,
                Code        = Code.FromAsset("handlers/cloud"),
                Handler     = "ReceiveAlert.handler",
                Environment = new Dictionary <string, string>()
                {
                    ["MACKEREL_ALERT_TOPIC"] = eventSourceName,
                },
            });

            cloudReceiveAlertFunction.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps()
            {
                Actions = new string[]
                {
                    "iot:Publish",
                },
                Resources = new string[]
                {
                    "*",
                },
            }));

            var ggLambda = new Function(this, "DeviceReceiveAlert", new FunctionProps()
            {
                Runtime = Runtime.PYTHON_3_7,
                Code    = Code.FromAsset("handlers/device"),
                Handler = "ReceiveAlert.handler",
            });
            var ggLambdaVersion = ggLambda.AddVersion("v1");
            var ggLambdaAlias   = new Alias(this, "DeviceReceiveAlertAlias", new AliasProps()
            {
                AliasName = "v" + ggLambdaVersion.Version,
                Version   = ggLambdaVersion,
            });

            var toggleGpio = new Function(this, "DeviceToggleGpio", new FunctionProps()
            {
                Runtime = Runtime.PYTHON_3_7,
                Code    = Code.FromAsset("handlers/device"),
                Handler = "ToggleGpio.handler",
            });
            var toggleGpioVersion = toggleGpio.AddVersion("v1");
            var toggleGpioAlias   = new Alias(this, "DeviceToggleGpioAlias", new AliasProps()
            {
                AliasName = "v" + toggleGpioVersion.Version,
                Version   = toggleGpioVersion,
            });

            var ggCoreId = 0;
            var ggCore   = new CfnCoreDefinition(this, "MackerelAlertLampCore", new CfnCoreDefinitionProps()
            {
                Name           = "MackerelAlertLampCore",
                InitialVersion = new CfnCoreDefinition.CoreDefinitionVersionProperty()
                {
                    Cores = things.Select(x => new CfnCoreDefinition.CoreProperty()
                    {
                        Id             = (++ggCoreId).ToString(),
                        CertificateArn = x.CertArn,
                        // XXX ARN参照できないの?
                        //ThingArn = x.Thing.GetAtt("Arn").Reference.ToString(),
                        //ThingArn = x.Thing.GetAtt("resource.arn").Reference.ToString(),
                        ThingArn = $"arn:aws:iot:{this.Region}:{this.Account}:thing/{x.Thing.ThingName}",
                    }).ToArray(),
                }
            });

            things.ForEach(x =>
            {
                ggCore.AddDependsOn(x.Thing);
            });

            var gpioRw = new CfnResourceDefinition.ResourceInstanceProperty()
            {
                Id   = "gpio-rw",
                Name = "RaspberryPiGpioRw",
                ResourceDataContainer = new CfnResourceDefinition.ResourceDataContainerProperty()
                {
                    LocalDeviceResourceData = new CfnResourceDefinition.LocalDeviceResourceDataProperty()
                    {
                        SourcePath        = "/dev/gpiomem",
                        GroupOwnerSetting = new CfnResourceDefinition.GroupOwnerSettingProperty()
                        {
                            AutoAddGroupOwner = true,
                        },
                    }
                },
            };
            var ggResource = new CfnResourceDefinition(this, "MackerelAlertLampResource", new CfnResourceDefinitionProps()
            {
                Name           = "MackerelAlertLampResource",
                InitialVersion = new CfnResourceDefinition.ResourceDefinitionVersionProperty()
                {
                    Resources = new CfnResourceDefinition.ResourceInstanceProperty[]
                    {
                        gpioRw,
                    }
                },
            });

            var ggFunction = new CfnFunctionDefinition(this, "MackerelAlertLampFunction", new CfnFunctionDefinitionProps()
            {
                Name           = "MackerelAlertLampFunction",
                InitialVersion = new CfnFunctionDefinition.FunctionDefinitionVersionProperty()
                {
                    Functions = new CfnFunctionDefinition.FunctionProperty[]
                    {
                        new CfnFunctionDefinition.FunctionProperty()
                        {
                            Id                    = ggLambda.FunctionName + "-" + ggLambdaAlias.AliasName,
                            FunctionArn           = ggLambdaAlias.FunctionArn,
                            FunctionConfiguration = new CfnFunctionDefinition.FunctionConfigurationProperty()
                            {
                                // MemorySize と Timeout は必須である様子
                                MemorySize = 65535,
                                Timeout    = 10, // 秒
                            },
                        },
                        new CfnFunctionDefinition.FunctionProperty()
                        {
                            Id                    = toggleGpio.FunctionName + "-" + toggleGpioAlias.AliasName,
                            FunctionArn           = toggleGpioAlias.FunctionArn,
                            FunctionConfiguration = new CfnFunctionDefinition.FunctionConfigurationProperty()
                            {
                                // MemorySize と Timeout は必須である様子
                                MemorySize = 65535,
                                Timeout    = 10, // 秒
                            },
                        },
                    },
                },
            });

            // https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/raspberrypi-gpio-connector.html
            var gpioConnector = new CfnConnectorDefinition.ConnectorProperty()
            {
                Id           = "gpio-connector",
                ConnectorArn = $"arn:aws:greengrass:{this.Region}::/connectors/RaspberryPiGPIO/versions/1",
                Parameters   = new Dictionary <string, object>()
                {
                    ["GpioMem-ResourceId"] = gpioRw.Id,
                    //["InputGpios"] = "5,6U,7D",
                    //["InputPollPeriod"] = 50,
                    // 10, 9, 11番は配置連続しているのでとりあえずそれを使う
                    ["OutputGpios"] = "9L,10L,11L",
                }
            };
            var ggConnector = new CfnConnectorDefinition(this, "MackerelAlertLampConnector", new CfnConnectorDefinitionProps()
            {
                Name           = "MackerelAlertLampConnector",
                InitialVersion = new CfnConnectorDefinition.ConnectorDefinitionVersionProperty()
                {
                    Connectors = new CfnConnectorDefinition.ConnectorProperty[] {
                        gpioConnector,
                    },
                }
            });

            var ggSubscriptions = new CfnSubscriptionDefinition.SubscriptionProperty[]
            {
                // ReceiveAlert Cloud to Device
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "mackerel-alert-to-device",
                    Source  = "cloud",
                    Target  = ggLambdaAlias.FunctionArn,
                    Subject = eventSourceName,
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "mackerel-alert-gpio-write-11",
                    Source  = ggLambdaAlias.FunctionArn,
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/11/write",
                },
                // XXX Currently, when you create a subscription that uses the Raspberry Pi GPIO connector, you must specify a value for at least one of the + wildcards in the topic.
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-read",
                    Source  = "cloud",
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/9/read",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-write",
                    Source  = "cloud",
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/9/write",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-state",
                    Source  = gpioConnector.ConnectorArn,
                    Target  = "cloud",
                    Subject = "gpio/+/9/state",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-error",
                    Source  = gpioConnector.ConnectorArn,
                    Target  = "cloud",
                    Subject = "gpio/+/error",
                },
                //
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-read-10",
                    Source  = "cloud",
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/10/read",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-write-10",
                    Source  = "cloud",
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/10/write",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-state-10",
                    Source  = gpioConnector.ConnectorArn,
                    Target  = "cloud",
                    Subject = "gpio/+/10/state",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-read-11",
                    Source  = toggleGpioAlias.FunctionArn,
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/11/read",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-write-11",
                    Source  = toggleGpioAlias.FunctionArn,
                    Target  = gpioConnector.ConnectorArn,
                    Subject = "gpio/+/11/write",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-state-11",
                    Source  = gpioConnector.ConnectorArn,
                    Target  = "cloud",
                    Subject = "gpio/+/11/state",
                },
                new CfnSubscriptionDefinition.SubscriptionProperty()
                {
                    Id      = "gpio-test",
                    Source  = "cloud",
                    Target  = toggleGpioAlias.FunctionArn,
                    Subject = "gpio/test",
                },
            };
            var ggSubscription = new CfnSubscriptionDefinition(this, "MackerelAlertLampSubscription", new CfnSubscriptionDefinitionProps()
            {
                Name           = "MackerelAlertLampSubscription",
                InitialVersion = new CfnSubscriptionDefinition.SubscriptionDefinitionVersionProperty()
                {
                    Subscriptions = ggSubscriptions,
                },
            });

            var ggGroup = new Amazon.CDK.AWS.Greengrass.CfnGroup(this, "MackerelAlertLampGroup", new Amazon.CDK.AWS.Greengrass.CfnGroupProps()
            {
                Name = "MackerelAlertLamp",
                // XXX 引数にする
                RoleArn = "arn:aws:iam::854403262515:role/service-role/Greengrass_ServiceRole",
            });
            var ggVersionHash = Utils.ToHash(string.Join("-",
                                                         ggCore.AttrLatestVersionArn,
                                                         ggFunction.AttrLatestVersionArn,
                                                         ggResource.AttrLatestVersionArn,
                                                         ggConnector.AttrLatestVersionArn,
                                                         ggSubscription.AttrLatestVersionArn));
            var ggLatestVersion = new CfnGroupVersion(this, "MackerelAlertLampGroupVersion-" + ggVersionHash, new CfnGroupVersionProps()
            {
                GroupId = ggGroup.AttrId,
                CoreDefinitionVersionArn         = ggCore.AttrLatestVersionArn,
                FunctionDefinitionVersionArn     = ggFunction.AttrLatestVersionArn,
                ResourceDefinitionVersionArn     = ggResource.AttrLatestVersionArn,
                ConnectorDefinitionVersionArn    = ggConnector.AttrLatestVersionArn,
                SubscriptionDefinitionVersionArn = ggSubscription.AttrLatestVersionArn,
            });

            ggLatestVersion.AddDependsOn(ggGroup);
            ggLatestVersion.AddDependsOn(ggCore);
            ggLatestVersion.AddDependsOn(ggResource);
            ggLatestVersion.AddDependsOn(ggFunction);
            ggLatestVersion.AddDependsOn(ggConnector);
            ggLatestVersion.AddDependsOn(ggSubscription);

            var mackerelAlertBus = new EventBus(this, "mackerel-alert-bus", new EventBusProps()
            {
                EventSourceName = eventSourceName,
            });
            var mackerelAlertRule = new Rule(this, "mackerel-alert-rule", new RuleProps()
            {
                EventBus     = mackerelAlertBus,
                EventPattern = new EventPattern()
                {
                    Account = new string[] {
                        this.Account,
                    },
                },
                Targets = new IRuleTarget[] {
                    new LambdaFunction(cloudReceiveAlertFunction),
                },
            });
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="id"></param>
        /// <param name="props"></param>
        public LogAggregator(Construct scope, string id, LogAggregatorProps props)
            : base(scope, id)
        {
            // The Kinesis stream that will receive all lambda logs.
            var kinesisStream = new Amazon.CDK.AWS.Kinesis.Stream(this, "Stream", props.KinesisStreamProps);

            // Forward all records from kinesis to the log shipper.
            props.LogShipper.AddEventSource(new KinesisEventSource(kinesisStream,
                                                                   new KinesisEventSourceProps {
                BatchSize         = props.KinesisBatchSize,
                MaxBatchingWindow = props.KinesisMaxBatchingWindow,
                StartingPosition  = StartingPosition.TRIM_HORIZON,
            }));

            // Create a role (containing a policy) that can be assumed by CloudWatch logs to put records in Kinesis.
            var statement = new PolicyStatement();

            statement.AddActions(new[] { "kinesis:PutRecords", "kinesis:PutRecord" });
            statement.AddResources(new[] { kinesisStream.StreamArn });

            var cloudWatchLogsToKinesisRole = new Role(this, "CloudWatchLogsToKinesis", new RoleProps
            {
                AssumedBy = new ServicePrincipal("logs.amazonaws.com")
            });

            cloudWatchLogsToKinesisRole.AttachInlinePolicy(new Policy(this, "CanPutRecordsInKinesis", new PolicyProps
            {
                Statements = new[] { statement }
            }));

            // This CloudWatch rule will trigger whenever a new LogGroup is created. This assumes
            // that CloudTrail is enabled.
            var createLogGroupEventRule = new Rule(this, "CreateLogGroupEvent", new RuleProps {
                Description  = "Fires whenever CloudTrail detects that a log group is created",
                EventPattern = new EventPattern {
                    Source     = new[] { "aws.logs" },
                    DetailType = new[] { "AWS API Call via CloudTrail" },
                    Detail     = new Dictionary <string, object>
                    {
                        { "eventSource", new string[] { "logs.amazonaws.com" } },
                        { "eventName", new string[] { "CreateLogGroup" } },
                    }
                }
            });

            if (props.CloudWatchLogRetentionInDays.HasValue)
            {
                var setLogGroupExpirationLambda = new Function(this, "SetLogGroupExpiration", new FunctionProps
                {
                    Runtime     = Runtime.NODEJS_10_X,
                    Handler     = "index.handler",
                    Description = $"Sets the log retention policy to {props.CloudWatchLogRetentionInDays} days when a log group is created.",
                    MemorySize  = 128,
                    Environment = new Dictionary <string, string>
                    {
                        { "retention_days", props.CloudWatchLogRetentionInDays.Value.ToString() },
                        { "prefix", props.LogGroupsPrefix },
                    },
                    Code = Code.FromInline(EmbeddedResourceReader.Read("Resources.SetExpiry.js"))
                });

                // This lambda must be able to change the logs retention policy.
                setLogGroupExpirationLambda.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
                {
                    Effect    = Effect.ALLOW,
                    Actions   = new[] { "logs:PutRetentionPolicy" },
                    Resources = new[] { "*" },
                }));

                // This lambda should be invoked automatically when a log group is created.
                createLogGroupEventRule.AddTarget(new LambdaFunction(setLogGroupExpirationLambda));
            }

            var excludedLogGroups = props.LogShipper == null ? "" : $"/aws/lambda/{props.LogShipper.FunctionName}";

            // This function will be invoked whenever a CloudWatch log group is created. It will
            // subscribe the log group to our Kinesis Data Stream so that all logs end up in the
            // DataStream.
            var subscribeLogGroupsToKinesisLambda = new Function(this, "SubscribeLogGroupsToKinesis", new FunctionProps
            {
                Runtime     = Runtime.NODEJS_10_X,
                Handler     = "index.handler",
                Description = "Subscribe logs to the Kinesis stream",
                MemorySize  = 128,
                Environment = new Dictionary <string, string>
                {
                    { "arn", kinesisStream.StreamArn },
                    { "role_arn", cloudWatchLogsToKinesisRole.RoleArn },
                    { "prefix", props.LogGroupsPrefix },
                    { "excluded_log_groups", excludedLogGroups },
                    { "filter_pattern", props.CloudWatchLogsFilterPattern.ToString() },
                },
                Code = Code.FromInline(EmbeddedResourceReader.Read("Resources.SubscribeLogGroupsToKinesis.js"))
            });

            subscribeLogGroupsToKinesisLambda.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new [] { "logs:PutSubscriptionFilter" },
                Resources = new[] { "*" },
            }));

            subscribeLogGroupsToKinesisLambda.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new[] { "iam:PassRole" },
                Resources = new[] { "*" },
            }));

            createLogGroupEventRule.AddTarget(new LambdaFunction(subscribeLogGroupsToKinesisLambda));
        }
Пример #8
0
        internal StepFunctionDemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            Bucket stepFunctionDemoBucket = new Bucket(this, "StepFunctionDemoBucket", new BucketProps
            {
                Encryption    = BucketEncryption.S3_MANAGED,
                RemovalPolicy = RemovalPolicy.RETAIN
            });

            Table stepFunctionDemoTable = new Table(this, "StepFunctionDemoTable", new TableProps {
                BillingMode  = BillingMode.PROVISIONED,
                PartitionKey = new Amazon.CDK.AWS.DynamoDB.Attribute
                {
                    Name = "Id",
                    Type = AttributeType.STRING
                },
                RemovalPolicy = RemovalPolicy.DESTROY
            });

            //Step Function invoking Lambda function
            Function invokeOddEvenStepFunction = new Function(this, "InvokeOddEvenStepFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::InvokeOddEvenStepFunction",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Lambda Function that invokes the Demo Step Function",
            });


            //Function to calculate Odd or Even
            Function oddOrEvenFunction = new Function(this, "OddOrEvenFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::OddOrEvenFunction",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Lambda Function that calculates odd or even",
            });

            //Demo Lambda to perform Process 1
            Function process1Function = new Function(this, "Process1Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process1Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process1",
            });

            Function processAFunction = new Function(this, "ProcessAFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process1Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process1",
            });

            //Demo Lambda to perform Process 2
            Function process2Function = new Function(this, "Process2Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process2Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs process2",
            });

            //Demo Lambda to perform Process 1
            Function process11Function = new Function(this, "Process11Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process11Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs job process1",
            });

            //Demo Lambda to perform Process 2
            Function process12Function = new Function(this, "Process12Function", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::Process12Function",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that runs job process2",
            });

            Function taskTokenExecutorFunction = new Function(this, "TaskTokenExecutorFunction", new FunctionProps
            {
                Runtime     = Runtime.DOTNET_CORE_3_1,
                Code        = Code.FromAsset("src/Demo.Services.Lambda/bin/Release/netcoreapp3.1/Demo.Services.Lambda.zip"),
                Handler     = "Demo.Services.Lambda::Demo.Services.Lambda.Functions::TaskTokenExecutor",
                Timeout     = Duration.Minutes(5),
                MemorySize  = 512,
                Description = "Demo Lambda Function that executes Task Token Step",
                Environment = new Dictionary <string, string>()
                {
                    ["STEP_FUNCTION_DEMO_BUCKET"] = stepFunctionDemoBucket.BucketName
                }
            });

            stepFunctionDemoBucket.GrantReadWrite(taskTokenExecutorFunction);


            var oddEvenFunction = new Task(this, "OddEvenFunction", new TaskProps
            {
                Task = new InvokeFunction(oddOrEvenFunction.LatestVersion)
            });


            var process1 = new Task(this, "Process1", new TaskProps
            {
                Task = new InvokeFunction(process1Function.LatestVersion)
            });

            var processA = new Task(this, "ProcessA", new TaskProps
            {
                Task = new InvokeFunction(processAFunction.LatestVersion)
            });


            var process2 = new Task(this, "Process2", new TaskProps
            {
                Task = new InvokeFunction(process2Function.LatestVersion)
            });

            var process11 = new Task(this, "Process11", new TaskProps
            {
                Task       = new InvokeFunction(process11Function.LatestVersion),
                ResultPath = "$.Resolved"
            });

            var process12 = new Task(this, "Process12", new TaskProps
            {
                Task = new InvokeFunction(process12Function.LatestVersion)
            });

            var taskTokenExecutor = new Task(this, "TaskTokenExecutor", new TaskProps
            {
                Task = new RunLambdaTask(taskTokenExecutorFunction.LatestVersion, new RunLambdaTaskProps()
                {
                    IntegrationPattern = ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN,
                    Payload            = TaskInput.FromContextAt("$$.Task.Token")
                }),
                Parameters = new Dictionary <string, object>
                {
                    ["Payload"] = new Dictionary <string, object>
                    {
                        ["TaskToken.$"] = "$$.Task.Token",
                        ["State.$"]     = "$"
                    }
                }
            });


            //Choice to go to Process 1 or Process 2 based on input number is odd or even.
            var isEven = new Choice(this, "Is the number Even?");
            var isResolvedOrOverriden = new Choice(this, "Is Resolved Or Overriden?");

            //var chain1 = Chain.Start(oddEvenFunction)
            //    .Next(isEven
            //            .When(
            //                Condition.StringEquals("$.Result", "Even"),
            //                Chain.Start(process1)
            //                    .Next(process11)
            //                    .Next(isResolvedOrOverriden
            //                        .When(
            //                            Condition.Or(
            //                                new[]
            //                                {
            //                                    Condition.BooleanEquals("$.Resolved", true),
            //                                    Condition.BooleanEquals("$.Override", true)
            //                                }), process12)
            //                        .Otherwise(process2)))
            //            .When(Condition.StringEquals("$.Result", "Odd"), process2));

            var chain1 = Chain.Start(oddEvenFunction)
                         .Next(isEven
                               .When(
                                   Condition.StringEquals("$.Result", "Even"),
                                   Chain.Start(process1)
                                   .Next(taskTokenExecutor)
                                   .Next(isResolvedOrOverriden
                                         .When(
                                             Condition.Or(
                                                 new[]
            {
                Condition.BooleanEquals("$.Resolved", true),
                Condition.BooleanEquals("$.Override", true)
            }), process12)
                                         .Otherwise(process2)))
                               .When(Condition.StringEquals("$.Result", "Odd"), process2));


            //State Machine

            var stateMachine = new StateMachine(this, "JobDemoStateMachine", new StateMachineProps
            {
                StateMachineName = "JobDemoStateMachine",
                Timeout          = Duration.Minutes(5),
                Definition       = chain1
            });

            stateMachine.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "DynamoDBFullAccessForStepFunction", "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"));

            stateMachine.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "LambdaFullAccessForStepFunction", "arn:aws:iam::aws:policy/AWSLambdaFullAccess"));

            var demofargateTask1 = new FargateTaskDefinition(this,
                                                             "demoECSTask1Definition", new FargateTaskDefinitionProps
            {
                MemoryLimitMiB = 4096,
                Cpu            = 2048
            });
            var demofargateTask2 = new FargateTaskDefinition(this,
                                                             "demoECSTask2Definition", new FargateTaskDefinitionProps
            {
                MemoryLimitMiB = 4096,
                Cpu            = 2048
            });

            stepFunctionDemoBucket.GrantReadWrite(demofargateTask2.TaskRole);

            IVpc publicVpc = Vpc.FromLookup(this, "PublicVPC", new VpcLookupOptions
            {
                Tags = new Dictionary <string, string>
                {
                    ["Paces:VpcType"] = "Public"
                }
            });
            var cluster = Cluster.FromClusterAttributes(this, "PublicCluster", new ClusterAttributes
            {
                ClusterName    = "OHC-PACES",
                Vpc            = publicVpc,
                SecurityGroups = new[]
                { SecurityGroup.FromSecurityGroupId(this, "SecurityGroup", "sg-0a1bab8166d8fb715") }
            });

            var container1 = demofargateTask1.AddContainer("app", new ContainerDefinitionOptions
            {
                Image = ContainerImage.FromAsset(".", new AssetImageProps
                {
                    File = "Dockerfile"
                }),
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "demoECSTask1LogGroup", new LogGroupProps
                    {
                        LogGroupName = "/ecs/demoECSTask1-" + RandomString.Generate(10, StackId),
                    }),
                    StreamPrefix = "logs"
                }),
            });


            var container2 = demofargateTask2.AddContainer("app", new ContainerDefinitionOptions
            {
                Image = ContainerImage.FromAsset(".", new AssetImageProps
                {
                    File = "Dockerfile.1"
                }),
                Environment = new Dictionary <string, string>
                {
                    ["STEP_FUNCTION_DEMO_BUCKET"] = stepFunctionDemoBucket.BucketName
                },
                Logging = LogDriver.AwsLogs(new AwsLogDriverProps
                {
                    LogGroup = new LogGroup(this, "demoECSTask2LogGroup", new LogGroupProps
                    {
                        LogGroupName = $"/ecs/demoECSTask2-{RandomString.Generate(10, StackId)}",
                    }),
                    StreamPrefix = "logs"
                })
            });


            Rule rule = new Rule(this, "DemoJobRule", new RuleProps
            {
                Schedule = Schedule.Cron(new CronOptions
                {
                    Day    = "*",
                    Hour   = "*",
                    Minute = "1",
                    Month  = "*",
                    Year   = "*"
                }),
                Description = "Runs demo job fargate task",
                Targets     = new IRuleTarget[]
                {
                    new EcsTask(
                        new EcsTaskProps
                    {
                        Cluster         = cluster,
                        TaskDefinition  = demofargateTask2,
                        SubnetSelection = new SubnetSelection
                        {
                            OnePerAz = true
                        }
                    })
                }
            });



            //var ecsTask1 = new Task(this, "ecsTask1", new TaskProps
            //{
            //    InputPath = "$",
            //    Task = new CustomTask(new RunEcsFargateTaskProps
            //    {

            //        Cluster = Cluster.FromClusterAttributes(this, "PublicCluster", new ClusterAttributes
            //        {
            //            ClusterName = "OHC-PACES",
            //            Vpc = publicVpc,
            //            SecurityGroups = new[] { SecurityGroup.FromSecurityGroupId(this, "SecurityGroup", "sg-0a1bab8166d8fb715") }
            //        }),
            //        TaskDefinition = fargateTask1,

            //        ContainerOverrides = new[]
            //        {
            //            new ContainerOverride
            //            {
            //               ContainerDefinition = container,
            //               Command = new []{"$.Data"}
            //            },

            //        }
            //    })
            //});

            var ecsTask1 = new Task(this, "EcsTask1", new TaskProps
            {
                InputPath = "$",
                Task      = new RunEcsFargateTask(new RunEcsFargateTaskProps
                {
                    Cluster        = cluster,
                    TaskDefinition = demofargateTask1,

                    //ContainerOverrides = new[]
                    //{
                    //    new ContainerOverride
                    //    {
                    //        ContainerDefinition = container,
                    //
                    //    },

                    //}
                }),
                Parameters = new Dictionary <string, object>
                {
                    ["Overrides"] = new Dictionary <string, object>
                    {
                        ["ContainerOverrides"] = new Dictionary <string, string>[]
                        {
                            new Dictionary <string, string> {
                                ["Name"]      = "app",
                                ["Command.$"] = "$.ECSPayload"
                            }
                        }
                    }
                }
            });

            var chain2 = Chain.Start(processA).Next(ecsTask1);


            var stateMachineWithTask = new StateMachine(this, "JobDemoStateMachine-1", new StateMachineProps
            {
                StateMachineName = "JobDemoStateMachine-1",
                Timeout          = Duration.Minutes(15),
                Definition       = chain2,
                Role             = Role.FromRoleArn(this, "StateMachineWithTaskRole",
                                                    "arn:aws:iam::342600918501:role/service-role/PacesEdi274DefaultStateMachineRole")
            });

            //All Policies
            // 1. Invoke function policies

            invokeOddEvenStepFunction.Role?.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "InvokeLambdaPolicy", "arn:aws:iam::aws:policy/AWSLambdaFullAccess"));

            var policyStatement = new PolicyStatement
            {
                Sid    = "CanInvokeStepFunctions",
                Effect = Effect.ALLOW
            };

            policyStatement.AddActions(new[] { "states:StartExecution" });

            invokeOddEvenStepFunction.AddToRolePolicy(policyStatement);
            policyStatement.AddResources(stateMachine.StateMachineArn);
            invokeOddEvenStepFunction.AddEnvironment(Functions.StateMachineArnKey, stateMachine.StateMachineArn);

            process12Function.AddEnvironment(Functions.StepFunctionDemoBucketKey, stepFunctionDemoBucket.BucketName);

            stepFunctionDemoBucket.GrantReadWrite(process12Function);


            var policyStatementDemofargateTask2 = new PolicyStatement
            {
                Sid    = "CanNotifyStepFunction",
                Effect = Effect.ALLOW
            };

            policyStatementDemofargateTask2.AddActions(new[] { "states:SendTask*" });
            demofargateTask2.AddToExecutionRolePolicy(policyStatementDemofargateTask2);
            demofargateTask2.AddToTaskRolePolicy(policyStatementDemofargateTask2);

            policyStatementDemofargateTask2.AddAllResources();
        }