Skip to content

Commit

Permalink
feat(AWS APIGW): Support association of VPC endpoint ids (#7382)
Browse files Browse the repository at this point in the history
  • Loading branch information
altrem committed Feb 25, 2020
1 parent 3e1e1f4 commit 19012a9
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 3 deletions.
18 changes: 18 additions & 0 deletions docs/providers/aws/events/apigateway.md
Expand Up @@ -655,6 +655,24 @@ functions:
method: get
```

API Gateway also supports the association of VPC endpoints if you have an API Gateway REST API using the PRIVATE endpoint configuration. This feature simplifies the invocation of a private API through the generation of the following AWS Route 53 alias:

```
https://<rest_api_id>-<vpc_endpoint_id>.execute-api.<aws_region>.amazonaws.com
```

Here's an example configuration:

```yml
service: my-service
provider:
name: aws
endpointType: PRIVATE
vpcEndpointIds:
- vpce-123
- vpce-456
```

### Request Parameters

To pass optional and required parameters to your functions, so you can use them in API Gateway tests and SDK generation, marking them as `true` will make them required, `false` will make them optional.
Expand Down
27 changes: 24 additions & 3 deletions lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js
Expand Up @@ -15,6 +15,7 @@ module.exports = {
this.apiGatewayRestApiLogicalId = this.provider.naming.getRestApiLogicalId();

let endpointType = 'EDGE';
let vpcEndpointIds;
let BinaryMediaTypes;
if (apiGateway.binaryMediaTypes) {
BinaryMediaTypes = apiGateway.binaryMediaTypes;
Expand All @@ -35,6 +36,28 @@ module.exports = {
throw new this.serverless.classes.Error(message);
}
endpointType = endpointType.toUpperCase();

if (this.serverless.service.provider.vpcEndpointIds) {
vpcEndpointIds = this.serverless.service.provider.vpcEndpointIds;

if (endpointType !== 'PRIVATE') {
throw new this.serverless.classes.Error(
'VPC endpoint IDs are only available for private APIs'
);
}

if (!Array.isArray(vpcEndpointIds)) {
throw new this.serverless.classes.Error('vpcEndpointIds must be an array');
}
}
}

const EndpointConfiguration = {
Types: [endpointType],
};

if (vpcEndpointIds) {
EndpointConfiguration.VpcEndpointIds = vpcEndpointIds;
}

_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
Expand All @@ -43,9 +66,7 @@ module.exports = {
Properties: {
Name: this.provider.naming.getApiGatewayName(),
BinaryMediaTypes,
EndpointConfiguration: {
Types: [endpointType],
},
EndpointConfiguration,
},
},
});
Expand Down
Expand Up @@ -169,6 +169,24 @@ describe('#compileRestApi()', () => {
expect(() => awsCompileApigEvents.compileRestApi()).to.not.throw(Error);
});

it('should compile if endpointType property is PRIVATE and vpcEndpointIds property is [id1]', () => {
awsCompileApigEvents.serverless.service.provider.endpointType = 'PRIVATE';
awsCompileApigEvents.serverless.service.provider.vpcEndpointIds = ['id1'];
expect(() => awsCompileApigEvents.compileRestApi()).to.not.throw(Error);
});

it('should throw error if endpointType property is PRIVATE and vpcEndpointIds property is not an array', () => {
awsCompileApigEvents.serverless.service.provider.endpointType = 'PRIVATE';
awsCompileApigEvents.serverless.service.provider.vpcEndpointIds = 'id1';
expect(() => awsCompileApigEvents.compileRestApi()).to.throw(Error);
});

it('should throw error if endpointType property is not PRIVATE and vpcEndpointIds property is [id1]', () => {
awsCompileApigEvents.serverless.service.provider.endpointType = 'Testing';
awsCompileApigEvents.serverless.service.provider.vpcEndpointIds = ['id1'];
expect(() => awsCompileApigEvents.compileRestApi()).to.throw(Error);
});

it('throw error if endpointType property is not EDGE or REGIONAL', () => {
awsCompileApigEvents.serverless.service.provider.endpointType = 'Testing';
expect(() => awsCompileApigEvents.compileRestApi()).to.throw('endpointType must be one of');
Expand Down

0 comments on commit 19012a9

Please sign in to comment.