CDK DnsValidatedCertificate:当托管区域是父账户的一部分时,是否可以在链接的 AWS 账户中创建证书?

car*_*iem 5 amazon-web-services aws-cloudformation amazon-iam aws-sts aws-cdk

我正在尝试使用 AWS 的云开发工具包为我网站的某些子域创建 SSL 证书。问题是我正在使用 AWS Organizations 并且相关资源属于不同的 AWS 账户。我的域的托管区域是我们主帐户的一部分,但我正在运行 CDK 在链接帐户中部署堆栈。这意味着该类DnsValidatedCertificate 能够请求新证书(堆栈回滚后它们在ACM中仍然可见),但在尝试创建 DNS 记录以自动验证请求时会引发错误。

这是错误(我的帐号和堆栈名称已编辑):

 5/6 | 22:44:14 | CREATE_FAILED        | AWS::CloudFormation::CustomResource | SubSubDomainsCertificate/CertificateRequestorResource/Default (SubSubDomainsCertificateCertificateRequestorResourceBC626C85) Failed to create resource. User: arn:aws:sts::123456789012:assumed-role/MyStack-SubSubDomainsCertificateCertificat-16QRI74P8POO2/MyStack-SubSubDomainsCertificateCertificat-BXZ55WHIH1XC is not authorized to access this resource
        new CustomResource (C:\repos\my-project\node_modules\@aws-cdk\aws-cloudformation\lib\custom-resource.ts:92:21)
        \_ new DnsValidatedCertificate (C:\repos\my-project\node_modules\@aws-cdk\aws-certificatemanager\lib\dns-validated-certificate.ts:81:29)
        \_ new MyStack (C:\repos\my-project\.elasticbeanstalk\api-stack.js:91:25)
Run Code Online (Sandbox Code Playgroud)

这是相关的 CDK 代码(同样,HZ 和域已编辑):

    // Executed with `cdk deploy --profile profileForLinkedAwsAccount`
    const hostedZone = route53.HostedZone.fromHostedZoneAttributes(
      this,
      'MyDomainHostedZone',
      {
        hostedZoneId: 'Z2ABC1234RYN', // in master AWS account
        zoneName: 'mydomain.com.'
      }
    );
    const certificate = new certificatemanager.DnsValidatedCertificate(
      this,
      'SubSubDomainsCertificate',
      {
        domainName: `*.demo.mydomain.com`,
        hostedZone,
        region: 'us-east-1',
        validationMethod: certificatemanager.ValidationMethod.DNS // ???
      }
    );
Run Code Online (Sandbox Code Playgroud)

那么,有什么方法可以配置 CDK 来自动进行 DNS 验证吗?或者我是否需要使用不同的配置文件来执行此操作作为第二步?

编辑:根据 Michael 的建议,我添加了一个名LinkedAccountCertValidatorRole为主AWS 帐户角色。我附加到该角色的托管策略及其信任关系如下所示。不幸的是,我仍然遇到同样的错误。此外,“访问顾问”选项卡指示该角色从未使用过该策略。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "route53:ChangeResourceRecordSets",
            "Resource": "arn:aws:route53:::hostedzone/Z2ABC1234RYN"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

car*_*iem 5

为了完整起见,我将在这里发布简单的答案:使用Certificate类而不是DnsValidatedCertificate。我可以让 CDK 创建证书请求,但不能让它尝试自动验证子域。这意味着我必须:

  1. 去关联账户的Amazon Certificate Manager中查找请求,
  2. 检查(或导出)它要求添加的 CNAME 记录,并且
  3. 切换到主 AWS 账户并在Route53中添加记录。
// Executed with `cdk deploy --profile profileForLinkedAwsAccount`
const certificate = new certificatemanager.Certificate(this, 'SubSubDomainsCertificate', {
  domainName: `*.${SUBDOMAIN}.mydomain.com`,
  validationMethod: ValidationMethod.DNS
});
Run Code Online (Sandbox Code Playgroud)

目前我已经选择了这个选项,但是如果能够完全自动化该过程就更好了。


Mic*_*ale 2

正确使用 IAM 可能会很痛苦。首先也是最重要的是,您创建的角色必须与可以承担该角色的用户/帐户/组具有信任关系。我没有看到你在OP中提到过这一点。我不知道 CDK 是什么,所以我无法清楚地了解您在做什么。

角色具有可以执行的操作的权限。还有一个信任关系部分定义了谁或什么可以承担该角色。

可信关系应该有一个到组织主帐户的映射,例如......

在主帐户中创建角色并附加权限:

My_Role_To_Assume
Assign Permissions in Master:

Trust Relationship(Master Account)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::0123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Run Code Online (Sandbox Code Playgroud)

在主帐户中创建一个组,并将用户分配到该组。组权限,应该有一个策略文档,显示允许用户承担哪些角色和子帐号。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Resource": [
        "arn:aws:iam::987654321098:role/My_Role_To_Assume",
        "arn:aws:iam::567890123456:role/My_Other_Role_Assume"
      ]
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

然后在帐户中您希望角色能够访问。创建一个具有相同名称的角色(不是必须的,但更容易记住角色的用途)。

My_Role_To_Assume
Assign Permissions for role in sub-account:

Attach Trust Realtionship policy for sub-account role to trust master account:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::0123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

您可以调整每个帐户中的权限集,以提供对资源更细粒度的控制/访问。通常在主账户中,您可能没有任何权限,除了 IAM 密码、密钥管理等。

这种方法效果很好,总体要点是您在根级别创建信任关系,但主帐户中的组策略规定了子帐户中的用户/组可以承担哪些角色。

由于您使用的是 CLI,因此在子账户中创建或更新资源之前,您必须发出 aws sts 调用来承担该角色。有一些脚本可以为您处理这个问题。

例子:

#! /bin/bash
#
# Dependencies:
#   yum install -y jq
#
# Setup:
#   chmod +x ./assume_cloudadmin_role.sh
#
# Execute:
#   source ./assume_cloudadmin_role.sh
#
# Description:
#   Makes assuming an AWS IAM role (+ exporting new temp keys) easier. You're users access key and secret must allow you to assume the role in the sts CLI call.

unset  AWS_SESSION_TOKEN
export AWS_ACCESS_KEY_ID=<place_your_key_here> #Master Account API Key
export AWS_SECRET_ACCESS_KEY=<place_your_secret_here>#Master Account API Secret
export AWS_REGION=us-east-1

temp_role=$(aws sts assume-role \
                    --role-arn "arn:aws:iam::0123456789012:role/My_Role_To_Assume" \
                    --role-session-name "temp_cli_role")

export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $temp_role | jq -r .Credentials.SessionToken)

env | grep -i AWS_
Run Code Online (Sandbox Code Playgroud)

此调用将设置您的访问密钥和秘密+会话令牌以对子帐户执行操作。

希望你能成功!