Beispiel #1
0
def render_s3(context, template):
    for bucket_name in context['s3']:
        props = {
            'DeletionPolicy':
            context['s3'][bucket_name]['deletion-policy'].capitalize(),
            'Tags':
            s3.Tags(**aws.generic_tags(context, name=False)),
        }
        bucket_title = _sanitize_title(bucket_name) + "Bucket"
        if context['s3'][bucket_name]['cors']:
            # generic configuration for allowing read-only access
            props['CorsConfiguration'] = s3.CorsConfiguration(CorsRules=[
                s3.CorsRules(AllowedHeaders=['*'],
                             AllowedMethods=['GET', 'HEAD'],
                             AllowedOrigins=['*'])
            ])
        if context['s3'][bucket_name]['website-configuration']:
            index_document = context['s3'][bucket_name][
                'website-configuration'].get('index-document', 'index.html')
            props['WebsiteConfiguration'] = s3.WebsiteConfiguration(
                IndexDocument=index_document)
            _add_bucket_policy(template, bucket_title, bucket_name)

        if context['s3'][bucket_name]['public']:
            _add_bucket_policy(template, bucket_title, bucket_name)
            props['AccessControl'] = s3.PublicRead

        if context['s3'][bucket_name]['encryption']:
            props['BucketEncryption'] = _bucket_kms_encryption(
                context['s3'][bucket_name]['encryption'])

        template.add_resource(
            s3.Bucket(bucket_title, BucketName=bucket_name, **props))
Beispiel #2
0
    def add_bucket(self, name, access_control, static_site, route53,
                   public_hosted_zone):
        """
        Helper method creates a directory service resource
        @param name [string] Fully qualified name for the bucket
        (corp.example.com)
        @param access_control [string] type of access control for the bucket
        @param static_site [boolean] should the bucket host a static site
        @param route53 [boolean] create a route53 entry?
        """

        if route53:
            self.add_dns_alias(name, "s3-website-us-east-1.amazonaws.com",
                               "Z3AQBSTGFYJSTF", public_hosted_zone)

        if access_control == "PublicRead":
            policy = s3.BucketPolicy(name.replace('.', '') + "BucketPolicy",
                                     Bucket=name,
                                     PolicyDocument={
                                         "Statement": [{
                                             "Sid":
                                             "PublicReadForGetBucketObjects",
                                             "Effect":
                                             "Allow",
                                             "Principal":
                                             "*",
                                             "Action":
                                             "s3:GetObject",
                                             "Resource":
                                             "arn:aws:s3:::%s/*" % name
                                         }]
                                     })
            self.add_resource(policy)

        bucket = s3.Bucket(
            name.replace('.', '') + "Bucket",
            BucketName=name,
            AccessControl=access_control,
        )

        if static_site:
            web_config = s3.WebsiteConfiguration(IndexDocument='index.html')
            bucket.properties['WebsiteConfiguration'] = web_config

        return self.add_resource(bucket)
Beispiel #3
0
def render_s3(context, template):
    for bucket_name in context['s3']:
        props = {
            'DeletionPolicy':
            context['s3'][bucket_name]['deletion-policy'].capitalize()
        }
        bucket_title = _sanitize_title(bucket_name) + "Bucket"
        if context['s3'][bucket_name]['cors']:
            # generic configuration for allowing read-only access
            props['CorsConfiguration'] = s3.CorsConfiguration(CorsRules=[
                s3.CorsRules(AllowedHeaders=['*'],
                             AllowedMethods=['GET', 'HEAD'],
                             AllowedOrigins=['*'])
            ])
        if context['s3'][bucket_name]['website-configuration']:
            index_document = context['s3'][bucket_name][
                'website-configuration'].get('index-document', 'index.html')
            props['WebsiteConfiguration'] = s3.WebsiteConfiguration(
                IndexDocument=index_document)
            template.add_resource(
                s3.BucketPolicy("%sPolicy" % bucket_title,
                                Bucket=bucket_name,
                                PolicyDocument={
                                    "Version":
                                    "2012-10-17",
                                    "Statement": [{
                                        "Sid":
                                        "AddPerm",
                                        "Effect":
                                        "Allow",
                                        "Principal":
                                        "*",
                                        "Action": ["s3:GetObject"],
                                        "Resource":
                                        ["arn:aws:s3:::%s/*" % bucket_name]
                                    }]
                                }))
        template.add_resource(
            s3.Bucket(bucket_title, BucketName=bucket_name, **props))
