Beispiel #1
0
    def create_custom_cloudformation_resources(self):
        t = self.template

        queue = sqs.Queue("CustomResourcesQueue")
        topic = sns.Topic(
            "CustomResourcesTopic",
            Subscription=[sns.Subscription(
                Protocol="sqs",
                Endpoint=GetAtt("CustomResourcesQueue", "Arn"))])
        queue_policy = sqs.QueuePolicy(
            "CustomResourcesQueuePolicy",
            Queues=[Ref(queue)],
            PolicyDocument=sns_to_sqs_policy(Ref(topic)))

        t.add_resource(queue)
        t.add_resource(topic)
        t.add_resource(queue_policy)
 def _create_sns_subscriptions(self):
     protocol = Parameter(
         'SNSProtocol',
         Type='String',
         Description=('The protocol type for the SNS subscription used '
                      'for pipeline event notifications (e.g "email")'))
     endpoint = Parameter(
         'SNSEndpoint',
         Type='String',
         Description=('The endpoint value for the SNS subscription used '
                      'for pipeline event notifications.  If the protocol '
                      'type is "email" then this value is the email '
                      'address.'))
     self._t.add_parameter([protocol, endpoint])
     return [
         sns.Subscription(
             Protocol=protocol.Ref(),
             Endpoint=endpoint.Ref(),
         )
     ]
from troposphere import apigatewayv2
from jinja2 import Template as jinja_template

domain = os.environ.get("EMAIL_CONTACT_DOMAIN", "http://test")
parsed_domain = urlparse(domain)
if not parsed_domain.scheme:
    raise ValueError(
        f"Domain '{domain}' requires a scheme. This is needed for CORS headers."
    )
email_target = os.environ.get("EMAIL_TARGET", "*****@*****.**")
recaptcha_secret = os.environ.get("RECAPTCHA_SECRET")
cdomain = parsed_domain.netloc.replace(
    ".", "-")[:24]  # AWS names have a character limit

### SNS
send_to = sns.Subscription(Protocol="email", Endpoint=email_target)

topic = sns.Topic("EmailContactForm", Subscription=[send_to])

### Lambda
environment = {"ORIGIN_DOMAIN": domain, "TOPIC_ARN": Ref(topic)}
if recaptcha_secret:
    environment["RECAPTCHA_SECRET"] = recaptcha_secret

lambda_environment = awslambda.Environment(Variables=environment)

sns_publish_policy = iam.Policy(
    PolicyName=f"lambda-sns-publish-policy-contact-form-{cdomain}",
    PolicyDocument={
        "Version":
        "2012-10-17",
        Runtime='python3.6',
        Timeout=30,
        Environment=awslambda.Environment(
            Variables={
                'SOURCE_REGION': Ref(AWS_REGION),
                'TARGET_REGION': Ref(target_region_parameter),
                'KMS_KEY_ID': Ref(kms_key_parameter),
                'CLUSTERS_TO_USE': Ref(clusters_to_use_parameter)
            })))

# SNS topic for event subscriptions
rds_topic = template.add_resource(
    sns.Topic('RDSBackupTopic',
              Subscription=[
                  sns.Subscription(
                      Protocol="lambda",
                      Endpoint=GetAtt(backup_rds_function, 'Arn'),
                  )
              ]))

# Event subscription - RDS will notify SNS when backup is started and finished
template.add_resource(
    rds.EventSubscription("RDSBackupEvent",
                          Enabled=True,
                          EventCategories=["backup"],
                          SourceType="db-instance",
                          SnsTopicArn=Ref(rds_topic),
                          SourceIds=If("UseAllDatabases", Ref(AWS_NO_VALUE),
                                       Ref(databases_to_use_parameter))))

# Permission for SNS to trigger the Lambda
template.add_resource(
)

#
# Resources
#

