Skip to content

Commit

Permalink
feat(apigateway): configure endpoint types on SpecRestApi (#9068)
Browse files Browse the repository at this point in the history
feat(apigateway): adding the ability to set the endpoint configuration for the OpenAPI 3.0

With this change, it will be possible to modify this by providing the endpointTypes as shown here:

```
const api = new apigateway.SpecRestApi(this, 'ExampleRestApi', {
  apiDefinition: apigateway.ApiDefinition.fromInline(replacedSwagger),
  endpointTypes: [apigateway.EndpointType.PRIVATE],
});
```
Note: For private endpoints you will still need to provide the `x-amazon-apigateway-endpoint-configuration` and `x-amazon-apigateway-policy` in your openApi file.

The following is an example with both settings:
```json
{
    "openapi": "3.0.2",
    "servers" : [
      {
        "x-amazon-apigateway-endpoint-configuration": {
          "vpcEndpointIds": [
            "vpce-00111a1111a1aa011"
          ]
        }
      }
    ],
    "paths": { ... },
    "x-amazon-apigateway-policy": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": "*",
                "Action": [
                    "execute-api:Invoke",
                    "execute-api:GET"
                ],
                "Resource": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*",
                "Condition": {
                    "StringEquals": {
                      "aws:sourceVpce": "vpce-00111a1111a1aa011"
                    }
                }
            }
        ]
    }
}
```

Checklist for this PR:
🧪 Testing: adding integration testing for private API gateway.
📄 Docs: Add example in the README documentation about how to create a private API gateway with swagger

Fixes #9060

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
  • Loading branch information
IsmaelMartinez committed Aug 4, 2020
1 parent e3f6ae3 commit 7673e48
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 30 deletions.
21 changes: 20 additions & 1 deletion packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ running on AWS Lambda, or any web application.
- [Private Integrations](#private-integrations)
- [Gateway Response](#gateway-response)
- [OpenAPI Definition](#openapi-definition)
- [Endpoint configuration](#endpoint-configuration)
- [APIGateway v2](#apigateway-v2)

## Defining APIs
Expand Down Expand Up @@ -992,11 +993,29 @@ to configure these.
There are a number of limitations in using OpenAPI definitions in API Gateway. Read the [Amazon API Gateway important
notes for REST APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html#api-gateway-known-issues-rest-apis)
for more details.
**Note:** When starting off with an OpenAPI definition using `SpecRestApi`, it is not possible to configure some
properties that can be configured directly in the OpenAPI specification file. This is to prevent people duplication
of these properties and potential confusion.
### Endpoint configuration
By default, `SpecRestApi` will create an edge optimized endpoint.
This can be modified as shown below:
```ts
const api = new apigateway.SpecRestApi(this, 'ExampleRestApi', {
// ...
endpointTypes: [apigateway.EndpointType.PRIVATE]
});
```
**Note:** For private endpoints you will still need to provide the
[`x-amazon-apigateway-policy`](https://docs.aws.amazon.com/apigateway/latest/developerguide/openapi-extensions-policy.html) and
[`x-amazon-apigateway-endpoint-configuration`](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-endpoint-configuration.html)
in your openApi file.
## APIGateway v2
APIGateway v2 APIs are now moved to its own package named `aws-apigatewayv2`. For backwards compatibility, existing
Expand Down
61 changes: 32 additions & 29 deletions packages/@aws-cdk/aws-apigateway/lib/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ export interface RestApiBaseProps {
* @default - when no export name is given, output will be created without export
*/
readonly endpointExportName?: string;

/**
* A list of the endpoint types of the API. Use this property when creating
* an API.
*
* @default EndpointType.EDGE
*/
readonly endpointTypes?: EndpointType[];
}

/**
Expand Down Expand Up @@ -218,18 +226,9 @@ export interface RestApiProps extends RestApiOptions {
* The EndpointConfiguration property type specifies the endpoint types of a REST API
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-restapi-endpointconfiguration.html
*
* @default - No endpoint configuration
* @default EndpointType.EDGE
*/
readonly endpointConfiguration?: EndpointConfiguration;

/**
* A list of the endpoint types of the API. Use this property when creating
* an API.
*
* @default - No endpoint types.
* @deprecated this property is deprecated, use endpointConfiguration instead
*/
readonly endpointTypes?: EndpointType[];
}

/**
Expand Down Expand Up @@ -423,6 +422,25 @@ export abstract class RestApiBase extends Resource implements IRestApi {
}
}
}

/**
* @internal
*/
protected _configureEndpoints(props: RestApiProps): CfnRestApi.EndpointConfigurationProperty | undefined {
if (props.endpointTypes && props.endpointConfiguration) {
throw new Error('Only one of the RestApi props, endpointTypes or endpointConfiguration, is allowed');
}
if (props.endpointConfiguration) {
return {
types: props.endpointConfiguration.types,
vpcEndpointIds: props.endpointConfiguration?.vpcEndpoints?.map(vpcEndpoint => vpcEndpoint.vpcEndpointId),
};
}
if (props.endpointTypes) {
return { types: props.endpointTypes };
}
return undefined;
}
}

/**
Expand Down Expand Up @@ -463,6 +481,7 @@ export class SpecRestApi extends RestApiBase {
failOnWarnings: props.failOnWarnings,
body: apiDefConfig.inlineDefinition ? apiDefConfig.inlineDefinition : undefined,
bodyS3Location: apiDefConfig.inlineDefinition ? undefined : apiDefConfig.s3Location,
endpointConfiguration: this._configureEndpoints(props),
parameters: props.parameters,
});
this.node.defaultChild = resource;
Expand Down Expand Up @@ -560,7 +579,7 @@ export class RestApi extends RestApiBase {
failOnWarnings: props.failOnWarnings,
minimumCompressionSize: props.minimumCompressionSize,
binaryMediaTypes: props.binaryMediaTypes,
endpointConfiguration: this.configureEndpoints(props),
endpointConfiguration: this._configureEndpoints(props),
apiKeySourceType: props.apiKeySourceType,
cloneFrom: props.cloneFrom ? props.cloneFrom.restApiId : undefined,
parameters: props.parameters,
Expand Down Expand Up @@ -639,22 +658,6 @@ export class RestApi extends RestApiBase {

return [];
}

private configureEndpoints(props: RestApiProps): CfnRestApi.EndpointConfigurationProperty | undefined {
if (props.endpointTypes && props.endpointConfiguration) {
throw new Error('Only one of the RestApi props, endpointTypes or endpointConfiguration, is allowed');
}
if (props.endpointConfiguration) {
return {
types: props.endpointConfiguration.types,
vpcEndpointIds: props.endpointConfiguration?.vpcEndpoints?.map(vpcEndpoint => vpcEndpoint.vpcEndpointId),
};
}
if (props.endpointTypes) {
return { types: props.endpointTypes };
}
return undefined;
}
}

/**
Expand All @@ -666,7 +669,7 @@ export interface EndpointConfiguration {
/**
* A list of endpoint types of an API or its custom domain name.
*
* @default - no endpoint types.
* @default EndpointType.EDGE
*/
readonly types: EndpointType[];

Expand Down Expand Up @@ -752,4 +755,4 @@ class RootResource extends ResourceBase {

function ignore(_x: any) {
return;
}
}
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/test.restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1018,5 +1018,29 @@ export = {
}));
test.done();
},

'"endpointTypes" can be used to specify endpoint configuration for SpecRestApi'(test: Test) {
// GIVEN
const stack = new Stack();

// WHEN
const api = new apigw.SpecRestApi(stack, 'api', {
apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }),
endpointTypes: [ apigw.EndpointType.EDGE, apigw.EndpointType.PRIVATE ],
});

api.root.addMethod('GET');

// THEN
expect(stack).to(haveResource('AWS::ApiGateway::RestApi', {
EndpointConfiguration: {
Types: [
'EDGE',
'PRIVATE',
],
},
}));
test.done();
},
},
};

0 comments on commit 7673e48

Please sign in to comment.