Beispiel #4
0
def S3_Buckets(key):
    global bucket_name

    for n, v in getattr(cfg, key).items():
        resname = f"{key}{n}"
        name = n
        bucket_name = getattr(cfg, f"{key}Name{n}")

        ## Policy Read
        PolicyReadConditions = []
        PolicyReadPrincipal = []
        for m, w in v["AccountsRead"].items():
            accountread_name = f"{resname}AccountsRead{m}"
            # conditions
            add_obj(get_condition(accountread_name, "not_equals", "none"))

            PolicyReadConditions.append(Condition(accountread_name))
            PolicyReadPrincipal.append(
                If(
                    accountread_name,
                    get_subvalue("arn:aws:iam::${1M}:root", accountread_name),
                    Ref("AWS::NoValue"),
                ))
        # conditions
        if PolicyReadConditions:
            c_PolicyRead = {
                f"{resname}PolicyRead":
                Or(Equals("1", "0"), Equals("1", "0"), *PolicyReadConditions)
            }
        else:
            c_PolicyRead = {f"{resname}PolicyRead": Equals("True", "False")}

        ## Policy Write
        PolicyWriteConditions = []
        PolicyWritePrincipal = []
        for m, w in v["AccountsWrite"].items():
            accountwrite_name = f"{resname}AccountsWrite{m}"
            # conditions
            add_obj(get_condition(accountwrite_name, "not_equals", "none"))

            PolicyWriteConditions.append(Condition(accountwrite_name))
            PolicyWritePrincipal.append(
                If(
                    accountwrite_name,
                    get_subvalue("arn:aws:iam::${1M}:root", accountwrite_name),
                    Ref("AWS::NoValue"),
                ))
        # conditions
        if PolicyWriteConditions:
            c_PolicyWrite = {
                f"{resname}PolicyWrite":
                Or(Equals("1", "0"), Equals("1", "0"), *PolicyWriteConditions)
            }
        else:
            c_PolicyWrite = {f"{resname}PolicyWrite": Equals("True", "False")}

        ## Policy Delete
        PolicyDeleteConditions = []
        PolicyDeletePrincipal = []
        for m, w in v["AccountsDelete"].items():
            accountwrite_name = f"{resname}AccountsDelete{m}"
            # conditions
            add_obj(get_condition(accountwrite_name, "not_equals", "none"))

            PolicyDeleteConditions.append(Condition(accountwrite_name))
            PolicyDeletePrincipal.append(
                If(
                    accountwrite_name,
                    get_subvalue("arn:aws:iam::${1M}:root", accountwrite_name),
                    Ref("AWS::NoValue"),
                ))
        # conditions
        if PolicyDeleteConditions:
            c_PolicyDelete = {
                f"{resname}PolicyDelete":
                Or(Equals("1", "0"), Equals("1", "0"), *PolicyDeleteConditions)
            }
        else:
            c_PolicyDelete = {
                f"{resname}PolicyDelete": Equals("True", "False")
            }

        c_Create = get_condition(resname, "equals", "yes", f"{resname}Create")

        c_Versioning = get_condition(f"{resname}Versioning", "equals",
                                     "Enabled")

        c_Cors = get_condition(f"{resname}Cors", "equals", "yes")

        c_Replica = {
            f"{resname}Replica":
            And(
                Condition(resname),
                get_condition("", "equals", "yes",
                              f"{resname}ReplicationEnabled"),
            )
        }
        c_ReplicaPolicyStatement = get_condition(
            f"{resname}PolicyStatementReplicaPrincipal", "not_equals", "none")

        add_obj([
            c_PolicyRead,
            c_PolicyWrite,
            c_PolicyDelete,
            c_Create,
            c_Versioning,
            c_Cors,
            c_Replica,
            c_ReplicaPolicyStatement,
        ])

        # resources
        r_Bucket = S3Bucket(resname, key=v)

        Replica_Rules = []
        for m, w in v["Replication"]["ConfigurationRules"].items():
            replica_name = f"{resname}ReplicationConfigurationRules{m}"

            # parameters
            p_replicabucket = Parameter(
                f"{replica_name}DestinationBucket",
                Description=
                "Replica Destination Bucket - empty for default based on Env/Roles/Region",
            )
            add_obj(p_replicabucket)

            # conditions
            add_obj([
                get_condition(f"{replica_name}DestinationBucket", "not_equals",
                              "none")
            ])

            # resources
            rule = s3.ReplicationConfigurationRules(replica_name,
                                                    Status="Enabled")
            auto_get_props(rule)

            Replica_Rules.append(
                If(f"{replica_name}DestinationBucket", rule,
                   Ref("AWS::NoValue")))

        if Replica_Rules:
            ReplicationConfiguration = s3.ReplicationConfiguration(
                "",
                Role=GetAtt(f"Role{resname}Replica", "Arn"),
                Rules=Replica_Rules)
            r_Bucket.ReplicationConfiguration = If(f"{resname}Replica",
                                                   ReplicationConfiguration,
                                                   Ref("AWS::NoValue"))

        PolicyStatementReplicaResources = []
        for m, w in v["PolicyStatementReplica"]["Resource"].items():
            polstatname = f"{resname}PolicyStatementReplicaResource{m}"
            # conditions
            add_obj(get_condition(f"{polstatname}Prefix", "not_equals",
                                  "none"))

            PolicyStatementReplicaResources.append(
                If(
                    f"{polstatname}Prefix",
                    get_subvalue("arn:aws:s3:::%s/${1M}*" % bucket_name,
                                 f"{polstatname}Prefix"),
                    Ref("AWS::NoValue"),
                ))

        BucketPolicyStatement = []

        r_Policy = S3BucketPolicy(
            f"BucketPolicy{name}",
            key=v,
            Condition=resname,
            Bucket=Ref(resname),
        )
        r_Policy.PolicyDocument["Statement"] = BucketPolicyStatement

        BucketPolicyStatement.extend([
            # At least one statement must be always present, create a simple one with no conditions
            S3BucketPolicyStatementBase(resname),
            S3BucketPolicyStatementReplica(resname,
                                           PolicyStatementReplicaResources),
            S3BucketPolicyStatementRead(resname, PolicyReadPrincipal),
            S3BucketPolicyStatementWrite(resname, PolicyWritePrincipal),
            S3BucketPolicyStatementDelete(resname, PolicyDeletePrincipal),
        ])

        r_IAMPolicyReplica = IAMPolicyBucketReplica(
            f"IAMPolicyReplicaBucket{name}",
            bucket=resname,
            bucket_name=bucket_name,
            mapname=f"{resname}ReplicationConfigurationRules",
            key=v["Replication"]["ConfigurationRules"],
        )

        try:
            bucket_policies = getattr(cfg, "BucketPolicy")
        except Exception:
            pass
        else:
            for policy_name, policy_value in bucket_policies.items():
                BucketPolicyStatement.append(get_dictvalue(policy_value))

        if "WebsiteConfiguration" in v:
            r_Bucket.WebsiteConfiguration = s3.WebsiteConfiguration(
                f"{resname}WebsiteConfiguration")
            auto_get_props(r_Bucket.WebsiteConfiguration)

        if "PolicyStatement" in v:
            FixedStatements = []
            for fsn, fsv in v["PolicyStatement"].items():
                FixedStatement = IAMPolicyStatement(fsv)
                FixedStatement["Principal"] = {"AWS": eval(fsv["Principal"])}
                FixedStatement["Sid"] = fsv["Sid"]
                FixedStatements.append(FixedStatement)
            BucketPolicyStatement.extend(FixedStatements)

        if "PolicyStatementExGetObjectPrincipal" in v:
            BucketPolicyStatement.append(
                S3BucketPolicyStatementAllowGetObject(
                    resname,
                    get_endvalue(
                        f"{resname}PolicyStatementExGetObjectPrincipal"),
                    "AllowGetObjectExPrincipal",
                ))

        PolicyCloudFrontOriginAccessIdentityPrincipal = []
        if "CloudFrontOriginAccessIdentity" in v:
            identityname = v["CloudFrontOriginAccessIdentity"]
            identityresname = f"CloudFrontOriginAccessIdentity{identityname}"

            PolicyCloudFrontOriginAccessIdentityPrincipal.append(
                Sub("arn:aws:iam::cloudfront:user/"
                    "CloudFront Origin Access Identity ${%s}" %
                    identityresname))

            for ixn, ixv in v["CloudFrontOriginAccessIdentityExtra"].items():
                ixname = f"{resname}CloudFrontOriginAccessIdentityExtra{ixn}"
                # conditions
                add_obj(get_condition(ixname, "not_equals", "none"))

                PolicyCloudFrontOriginAccessIdentityPrincipal.append(
                    If(
                        ixname,
                        get_subvalue(
                            "arn:aws:iam::cloudfront:user/"
                            "CloudFront Origin Access Identity ${1M}",
                            ixname,
                        ),
                        Ref("AWS::NoValue"),
                    ))

            # conditions
            identitycondname = f"{resname}CloudFrontOriginAccessIdentity"
            c_identity = {
                identitycondname:
                And(
                    Condition(resname),
                    get_condition("", "not_equals", "none", identitycondname),
                )
            }

            add_obj(c_identity)

            # resources
            BucketPolicyStatement.append(
                S3BucketPolicyStatementAllowGetObject(
                    resname,
                    PolicyCloudFrontOriginAccessIdentityPrincipal,
                    "AllowCFAccess",
                ))

            r_OriginAccessIdentity = CFOriginAccessIdentity(
                identityresname,
                comment=identityname,
                Condition=identitycondname)

            add_obj(r_OriginAccessIdentity)

            # outputs
            o_OriginAccessIdentity = Output(identityresname,
                                            Value=Ref(identityresname),
                                            Condition=identitycondname)

            add_obj(o_OriginAccessIdentity)

        add_obj([r_Bucket, r_Policy, r_IAMPolicyReplica])

        # outputs
        o_Bucket = Output(resname)
        outvalue = If(resname, Ref(resname), Sub(bucket_name))
        if "OutputValueRegion" in v:
            condname = f"{resname}OutputValueRegion"
            # conditions
            add_obj(get_condition(condname, "not_equals", "AWSRegion"))

            outvalue = If(
                condname,
                Sub(
                    "${Region}-%s" %
                    bucket_name.replace("${AWS::Region}-", "", 1),
                    **{"Region": get_endvalue(condname)},
                ),
                outvalue,
            )
            o_Bucket.Export = Export(resname)
        else:
            o_Bucket.Condition = resname

        o_Bucket.Value = outvalue

        add_obj([o_Bucket])