alarm_topic = t.add_resource(sns.Topic(
    'AlarmTopic',

    DisplayName=If('HasDisplayNameCondition', Ref(param_display_name),
                   Ref(AWS_NO_VALUE)),

    Subscription=[

        sns.Subscription(
            Endpoint=Select(0, Ref(param_alarm_emails)),
            Protocol='email'),

        If('TwoEmailsCondition',
           sns.Subscription(
               Endpoint=Select(1, Ref(param_alarm_emails)),
               Protocol='email'
           ),
           Ref(AWS_NO_VALUE)),

        If('ThreeEmailsCondition',
           sns.Subscription(
               Endpoint=Select(2, Ref(param_alarm_emails)),
               Protocol='email'
           ),
           Ref(AWS_NO_VALUE)),
def main():
    # TODO:
    # - SNS topic is probably not complete
    # - BuildCopyCFNProject Encryption keys
    # - build_copy_cfn_project, validate_resource_project TimeoutInMinutes property
    # - Lambda function execute permissions
    # - Build role GetBucketTagging permissions. Only used in build-env step, may be obsolete in other scenarios
    # - Add customer name to CodeCommit repositories
    # - What to do with the password of the codecommit user?
    # - InputArtifact is not used in pipeline
    # - buildspec.env in project definition itself
    # - CodeCommitUser Permissions on troporepo and CFNvalidaterepo only!

    # INIT section

    template = Template()
    projectName = "dummy-mytestrepo"

    # PARAMETERS section

    github_oauth_token_parameter = template.add_parameter(
        Parameter(
            "GithubOauthToken",
            Type="String",
            Description="Github OAuthToken",
            NoEcho=True,
        ))

    github_owner_parameter = template.add_parameter(
        Parameter(
            "GithubOwner",
            Type="String",
            Description="Github owner",
            Default="cta-int",
        ))

    github_branch_parameter = template.add_parameter(
        Parameter(
            "GithubBranch",
            Type="String",
            Description="Github branch",
            Default="master",
        ))

    github_repository_parameter = template.add_parameter(
        Parameter(
            "GithubRepository",
            Type="String",
            Description="Github repository",
            Default="aws-bootstrap",
        ))

    # RESOURCES section

    approve_topic = template.add_resource(
        sns.Topic("ApproveTopic",
                  Subscription=[
                      sns.Subscription(
                          Endpoint="*****@*****.**",
                          Protocol="email",
                      )
                  ]))

    artifact_store_s3_bucket = template.add_resource(
        s3.Bucket(
            "ArtifactStoreS3Bucket",
            AccessControl=s3.Private,
        ))

    # ROLES section

    cloud_formation_role = template.add_resource(
        iam.Role(
            "CloudFormationRole",
            AssumeRolePolicyDocument=Policy(
                Version="2012-10-17",
                Statement=[
                    Statement(Effect=Allow,
                              Principal=Principal(
                                  "Service", "cloudformation.amazonaws.com"),
                              Action=[Action("sts", "AssumeRole")])
                ]),
            Path="/",
            Policies=[
                iam.Policy(PolicyName="CloudFormationNestedCFNAccessPolicy",
                           PolicyDocument=Policy(Version="2012-10-17",
                                                 Statement=[
                                                     Statement(
                                                         Effect=Allow,
                                                         Action=[Action("*")],
                                                         Resource=["*"])
                                                 ]))
            ]))

    code_build_role = template.add_resource(
        iam.Role(
            "CodeBuildRole",
            AssumeRolePolicyDocument=Policy(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service",
                                            "codebuild.amazonaws.com"),
                        Action=[Action("sts", "AssumeRole")],
                    )
                ]),
            Path="/",
            Policies=[
                iam.Policy(
                    PolicyName="CodeBuildAccessPolicy",
                    PolicyDocument=Policy(
                        Version="2012-10-17",
                        Statement=[
                            Statement(
                                Effect=Allow,
                                Action=[
                                    Action("cloudformation", "Get*"),
                                    Action("cloudformation", "Describe*"),
                                    Action("cloudformation", "List*"),
                                ],
                                Resource=[
                                    Sub("arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}*"
                                        ),
                                ]),
                            Statement(Effect=Allow,
                                      Action=[
                                          Action("ec2", "Describe*"),
                                          Action("cloudformation",
                                                 "ValidateTemplate"),
                                          Action("elasticloadbalancing",
                                                 "Describe*"),
                                          Action("autoscaling", "Describe*"),
                                          Action("iam", "Get*"),
                                          Action("iam", "List*"),
                                          Action("logs", "Describe*"),
                                          Action("logs", "Get*"),
                                          Action("tag", "Get*"),
                                      ],
                                      Resource=["*"]),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    Action("logs", "CreateLogGroup"),
                                    Action("logs", "CreateLogStream"),
                                    Action("logs", "PutLogEvents"),
                                ],
                                Resource=[
                                    Sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*"
                                        ),
                                ]),
                            Statement(Effect=Allow,
                                      Action=[
                                          Action("lambda", "ListFunctions"),
                                          Action("lambda", "InvokeFunction"),
                                      ],
                                      Resource=[
                                          "*",
                                      ]),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    Action("s3",
                                           "PutObject"),
                                    Action("s3",
                                           "GetObject"),
                                    Action("s3",
                                           "GetObjectVersion"),
                                    Action("s3",
                                           "ListBucket"),
                                ],
                                Resource=[
                                    Sub("arn:aws:s3:::codepipeline-${AWS::Region}-*"
                                        ),
                                    GetAtt(artifact_store_s3_bucket, "Arn"),
                                    Join("", [
                                        GetAtt(artifact_store_s3_bucket,
                                               "Arn"), "/*"
                                    ]),
                                ]),
                            Statement(Effect=Allow,
                                      Action=[
                                          Action("s3", "GetBucketTagging"),
                                      ],
                                      Resource=[
                                          Sub("arn:aws:s3:::*"),
                                      ])
                        ]))
            ]))

    code_pipeline_role = template.add_resource(
        iam.Role(
            "CodePipelineRole",
            AssumeRolePolicyDocument=Policy(
                Version="2012-10-17",
                Statement=[
                    Statement(
                        Effect=Allow,
                        Principal=Principal("Service",
                                            "codepipeline.amazonaws.com"),
                        Action=[Action("sts", "AssumeRole")],
                    )
                ]),
            Path="/",
            Policies=[
                iam.Policy(
                    PolicyName="CodePipelineAccessPolicy",
                    PolicyDocument=Policy(
                        Version="2012-10-17",
                        Statement=[
                            Statement(Effect=Allow,
                                      Action=[Action("s3", "*")],
                                      Resource=[
                                          GetAtt(artifact_store_s3_bucket,
                                                 "Arn"),
                                          Join("", [
                                              GetAtt(artifact_store_s3_bucket,
                                                     "Arn"), "/*"
                                          ]),
                                      ]),
                            Statement(Effect=Allow,
                                      Action=[
                                          Action("sns", "Publish"),
                                      ],
                                      Resource=[
                                          Ref(approve_topic),
                                      ]),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    Action("codebuild", "StartBuild"),
                                    Action("codebuild", "BatchGetBuilds"),
                                ],
                                Resource=[
                                    Sub("arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/codebuild-"
                                        + projectName),
                                ]),
                            Statement(Effect=Allow,
                                      Action=[
                                          Action("lambda", "ListFunctions"),
                                          Action("lambda", "InvokeFunction"),
                                      ],
                                      Resource=[
                                          "*",
                                      ]),
                            Statement(
                                Effect=Allow,
                                Action=[
                                    Action("iam", "PassRole"),
                                ],
                                Resource=[
                                    GetAtt(cloud_formation_role, "Arn"),
                                ],
                            )
                        ]))
            ]))

    code_build_dummy = template.add_resource(
        codebuild.Project(
            "CodeBuildDummy",
            Source=codebuild.Source(Type="CODEPIPELINE"),
            Artifacts=codebuild.Artifacts(Type="CODEPIPELINE"),
            Description="Generate cloudformation templates",
            Environment=codebuild.Environment(
                ComputeType='BUILD_GENERAL1_SMALL',
                Image='aws/codebuild/python:3.3.6',
                Type='LINUX_CONTAINER',
            ),
            Name="codebuild-" + projectName,
            ServiceRole=GetAtt(code_build_role, "Arn"),
        ))

    code_pipeline_dummy = template.add_resource(
        codepipeline.Pipeline(
            "CodePipelineDummy",
            Name="pipeline-" + projectName,
            RoleArn=GetAtt(code_pipeline_role, "Arn"),
            ArtifactStore=codepipeline.ArtifactStore(
                Type="S3",
                Location=Ref(artifact_store_s3_bucket),
            ),
            Stages=[
                codepipeline.Stages(
                    Name="Source",
                    Actions=[
                        codepipeline.Actions(
                            Name="Source",
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Source",
                                Owner="ThirdParty",
                                Provider="GitHub",
                                Version="1",
                            ),
                            OutputArtifacts=[
                                codepipeline.OutputArtifacts(Name="Source", )
                            ],
                            Configuration={
                                "Branch": Ref(github_branch_parameter),
                                "Repo": Ref(github_repository_parameter),
                                "PollForSourceChanges": True,
                                "Owner": Ref(github_owner_parameter),
                                "OAuthToken":
                                Ref(github_oauth_token_parameter),
                            },
                            RunOrder="1",
                        ),
                    ]),
                codepipeline.Stages(
                    Name="Build",
                    Actions=[
                        codepipeline.Actions(
                            Name="Build",
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Build",
                                Owner="AWS",
                                Provider="CodeBuild",
                                Version="1",
                            ),
                            InputArtifacts=[
                                codepipeline.InputArtifacts(Name="Source", )
                            ],
                            OutputArtifacts=[
                                codepipeline.OutputArtifacts(Name="Build", )
                            ],
                            Configuration={
                                "ProjectName": Ref(code_build_dummy),
                            },
                            RunOrder="1",
                        ),
                    ]),
                codepipeline.Stages(
                    Name="UAT",
                    Actions=[
                        codepipeline.Actions(
                            Name="CreateUATStack",
                            InputArtifacts=[
                                codepipeline.InputArtifacts(Name="Build", )
                            ],
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Invoke",
                                Owner="AWS",
                                Version="1",
                                Provider="Lambda",
                            ),
                            Configuration={
                                "FunctionName":
                                "lambda-cfn-provider",
                                "UserParameters":
                                Sub(
                                    json.dumps({
                                        "ActionMode":
                                        "CREATE_UPDATE",
                                        "ConfigPath":
                                        "Build::config.json",
                                        "StackName":
                                        projectName + "-UAT",
                                        "TemplatePath":
                                        "Build::dummy.json",
                                    }))
                            },
                            OutputArtifacts=[
                                codepipeline.OutputArtifacts(
                                    Name="CreateUATStack", )
                            ],
                            RunOrder="1",
                        ),
                        codepipeline.Actions(
                            Name="CreatePRODChangeSet",
                            InputArtifacts=[
                                codepipeline.InputArtifacts(Name="Build", )
                            ],
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Invoke",
                                Owner="AWS",
                                Version="1",
                                Provider="Lambda",
                            ),
                            Configuration={
                                "FunctionName":
                                "lambda-cfn-provider",
                                "UserParameters":
                                Sub(
                                    json.dumps({
                                        "ActionMode":
                                        "CHANGE_SET_REPLACE",
                                        "ChangeSetName":
                                        projectName + "-PROD-CHANGE-SET",
                                        "StackName":
                                        projectName + "-PROD",
                                        "TemplateConfiguration":
                                        "Build::config.json",
                                        "TemplatePath":
                                        "Build::dummy.json",
                                    }))
                            },
                            OutputArtifacts=[
                                codepipeline.OutputArtifacts(
                                    Name="CreatePRODChangeSet", )
                            ],
                            RunOrder="2",
                        ),
                    ]),
                codepipeline.Stages(
                    Name="PROD-ApproveChangeSet",
                    Actions=[
                        codepipeline.Actions(
                            Name="ApprovePRODChangeSet",
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Approval",
                                Owner="AWS",
                                Version="1",
                                Provider="Manual",
                            ),
                            Configuration={
                                "NotificationArn": Ref(approve_topic),
                                "CustomData":
                                "Approve deployment in production.",
                            },
                            RunOrder="1",
                        ),
                    ]),
                codepipeline.Stages(
                    Name="PROD-ExecuteChangeSet",
                    Actions=[
                        codepipeline.Actions(
                            Name="ExecutePRODChangeSet",
                            InputArtifacts=[
                                codepipeline.InputArtifacts(Name="Build", )
                            ],
                            ActionTypeId=codepipeline.ActionTypeID(
                                Category="Invoke",
                                Owner="AWS",
                                Version="1",
                                Provider="Lambda",
                            ),
                            Configuration={
                                "FunctionName":
                                "lambda-cfn-provider",
                                "UserParameters":
                                Sub(
                                    json.dumps({
                                        "ActionMode":
                                        "CHANGE_SET_EXECUTE",
                                        "ChangeSetName":
                                        projectName + "-PROD-CHANGE-SET",
                                        "StackName":
                                        projectName + "-PROD",
                                    }))
                            },
                            OutputArtifacts=[
                                codepipeline.OutputArtifacts(
                                    Name="ExecutePRODChangeSet", )
                            ],
                            RunOrder="1",
                        ),
                    ]),
            ]))

    # OUTPUT section

    template.add_output([
        Output(
            "ArtifactStoreS3Bucket",
            Description=
            "ResourceName of the S3 bucket containg the artifacts of the pipeline(s)",
            Value=Ref(artifact_store_s3_bucket),
            Export=Export(projectName + "-ArtifactS3Bucket"),
        ),
        Output(
            "ArtifactStoreS3BucketArn",
            Description=
            "Arn of the S3 bucket containg the artifacts of the pipeline(s)",
            Value=GetAtt(artifact_store_s3_bucket, "Arn"),
            Export=Export(projectName + "-ArtifactS3BucketArn"),
        ),
        Output(
            "CodeBuildRole",
            Description=
            "Logical name of the role that is used by the CodeBuild projects in the CodePipeline",
            Value=Ref(code_build_role),
            Export=Export(projectName + "-CodeBuildRole"),
        ),
        Output(
            "CloudFormationRoleArn",
            Description=
            "Arn of the S3 bucket containing the artifacts of the pipeline(s)",
            Value=GetAtt(cloud_formation_role, "Arn"),
            Export=Export(projectName + "-CloudFormationRoleArn"),
        ),
        Output(
            "CodePipelineRoleArn",
            Description=
            "Logical name of the role that is used by the CodePipeline",
            Value=GetAtt(code_pipeline_role, "Arn"),
            Export=Export(projectName + "-CodePipelineRoleArn"),
        )
    ])

    print(template.to_json())
                        '([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|'
                        '([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.'
                        '([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'),
        Default='example.com',
        Description=
        'FQDN of the main domain or subdomain used to access the site.',
        MaxLength=100,
        MinLength=4,
        Type='String'))
