public EcsStack(Construct parent, string id, EcsStackProps props) : base(parent, id)
        {
            this.ecsCluster = new Cluster(this, "Cluster", new ClusterProps
            {
                Vpc = props.Vpc,
            });
            this.ecsCluster.Connections.AllowFromAnyIpv4(Port.Tcp(8080));
            Console.Write(props.ecrRepository.RepositoryArn);
            this.ecsService = new NetworkLoadBalancedFargateService(this, "Service", new NetworkLoadBalancedFargateServiceProps()
            {
                Cluster            = this.ecsCluster,
                DesiredCount       = 1,
                PublicLoadBalancer = true,
                TaskImageOptions   = new NetworkLoadBalancedTaskImageOptions
                {
                    EnableLogging = true,
                    ContainerPort = 8080,
                    Image         = ContainerImage.FromEcrRepository(props.ecrRepository),
                }
            }
                                                                    );
            this.ecsService.Service.Connections.AllowFrom(Peer.Ipv4(props.Vpc.VpcCidrBlock), Port.Tcp(8080));

            var taskDefinitionPolicy = new PolicyStatement();

            taskDefinitionPolicy.AddActions(
                // Rules which allow ECS to attach network interfaces to instances
                // on your behalf in order for awsvpc networking mode to work right
                "ec2:AttachNetworkInterface",
                "ec2:CreateNetworkInterface",
                "ec2:CreateNetworkInterfacePermission",
                "ec2:DeleteNetworkInterface",
                "ec2:DeleteNetworkInterfacePermission",
                "ec2:Describe*",
                "ec2:DetachNetworkInterface",

                // Rules which allow ECS to update load balancers on your behalf
                //  with the information sabout how to send traffic to your containers
                "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
                "elasticloadbalancing:DeregisterTargets",
                "elasticloadbalancing:Describe*",
                "elasticloadbalancing:RegisterInstancesWithLoadBalancer",
                "elasticloadbalancing:RegisterTargets",

                //  Rules which allow ECS to run tasks that have IAM roles assigned to them.
                "iam:PassRole",

                //  Rules that let ECS create and push logs to CloudWatch.
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup");
            taskDefinitionPolicy.AddAllResources();

            this.ecsService.Service.TaskDefinition.AddToExecutionRolePolicy(
                taskDefinitionPolicy
                );

            var taskRolePolicy = new PolicyStatement();

            taskRolePolicy.AddActions(
                // Allow the ECS Tasks to download images from ECR
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                // Allow the ECS tasks to upload logs to CloudWatch
                "logs:CreateLogStream",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
                );
            taskRolePolicy.AddAllResources();

            this.ecsService.Service.TaskDefinition.AddToTaskRolePolicy(
                taskRolePolicy
                );
        }
        public XRayStack(Construct parent, string id) : base(parent, id)
        {
            var table = new Table(this, "Table", new TableProps()
            {
                TableName    = "MysfitsQuestionsTable",
                PartitionKey = new Attribute
                {
                    Name = "QuestionId",
                    Type = AttributeType.STRING
                },
                Stream = StreamViewType.NEW_IMAGE
            });

            var postQuestionLambdaFunctionPolicyStmDDB = new PolicyStatement();

            postQuestionLambdaFunctionPolicyStmDDB.AddActions("dynamodb:PutItem");
            postQuestionLambdaFunctionPolicyStmDDB.AddResources(table.TableArn);

            var LambdaFunctionPolicyStmXRay = new PolicyStatement();

            LambdaFunctionPolicyStmXRay.AddActions(
                //  Allows the Lambda function to interact with X-Ray
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords",
                "xray:GetSamplingRules",
                "xray:GetSamplingTargets",
                "xray:GetSamplingStatisticSummaries"
                );
            LambdaFunctionPolicyStmXRay.AddAllResources();

            var mysfitsPostQuestion = new Function(this, "PostQuestionFunction", new FunctionProps
            {
                Handler     = "mysfitsPostQuestion.postQuestion",
                Runtime     = Runtime.PYTHON_3_6,
                Description =
                    "A microservice Lambda function that receives a new question submitted to the MythicalMysfits website from a user and inserts it into a DynamoDB database table.",
                MemorySize    = 128,
                Code          = Code.FromAsset("../../lambda-questions/PostQuestionsService"),
                Timeout       = Duration.Seconds(30),
                InitialPolicy = new[]
                {
                    postQuestionLambdaFunctionPolicyStmDDB,
                    LambdaFunctionPolicyStmXRay
                },
                Tracing = Tracing.ACTIVE
            });

            var topic = new Topic(this, "Topic", new TopicProps
            {
                DisplayName = "MythicalMysfitsQuestionsTopic",
                TopicName   = "MythicalMysfitsQuestionsTopic"
            });

            topic.AddSubscription(new EmailSubscription("REPLACE@EMAIL_ADDRESS"));

            var postQuestionLambdaFunctionPolicyStmSNS = new PolicyStatement();

            postQuestionLambdaFunctionPolicyStmSNS.AddActions("sns:Publish");
            postQuestionLambdaFunctionPolicyStmSNS.AddResources(topic.TopicArn);

            var mysfitsProcessQuestionStream = new Function(this, "ProcessQuestionStreamFunction", new FunctionProps
            {
                Handler     = "mysfitsProcessStream.processStream",
                Runtime     = Runtime.PYTHON_3_6,
                Description =
                    "An AWS Lambda function that will process all new questions posted to mythical mysfits" +
                    " and notify the site administrator of the question that was asked.",
                MemorySize    = 128,
                Code          = Code.FromAsset("../../lambda-questions/ProcessQuestionsStream"),
                Timeout       = Duration.Seconds(30),
                InitialPolicy = new[]
                {
                    postQuestionLambdaFunctionPolicyStmSNS,
                    LambdaFunctionPolicyStmXRay
                },
                Tracing     = Tracing.ACTIVE,
                Environment = new Dictionary <string, string>()
                {
                    { "SNS_TOPIC_ARN", topic.TopicArn }
                },
                Events = new IEventSource[]
                {
                    new DynamoEventSource(table, new DynamoEventSourceProps
                    {
                        StartingPosition = StartingPosition.TRIM_HORIZON,
                        BatchSize        = 1
                    })
                }
            });

            var questionsApiRole = new Role(this, "QuestionsApiRole", new RoleProps
            {
                AssumedBy = new ServicePrincipal("apigateway.amazonaws.com")
            });

            var apiPolicy = new PolicyStatement();

            apiPolicy.AddActions("lambda:InvokeFunction");
            apiPolicy.AddResources(mysfitsPostQuestion.FunctionArn);
            new Policy(this, "QuestionsApiPolicy", new PolicyProps
            {
                PolicyName = "questions_api_policy",
                Statements = new[]
                {
                    apiPolicy
                },
                Roles = new IRole[]
                {
                    questionsApiRole
                }
            });

            var questionsIntegration = new LambdaIntegration(mysfitsPostQuestion, new LambdaIntegrationOptions
            {
                CredentialsRole      = questionsApiRole,
                IntegrationResponses = new IntegrationResponse[]
                {
                    new IntegrationResponse()
                    {
                        StatusCode        = "200",
                        ResponseTemplates = new Dictionary <string, string>
                        {
                            { "application/json", "{\"status\":\"OK\"}" }
                        }
                    }
                }
            });

            var api = new LambdaRestApi(this, "APIEndpoint", new LambdaRestApiProps
            {
                Handler       = mysfitsPostQuestion,
                RestApiName   = "Questions API Service",
                DeployOptions = new StageOptions
                {
                    TracingEnabled = true
                },
                Proxy = false
            });

            var questionsMethod = api.Root.AddResource("questions");

            questionsMethod.AddMethod("POST", questionsIntegration, new MethodOptions
            {
                MethodResponses = new MethodResponse[]
                {
                    new MethodResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters = new Dictionary <string, bool>()
                        {
                            { "method.response.header.Access-Control-Allow-Headers", true },
                            { "method.response.header.Access-Control-Allow-Methods", true },
                            { "method.response.header.Access-Control-Allow-Origin", true },
                        }
                    }
                },
                AuthorizationType = AuthorizationType.NONE
            });

            questionsMethod.AddMethod("OPTIONS", new MockIntegration(new IntegrationOptions
            {
                IntegrationResponses = new IntegrationResponse[]
                {
                    new IntegrationResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters = new Dictionary <string, string>
                        {
                            {
                                "method.response.header.Access-Control-Allow-Headers",
                                "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
                            },
                            { "method.response.header.Access-Control-Allow-Origin", "'*'" },
                            { "method.response.header.Access-Control-Allow-Credentials", "'false'" },
                            { "method.response.header.Access-Control-Allow-Methods", "'OPTIONS,GET,PUT,POST,DELETE'" }
                        }
                    }
                },
                PassthroughBehavior = PassthroughBehavior.NEVER,
                RequestTemplates    = new Dictionary <string, string>
                {
                    { "application/json", "{\"statusCode\": 200}" }
                }
            }),
                                      new MethodOptions
            {
                MethodResponses = new MethodResponse[]
                {
                    new MethodResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters = new Dictionary <string, bool>
                        {
                            { "method.response.header.Access-Control-Allow-Headers", true },
                            { "method.response.header.Access-Control-Allow-Methods", true },
                            { "method.response.header.Access-Control-Allow-Credentials", true },
                            { "method.response.header.Access-Control-Allow-Origin", true }
                        }
                    }
                }
            }
                                      );
        }
