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") ], )
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