# endregion

# region Resources
notifications = template.add_resource(
    sns.Topic('Notifications',
              Subscription=[
                  sns.Subscription(Endpoint=Ref(email), Protocol='email'),
                  sns.Subscription(Endpoint=Ref(phone), Protocol='sms')
              ]))

main_domain_check = template.add_resource(
    route53.HealthCheck('MainDomainCheck',
                        HealthCheckConfig=route53.HealthCheckConfiguration(
                            EnableSNI=True,
                            FullyQualifiedDomainName=Ref(main_domain),
                            Port='443',
                            Type='HTTPS')))

main_domain_alarm = template.add_resource(
    cloudwatch.Alarm(
        'MainDomainAlarm',
        AlarmActions=[Ref(notifications)],
def GenerateStepPublisherLayer():
    t = Template()

    t.add_description("""\
    StepScheduler Layer
    """)

    stackname_param = t.add_parameter(
        Parameter(
            "StackName",
            Description="Environment Name (default: hackathon)",
            Type="String",
            Default="hackathon",
        ))

    vpcid_param = t.add_parameter(
        Parameter(
            "VpcId",
            Type="String",
            Description="VpcId of your existing Virtual Private Cloud (VPC)",
            Default="vpc-fab00e9f"))

    subnets = t.add_parameter(
        Parameter(
            "Subnets",
            Type="CommaDelimitedList",
            Description=(
                "The list SubnetIds, for public subnets in the "
                "region and in your Virtual Private Cloud (VPC) - minimum one"
            ),
            Default="subnet-b68f3bef,subnet-9a6208ff,subnet-bfdd4fc8"))

    keypair_param = t.add_parameter(
        Parameter("KeyPair",
                  Description="Name of an existing EC2 KeyPair to enable SSH "
                  "access to the instance",
                  Type="String",
                  Default="glueteam"))

    scheduler_ami_id_param = t.add_parameter(
        Parameter(
            "SchedulerAmiId",
            Description="Scheduler server AMI ID (default: ami-a10897d6)",
            Type="String",
            Default="ami-a10897d6"))

    cluster_ami_id_param = t.add_parameter(
        Parameter("ClusterAmiId",
                  Description="Cluster server AMI ID (default: ami-3db4ca4a)",
                  Type="String",
                  Default="ami-3db4ca4a"))

    iam_role_param = t.add_parameter(
        Parameter(
            "IamRole",
            Description="IAM Role name",
            Type="String",
        ))

    hashkeyname_param = t.add_parameter(
        Parameter(
            "HaskKeyElementName",
            Description="HashType PrimaryKey Name (default: id)",
            Type="String",
            AllowedPattern="[a-zA-Z0-9]*",
            MinLength="1",
            MaxLength="2048",
            ConstraintDescription="must contain only alphanumberic characters",
            Default="id"))

    crontab_tablename_param = t.add_parameter(
        Parameter(
            "CrontabTablename",
            Description="Crontab Table Name",
            Type="String",
        ))

    containerlauncher_param = t.add_parameter(
        Parameter(
            "Containerlauncher",
            Description=
            "Container Launcher zip file (default: containerLauncher-1.0.zip)",
            Type="String",
            Default="containerLauncher-1.0.zip"))

    zipfileversion_param = t.add_parameter(
        Parameter(
            "ZipfileVersion",
            Description="Container Launcher zip file version",
            Type="String",
        ))

    # --------- Lambda Container Launcher

    lambda_function = t.add_resource(
        Function(
            "containerLauncher",
            Code=Code(
                S3Bucket="hackathon-glueteam-lambda",
                S3Key=Ref(containerlauncher_param),
                S3ObjectVersion=Ref(zipfileversion_param),
            ),
            Description=Join('',
                             [Ref(stackname_param), " container Launcher"]),
            MemorySize=256,
            Handler="com.philips.glueteam.DockerLauncher::myHandler",
            Runtime="java8",
            Timeout=60,
            Role=Join('', [
                "arn:aws:iam::",
                Ref("AWS::AccountId"), ":role/",
                Ref(iam_role_param)
            ]),
        ))

    townclock_topic = t.add_resource(
        sns.Topic(
            "TownClock",
            Subscription=[
                sns.Subscription(Endpoint=GetAtt("containerLauncher", "Arn"),
                                 Protocol="lambda"),
            ],
        ))

    # --------- Scheduler instance

    scheduler_sg = t.add_resource(
        ec2.SecurityGroup(
            'SchedulerSG',
            GroupDescription='Security group for Scheduler host',
            VpcId=Ref(vpcid_param),
            Tags=Tags(Name=Join("", [Ref(stackname_param), "SchedulerSG"])),
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="8080",
                    ToPort="8080",
                    CidrIp="0.0.0.0/0",
                ),
            ]))

    cluster = t.add_resource(ecs.Cluster("ECSCluster", ))

    scheduler_host = t.add_resource(
        ec2.Instance(
            'SchedulerHost',
            ImageId=Ref(scheduler_ami_id_param),
            InstanceType='t2.micro',
            KeyName=Ref(keypair_param),
            IamInstanceProfile=Ref(iam_role_param),
            NetworkInterfaces=[
                ec2.NetworkInterfaceProperty(
                    AssociatePublicIpAddress=True,
                    SubnetId=Select(0, Ref(subnets)),
                    DeleteOnTermination=True,
                    GroupSet=[
                        Ref(scheduler_sg),
                    ],
                    DeviceIndex=0,
                ),
            ],
            Tags=Tags(Name=Join("", [Ref(stackname_param), "Scheduler"]),
                      Id=Join("", [Ref(stackname_param), "Scheduler"])),
            UserData=Base64(
                Join('', [
                    '#!/bin/bash\n',
                    'yum update -y aws-cfn-bootstrap\n',
                    'sns_topic_arn="',
                    Ref(townclock_topic),
                    '"\n',
                    'region="',
                    Ref("AWS::Region"),
                    '"\n',
                    'crontab_tablename="',
                    Ref(crontab_tablename_param),
                    '"\n',
                    'ecs_clustername="',
                    Ref(cluster),
                    '"\n',
                    'publish_source=https://raw.githubusercontent.com/hngkr/hackathon/master/ansible/files/unreliable-town-clock-publish\n',
                    'publish=/usr/local/bin/unreliable-town-clock-publish\n',
                    'curl -s --location --retry 10 -o $publish $publish_source\n',
                    'chmod +x $publish\n',
                    'cat <<EOF >/etc/cron.d/unreliable-town-clock\n',
                    '*/2 * * * * ec2-user $publish "$sns_topic_arn" "$region" "$crontab_tablename" "$ecs_clustername"\n',
                    'EOF\n',
                ])),
        ))

    cluster_sg = t.add_resource(
        ec2.SecurityGroup(
            'ClusterSG',
            GroupDescription='Security group for Cluster host',
            VpcId=Ref(vpcid_param),
            Tags=Tags(Name=Join("", [Ref(stackname_param), "ClusterSG"])),
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
            ]))

    cluster_host = t.add_resource(
        ec2.Instance(
            'ClusterHost',
            ImageId=Ref(cluster_ami_id_param),
            InstanceType='t2.micro',
            KeyName=Ref(keypair_param),
            # TODO: Should have multiple separate iam roles for townclock / clusterhost
            IamInstanceProfile=Ref(iam_role_param),
            NetworkInterfaces=[
                ec2.NetworkInterfaceProperty(
                    AssociatePublicIpAddress=True,
                    SubnetId=Select(0, Ref(subnets)),
                    DeleteOnTermination=True,
                    GroupSet=[
                        Ref(cluster_sg),
                    ],
                    DeviceIndex=0,
                ),
            ],
            Tags=Tags(Name=Join("", [Ref(stackname_param), "ClusterNode"]),
                      Id=Join("", [Ref(stackname_param), "ClusterNode"])),
            UserData=Base64(
                Join('', [
                    '#!/bin/bash\n',
                    'mkdir /etc/ecs\n',
                    'cat <<EOF >/etc/ecs/ecs.config\n',
                    'ECS_CLUSTER=',
                    Ref(cluster),
                    '\n',
                    'EOF\n',
                ])),
        ))

    # --------- Expected DynamoDB Tables

    dirtylist_table = t.add_resource(
        dynamodb.Table(
            "DirtyList",
            AttributeDefinitions=[
                dynamodb.AttributeDefinition(Ref(hashkeyname_param), "S"),
            ],
            KeySchema=[dynamodb.Key(Ref(hashkeyname_param), "HASH")],
            ProvisionedThroughput=dynamodb.ProvisionedThroughput(1, 1)))

    runlog_table = t.add_resource(
        dynamodb.Table(
            "RunLog",
            AttributeDefinitions=[
                dynamodb.AttributeDefinition(Ref(hashkeyname_param), "S"),
            ],
            KeySchema=[dynamodb.Key(Ref(hashkeyname_param), "HASH")],
            ProvisionedThroughput=dynamodb.ProvisionedThroughput(1, 1)))

    # --------- Outputs
    t.add_output(
        [Output(
            "clusterid",
            Description="Cluster Id",
            Value=Ref(cluster),
        )])

    t.add_output([
        Output(
            "dirtylist",
            Description="DirtyList Tablename",
            Value=Ref(dirtylist_table),
        )
    ])

    t.add_output([
        Output(
            "runlog",
            Description="Runlog Tablename",
            Value=Ref(runlog_table),
        )
    ])

    t.add_output([
        Output(
            "lambdafunctionname",
            Description="Lambda Function Name",
            Value=Ref(lambda_function),
        )
    ])

    t.add_output([
        Output(
            "clocktowertopicarn",
            Description="Clock Tower Topic Arn",
            Value=Ref(townclock_topic),
        )
    ])

    return t