Beispiel #5
0
from troposphere import Template, Output, GetAtt
import troposphere.s3 as s3

t = Template()

s3bucket = t.add_resource(s3.Bucket(
  'S3Bucket',
  AccessControl=s3.PublicRead,
  WebsiteConfiguration=s3.WebsiteConfiguration(
    IndexDocument='index.html',
    ErrorDocument='error.html'
  )
))

t.add_output(
  Output(
    'WebsiteURL',
    Value=GetAtt(s3bucket, 'WebsiteURL'),
    Description='URL for website hosted on S3'
  )
)

print(t.to_yaml())
Beispiel #6
0
    ))

error_page = template.add_parameter(
    Parameter(
        'WebsitePageError',
        Type=c.STRING,
        Default='error.html',
        Description='Error page for your site',
    ))

root_bucket = template.add_resource(
    s3.Bucket('RootBucket',
              AccessControl=s3.PublicRead,
              BucketName=Ref(domain),
              WebsiteConfiguration=s3.WebsiteConfiguration(
                  IndexDocument=Ref(index_page),
                  ErrorDocument=Ref(error_page),
              )))
root_bucket_arn = Join('', ['arn:aws:s3:::', Ref(root_bucket), '/*'])

template.add_resource(
    s3.BucketPolicy('RootBucketPolicy',
                    Bucket=Ref(root_bucket),
                    PolicyDocument={
                        'Statement': [{
                            'Action': ['s3:GetObject'],
                            'Effect': 'Allow',
                            'Resource': root_bucket_arn,
                            'Principal': '*',
                        }]
                    }))
