【问题标题】:'SiteCertificate' object has no attribute 'certificate_arn' with AWS CDK“SiteCertificate”对象在 AWS CDK 中没有属性“certificate_arn”
【发布时间】:2020-06-13 13:18:29
【问题描述】:

我正在尝试将 CloudFormation 项目移至 AWS CDK。我从前端开始,它是一个静态站点,在带有证书管理器证书的 S3 存储桶前面使用 CloudFront 分配。

以下是我用来构建此堆栈的各种组件:

from aws_cdk import core

from cert import SiteCertificate
from hosted_zone import HostedZone
from static_site import StaticSite


class AwscdkStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        self.hosted_zone = HostedZone(self, "HostedZone")

        self.certificate = SiteCertificate(self, "SiteCert")

        self.static_site = StaticSite(
            self, 'StaticSite',
            hosted_zone=self.hosted_zone,
            certificate=self.certificate
        )

托管区域

import os

from aws_cdk import (
    core,
    aws_route53 as route53
)


class HostedZone(core.Construct):

    def __init__(self, scope: core.Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
            self, "hosted_zone",
            hosted_zone_id=os.environ.get("HOSTED_ZONE_ID", "ABC123"),
            zone_name=os.environ.get("DOMAIN_NAME", "mysite.com")
        )

证书

import os

from aws_cdk import (
    core,
    aws_certificatemanager as acm,
)

class SiteCertificate(core.Construct):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        cert = acm.Certificate(
            self, "SiteCertificate",
            domain_name=f"*.{os.environ.get('DOMAIN_NAME', 'mysite.com')}"
        )

静态站点

这包含 S3 存储桶、策略和 CloudFront 分布(我可能想将它们分成不同的文件)

import os

from aws_cdk import (
    aws_certificatemanager as acm,
    aws_s3 as s3,
    aws_cloudfront as cloudfront,
    aws_route53 as route53,
    aws_iam as iam,
    core
)


class StaticSite(core.Construct):

    def __init__(
        self,
        scope: core.Construct,
        id: str,
        hosted_zone: route53.IHostedZone,
        certificate: acm.ICertificate,
        **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

        self.static_site_bucket = s3.Bucket(
            self, "StaticSiteBucket",
            access_control=s3.BucketAccessControl.PUBLIC_READ,
            bucket_name=os.environ.get("DOMAIN_NAME", "mysite.com"),
            removal_policy=core.RemovalPolicy.DESTROY,
        )

        self.policy_statement = iam.PolicyStatement(
            actions=["s3:GetObject"],
            resources=[f"{self.static_site_bucket.bucket_arn}/*"]
        )

        self.policy_statement.add_any_principal()

        self.static_site_policy_document = iam.PolicyDocument(
            statements=[self.policy_statement]
        )

        self.static_site_bucket.add_to_resource_policy(
            self.policy_statement
        )

        self.distribution = cloudfront.CloudFrontWebDistribution(
            self, "CloudFrontDistribution",
            origin_configs=[
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=self.static_site_bucket
                    ),
                    behaviors=[cloudfront.Behavior(is_default_behavior=True)]
                )
            ],
            alias_configuration=cloudfront.AliasConfiguration(
                acm_cert_ref=certificate.certificate_arn,
                names=[
                    os.environ.get("DOMAIN_NAME", "mysite.com"),
                    f"*.{os.environ.get('DOMAIN_NAME', 'mysite.com')}"]
            ),
            error_configurations=[
                {
                    "errorCode": 403,
                    "errorCachingMinTtl": 0,
                    "responseCode": 200,
                    "responsePagePath": "/index.html"
                },
                {
                    "errorCode": 404,
                    "errorCachingMinTtl": 0,
                    "responseCode": 200,
                    "responsePagePath": "/index.html"
                }
            ]
        )

我还没有部署任何东西,我只是在本地使用cdk synth 进行测试。我一直在运行cdk synth,每次添加我的 CDK 文件,CloudFormation 输出与我目前用于部署项目的 CloudFormation 模板中的输出类似。当我运行cdk sythn 时,出现以下错误:

AttributeError: 'SiteCertificate' object has no attribute 'certificate_arn'

我在这里使用了正确的构造吗?在我可以访问它的 ARN 之前,证书是否需要存在?我试过使用DnsValidatedCertificate,但我得到了同样的错误。我还注意到这种方法是实验性的,所以我不确定这是否与我看到此错误的原因有关。

【问题讨论】:

    标签: python amazon-web-services aws-cdk infrastructure-as-code


    【解决方案1】:

    您似乎缺少SiteCertificate 上的属性定义

            self.certificate = SiteCertificate(self, "SiteCert")
    
            self.static_site = StaticSite(
                self, 'StaticSite',
                hosted_zone=self.hosted_zone,
                certificate=self.certificate
            )
    

    在 StaticSite 中,您引用了 certificate.certificate_arn,但 SiteCertificate 没有定义该属性。

    class SiteCertificate(core.Construct):
    
        def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
            super().__init__(scope, id, **kwargs)
    
            cert = acm.Certificate(
                self, "SiteCertificate",
                domain_name=f"*.{os.environ.get('DOMAIN_NAME', 'mysite.com')}"
            )
            // Add this
            self.certificate_arn = cert.certificate_arn
    

    或者让你的SiteCertificate 继承自 acm.Ceritificate

    class SiteCertificate(acm.Certificate):
    
        def __init__(self, scope: core.Construct) -> None:
            super().__init__(scope, "SiteCertificate",
                domain_name=f"*.{os.environ.get('DOMAIN_NAME', 'mysite.com')}")
    

    我不是 python 专家,所以我可能会遗漏一些东西。

    【讨论】:

    • 谢谢!我尝试让 SiteCertificate 继承自 acm.Certificate 并且它有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2012-12-01
    • 2021-08-03
    • 2020-05-15
    相关资源
    最近更新 更多