介绍
我有一些 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 错误,但这完全不像是在瞎忙。我可能会再花两个小时慢慢解决这个子问题,结果却发现整个事情会因为其他原因而失败。