Beispiel #7
0
def generate_cf_template():
    """
    Returns an entire CloudFormation stack by using troposphere to construct
    each piece
    """
    # Header of CloudFormation template
    t = Template()
    t.add_version("2010-09-09")
    t.add_description("Lambda Chat AWS Resources")
    # Paramters
    description = "should match [0-9]+-[a-z0-9]+.apps.googleusercontent.com"
    google_oauth_client_id = t.add_parameter(Parameter(
        "GoogleOAuthClientID",
        AllowedPattern="[0-9]+-[a-z0-9]+.apps.googleusercontent.com",
        Type="String",
        Description="The Client ID of your Google project",
        ConstraintDescription=description
    ))

    website_s3_bucket_name = t.add_parameter(Parameter(
        "WebsiteS3BucketName",
        AllowedPattern="[a-zA-Z0-9\-]*",
        Type="String",
        Description="Name of S3 bucket to store the website in",
        ConstraintDescription="can contain only alphanumeric characters and dashes.",
    ))

    # The SNS topic the website will publish chat messages to
    website_sns_topic = t.add_resource(sns.Topic(
        'WebsiteSnsTopic',
        TopicName='lambda-chat',
        DisplayName='Lambda Chat'
    ))
    t.add_output(Output(
        "WebsiteSnsTopic",
        Description="sns_topic_arn",
        Value=Ref(website_sns_topic),
    ))

    # The IAM Role and Policy the website will assume to publish to SNS
    website_role = t.add_resource(iam.Role(
        "WebsiteRole",
        Path="/",
        AssumeRolePolicyDocument=Policy(
            Statement=[
                Statement(
                    Effect=Allow,
                    Action=[Action("sts", "AssumeRoleWithWebIdentity")],
                    Principal=Principal("Federated", "accounts.google.com"),
                    Condition=Condition(
                        StringEquals(
                            "accounts.google.com:aud",
                            Ref(google_oauth_client_id)
                        )
                    ),
                ),
            ],
        ),
    ))
    t.add_resource(iam.PolicyType(
        "WebsitePolicy",
        PolicyName="lambda-chat-website-policy",
        Roles=[Ref(website_role)],
        PolicyDocument=Policy(
            Version="2012-10-17",
            Statement=[
                Statement(
                    Effect=Allow,
                    Action=[Action("sns", "Publish")],
                    Resource=[
                        Ref(website_sns_topic)
                    ],
                ),
            ],
        )
    ))
    t.add_output(Output(
        "WebsiteRole",
        Description="website_iam_role_arn",
        Value=GetAtt(website_role, "Arn"),
    ))

    website_bucket = t.add_resource(s3.Bucket(
        'WebsiteS3Bucket',
        BucketName=Ref(website_s3_bucket_name),
        WebsiteConfiguration=s3.WebsiteConfiguration(
            ErrorDocument="error.html",
            IndexDocument="index.html"
        )
    ))
    t.add_output(Output(
        "S3Bucket",
        Description="s3_bucket",
        Value=Ref(website_bucket),
    ))
    t.add_resource(s3.BucketPolicy(
        'WebsiteS3BucketPolicy',
        Bucket=Ref(website_bucket),
        PolicyDocument={
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "PublicAccess",
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": ["s3:GetObject"],
                    "Resource": [{
                        "Fn::Join": [
                            "",
                            [
                                "arn:aws:s3:::",
                                {
                                    "Ref": "WebsiteS3Bucket",
                                },
                                "/*"
                            ]
                        ]
                    }]
                }
            ]
        }
    ))

    return t
              Type='String',
              Default='error.html',
              Description='The name of the error document for the website.'))

#
# Resource
#

bucket = t.add_resource(
    s3.Bucket(
        'Bucket',
        BucketName=Join('.',
                        [Ref(param_domain_name),
                         Ref(param_hosted_domain)]),
        WebsiteConfiguration=s3.WebsiteConfiguration(
            IndexDocument=Ref(param_index_doc),
            ErrorDocument=Ref(param_error_doc),
        ),
    ))

