Skip to content

Conversation

@Kasra-G
Copy link
Contributor

@Kasra-G Kasra-G commented Aug 1, 2025

Issue # (if applicable)

Closes #28078.

Reason for this change

Allowing the option to restrict the hosted zone names the delegation role can create records for encourages minimum permissions setup. The linked issue establishes a fairly common usecase - different roles for dev.example.come and prod.example.com,

Description of changes

Adds the interface GrantDelegationOptions, with optional readonly prop delegatedZoneNames. This interface is used as an optional prop to hostedZone.grantDelegation().

Example usage:

declare const zone: IHostedZone
declare const role: Role

zone.grantDelegation(role, {
  delegatedZoneNames: ['a.example.com'],
})

Added some validation that ensures each of the delegatedZoneNames is a valid subdomain of the parent hosted zone.

Additionally, updated the README with usage instructions and fixed an outdated code example for how to use grantDelegation. This code example was giving too broad permissions that what was necessary.

Describe any new or updated permissions being added

when delegatedZoneNames is provided with [a.example.com], the following condition is added:

"ForAllValues:StringEquals": {
 "route53:ChangeResourceRecordSetsRecordTypes": [
  "NS"
 ],
 "route53:ChangeResourceRecordSetsActions": [
  "UPSERT",
  "DELETE"
 ],
+ "route53:ChangeResourceRecordSetsNormalizedRecordNames": [
+  "a.example.com"
+ ]

Description of how you validated changes

Updated Integ and unit tests

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@github-actions github-actions bot added the beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK label Aug 1, 2025
@aws-cdk-automation aws-cdk-automation requested a review from a team August 1, 2025 09:22
@github-actions github-actions bot added effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 labels Aug 1, 2025
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 88ea9b1
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Aug 1, 2025
Copy link
Contributor

@pahud pahud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor suggestions for consideration:

  1. Input Validation: Consider adding validation that the provided record names are valid DNS names to catch errors early rather than at IAM policy evaluation time.

  2. Documentation Enhancement: It might be helpful to clarify in the README that the record names should be the actual NS record names that will be created (e.g., for delegating beta.example.com, you'd specify ['beta.example.com']).

  3. Property Naming: While nameEquals is clear, recordNames or allowedRecordNames might be slightly more intuitive for users.

These are minor suggestions - the core implementation is solid. Thanks for contributing this useful feature to the CDK!

@Kasra-G
Copy link
Contributor Author

Kasra-G commented Aug 8, 2025

Thanks for the review - I can add the input validation and update the docs. For input validation I will likely just reuse this.

I was thinking about it, and using recordNames might mean users might expect to be able to do something like this

zone.grantDelegation(role, {
  recordNames: ['beta'],
})

instead of

zone.grantDelegation(role, {
  recordNames: ['beta.example.com'],
})

What do you think of using the logic in this function to make it so that usage would also work?

@jochemd
Copy link

jochemd commented Aug 9, 2025

Maybe the property should be named subZones or childZones to reinforce this only grants rights to create NS records.

Update: so according to RFC 9499 DNS Terminology there is no uniform name, but child zone is definitely the most common name.

@Kasra-G
Copy link
Contributor Author

Kasra-G commented Sep 1, 2025

Maybe the property should be named subZones or childZones to reinforce this only grants rights to create NS records.

I think the delegation in the grant name is enough to tell the user that it allows NS record manipulation only. but I do agree we should change the variable name.

What do you think of using the logic in this function to make it so that usage would also work?

I think after some time I have gone back against supporting the rather complex logic in that function for determining whether to append the hosted zone name to the record name or not.

I think it is a lot simpler to require the hosted zone name you are delegating to, ie: delegatedZoneNames. We already have pre-existing logic for validating zone name so this should be easy enough to add, and it is precise in the name we expect. Besides, the record name should match the delegated hosted zone name anyway. I will add some comments that explain the expected record name(s) will match the delegated zone name(s).

Additionally, the lambda handler for creating the zone delegation uses DelegatedZoneName as well

I was also considering removing the ability to give a list of zone names, but I suppose it doesn't hurt.

@Kasra-G Kasra-G force-pushed the ft/route53-grant-delegation-name branch from 88ea9b1 to 005bb30 Compare September 2, 2025 03:20
@Kasra-G
Copy link
Contributor Author

Kasra-G commented Sep 2, 2025

I have updated the PR to use delegatedZoneNames instead of recordNames and added some extra validation, namely the existing validation in validateZoneName and some extra checks that make sure the delegated zone names are each some subzone of the parent hosted zone. Please let me know if you prefer something else. It's rather tough to settle on a name.

child zone is definitely the most common

I personally think delegatedZoneNames, subZoneNames, childZoneNames are all pretty equal - just have to pick one. Let me know if theres any disagreement here - I think users will understand no matter which one we pick

@Kasra-G Kasra-G requested a review from pahud September 2, 2025 03:51
@Kasra-G Kasra-G changed the title feat(route53): support specifying record names when using grantDelegation feat(route53): support restricting delegated zone names when using grantDelegation Sep 3, 2025
@Kasra-G
Copy link
Contributor Author

Kasra-G commented Sep 9, 2025

Exemption requested for the Security Guardian check - the fix would be to restrict the trust policy on the delegation role to specific role name, but the CrossAccountZoneDelegationRecord does not allow you to specify a role name.

Additionally, the integ test is using conditions to limit access

@aws-cdk-automation aws-cdk-automation added pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback. and removed pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. labels Oct 17, 2025
@aws-cdk-automation aws-cdk-automation added the pr/needs-further-review PR requires additional review from our team specialists due to the scope or complexity of changes. label Oct 23, 2025
@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Oct 23, 2025

export function makeGrantDelegation(grantee: iam.IGrantable, hostedZoneArn: string): iam.Grant {
function stripTrailingDot(zoneName: string) {
return zoneName.endsWith('.') ? zoneName.substring(0, zoneName.length - 1) : zoneName;
Copy link
Member

@Abogical Abogical Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zoneName here could be a token, so we can't really do normal string operations here unless we either:

  • Use Cloudformation intrinsic functions to preform the string operation instead.
  • Throw an error if zoneName is an unresolved token.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also apply to line R52 above? This token check was not being done there before

Additionally I do have a more general question on the trailing dot. The delegatedZoneName needs to match exactly with whatever is used as the hosted zone name in the CrossAccountZoneDelegationRecord, including the trailing dot, if we use the StringEquals condition, which may not be intuitive. I wonder if it makes sense to instead use StringLike so we can allow requests whether or not the trailing dot exists. Alternatively we could just document the trailing dot issue and let users deal with it.

Copy link
Member

@Abogical Abogical Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • If its been done before then I'll allow it. It was probably incorrect in the first place but that's outside the scope of the PR.
  • I might be misunderstanding this, but are you talking about the IAM statements for the conditions? If so, then according to the AWS docs, it recommends using StringEquals with a normalized DNS name without the trailing dot:

For route53:ChangeResourceRecordSetsNormalizedRecordNames:

  • All letters must be lowercase.

  • The DNS name must be without the trailing dot.

  • Characters other than a–z, 0–9, - (hyphen), _ (underscore), and . (period, as a delimiter between labels) must use escape codes in the format \three-digit octal code. For example, \052 is the octal code for character *.

You say we should include the trailing dot which is incorrect in this situation, so I'm not sure what exactly are you referring to.

@Abogical Abogical self-assigned this Oct 30, 2025
@aws-cdk-automation aws-cdk-automation removed the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Oct 30, 2025

export function makeGrantDelegation(grantee: iam.IGrantable, hostedZone: IHostedZone, delegationOptions?: GrantDelegationOptions): iam.Grant {
const delegatedZoneNames = delegationOptions?.delegatedZoneNames;
delegatedZoneNames?.forEach(zoneName => validateDelegatedZoneName(hostedZone.zoneName, zoneName));
Copy link
Member

@Abogical Abogical Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, this doesn't check if the delegated zone name has a trailing dot. It should be normalized and not have a trailing dot. Throw an error if it does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 pr/needs-further-review PR requires additional review from our team specialists due to the scope or complexity of changes. pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

aws-route53: restrict domain names in cross-account delegation

5 participants