Exemplo n.º 3
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();
        }
Exemplo n.º 4
0
        public KinesisFirehoseStack(Construct parent, string id, KinesisFirehoseStackProps props) : base(parent, id,
                                                                                                         props)
        {
            var clicksDestinationBucket = new Bucket(this, "Bucket", new BucketProps
            {
                Versioned = true
            });

            var firehoseDeliveryRole = new Role(this, "FirehoseDeliveryRole", new RoleProps
            {
                RoleName    = "FirehoseDeliveryRole",
                AssumedBy   = new ServicePrincipal("firehose.amazonaws.com"),
                ExternalIds = new string[]
                {
                    Aws.ACCOUNT_ID
                }
            });

            var firehoseDeliveryPolicyS3Stm = new PolicyStatement();

            firehoseDeliveryPolicyS3Stm.AddActions("s3:AbortMultipartUpload",
                                                   "s3:GetBucketLocation",
                                                   "s3:GetObject",
                                                   "s3:ListBucket",
                                                   "s3:ListBucketMultipartUploads",
                                                   "s3:PutObject");
            firehoseDeliveryPolicyS3Stm.AddResources(clicksDestinationBucket.BucketArn);
            firehoseDeliveryPolicyS3Stm.AddResources(clicksDestinationBucket.ArnForObjects("*"));

            var lambdaFunctionPolicy = new PolicyStatement();

            lambdaFunctionPolicy.AddActions("dynamodb:GetItem");
            lambdaFunctionPolicy.AddResources(props.TableArn);
            var LambdaFunctionPolicyStmXRay = new PolicyStatement();

            LambdaFunctionPolicyStmXRay.AddActions(
                //  Allows the Lambda function to interact with X-Ray
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords",
                "xray:GetSamplingRules",
                "xray:GetSamplingTargets",
                "xray:GetSamplingStatisticSummaries"
                );
            LambdaFunctionPolicyStmXRay.AddAllResources();
            var mysfitsClicksProcessor = new Function(this, "Function", new FunctionProps
            {
                Handler     = "streaming_lambda::streaming_lambda.function::FunctionHandlerAsync",
                Runtime     = Runtime.DOTNET_CORE_2_1,
                Description = "An Amazon Kinesis Firehose stream processor that enriches click records" +
                              " to not just include a mysfitId, but also other attributes that can be analyzed later.",
                MemorySize    = 128,
                Code          = Code.FromAsset("../lambda/stream/bin/Debug/netcoreapp2.1/Publish"),
                Timeout       = Duration.Seconds(30),
                Tracing       = Tracing.ACTIVE,
                InitialPolicy = new PolicyStatement[]
                {
                    lambdaFunctionPolicy,
                    LambdaFunctionPolicyStmXRay
                },
                Environment = new Dictionary <string, string>()
                {
                    {
                        "mysfits_api_url",
                        string.Format($"https://${props.APIid}.execute-api.{Amazon.CDK.Aws.REGION}.amazonaws.com/prod/")
                    }
                }
            });

            var firehoseDeliveryPolicyLambdaStm = new PolicyStatement();

            firehoseDeliveryPolicyLambdaStm.AddActions("lambda:InvokeFunction");
            firehoseDeliveryPolicyLambdaStm.AddResources(mysfitsClicksProcessor.FunctionArn);
            firehoseDeliveryRole.AddToPolicy(firehoseDeliveryPolicyS3Stm);
            firehoseDeliveryRole.AddToPolicy(firehoseDeliveryPolicyLambdaStm);

            var mysfitsFireHoseToS3 = new CfnDeliveryStream(this, "DeliveryStream", new CfnDeliveryStreamProps
            {
                ExtendedS3DestinationConfiguration = new CfnDeliveryStream.ExtendedS3DestinationConfigurationProperty()
                {
                    BucketArn      = clicksDestinationBucket.BucketArn,
                    BufferingHints = new CfnDeliveryStream.BufferingHintsProperty
                    {
                        IntervalInSeconds = 60,
                        SizeInMBs         = 50
                    },
                    CompressionFormat       = "UNCOMPRESSED",
                    Prefix                  = "firehose/",
                    RoleArn                 = firehoseDeliveryRole.RoleArn,
                    ProcessingConfiguration = new CfnDeliveryStream.ProcessingConfigurationProperty
                    {
                        Enabled    = true,
                        Processors = new CfnDeliveryStream.ProcessorProperty[]
                        {
                            new CfnDeliveryStream.ProcessorProperty()
                            {
                                Type       = "Lambda",
                                Parameters = new CfnDeliveryStream.ProcessorParameterProperty
                                {
                                    ParameterName  = "LambdaArn",
                                    ParameterValue = mysfitsClicksProcessor.FunctionArn
                                }
                            }
                        }
                    }
                }
            });

            new CfnPermission(this, "Permission", new CfnPermissionProps
            {
                Action        = "lambda:InvokeFunction",
                FunctionName  = mysfitsClicksProcessor.FunctionArn,
                Principal     = "firehose.amazonaws.com",
                SourceAccount = Amazon.CDK.Aws.ACCOUNT_ID,
                SourceArn     = mysfitsFireHoseToS3.AttrArn
            });

            var clickProcessingApiRole = new Role(this, "ClickProcessingApiRole", new RoleProps
            {
                AssumedBy = new ServicePrincipal("apigateway.amazonaws.com")
            });

            var apiPolicy = new PolicyStatement();

            apiPolicy.AddActions("firehose:PutRecord");
            apiPolicy.AddResources(mysfitsFireHoseToS3.AttrArn);
            new Policy(this, "ClickProcessingApiPolicy", new PolicyProps
            {
                PolicyName = "api_gateway_firehose_proxy_role",
                Statements = new PolicyStatement[]
                {
                    apiPolicy
                },
                Roles = new[] { clickProcessingApiRole }
            });

            var api = new RestApi(this, "APIEndpoint", new RestApiProps
            {
                RestApiName    = "ClickProcessing API Service",
                CloudWatchRole = false,
                EndpointTypes  = new EndpointType[]
                {
                    EndpointType.REGIONAL
                }
            });

            var clicks = api.Root.AddResource("clicks");

            clicks.AddMethod("PUT", new AwsIntegration(new AwsIntegrationProps
            {
                Service = "firehose",
                IntegrationHttpMethod = "POST",
                Action  = "PutRecord",
                Options = new IntegrationOptions
                {
                    ConnectionType       = ConnectionType.INTERNET,
                    CredentialsRole      = clickProcessingApiRole,
                    IntegrationResponses = new IntegrationResponse[]
                    {
                        new IntegrationResponse()
                        {
                            StatusCode        = "200",
                            ResponseTemplates =
                            {
                                { "application/json", "{\"status\":\"OK\"}" }
                            },
                            ResponseParameters =
                            {
                                { "method.response.header.Access-Control-Allow-Headers", "'Content-Type'" },
                                { "method.response.header.Access-Control-Allow-Methods", "'OPTIONS,PUT'"  },
                                { "method.response.header.Access-Control-Allow-Origin",  "'*'"            }
                            }
                        }
                    },
                    RequestParameters =
                    {
                        { "integration.request.header.Content-Type", "'application/x-amz-json-1.1'" }
                    },
                    RequestTemplates =
                    {
                        {
                            "application/json",
                            "{\"DeliveryStreamName\":\"" + mysfitsFireHoseToS3.Ref +
                            "\", \"Record\": { \"Data\": \"$util.base64Encode($input.json('$'))\"}"
                        }
                    }
                }
            }),
                             new MethodOptions
            {
                MethodResponses = new MethodResponse[]
                {
                    new MethodResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters =
                        {
                            { "method.response.header.Access-Control-Allow-Headers", true },
                            { "method.response.header.Access-Control-Allow-Methods", true },
                            { "method.response.header.Access-Control-Allow-Origin",  true }
                        }
                    }
                }
            });

            clicks.AddMethod("OPTIONS", new MockIntegration(new IntegrationOptions
            {
                IntegrationResponses = new IntegrationResponse[]
                {
                    new IntegrationResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters = new Dictionary <string, string>
                        {
                            {
                                "method.response.header.Access-Control-Allow-Headers",
                                "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
                            },
                            { "method.response.header.Access-Control-Allow-Origin", "'*'" },
                            { "method.response.header.Access-Control-Allow-Credentials", "'false'" },
                            { "method.response.header.Access-Control-Allow-Methods", "'OPTIONS,GET,PUT,POST,DELETE'" }
                        }
                    }
                },
                PassthroughBehavior = PassthroughBehavior.NEVER,
                RequestTemplates    = new Dictionary <string, string>
                {
                    { "application/json", "{\"statusCode\": 200}" }
                }
            }),
                             new MethodOptions
            {
                MethodResponses = new MethodResponse[]
                {
                    new MethodResponse
                    {
                        StatusCode         = "200",
                        ResponseParameters = new Dictionary <string, bool>
                        {
                            { "method.response.header.Access-Control-Allow-Headers", true },
                            { "method.response.header.Access-Control-Allow-Methods", true },
                            { "method.response.header.Access-Control-Allow-Credentials", true },
                            { "method.response.header.Access-Control-Allow-Origin", true }
                        }
                    }
                }
            });
        }