bucket_policy = t.add_resource(
    s3.BucketPolicy(
        'BucketPolicy',
        Bucket=Ref(bucket),
        PolicyDocument={
            'Version':
            '2012-10-17',
            'Statement': [{
                'Sid': 'PublicReadGetObject',
                'Effect': 'Allow',
                'Principal': '*',
                'Action': ['s3:GetObject'],
Beispiel #9
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_description('Static Website - Bucket and Distribution')

        # Conditions
        template.add_condition(
            'AcmCertSpecified',
            And(Not(Equals(variables['AcmCertificateArn'].ref, '')),
                Not(Equals(variables['AcmCertificateArn'].ref, 'undefined'))))
        template.add_condition(
            'AliasesSpecified',
            And(Not(Equals(Select(0, variables['Aliases'].ref), '')),
                Not(Equals(Select(0, variables['Aliases'].ref), 'undefined'))))
        template.add_condition(
            'CFLoggingEnabled',
            And(Not(Equals(variables['LogBucketName'].ref, '')),
                Not(Equals(variables['LogBucketName'].ref, 'undefined'))))
        template.add_condition(
            'DirectoryIndexSpecified',
            And(Not(Equals(variables['RewriteDirectoryIndex'].ref, '')),
                Not(Equals(variables['RewriteDirectoryIndex'].ref,
                           'undefined')))  # noqa
        )
        template.add_condition(
            'WAFNameSpecified',
            And(Not(Equals(variables['WAFWebACL'].ref, '')),
                Not(Equals(variables['WAFWebACL'].ref, 'undefined'))))

        # Resources
        oai = template.add_resource(
            cloudfront.CloudFrontOriginAccessIdentity(
                'OAI',
                CloudFrontOriginAccessIdentityConfig=cloudfront.
                CloudFrontOriginAccessIdentityConfig(  # noqa pylint: disable=line-too-long
                    Comment='CF access to website')))

        bucket = template.add_resource(
            s3.Bucket(
                'Bucket',
                AccessControl=s3.Private,
                LifecycleConfiguration=s3.LifecycleConfiguration(Rules=[
                    s3.LifecycleRule(NoncurrentVersionExpirationInDays=90,
                                     Status='Enabled')
                ]),
                VersioningConfiguration=s3.VersioningConfiguration(
                    Status='Enabled'),
                WebsiteConfiguration=s3.WebsiteConfiguration(
                    IndexDocument='index.html', ErrorDocument='error.html')))
        template.add_output(
            Output('BucketName',
                   Description='Name of website bucket',
                   Value=bucket.ref()))

        allowcfaccess = template.add_resource(
            s3.BucketPolicy(
                'AllowCFAccess',
                Bucket=bucket.ref(),
                PolicyDocument=PolicyDocument(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Action=[awacs.s3.GetObject],
                            Effect=Allow,
                            Principal=Principal(
                                'CanonicalUser',
                                oai.get_att('S3CanonicalUserId')),
                            Resource=[Join('', [bucket.get_att('Arn'), '/*'])])
                    ])))

        cfdirectoryindexrewriterole = template.add_resource(
            iam.Role('CFDirectoryIndexRewriteRole',
                     Condition='DirectoryIndexSpecified',
                     AssumeRolePolicyDocument=PolicyDocument(
                         Version='2012-10-17',
                         Statement=[
                             Statement(Effect=Allow,
                                       Action=[awacs.sts.AssumeRole],
                                       Principal=Principal(
                                           'Service', [
                                               'lambda.amazonaws.com',
                                               'edgelambda.amazonaws.com'
                                           ]))
                         ]),
                     ManagedPolicyArns=[
                         IAM_ARN_PREFIX + 'AWSLambdaBasicExecutionRole'
                     ]))

        cfdirectoryindexrewrite = template.add_resource(
            awslambda.Function(
                'CFDirectoryIndexRewrite',
                Condition='DirectoryIndexSpecified',
                Code=awslambda.Code(ZipFile=Join(
                    '',
                    [
                        "'use strict';\n",
                        "exports.handler = (event, context, callback) => {\n",
                        "\n",
                        "    // Extract the request from the CloudFront event that is sent to Lambda@Edge\n",  # noqa pylint: disable=line-too-long
                        "    var request = event.Records[0].cf.request;\n",
                        "    // Extract the URI from the request\n",
                        "    var olduri = request.uri;\n",
                        "    // Match any '/' that occurs at the end of a URI. Replace it with a default index\n",  # noqa pylint: disable=line-too-long
                        "    var newuri = olduri.replace(/\\/$/, '\\/",
                        variables['RewriteDirectoryIndex'].ref,
                        "');\n",  # noqa
                        "    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin\n",  # noqa pylint: disable=line-too-long
                        "    console.log(\"Old URI: \" + olduri);\n",
                        "    console.log(\"New URI: \" + newuri);\n",
                        "    // Replace the received URI with the URI that includes the index page\n",  # noqa pylint: disable=line-too-long
                        "    request.uri = newuri;\n",
                        "    // Return to CloudFront\n",
                        "    return callback(null, request);\n",
                        "\n",
                        "};\n"
                    ])),
                Description=
                'Rewrites CF directory HTTP requests to default page',  # noqa
                Handler='index.handler',
                Role=cfdirectoryindexrewriterole.get_att('Arn'),
                Runtime='nodejs8.10'))

        # Generating a unique resource name here for the Lambda version, so it
        # updates automatically if the lambda code changes
        code_hash = hashlib.md5(
            str(cfdirectoryindexrewrite.properties['Code'].
                properties['ZipFile'].to_dict()).encode()  # noqa pylint: disable=line-too-long
        ).hexdigest()

        cfdirectoryindexrewritever = template.add_resource(
            awslambda.Version('CFDirectoryIndexRewriteVer' + code_hash,
                              Condition='DirectoryIndexSpecified',
                              FunctionName=cfdirectoryindexrewrite.ref()))

        cfdistribution = template.add_resource(
            cloudfront.Distribution(
                'CFDistribution',
                DependsOn=allowcfaccess.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    Aliases=If('AliasesSpecified', variables['Aliases'].ref,
                               NoValue),
                    Origins=[
                        cloudfront.Origin(
                            DomainName=Join(
                                '.', [bucket.ref(), 's3.amazonaws.com']),
                            S3OriginConfig=cloudfront.S3Origin(
                                OriginAccessIdentity=Join(
                                    '', [
                                        'origin-access-identity/cloudfront/',
                                        oai.ref()
                                    ])),
                            Id='S3Origin')
                    ],
                    DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                        AllowedMethods=['GET', 'HEAD'],
                        Compress=False,
                        DefaultTTL='86400',
                        ForwardedValues=cloudfront.ForwardedValues(
                            Cookies=cloudfront.Cookies(Forward='none'),
                            QueryString=False,
                        ),
                        LambdaFunctionAssociations=If(
                            'DirectoryIndexSpecified',
                            [
                                cloudfront.LambdaFunctionAssociation(
                                    EventType='origin-request',
                                    LambdaFunctionARN=cfdirectoryindexrewritever
                                    .ref()  # noqa
                                )
                            ],
                            NoValue),
                        TargetOriginId='S3Origin',
                        ViewerProtocolPolicy='redirect-to-https'),
                    DefaultRootObject='index.html',
                    Logging=If(
                        'CFLoggingEnabled',
                        cloudfront.Logging(Bucket=Join('.', [
                            variables['LogBucketName'].ref, 's3.amazonaws.com'
                        ])), NoValue),
                    PriceClass=variables['PriceClass'].ref,
                    Enabled=True,
                    WebACLId=If('WAFNameSpecified', variables['WAFWebACL'].ref,
                                NoValue),
                    ViewerCertificate=If(
                        'AcmCertSpecified',
                        cloudfront.ViewerCertificate(
                            AcmCertificateArn=variables['AcmCertificateArn'].
                            ref,  # noqa
                            SslSupportMethod='sni-only'),
                        NoValue))))
        template.add_output(
            Output('CFDistributionId',
                   Description='CloudFront distribution ID',
                   Value=cfdistribution.ref()))
        template.add_output(
            Output('CFDistributionDomainName',
                   Description='CloudFront distribution domain name',
                   Value=cfdistribution.get_att('DomainName')))
Beispiel #10
0
    def _build_template(self, template):

        t = template
        s3b = t.add_resource(s3.Bucket(self.name))

        if self.public_read:
            s3b.AccessControl = s3.PublicRead
            t.add_resource(
                s3.BucketPolicy('{}BucketPolicy'.format(self.name),
                                Bucket=Ref(s3b),
                                PolicyDocument={
                                    "Statement": [{
                                        "Action": ["s3:GetObject"],
                                        "Effect":
                                        "Allow",
                                        "Resource":
                                        Join('',
                                             ["arn:aws:s3:::",
                                              Ref(s3b), "/*"]),
                                        "Principal":
                                        "*"
                                    }]
                                }))

        versioning = "Suspended"

        if self.versioning:
            versioning = "Enabled"

        s3b.VersioningConfiguration = s3.VersioningConfiguration(
            Status=versioning)

        if self.website_mode:
            s3b.WebsiteConfiguration = s3.WebsiteConfiguration(
                **self.website_config)

        if self.cors_enabled is True \
                and len(self.cors_rules) <= 0:
            self.add_cors_rule("CorsAll", ['*'], ['GET', 'POST', 'PUT'], ['*'],
                               3000)

        if len(self.cors_rules) > 0:
            cors = s3.CorsConfiguration(CorsRules=self.cors_rules)
            s3b.CorsConfiguration = cors

        if len(self.lifecycle_rules) > 0:
            s3b.LifecycleConfiguration = s3.LifecycleConfiguration(Rules=[])
            for lcr in self.lifecycle_rules:
                s3b.LifecycleConfiguration.Rules.append(lcr)

        t.add_output([
            Output("{}BucketName".format(self.name),
                   Value=Ref(s3b),
                   Description="{} Bucket Name".format(self.name)),
            Output("{}BucketUrl".format(self.name),
                   Value=GetAtt(s3b, "DomainName"),
                   Description="{} Bucket Name".format(self.name)),
            Output('{}WebsiteUrl'.format(self.name),
                   Value=GetAtt(s3b, 'WebsiteURL'))
        ])

        return s3b
Beispiel #11
0
    def __init__(self, key):
        global bucket_name

        for n, v in getattr(cfg, key).items():
            resname = f'{key}{n}'
            name = n
            if not ('Enabled' in v and v['Enabled'] is True):
                continue
            bucket_name = getattr(cfg, resname)
            # parameters
            p_ReplicaDstRegion = Parameter(f'{resname}ReplicaDstRegion')
            p_ReplicaDstRegion.Description = (
                'Region to Replicate Bucket - None to disable - '
                'empty for default based on env/role')
            p_ReplicaDstRegion.AllowedValues = ['', 'None'] + cfg.regions

            add_obj(p_ReplicaDstRegion)

            PolicyReadConditions = []
            PolicyReadPrincipal = []

            for m, w in v['AccountsRead'].items():
                accountread_name = f'{resname}AccountsRead{m}'
                # conditions
                add_obj(get_condition(accountread_name, 'not_equals', 'None'))

                PolicyReadConditions.append(Condition(accountread_name))
                PolicyReadPrincipal.append(
                    If(
                        accountread_name,
                        get_subvalue('arn:aws:iam::${1M}:root',
                                     accountread_name), Ref('AWS::NoValue')))

            # conditions
            if PolicyReadConditions:
                c_PolicyRead = {
                    f'{resname}PolicyRead':
                    Or(Equals('1', '0'), Equals('1', '0'),
                       *PolicyReadConditions)
                }
            else:
                c_PolicyRead = {
                    f'{resname}PolicyRead': Equals('True', 'False')
                }

            PolicyWriteConditions = []
            PolicyWritePrincipal = []

            for m, w in v['AccountsWrite'].items():
                accountwrite_name = f'{resname}AccountsWrite{m}'
                # conditions
                add_obj(get_condition(accountwrite_name, 'not_equals', 'None'))

                PolicyWriteConditions.append(Condition(accountwrite_name))
                PolicyWritePrincipal.append(
                    If(
                        accountwrite_name,
                        get_subvalue('arn:aws:iam::${1M}:root',
                                     accountwrite_name), Ref('AWS::NoValue')))

            # conditions
            if PolicyWriteConditions:
                c_PolicyWrite = {
                    f'{resname}PolicyWrite':
                    Or(Equals('1', '0'), Equals('1', '0'),
                       *PolicyWriteConditions)
                }
            else:
                c_PolicyWrite = {
                    f'{resname}PolicyWrite': Equals('True', 'False')
                }

            c_Create = get_condition(resname, 'not_equals', 'None',
                                     f'{resname}Create')

            c_Versioning = get_condition(f'{resname}Versioning', 'not_equals',
                                         'None')

            c_Cors = get_condition(f'{resname}Cors', 'not_equals', 'None')

            c_ReplicaSrcAccount = get_condition(f'{resname}ReplicaSrcAccount',
                                                'not_equals', 'None')

            c_ReplicaDstOwner = get_condition(f'{resname}ReplicaDstOwner',
                                              'not_equals', 'None')

            # c_AccountRO = get_condition(
            #    f'{resname}AccountRO', 'not_equals', 'None')

            c_Replica = {
                f'{resname}Replica':
                And(
                    Condition(resname),
                    get_condition('', 'not_equals', 'None',
                                  f'{resname}ReplicaDstRegion'))
            }

            add_obj([
                c_PolicyRead,
                c_PolicyWrite,
                c_Create,
                c_Versioning,
                c_Cors,
                c_ReplicaSrcAccount,
                c_ReplicaDstOwner,
                c_Replica,
            ])

            # resources
            BucketPolicyStatement = []

            r_Bucket = S3Bucket(resname, key=v)

            r_Policy = S3BucketPolicy(f'BucketPolicy{name}', key=v)
            r_Policy.Condition = resname
            r_Policy.Bucket = Sub(bucket_name)
            r_Policy.PolicyDocument['Statement'] = BucketPolicyStatement

            # At least one statement must be always present,
            # create a simple one with no conditions
            BucketPolicyStatement.extend(S3BucketPolicyStatementBase(resname))

            BucketPolicyStatement.extend(
                S3BucketPolicyStatementReplica(resname, v))

            r_Role = IAMRoleBucketReplica(f'Role{resname}Replica')

            BucketPolicyStatement.extend(
                S3BucketPolicyStatementRead(resname, PolicyReadPrincipal))

            BucketPolicyStatement.extend(
                S3BucketPolicyStatementWrite(resname, PolicyWritePrincipal))

            r_IAMPolicyReplica = IAMPolicyBucketReplica(
                f'IAMPolicyReplicaBucket{name}',
                bucket=resname,
                bucket_name=bucket_name,
                key=v)

            try:
                lambda_arn = eval(
                    v['NotificationConfiguration']['LambdaConfigurations']
                    ['Trigger']['Function'])
            except:
                pass
            else:
                if 'Fn::GettAtt' in lambda_arn.data:
                    permname = '%s%s' % (
                        lambda_arn.data['Fn::GettAtt'].replace(
                            'Lambda', 'LambdaPermission'), resname)
                else:
                    permname = 'LambdaPermission'

                r_LambdaPermission = LambdaPermissionS3(permname,
                                                        key=lambda_arn,
                                                        source=resname)

                add_obj(r_LambdaPermission)

                BucketPolicyStatement.extend(
                    S3BucketPolicyStatementSes(resname))

            if 'WebsiteConfiguration' in v:
                r_Bucket.WebsiteConfiguration = s3.WebsiteConfiguration(
                    f'{resname}WebsiteConfiguration')
                auto_get_props(r_Bucket.WebsiteConfiguration,
                               v['WebsiteConfiguration'],
                               recurse=True)

            if 'PolicyStatement' in v:
                FixedStatements = []
                for fsn, fsv in v['PolicyStatement'].items():
                    FixedStatement = IAMPolicyStatement(fsv)
                    FixedStatement['Principal'] = {
                        'AWS': eval(fsv['Principal'])
                    }
                    FixedStatement['Sid'] = fsv['Sid']
                    FixedStatements.append(FixedStatement)
                BucketPolicyStatement.extend(FixedStatements)

            PolicyCloudFrontOriginAccessIdentityPrincipal = []
            if 'CloudFrontOriginAccessIdentity' in v:
                identityname = v['CloudFrontOriginAccessIdentity']
                identityresname = (
                    f'CloudFrontOriginAccessIdentity{identityname}')

                PolicyCloudFrontOriginAccessIdentityPrincipal.append(
                    Sub('arn:aws:iam::cloudfront:user/'
                        'CloudFront Origin Access Identity ${%s}' %
                        identityresname))

                for ixn, ixv in (
                        v['CloudFrontOriginAccessIdentityExtra'].items()):
                    ixname = (
                        f'{resname}CloudFrontOriginAccessIdentityExtra{ixn}')
                    # conditions
                    add_obj(get_condition(ixname, 'not_equals', 'None'))

                    PolicyCloudFrontOriginAccessIdentityPrincipal.append(
                        If(
                            ixname,
                            get_subvalue(
                                'arn:aws:iam::cloudfront:user/'
                                'CloudFront Origin Access Identity ${1M}',
                                ixname), Ref('AWS::NoValue')))

                # conditions
                identitycondname = f'{resname}CloudFrontOriginAccessIdentity'
                c_identity = get_condition(identitycondname, 'not_equals',
                                           'None')

                add_obj(c_identity)

                # resources
                BucketPolicyStatement.extend(
                    S3BucketPolicyStatementCFOriginAccessIdentity(
                        resname,
                        PolicyCloudFrontOriginAccessIdentityPrincipal))

                r_OriginAccessIdentity = CFOriginAccessIdentity(
                    identityresname, comment=identityname)
                r_OriginAccessIdentity.Condition = identitycondname

                add_obj([
                    r_OriginAccessIdentity,
                ])

                # outputs
                o_OriginAccessIdentity = Output(identityresname)
                o_OriginAccessIdentity.Value = Ref(identityresname)
                o_OriginAccessIdentity.Condition = identitycondname

                add_obj(o_OriginAccessIdentity)

            add_obj([
                r_Bucket,
                r_Policy,
                # r_PolicyReplica,
                # r_PolicyRO,
                r_IAMPolicyReplica,
                r_Role
            ])

            # outputs
            outvaluebase = Sub(bucket_name)
            if 'OutputValueRegion' in v:
                condname = f'{resname}OutputValueRegion'
                # conditions
                add_obj(get_condition(condname, 'not_equals', 'AWSRegion'))

                outvaluebase = If(
                    condname,
                    Sub(
                        '${Region}-%s' %
                        bucket_name.replace('${AWS::Region}-', '', 1),
                        **{'Region': get_endvalue(condname)}), outvaluebase)

            o_Bucket = Output(resname)
            o_Bucket.Value = If(resname, Ref(resname), outvaluebase)
            if resname == 'BucketAppRepository':
                o_Bucket.Export = Export(resname)

            add_obj([
                o_Bucket,
            ])
Beispiel #12
0
bucket_name = template.add_parameter(
    Parameter(
        "WebsiteBucketName",
        Description="Name for the website asset bucket",
        Type="String",
    ), )

website_bucket = template.add_resource(
    s3.Bucket(
        "WebsiteBucket",
        BucketName=Ref(bucket_name),
        AccessControl="PublicRead",
        VersioningConfiguration=s3.VersioningConfiguration(Status="Enabled"),
        DeletionPolicy="Retain",
        WebsiteConfiguration=s3.WebsiteConfiguration(
            IndexDocument="index.html", ),
    ))

website_bucket_policy = template.add_resource(
    s3.BucketPolicy(
        "WebsiteBucketPolicy",
        PolicyDocument=dict(Statement=dict(
            Effect="Allow",
            Principal="*",
            Action=["s3:GetObject"],
            Resource=Join(
                "",
                ["arn:aws:s3:::", Ref(website_bucket), "/*"]),
        ), ),
        Bucket=Ref(website_bucket),
    ))
Beispiel #13
0
        'zone_name': 'trentnielsen.me',
        'redirect_target': 'resume.trentnielsen.me',
        'alt_sub': 'www',
    },
}

for src_domain, domain_info in redirect_domains.items():

    bucketResourceName = "{}0{}0Bucket".format(app_group_ansi,
                                               src_domain.replace('.', '0'))

    redirectBucket = t.add_resource(
        Bucket(bucketResourceName,
               BucketName='{}'.format(src_domain),
               Tags=DefaultTags + Tags(Component='{}'.format(src_domain)),
               WebsiteConfiguration=(s3.WebsiteConfiguration(
                   IndexDocument='index.html'))))

    # Set some cdn based values and defaults
    dns_domain = domain_info['zone_name']
    cdn_domain = '{}'.format(src_domain)
    max_ttl = 31536000,
    default_ttl = 86400,

    # If an alt_sub domain is not specified use empty string
    if domain_info['alt_sub'] != '':
        alternate_name = '{}.{}'.format(domain_info['alt_sub'], src_domain)
    else:
        alternate_name = ''

    # Provision certificate for CDN
    cdnCertificate = t.add_resource(
Beispiel #14
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_description('Static Website - Bucket and Distribution')

        # Conditions
        template.add_condition(
            'AcmCertSpecified',
            And(Not(Equals(variables['AcmCertificateArn'].ref, '')),
                Not(Equals(variables['AcmCertificateArn'].ref, 'undefined'))))
        template.add_condition(
            'AliasesSpecified',
            And(Not(Equals(Select(0, variables['Aliases'].ref), '')),
                Not(Equals(Select(0, variables['Aliases'].ref), 'undefined'))))
        template.add_condition(
            'CFLoggingEnabled',
            And(Not(Equals(variables['LogBucketName'].ref, '')),
                Not(Equals(variables['LogBucketName'].ref, 'undefined'))))
        template.add_condition(
            'WAFNameSpecified',
            And(Not(Equals(variables['WAFWebACL'].ref, '')),
                Not(Equals(variables['WAFWebACL'].ref, 'undefined'))))

        # Resources
        oai = template.add_resource(
            cloudfront.CloudFrontOriginAccessIdentity(
                'OAI',
                CloudFrontOriginAccessIdentityConfig=cloudfront.
                CloudFrontOriginAccessIdentityConfig(  # noqa pylint: disable=line-too-long
                    Comment='CF access to website')))

        bucket = template.add_resource(
            s3.Bucket(
                'Bucket',
                AccessControl=s3.Private,
                LifecycleConfiguration=s3.LifecycleConfiguration(Rules=[
                    s3.LifecycleRule(NoncurrentVersionExpirationInDays=90,
                                     Status='Enabled')
                ]),
                VersioningConfiguration=s3.VersioningConfiguration(
                    Status='Enabled'),
                WebsiteConfiguration=s3.WebsiteConfiguration(
                    IndexDocument='index.html', ErrorDocument='error.html')))
        template.add_output(
            Output('BucketName',
                   Description='Name of website bucket',
                   Value=bucket.ref()))

        allowcfaccess = template.add_resource(
            s3.BucketPolicy(
                'AllowCFAccess',
                Bucket=bucket.ref(),
                PolicyDocument=Policy(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Action=[awacs.s3.GetObject],
                            Effect=Allow,
                            Principal=Principal(
                                'CanonicalUser',
                                oai.get_att('S3CanonicalUserId')),
                            Resource=[Join('', [bucket.get_att('Arn'), '/*'])])
                    ])))

        cfdistribution = template.add_resource(
            cloudfront.Distribution(
                'CFDistribution',
                DependsOn=allowcfaccess.title,
                DistributionConfig=cloudfront.DistributionConfig(
                    Aliases=If('AliasesSpecified', variables['Aliases'].ref,
                               NoValue),
                    Origins=[
                        cloudfront.Origin(
                            DomainName=Join(
                                '.', [bucket.ref(), 's3.amazonaws.com']),
                            S3OriginConfig=cloudfront.S3Origin(
                                OriginAccessIdentity=Join(
                                    '', [
                                        'origin-access-identity/cloudfront/',
                                        oai.ref()
                                    ])),
                            Id='S3Origin')
                    ],
                    DefaultCacheBehavior=cloudfront.DefaultCacheBehavior(
                        AllowedMethods=['GET', 'HEAD'],
                        Compress=False,
                        DefaultTTL='86400',
                        ForwardedValues=cloudfront.ForwardedValues(
                            Cookies=cloudfront.Cookies(Forward='none'),
                            QueryString=False,
                        ),
                        TargetOriginId='S3Origin',
                        ViewerProtocolPolicy='redirect-to-https'),
                    DefaultRootObject='index.html',
                    Logging=If(
                        'CFLoggingEnabled',
                        cloudfront.Logging(Bucket=Join('.', [
                            variables['LogBucketName'].ref, 's3.amazonaws.com'
                        ])), NoValue),
                    PriceClass=variables['PriceClass'].ref,
                    Enabled=True,
                    WebACLId=If('WAFNameSpecified', variables['WAFWebACL'].ref,
                                NoValue),
                    ViewerCertificate=If(
                        'AcmCertSpecified',
                        cloudfront.ViewerCertificate(
                            AcmCertificateArn=variables['AcmCertificateArn'].
                            ref,  # noqa
                            SslSupportMethod='sni-only'),
                        NoValue))))
        template.add_output(
            Output('CFDistributionId',
                   Description='CloudFront distribution ID',
                   Value=cfdistribution.ref()))
        template.add_output(
            Output('CFDistributionDomainName',
                   Description='CloudFront distribution domain name',
                   Value=cfdistribution.get_att('DomainName')))