Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Oct 12, 2022
2 parents d3796e3 + 700f9c4 commit 9bce521
Show file tree
Hide file tree
Showing 861 changed files with 32,119 additions and 4,269 deletions.
2 changes: 1 addition & 1 deletion docs/DESIGN_GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ new lambda.Function(this, 'MyFunction', {
code: lambda.Code.bucket(myBucket, 'bundle.zip'), // or
code: lambda.Code.inline('code')
// etc
}
})
```

### Attributes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"devDependencies": {
"@types/prettier": "2.6.0",
"@yarnpkg/lockfile": "^1.1.0",
"cdk-generate-synthetic-examples": "^0.1.23",
"cdk-generate-synthetic-examples": "^0.1.29",
"conventional-changelog-cli": "^2.2.2",
"fs-extra": "^9.1.0",
"graceful-fs": "^4.2.10",
Expand Down
64 changes: 62 additions & 2 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,22 @@ declare const lambdaFn: lambda.Function;
importedKey.grantRead(lambdaFn);
```

### Adding an API Key to an imported RestApi

API Keys are added to ApiGateway Stages, not to the API itself. When you import a RestApi
it does not have any information on the Stages that may be associated with it. Since adding an API
Key requires a stage, you should instead add the Api Key to the imported Stage.

```ts
declare const restApi: apigateway.IRestApi;
const importedStage = apigateway.Stage.fromStageAttributes(this, 'imported-stage', {
stageName: 'myStageName',
restApi,
});

importedStage.addApiKey('MyApiKey');
```

### ⚠️ Multiple API Keys

It is possible to specify multiple API keys for a given Usage Plan, by calling `usagePlan.addApiKey()`.
Expand Down Expand Up @@ -426,7 +442,7 @@ declare const api: apigateway.RestApi;

