如何设置我的 HostedZone 以便它委托给另一个 AWS 账户中的父 DNS 记录?

如何设置我的 HostedZone 以便它委托给另一个 AWS 账户中的父 DNS 记录?

介绍

我有一些 TypeScript 代码,使用 CDK 创建 API 网关和 Lambda。它可以运行并部署到标准 AWS URL。到目前为止一切顺利。

我现在需要转移 API 网关,以便它在自定义域上运行,这样它就可以在 Web 应用中设置 cookie。事实证明,这要困难得多,我怀疑我遇到困难是因为我对 TypeScript、AWS 和 CDK 都很陌生。网上有很多文档资源,但大多数都需要我重写我手头的宝贵的少量工作代码,而我不愿意这样做。

我手动创建了一个证书,因为这需要验证,因此在代码中创建它毫无意义。除此之外,我希望所有其他资源都由堆栈中的 CDK 代码创建。在我看来,如果我必须手动配置,那么 CDK 的目的就落空了。

问题

以下代码部署了我需要的一切gatekeeper.d.aws.example.com- HostedZone、ARecord、LambdaRestApi 和 Function (lambda)。但是它不起作用,因为新分配的 NS 记录与gatekeeper.d.aws.example.com父级中的记录不匹配d.aws.example.com

我认为这意味着虽然d.aws.example.com“已知”,但gateway子域不能委托给它。

这是我的工作代码:

// Create the lambda resource
const referrerLambda = new lambda.Function(this, 'EisReferrerLambda', {
    runtime: lambda.Runtime.NODEJS_14_X,
    handler: 'index.handler',
    code: lambda.Code.fromAsset(path.join(__dirname, '../../src/lambda')),
    environment: env
});

// Set up the domain name on which the API should appear
const domainName = 'gatekeeper.d.aws.example.com';

// TODO need to fetch it with an env var? Or read from environment?
const certificateArn = 'arn:aws:acm:us-east-1:xxx:certificate/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy';

const certificate = acm.Certificate.fromCertificateArn(this, 'SslCertificate', certificateArn);

const hostedZone = new route53.HostedZone(this, 'EisReferrerHostedZone', {
    zoneName: domainName
});

// Add an A record
new route53.ARecord(this, 'DnsRecord', {
    zone: hostedZone,
    target: route53.RecordTarget.fromAlias(new targets.ApiGateway(apiGateway)),
});

// I think I need a DomainNameOptions object
const dno : DomainNameOptions = { certificate, domainName };

// Create the APIG resource
// See https://intro-to-cdk.workshop.aws/the-workshop/4-create-apigateway.html
const apiGateway = new apigw.LambdaRestApi(this, "EisReferrerApi", {
    handler: referrerLambda,
    // proxy = on means that the lambda handles all requests to the APIG,
    // instead of just explicit resource endpoints
    proxy: false,
    // deploy = on means that we get a default stage of "prod", I don't want
    // that - I'm creating a custom Deployment anyway
    deploy: false,
    // Point to a domain name options object
    domainName: dno
});

// Create an endpoint in the APIG
// https://docs.aws.amazon.com/cdk/api/latest/docs/aws-apigateway-readme.html#defining-apis
const items = apiGateway.root.addResource('gatekeeper');
items.addMethod('GET');  // GET /default/gatekeeper

// The deployment resource is just needed by the Stage system
const deployment = new apigw.Deployment(
    this,
    'EisReferrerDeployment',
    { api: apiGateway }
);

// Create a Stage (this affects the first component in the path
const stageName = 'default';
apiGateway.deploymentStage = new apigw.Stage(
    this,
    stageName,
    { deployment, stageName }
);

问题

从代码中可以看出,我找到了如何创建 A 记录,但创建/修改 NS 记录似乎更难。首先,似乎没有 NSRecord 类,至少根据从我的 IDE 自动完成功能探索类结构来看是这样。

一个基本的解决方案是允许我使用在其他地方设置的固定值(在“拥有”该域的 AWS 账户中)创建 NS 记录。更好的解决方案是读取这些记录,然后使用它们。

更新

为了看看我的想法是否正确,我运行了此部署代码,并手动修改了 HostedZone 中自动分配的 NS 记录以匹配父级(在另一个帐户中)中的记录。我想我必须等待此更改渗透到 DNS 系统中,然后我会更新结果。

更新 2

我的手动调节不起作用。因此,我找到了一个尝试新事物(请参阅“将 NS 记录添加到不同账户中的 HostedZone”):

// Commented out from earlier code
// const hostedZone = new route53.HostedZone(this, 'EisReferrerHostedZone', {
//     zoneName: domainName
// });

// In the account containing the HostedZone
const parentZone = new route53.PublicHostedZone(this, 'HostedZone', {
    zoneName: 'd.aws.example.com',
    crossAccountZoneDelegationPrincipal: new iam.AccountPrincipal('12345678012')
});

// In this account
const subZone = new route53.PublicHostedZone(this, 'SubZone', {
    zoneName: domainName
});

new route53.CrossAccountZoneDelegationRecord(this, 'delegate', {
    delegatedZone: subZone,
    parentHostedZoneId: parentZone.hostedZoneId,
    delegationRole: parentZone.crossAccountDelegationRole
});

这听起来正是我需要的,但我担心 AWS 文档在这里已经过时了 -crossAccountDelegationRole在我的 IDE 中以红色呈现,并且由于cdk diff运行时未定义而崩溃。

更新 3

我假设上面提到的属性是拼写错误或对库的过时版本的引用。我现在正在这样做:

new route53.CrossAccountZoneDelegationRecord(this, 'delegate', {
    delegatedZone: subZone,
    parentHostedZoneId: parentZone.hostedZoneId,
    delegationRole: parentZone.crossAccountZoneDelegationRole
});

这感觉非常接近,但它崩溃了:

无法创建资源。AccessDenied:用户:arn:aws:sts::xxxxxxxxxxxx:assumed-role / CustomCrossAccountZoneDelegationC-xxx无权执行:sts:AssumeRole资源:arn:aws:iam::yyyyyyyyyyyyy:role / HostedZoneCrossAccountZoneDelegat-yyy

我想知道我是否需要声明其他帐户的 IAM 凭证?我确实有。

无论如何,我不确定为什么需要权限 - 它不能只读取其他帐户中的 NS 记录并将其复制到本地帐户吗?无论如何,其他帐户中的 DNS 是公开的。

我愿意研究如何修复 IAM 错误,但这完全不像是在瞎忙。我可能会再花两个小时慢慢解决这个子问题,结果却发现整个事情会因为其他原因而失败。

相关内容