Exemplo n.º 5
0
        public DynamoDbStack(Construct parent, string id, DynamoDbStackProps props) : base(parent, id, props)
        {
            var dynamoDbEndpoint = props.Vpc.AddGatewayEndpoint("DynamoDbEndpoint", new GatewayVpcEndpointOptions
            {
                Service = GatewayVpcEndpointAwsService.DYNAMODB
            });

            var dynamoDbPolicy = new PolicyStatement();

            dynamoDbPolicy.AddAnyPrincipal();
            dynamoDbPolicy.AddActions("*");
            dynamoDbPolicy.AddAllResources();
            dynamoDbEndpoint.AddToPolicy(
                dynamoDbPolicy
                );

            this.table = new Table(this, "Table", new TableProps
            {
                TableName    = "MysfitsTable",
                PartitionKey = new Attribute
                {
                    Name = "MysfitId",
                    Type = AttributeType.STRING
                }
            });
            this.table.AddGlobalSecondaryIndex(new GlobalSecondaryIndexProps
            {
                IndexName    = "LawChaosIndex",
                PartitionKey = new Attribute
                {
                    Name = "LawChaos",
                    Type = AttributeType.STRING
                },
                SortKey = new Attribute
                {
                    Name = "MysfitId",
                    Type = AttributeType.STRING
                },
                ReadCapacity   = 5,
                WriteCapacity  = 5,
                ProjectionType = ProjectionType.ALL
            });
            this.table.AddGlobalSecondaryIndex(new GlobalSecondaryIndexProps
            {
                IndexName    = "GoodEvilIndex",
                PartitionKey = new Attribute
                {
                    Name = "GoodEvil",
                    Type = AttributeType.STRING
                },
                SortKey = new Attribute
                {
                    Name = "MysfitId",
                    Type = AttributeType.STRING
                },
                ReadCapacity   = 5,
                WriteCapacity  = 5,
                ProjectionType = ProjectionType.ALL
            });

            var fargatePolicy = new PolicyStatement();

            fargatePolicy.AddActions(
                //  Allows the ECS tasks to interact with only the MysfitsTable in DynamoDB
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:UpdateItem",
                "dynamodb:GetItem",
                "dynamodb:DescribeTable"
                );
            fargatePolicy.AddResources(
                "arn:aws:dynamodb:*:*:table/MysfitsTable*"
                );
            props.fargateService.TaskDefinition.AddToTaskRolePolicy(
                fargatePolicy
                );
        }