forked from aws/aws-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ec2):
VpcEndpointService
construct
Add an experimental `VpcEndpointService` construct, to allow exposing Network Load Balancers as endpoints in a VPC.
- Loading branch information
1 parent
24ded60
commit a2713f3
Showing
7 changed files
with
312 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { ArnPrincipal } from '@aws-cdk/aws-iam'; | ||
import { Construct, IResource, Resource } from '@aws-cdk/core'; | ||
import { CfnVPCEndpointService, CfnVPCEndpointServicePermissions } from './ec2.generated'; | ||
|
||
/** | ||
* A load balancer that can host a VPC Endpoint Service | ||
* | ||
*/ | ||
export interface IVpcEndpointServiceLoadBalancer { | ||
/** | ||
* The ARN of the load balancer that hosts the VPC Endpoint Service | ||
*/ | ||
readonly loadBalancerArn: string; | ||
} | ||
|
||
/** | ||
* A VPC endpoint service. | ||
* @experimental | ||
*/ | ||
export interface IVpcEndpointService extends IResource { | ||
/** | ||
* Name of the Vpc Endpoint Service | ||
* @experimental | ||
*/ | ||
readonly vpcEndpointServiceName?: string; | ||
} | ||
|
||
/** | ||
* A VPC endpoint service | ||
* @resource AWS::EC2::VPCEndpointService | ||
* @experimental | ||
*/ | ||
export class VpcEndpointService extends Resource implements IVpcEndpointService { | ||
|
||
/** | ||
* One or more network load balancer ARNs to host the service. | ||
* @attribute | ||
*/ | ||
public readonly vpcEndpointServiceLoadBalancers: IVpcEndpointServiceLoadBalancer[]; | ||
|
||
/** | ||
* Whether to require manual acceptance of new connections to the service. | ||
* @experimental | ||
*/ | ||
public readonly acceptanceRequired: boolean; | ||
|
||
/** | ||
* One or more Principal ARNs to allow inbound connections to. | ||
* @experimental | ||
*/ | ||
public readonly whitelistedPrincipals: ArnPrincipal[]; | ||
|
||
private readonly endpointService: CfnVPCEndpointService; | ||
|
||
constructor(scope: Construct, id: string, props: VpcEndpointServiceProps) { | ||
super(scope, id); | ||
|
||
if (props.vpcEndpointServiceLoadBalancers === undefined || props.vpcEndpointServiceLoadBalancers.length === 0) { | ||
throw new Error("VPC Endpoint Service must have at least one load balancer specified."); | ||
} | ||
|
||
this.vpcEndpointServiceLoadBalancers = props.vpcEndpointServiceLoadBalancers; | ||
this.acceptanceRequired = props.acceptanceRequired !== undefined ? props.acceptanceRequired : true; | ||
this.whitelistedPrincipals = props.whitelistedPrincipals !== undefined ? props.whitelistedPrincipals : []; | ||
|
||
this.endpointService = new CfnVPCEndpointService(this, id, { | ||
networkLoadBalancerArns: this.vpcEndpointServiceLoadBalancers.map(lb => lb.loadBalancerArn), | ||
acceptanceRequired: this.acceptanceRequired | ||
}); | ||
|
||
if (this.whitelistedPrincipals.length > 0) { | ||
new CfnVPCEndpointServicePermissions(this, "Permissions", { | ||
serviceId: this.endpointService.ref, | ||
allowedPrincipals: this.whitelistedPrincipals.map(x => x.arn) | ||
}); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Construction properties for a VpcEndpointService. | ||
* @experimental | ||
*/ | ||
export interface VpcEndpointServiceProps { | ||
|
||
/** | ||
* Name of the Vpc Endpoint Service | ||
* @default - CDK generated name | ||
* @experimental | ||
*/ | ||
readonly vpcEndpointServiceName?: string; | ||
|
||
/** | ||
* One or more load balancers to host the VPC Endpoint Service. | ||
* @experimental | ||
*/ | ||
readonly vpcEndpointServiceLoadBalancers: IVpcEndpointServiceLoadBalancer[]; | ||
|
||
/** | ||
* Whether requests from service consumers to connect to the service through | ||
* an endpoint must be accepted. | ||
* @default true | ||
* @experimental | ||
*/ | ||
readonly acceptanceRequired?: boolean; | ||
|
||
/** | ||
* IAM users, IAM roles, or AWS accounts to allow inbound connections from. | ||
* These principals can connect to your service using VPC endpoints. Takes a | ||
* list of one or more ArnPrincipal. | ||
* @default - no principals | ||
* @experimental | ||
*/ | ||
readonly whitelistedPrincipals?: ArnPrincipal[]; | ||
} |
33 changes: 33 additions & 0 deletions
33
packages/@aws-cdk/aws-ec2/test/integ.vpc-endpoint-service.expected.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"Resources": { | ||
"MyVpcEndpointServiceWithNoPrincipals9B24276E": { | ||
"Type": "AWS::EC2::VPCEndpointService", | ||
"Properties": { | ||
"NetworkLoadBalancerArns": [ | ||
"arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a" | ||
], | ||
"AcceptanceRequired": false | ||
} | ||
}, | ||
"MyVpcEndpointServiceWithPrincipals41EE2DF2": { | ||
"Type": "AWS::EC2::VPCEndpointService", | ||
"Properties": { | ||
"NetworkLoadBalancerArns": [ | ||
"arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/1jd81k39sa421ffs" | ||
], | ||
"AcceptanceRequired": false | ||
} | ||
}, | ||
"MyVpcEndpointServiceWithPrincipalsPermissions29F9BD5A": { | ||
"Type": "AWS::EC2::VPCEndpointServicePermissions", | ||
"Properties": { | ||
"ServiceId": { | ||
"Ref": "MyVpcEndpointServiceWithPrincipals41EE2DF2" | ||
}, | ||
"AllowedPrincipals": [ | ||
"arn:aws:iam::123456789012:root" | ||
] | ||
} | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
packages/@aws-cdk/aws-ec2/test/integ.vpc-endpoint-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { ArnPrincipal } from '@aws-cdk/aws-iam'; | ||
import * as cdk from '@aws-cdk/core'; | ||
import * as ec2 from '../lib'; | ||
|
||
const app = new cdk.App(); | ||
|
||
/** | ||
* A load balancer that can host a VPC Endpoint Service | ||
*/ | ||
class DummyEndpointLoadBalacer implements ec2.IVpcEndpointServiceLoadBalancer { | ||
/** | ||
* The ARN of the load balancer that hosts the VPC Endpoint Service | ||
*/ | ||
public readonly loadBalancerArn: string; | ||
constructor(arn: string) { | ||
this.loadBalancerArn = arn; | ||
} | ||
} | ||
|
||
class VpcEndpointServiceStack extends cdk.Stack { | ||
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { | ||
super(scope, id, props); | ||
|
||
const nlbNoPrincipals = new DummyEndpointLoadBalacer( | ||
"arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"); | ||
|
||
new ec2.VpcEndpointService(this, "MyVpcEndpointServiceWithNoPrincipals", { | ||
vpcEndpointServiceLoadBalancers: [nlbNoPrincipals], | ||
acceptanceRequired: false, | ||
whitelistedPrincipals: [] | ||
}); | ||
|
||
const nlbWithPrincipals = new DummyEndpointLoadBalacer( | ||
"arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/1jd81k39sa421ffs"); | ||
const principalArn = new ArnPrincipal("arn:aws:iam::123456789012:root"); | ||
|
||
new ec2.VpcEndpointService(this, "MyVpcEndpointServiceWithPrincipals", { | ||
vpcEndpointServiceLoadBalancers: [nlbWithPrincipals], | ||
acceptanceRequired: false, | ||
whitelistedPrincipals: [principalArn] | ||
}); | ||
} | ||
} | ||
|
||
new VpcEndpointServiceStack(app, 'aws-cdk-ec2-vpc-endpoint-service'); | ||
app.synth(); |
106 changes: 106 additions & 0 deletions
106
packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { expect, haveResource } from '@aws-cdk/assert'; | ||
import { ArnPrincipal } from '@aws-cdk/aws-iam'; | ||
import { Stack } from '@aws-cdk/core'; | ||
import { Test } from 'nodeunit'; | ||
// tslint:disable-next-line:max-line-length | ||
import { IVpcEndpointServiceLoadBalancer, Vpc, VpcEndpointService } from '../lib'; | ||
|
||
/** | ||
* A load balancer that can host a VPC Endpoint Service | ||
*/ | ||
class DummyEndpointLoadBalacer implements IVpcEndpointServiceLoadBalancer { | ||
/** | ||
* The ARN of the load balancer that hosts the VPC Endpoint Service | ||
*/ | ||
public readonly loadBalancerArn: string; | ||
constructor(arn: string) { | ||
this.loadBalancerArn = arn; | ||
} | ||
} | ||
|
||
export = { | ||
'test vpc endpoint service': { | ||
'create endpoint service with no principals'(test: Test) { | ||
// GIVEN | ||
const stack = new Stack(); | ||
new Vpc(stack, "MyVPC"); | ||
|
||
// WHEN | ||
const lb = new DummyEndpointLoadBalacer("arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"); | ||
new VpcEndpointService(stack, "EndpointService", { | ||
vpcEndpointServiceLoadBalancers: [lb], | ||
acceptanceRequired: false, | ||
whitelistedPrincipals: [new ArnPrincipal("arn:aws:iam::123456789012:root")] | ||
}); | ||
// THEN | ||
expect(stack).to(haveResource('AWS::EC2::VPCEndpointService', { | ||
NetworkLoadBalancerArns: ["arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"], | ||
AcceptanceRequired: false | ||
})); | ||
|
||
expect(stack).notTo(haveResource('AWS::EC2::VPCEndpointServicePermissions', { | ||
ServiceId: { | ||
Ref: "EndpointServiceED36BE1F" | ||
}, | ||
AllowedPrincipals: [] | ||
})); | ||
|
||
test.done(); | ||
}, | ||
'create endpoint service with a principal'(test: Test) { | ||
// GIVEN | ||
const stack = new Stack(); | ||
|
||
// WHEN | ||
const lb = new DummyEndpointLoadBalacer("arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"); | ||
new VpcEndpointService(stack, "EndpointService", { | ||
vpcEndpointServiceLoadBalancers: [lb], | ||
acceptanceRequired: false, | ||
whitelistedPrincipals: [new ArnPrincipal("arn:aws:iam::123456789012:root")] | ||
}); | ||
|
||
// THEN | ||
expect(stack).to(haveResource('AWS::EC2::VPCEndpointService', { | ||
NetworkLoadBalancerArns: ["arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"], | ||
AcceptanceRequired: false | ||
})); | ||
|
||
expect(stack).to(haveResource('AWS::EC2::VPCEndpointServicePermissions', { | ||
ServiceId: { | ||
Ref: "EndpointServiceED36BE1F" | ||
}, | ||
AllowedPrincipals: ["arn:aws:iam::123456789012:root"] | ||
})); | ||
|
||
test.done(); | ||
}, | ||
|
||
'with acceptance requried'(test: Test) { | ||
// GIVEN | ||
const stack = new Stack(); | ||
|
||
// WHEN | ||
const lb = new DummyEndpointLoadBalacer("arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"); | ||
new VpcEndpointService(stack, "EndpointService", { | ||
vpcEndpointServiceLoadBalancers: [lb], | ||
acceptanceRequired: true, | ||
whitelistedPrincipals: [new ArnPrincipal("arn:aws:iam::123456789012:root")] | ||
}); | ||
|
||
// THEN | ||
expect(stack).to(haveResource('AWS::EC2::VPCEndpointService', { | ||
NetworkLoadBalancerArns: ["arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/Test/9bn6qkf4e9jrw77a"], | ||
AcceptanceRequired: true | ||
})); | ||
|
||
expect(stack).to(haveResource('AWS::EC2::VPCEndpointServicePermissions', { | ||
ServiceId: { | ||
Ref: "EndpointServiceED36BE1F" | ||
}, | ||
AllowedPrincipals: ["arn:aws:iam::123456789012:root"] | ||
})); | ||
|
||
test.done(); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters