aws-route53: VpcEndpointServiceDomainName missing vpce:AllowMultiRegion permission for cross-region PrivateLink
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
When using `VpcEndpointServiceDomainName` with a `VpcEndpointService` that has `allowedRegions` configured (cross-region PrivateLink), the custom resource Lambda fails with an IAM permission error. The construct does not include the `vpce:AllowMultiRegion` permission in the generated IAM policy.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Library Version
N/A
### Expected Behavior
The `VpcEndpointServiceDomainName` construct should automatically add `vpce:AllowMultiRegion` permission when the associated `VpcEndpointService` has cross-region access enabled via `allowedRegions`.
### Current Behavior
```
Received response status [FAILED] from custom resource. Message returned:
You are not authorized to perform this operation. User: arn:aws:sts::...:assumed-role/.../...
is not authorized to perform: ec2:ModifyVpcEndpointServiceConfiguration on resource:
arn:aws:ec2:us-east-1:...:vpc-endpoint-service/vpce-svc-...
because no identity-based policy allows the vpce:AllowMultiRegion action.
```
### Reproduction Steps
```typescript
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as route53 from 'aws-cdk-lib/aws-route53';
export class ReproStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, natGateways: 0 });
const nlb = new elbv2.NetworkLoadBalancer(this, 'Nlb', { vpc, internetFacing: false });
// VPC Endpoint Service with cross-region access
const endpointService = new ec2.VpcEndpointService(this, 'EndpointService', {
vpcEndpointServiceLoadBalancers: [nlb],
acceptanceRequired: false,
allowedRegions: ['us-east-1', 'us-west-2'], // <-- Cross-region PrivateLink
});
const publicZone = new route53.PublicHostedZone(this, 'TestZone', {
zoneName: 'example.test',
});
// VpcEndpointServiceDomainName - FAILS due to missing vpce:AllowMultiRegion
new route53.VpcEndpointServiceDomainName(this, 'DomainName', {
endpointService,
domainName: `vpce.${publicZone.zoneName}`,
publicHostedZone: publicZone,
});
}
}
```
The synthesized template shows the policy only includes `ec2:ModifyVpcEndpointServiceConfiguration`:
```yaml
DomainNameEnableDnsCustomResourcePolicy132C1FA1:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action: ec2:ModifyVpcEndpointServiceConfiguration # <-- MISSING vpce:AllowMultiRegion
Effect: Allow
Resource: arn:...:vpc-endpoint-service/...
```
### Possible Solution
As a workaround we have:
```typescript
const domainName = new route53.VpcEndpointServiceDomainName(this, 'DomainName', { ... });
const policy = domainName.node.findChild('EnableDns').node.findChild('CustomResourcePolicy').node.defaultChild as cdk.CfnResource;
policy.addPropertyOverride('PolicyDocument.Statement', [
{
Effect: 'Allow',
Action: 'ec2:ModifyVpcEndpointServiceConfiguration',
Resource: `arn:aws:ec2:${this.region}:${this.account}:vpc-endpoint-service/${endpointService.vpcEndpointServiceId}`,
},
{
Effect: 'Allow',
Action: 'vpce:AllowMultiRegion',
Resource: `arn:aws:ec2:${this.region}:${this.account}:vpc-endpoint-service/${endpointService.vpcEndpointServiceId}`,
},
]);
```
As for long term solutions, the `VpcEndpointServiceDomainName` construct should conditionally add `vpce:AllowMultiRegion` to the custom resource policy when the endpoint service has cross-region access enabled. Alternatively, always include the permission since it's ~harmless when not needed.
### Additional Information/Context
_No response_
### AWS CDK Library version (aws-cdk-lib)
aws-cdk-lib@2.229.1
### AWS CDK CLI version
2.1033.0
### Node.js Version
v24.4.1
### OS
macOS
### Language
TypeScript
### Language Version
_No response_
### Other information
_No response_
Contributor guide
Research direction
Start at the route53.VpcEndpointServiceDomainName construct and its custom resource policy generation. Synthesize the provided cross-region PrivateLink reproduction and inspect the generated DomainNameEnableDnsCustomResourcePolicy. Done means the policy includes vpce:AllowMultiRegion for services using allowedRegions while retaining the existing permission.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100