aws / aws/aws-cdk

aws-route53: VpcEndpointServiceDomainName missing vpce:AllowMultiRegion permission for cross-region PrivateLink

Open
#36,216 4 comments 1 reaction 0 assignees View on GitHub
@aws-cdk/aws-route53 bug effort/medium p2
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.