const key = new apigateway.RateLimitedApiKey(this, 'rate-limited-api-key', {
customerId: 'hello-customer',
resources: [api],
stages: [api.deploymentStage],
quota: {
limit: 10000,
period: apigateway.Period.MONTH
Expand Down Expand Up @@ -724,7 +740,51 @@ books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {

A full working example is shown below.

[Full token authorizer example](test/authorizers/integ.token-authorizer.lit.ts).
```ts
import * as path from 'path';
import * as lambda from '@aws-cdk/aws-lambda';
import { App, Stack } from '@aws-cdk/core';
import { MockIntegration, PassthroughBehavior, RestApi, TokenAuthorizer, Cors } from '../../lib';

/// !show
const app = new App();
const stack = new Stack(app, 'TokenAuthorizerInteg');

const authorizerFn = new lambda.Function(stack, 'MyAuthorizerFunction', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.token-authorizer.handler')),
});

const authorizer = new TokenAuthorizer(stack, 'MyAuthorizer', {
handler: authorizerFn,
});

const restapi = new RestApi(stack, 'MyRestApi', {
cloudWatchRole: true,
defaultMethodOptions: {
authorizer,
},
defaultCorsPreflightOptions: {
allowOrigins: Cors.ALL_ORIGINS,
},
});


restapi.root.addMethod('ANY', new MockIntegration({
integrationResponses: [
{ statusCode: '200' },
],
passthroughBehavior: PassthroughBehavior.NEVER,
requestTemplates: {
'application/json': '{ "statusCode": 200 }',
},
}), {
methodResponses: [
{ statusCode: '200' },
],
});
```

By default, the `TokenAuthorizer` looks for the authorization token in the request header with the key 'Authorization'. This can,
however, be modified by changing the `identitySource` property.
Expand Down
41 changes: 31 additions & 10 deletions packages/@aws-cdk/aws-apigateway/lib/api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Construct } from 'constructs';
import { CfnApiKey } from './apigateway.generated';
import { ResourceOptions } from './resource';
import { IRestApi } from './restapi';
import { IStage } from './stage';
import { QuotaSettings, ThrottleSettings, UsagePlan, UsagePlanPerApiStage } from './usage-plan';

/**
Expand Down Expand Up @@ -56,9 +57,17 @@ export interface ApiKeyProps extends ApiKeyOptions {
/**
* A list of resources this api key is associated with.
* @default none
* @deprecated - use `stages` instead
*/
readonly resources?: IRestApi[];

/**
* A list of Stages this api key is associated with.
*
* @default - the api key is not associated with any stages
*/
readonly stages?: IStage[];

/**
* An AWS Marketplace customer identifier to use when integrating with the AWS SaaS Marketplace.
* @link http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html#cfn-apigateway-apikey-customerid
Expand Down Expand Up @@ -168,7 +177,7 @@ export class ApiKey extends ApiKeyBase {
enabled: props.enabled ?? true,
generateDistinctId: props.generateDistinctId,
name: this.physicalName,
stageKeys: this.renderStageKeys(props.resources),
stageKeys: this.renderStageKeys(props.resources, props.stages),
value: props.value,
});

Expand All @@ -182,17 +191,29 @@ export class ApiKey extends ApiKeyBase {
});
}

private renderStageKeys(resources: IRestApi[] | undefined): CfnApiKey.StageKeyProperty[] | undefined {
if (!resources) {
private renderStageKeys(resources?: IRestApi[], stages?: IStage[]): CfnApiKey.StageKeyProperty[] | undefined {
if (!resources && !stages) {
return undefined;
}

return resources.map((resource: IRestApi) => {
const restApi = resource;
const restApiId = restApi.restApiId;
const stageName = restApi.deploymentStage!.stageName.toString();
return { restApiId, stageName };
});
if (resources && stages) {
throw new Error('Only one of "resources" or "stages" should be provided');
}

return resources
? resources.map((resource: IRestApi) => {
const restApi = resource;
if (!restApi.deploymentStage) {
throw new Error('Cannot add an ApiKey to a RestApi that does not contain a "deploymentStage".\n'+
'Either set the RestApi.deploymentStage or create an ApiKey from a Stage');
}
const restApiId = restApi.restApiId;
const stageName = restApi.deploymentStage!.stageName.toString();
return { restApiId, stageName };
})
: stages ? stages.map((stage => {
return { restApiId: stage.restApi.restApiId, stageName: stage.stageName };
})) : undefined;
}
}

Expand Down Expand Up @@ -258,4 +279,4 @@ const writePermissions = [
'apigateway:PUT',
'apigateway:PATCH',
'apigateway:DELETE',
];
];
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/lib/domain-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export interface DomainNameOptions {
/**
* The Transport Layer Security (TLS) version + cipher suite for this domain name.
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-domainname.html
* @default SecurityPolicy.TLS_1_0
* @default SecurityPolicy.TLS_1_2
*/
readonly securityPolicy?: SecurityPolicy;

Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/lib/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class Method extends Resource {

const defaultMethodOptions = props.resource.defaultMethodOptions || {};
const authorizer = options.authorizer || defaultMethodOptions.authorizer;
const authorizerId = authorizer?.authorizerId;
const authorizerId = authorizer?.authorizerId ? authorizer.authorizerId : undefined;

const authorizationTypeOption = options.authorizationType || defaultMethodOptions.authorizationType;
const authorizationType = authorizer?.authorizationType || authorizationTypeOption || AuthorizationType.NONE;
Expand Down
8 changes: 7 additions & 1 deletion packages/@aws-cdk/aws-apigateway/lib/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CfnResource, CfnResourceProps } from './apigateway.generated';
import { Cors, CorsOptions } from './cors';
import { Integration } from './integration';
import { MockIntegration } from './integrations';
import { Method, MethodOptions } from './method';
import { Method, MethodOptions, AuthorizationType } from './method';
import { IRestApi, RestApi } from './restapi';

export interface IResource extends IResourceBase {
Expand Down Expand Up @@ -296,6 +296,12 @@ export abstract class ResourceBase extends ResourceConstruct implements IResourc
{ statusCode: `${statusCode}`, responseParameters: integrationResponseParams, responseTemplates: renderResponseTemplate() },
],
}), {
authorizer: {
authorizerId: '',
authorizationType: AuthorizationType.NONE,
},
apiKeyRequired: false,
authorizationType: AuthorizationType.NONE,
methodResponses: [
{ statusCode: `${statusCode}`, responseParameters: methodResponseParams },
],
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-apigateway/lib/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,11 @@ export abstract class RestApiBase extends Resource implements IRestApi {
}

/**
* Add an ApiKey
* Add an ApiKey to the deploymentStage
*/
public addApiKey(id: string, options?: ApiKeyOptions): IApiKey {
return new ApiKey(this, id, {
resources: [this],
stages: [this.deploymentStage],
...options,
});
}
Expand Down
Loading

0 comments on commit 9bce521

Please sign in to comment.