Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apigatewayv2): http api - lambda authorizer #13181

Merged
merged 55 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
1ba6b83
feat(apigatewayv2): Add lambda authorizers
iRoachie Feb 21, 2021
73ebebd
add tests
iRoachie Feb 21, 2021
682d427
add test for payload, type mismatch
iRoachie Feb 21, 2021
7e8ccda
add docs
iRoachie Feb 21, 2021
34191d1
Add integ test
iRoachie Feb 21, 2021
957e560
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Feb 21, 2021
8a80217
nit: add newline character
iRoachie Feb 21, 2021
630ea2e
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Feb 21, 2021
0a53c51
update route to authorizer logic
iRoachie Feb 25, 2021
d67566c
docs: add doc string
iRoachie Feb 25, 2021
1b0adce
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Feb 25, 2021
5def7eb
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Mar 6, 2021
5949bd4
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Mar 17, 2021
9129a9d
docs: simply readme
iRoachie Mar 17, 2021
33763de
fix: move NONE to HttpRouteAuthorizerType
iRoachie Mar 17, 2021
91cd3a7
test: update integ
iRoachie Mar 17, 2021
25896dd
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Mar 25, 2021
c1aeade
chore: sort packages alphabetically
iRoachie Mar 25, 2021
a32ab8e
refactor: rename AuthorizerPayloadFormatVersion
iRoachie Mar 25, 2021
ff7809e
Update packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts
iRoachie Mar 25, 2021
1d45c5c
refactor: use response type for payload version
iRoachie Mar 25, 2021
7d31b59
docs: typo
iRoachie Mar 25, 2021
f295716
feat: allow returning iam policy with simple responses
iRoachie Mar 29, 2021
9f49b11
update expected test result
iRoachie Mar 29, 2021
cf87e5c
feat: set AuthorizerPayloadVersion.VERSION_2_0 for lambda authorizer
iRoachie Mar 29, 2021
351e0f6
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Mar 29, 2021
c00fcb8
Update packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts
iRoachie Mar 29, 2021
02f7059
Update packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ…
iRoachie Mar 29, 2021
7ef4c28
update integ for changes
iRoachie Mar 29, 2021
8d71ab6
remove IAM_SIMPLE, not needed
iRoachie Mar 29, 2021
ecc81d1
Update packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md
iRoachie Mar 29, 2021
37123c1
Update packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts
iRoachie Mar 30, 2021
5f6ce4e
chore: rename auth handler folder as per request
iRoachie Mar 31, 2021
c18045c
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie Mar 31, 2021
0d212da
make resultsCacheTtl default clearer
iRoachie Mar 31, 2021
db1a144
refactor: make authorizerName required
iRoachie Mar 31, 2021
6917caf
specify default for enableSimpleResponses
iRoachie Mar 31, 2021
fe6ae39
add catch for adding same authorizer to multiple apis
iRoachie Mar 31, 2021
df711fb
set default response type to be IAM
iRoachie Mar 31, 2021
dfa0780
feat: add invocationUri to IFunction
iRoachie Mar 31, 2021
15066dc
Revert "feat: add invocationUri to IFunction"
iRoachie May 2, 2021
7504489
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie May 2, 2021
1b3e30b
fix integ test
iRoachie May 2, 2021
caae4b7
update imports for assert
iRoachie May 2, 2021
4b90a2f
feat: add permission to invoke lambda
iRoachie May 2, 2021
ea51b9d
Rename HttpRouteAuthorizerType
iRoachie May 3, 2021
28351ac
feat: revert to using construct from constructs
iRoachie May 11, 2021
0a4f566
Update packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ…
iRoachie May 11, 2021
0107383
feat: remove public HttpRouteAuthorizerType
iRoachie May 11, 2021
162f8de
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie May 11, 2021
9aebab0
remove unnecessary enum
iRoachie May 11, 2021
007f5c9
Merge branch 'master' into ft/http-api-lambda-authorizers
iRoachie May 14, 2021
9d11f0c
fix upstream changes
iRoachie May 14, 2021
d00988d
refactor: use explicit guard for authorizationType
iRoachie May 14, 2021
681c46f
Merge branch 'master' into ft/http-api-lambda-authorizers
mergify[bot] May 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Route Authorization](#route-authorization)
- [JWT Authorizers](#jwt-authorizers)
- [User Pool Authorizer](#user-pool-authorizer)
- [Lambda Authorizers](#lambda-authorizers)

## Introduction

Expand Down Expand Up @@ -162,3 +163,32 @@ api.addRoutes({
authorizer,
});
```

## Lambda Authorizers

Lambda authorizers use a Lambda function to control access to your HTTP API. When a client calls your API, API Gateway invokes your Lambda function and uses the response to determine whether the client can access your API.

Lambda authorizers depending on their response, fall into either two types - Simple or IAM. You can learn about differences [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.payload-format-response).


```ts
// This function handles your auth logic
const authHandler = new Function(this, 'auth-function', {
//...
});

const authorizer = new HttpLambdaAuthorizer({
responseTypes: [HttpLambdaAuthorizerType.SIMPLE] // Define if returns simple and/or iam response
handler: authHandler,
});

const api = new HttpApi(stack, 'HttpApi');

api.addRoutes({
integration: new HttpProxyIntegration({
url: 'https://get-books-proxy.myproxy.internal',
}),
path: '/books',
authorizer,
});
```
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './user-pool';
export * from './jwt';
export * from './jwt';
export * from './lambda';
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class HttpJwtAuthorizer implements IHttpRouteAuthorizer {

return {
authorizerId: this.authorizer.authorizerId,
authorizationType: HttpAuthorizerType.JWT,
authorizationType: 'JWT',
};
}
}
130 changes: 130 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {
HttpAuthorizer,
HttpAuthorizerType,
HttpRouteAuthorizerBindOptions,
HttpRouteAuthorizerConfig,
IHttpRouteAuthorizer,
AuthorizerPayloadVersion,
IHttpApi,
} from '@aws-cdk/aws-apigatewayv2';
import { ServicePrincipal } from '@aws-cdk/aws-iam';
import { IFunction } from '@aws-cdk/aws-lambda';
import { Stack, Duration, Names } from '@aws-cdk/core';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct as CoreConstruct } from '@aws-cdk/core';

/**
* Specifies the type responses the lambda returns
*/
export enum HttpLambdaResponseType {
/** Returns simple boolean response */
SIMPLE,

/** Returns an IAM Policy */
IAM,
}

/**
* Properties to initialize HttpTokenAuthorizer.
*/
export interface HttpLambdaAuthorizerProps {

/**
* The name of the authorizer
*/
readonly authorizerName: string;

/**
* The identity source for which authorization is requested.
*
* @default ['$request.header.Authorization']
*/
readonly identitySource?: string[];

/**
* The lambda function used for authorization
*/
readonly handler: IFunction;

/**
* How long APIGateway should cache the results. Max 1 hour.
* Disable caching by setting this to `Duration.seconds(0)`.
*
* @default Duration.minutes(5)
*/
readonly resultsCacheTtl?: Duration;

/**
* The types of responses the lambda can return
*
* If HttpLambdaResponseType.SIMPLE is included then
* response format 2.0 will be used.
iRoachie marked this conversation as resolved.
Show resolved Hide resolved
*
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.payload-format-response
*
* @default [HttpLambdaResponseType.IAM]
*/
readonly responseTypes?: HttpLambdaResponseType[];
}

/**
* Authorize Http Api routes via a lambda function
*/
export class HttpLambdaAuthorizer implements IHttpRouteAuthorizer {
private authorizer?: HttpAuthorizer;
private httpApi?: IHttpApi;

constructor(private readonly props: HttpLambdaAuthorizerProps) {
}

public bind(options: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig {
if (this.httpApi && (this.httpApi.apiId !== options.route.httpApi.apiId)) {
throw new Error('Cannot attach the same authorizer to multiple Apis');
}

if (!this.authorizer) {
nija-at marked this conversation as resolved.
Show resolved Hide resolved
const id = this.props.authorizerName;

const responseTypes = this.props.responseTypes ?? [HttpLambdaResponseType.IAM];
const enableSimpleResponses = responseTypes.includes(HttpLambdaResponseType.SIMPLE) || undefined;

this.httpApi = options.route.httpApi;
this.authorizer = new HttpAuthorizer(options.scope, id, {
httpApi: options.route.httpApi,
identitySource: this.props.identitySource ?? [
'$request.header.Authorization',
],
type: HttpAuthorizerType.LAMBDA,
authorizerName: this.props.authorizerName,
enableSimpleResponses,
payloadFormatVersion: enableSimpleResponses ? AuthorizerPayloadVersion.VERSION_2_0 : AuthorizerPayloadVersion.VERSION_1_0,
authorizerUri: lambdaAuthorizerArn(this.props.handler),
resultsCacheTtl: this.props.resultsCacheTtl ?? Duration.minutes(5),
});

this.props.handler.addPermission(`${Names.nodeUniqueId(this.authorizer.node)}-Permission`, {
scope: options.scope as CoreConstruct,
principal: new ServicePrincipal('apigateway.amazonaws.com'),
sourceArn: Stack.of(options.route).formatArn({
service: 'execute-api',
resource: options.route.httpApi.apiId,
resourceName: `authorizers/${this.authorizer.authorizerId}`,
}),
});
}

return {
authorizerId: this.authorizer.authorizerId,
authorizationType: 'CUSTOM',
};
}
}

/**
* constructs the authorizerURIArn.
*/
function lambdaAuthorizerArn(handler: IFunction) {
return `arn:${Stack.of(handler).partition}:apigateway:${Stack.of(handler).region}:lambda:path/2015-03-31/functions/${handler.functionArn}/invocations`;
iRoachie marked this conversation as resolved.
Show resolved Hide resolved
}
nija-at marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class HttpUserPoolAuthorizer implements IHttpRouteAuthorizer {

return {
authorizerId: this.authorizer.authorizerId,
authorizationType: HttpAuthorizerType.JWT,
authorizationType: 'JWT',
};
}
}
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,16 @@
"dependencies": {
"@aws-cdk/aws-apigatewayv2": "0.0.0",
"@aws-cdk/aws-cognito": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
iRoachie marked this conversation as resolved.
Show resolved Hide resolved
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
"peerDependencies": {
"@aws-cdk/aws-apigatewayv2": "0.0.0",
"@aws-cdk/aws-cognito": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable no-console */

export const handler = async (event: AWSLambda.APIGatewayProxyEventV2) => {
const key = event.headers['x-api-key'];

return {
isAuthorized: key === '123',
};
};
Loading