from troposphere import sns, Ref

from stacks.parameters import email_address

emails_sns_topic = sns.Topic(
    "EmailsSNSTopic",
    Subscription=[
        sns.Subscription(Endpoint=Ref(email_address), Protocol="email")
    ],
)
Beispiel #10
0
    def build_template(self):

        t = self._init_template()

        # make iam policy
        policy = t.add_resource(
            iam.Role(
                "{}SlackSNSRole".format(self.stack_name),
                AssumeRolePolicyDocument=aws.Policy(Statement=[
                    aws.Statement(Action=[awacs.sts.AssumeRole],
                                  Effect=aws.Allow,
                                  Principal=aws.Principal(
                                      "Service", ["lambda.amazonaws.com"]))
                ]),
                Path="/",
                Policies=[
                    iam.Policy(
                        PolicyName='snspublic',
                        PolicyDocument=aws.PolicyDocument(Statement=[
                            aws.Statement(Effect=aws.Allow,
                                          Action=[
                                              awacs.sns.Publish,
                                              awacs.logs.PutLogEvents,
                                              awacs.logs.CreateLogGroup,
                                              awacs.logs.CreateLogStream,
                                          ],
                                          Resource=["*"])
                        ]))
                ],
                ManagedPolicyArns=[
                    # "arn:aws:iam::aws:policy/AdministratorAccess"
                ]))

        code = ["import sys"]
        # make lambda function
        fn = t.add_resource(
            awslambda.Function('{}SlackTopicFN'.format(self.stack_name),
                               Handler='index.handle',
                               Runtime='python3.6',
                               Role=GetAtt(policy, "Arn"),
                               Code=awslambda.Code(ZipFile=Join("", code))))

        topic = t.add_resource(
            sns.Topic(
                "{}SNSTopic".format(self.stack_name),
                TopicName=self.stack_name,
                DisplayName=self.stack_name,
                Subscription=[
                    sns.Subscription(Protocol='lambda',
                                     Endpoint=GetAtt(fn, "Arn"))
                ],
            ))

        t.add_resource(
            awslambda.Permission('{}LambdaPerm'.format(self.stack_name),
                                 Action='lambda:InvokeFunction',
                                 FunctionName=GetAtt(fn, "Arn"),
                                 SourceArn=Ref(topic),
                                 Principal="sns.amazonaws.com"))

        t.add_output(
            [Output("{}SNSTopic".format(self.stack_name), Value=Ref(topic))])

        return t
def get_template(version: str, default_region_value) -> t.Template:
    description = f"""Bootstrap template used to bootstrap a region of ServiceCatalog-Puppet master
{{"version": "{version}", "framework": "servicecatalog-puppet", "role": "bootstrap-master-region"}}"""

    template = t.Template(Description=description)

    version_parameter = template.add_parameter(
        t.Parameter("Version", Default=version, Type="String")
    )
    default_region_value_parameter = template.add_parameter(
        t.Parameter("DefaultRegionValue", Default=default_region_value, Type="String")
    )

    template.add_resource(
        ssm.Parameter(
            "DefaultRegionParam",
            Name="/servicecatalog-puppet/home-region",
            Type="String",
            Value=t.Ref(default_region_value_parameter),
            Tags={"ServiceCatalogPuppet:Actor": "Framework"},
        )
    )
    version_ssm_parameter = template.add_resource(
        ssm.Parameter(
            "Param",
            Name="service-catalog-puppet-regional-version",
            Type="String",
            Value=t.Ref(version_parameter),
            Tags={"ServiceCatalogPuppet:Actor": "Framework"},
        )
    )

    template.add_resource(
        s3.Bucket(
            "PipelineArtifactBucket",
            BucketName=t.Sub(
                "sc-puppet-pipeline-artifacts-${AWS::AccountId}-${AWS::Region}"
            ),
            VersioningConfiguration=s3.VersioningConfiguration(Status="Enabled"),
            BucketEncryption=s3.BucketEncryption(
                ServerSideEncryptionConfiguration=[
                    s3.ServerSideEncryptionRule(
                        ServerSideEncryptionByDefault=s3.ServerSideEncryptionByDefault(
                            SSEAlgorithm="AES256"
                        )
                    )
                ]
            ),
            PublicAccessBlockConfiguration=s3.PublicAccessBlockConfiguration(
                BlockPublicAcls=True,
                BlockPublicPolicy=True,
                IgnorePublicAcls=True,
                RestrictPublicBuckets=True,
            ),
            Tags=t.Tags({"ServiceCatalogPuppet:Actor": "Framework"}),
        )
    )

    regional_product_topic = template.add_resource(
        sns.Topic(
            "RegionalProductTopic",
            DisplayName="servicecatalog-puppet-cloudformation-regional-events",
            TopicName="servicecatalog-puppet-cloudformation-regional-events",
            Subscription=[
                sns.Subscription(
                    Endpoint=t.Sub(
                        "arn:${AWS::Partition}:sqs:${DefaultRegionValue}:${AWS::AccountId}:servicecatalog-puppet-cloudformation-events"
                    ),
                    Protocol="sqs",
                )
            ],
        ),
    )

    template.add_output(
        t.Output("Version", Value=t.GetAtt(version_ssm_parameter, "Value"))
    )
    template.add_output(
        t.Output("RegionalProductTopic", Value=t.Ref(regional_product_topic))
    )

    return template