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 - IAM authorizer support #17519

Merged
merged 55 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
01ee864
feat(apigatewayv2): add AWS_IAM authorizer support
misterjoshua Nov 16, 2021
b036ab6
refactor: use ?: optional syntax
misterjoshua Nov 16, 2021
c928252
refactor: make httpMethod a list
misterjoshua Nov 16, 2021
7651962
refactor: remove unneeded else block
misterjoshua Nov 16, 2021
f68870e
chore: expand on why authorizationType must be NONE
misterjoshua Nov 16, 2021
7baa434
refactor: add a safety error when iam is enabled and an authorizer set
misterjoshua Nov 16, 2021
a83a262
feat: add HttpIamAuthorizer
misterjoshua Nov 16, 2021
7190cbd
chore: update integ stack verification steps
misterjoshua Nov 16, 2021
7275bfa
docs: adjust some wording
misterjoshua Nov 16, 2021
7384149
remove enableIamAuthorization in favor of HttpIamAuthorization
misterjoshua Nov 16, 2021
dad0441
refactor: simplify the path variable logic to a replace
misterjoshua Nov 16, 2021
9e4440d
fix: add a single-trailing-newline to the readme
misterjoshua Nov 16, 2021
b8c6f3f
chore: improve the wording of the httpMethod option docs
misterjoshua Nov 16, 2021
6af5796
fix: iam authorizer example passes yarn rosetta:extract --strict
misterjoshua Nov 16, 2021
cf677de
fix: make the grantInvoke example work with rosetta:extract --strict
misterjoshua Nov 16, 2021
d8fa36e
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 17, 2021
1b36d28
refactor: better filename for iam authorizer
misterjoshua Nov 18, 2021
3326856
refactor: move the iam authorizer out of the authorizers package
misterjoshua Nov 18, 2021
1a18251
chore: remove the last of the other-package changes
misterjoshua Nov 18, 2021
e15ad8b
fix: export HttpIamAuthorizer so it is available alongside grantInvoke
misterjoshua Nov 18, 2021
b061e12
docs: add a grantInvoke example with defaultAuthorizer & integ test
misterjoshua Nov 20, 2021
876a361
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 20, 2021
962c301
refactor: change httpMethod -> httpMethods
misterjoshua Nov 20, 2021
48eaa71
fix: doc example no longerr gives rosetta warning
misterjoshua Nov 20, 2021
ec66563
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 21, 2021
fc5f640
feat: add routeArn
misterjoshua Nov 22, 2021
1ff91a6
fix: add th emissing @attribute doctag
misterjoshua Nov 22, 2021
de50380
refactor: change grantInvoke's default httpMethods to the route's method
misterjoshua Nov 22, 2021
58d1596
chore: remove unnecessary produceRouteArn default arg
misterjoshua Nov 22, 2021
a9875db
fix: align the title of the test with what it actually tests
misterjoshua Nov 22, 2021
b14b947
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 22, 2021
df4bfaf
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 25, 2021
089f7ba
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 26, 2021
ba92c36
Merge remote-tracking branch 'origin/master' into add-iam-authorizer
misterjoshua Nov 26, 2021
7517d0b
chore: test and update the integ test
misterjoshua Nov 26, 2021
58f1e26
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 26, 2021
11bdde5
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 29, 2021
6dc6fb1
chore: update the integ test so it works with 29039e8
misterjoshua Nov 29, 2021
d250a74
Merge branch 'master' into add-iam-authorizer
misterjoshua Nov 30, 2021
bf7e077
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 1, 2021
d31de47
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 2, 2021
5bd8bf6
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 3, 2021
488fd39
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 4, 2021
f546da0
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 5, 2021
1afe120
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 6, 2021
63bb1ff
refactor: review changes
misterjoshua Dec 7, 2021
c9dc5b1
refactor: further simplify HttpRouteKey
misterjoshua Dec 7, 2021
2d11bc5
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 13, 2021
b487850
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 14, 2021
007b1bd
Merge branch 'master' into add-iam-authorizer
misterjoshua Dec 16, 2021
fd3e10a
refactor: move the authorizer to the -authorizers package
misterjoshua Dec 17, 2021
e1e4a73
chore: remove some of the extraneous changes compared to master
misterjoshua Dec 17, 2021
8452922
chore: further cleanups
misterjoshua Dec 17, 2021
90ce8cf
chore: fix the docs
misterjoshua Dec 17, 2021
fb51b90
Merge branch 'master' into add-iam-authorizer
mergify[bot] Dec 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
25 changes: 25 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- [JWT Authorizers](#jwt-authorizers)
- [User Pool Authorizer](#user-pool-authorizer)
- [Lambda Authorizers](#lambda-authorizers)
- [IAM Authorizers](#iam-authorizers)
- [WebSocket APIs](#websocket-apis)
- [Lambda Authorizer](#lambda-authorizer)

Expand Down Expand Up @@ -199,6 +200,30 @@ api.addRoutes({
});
```

### IAM Authorizers

API Gateway supports IAM via the included `HttpIamAuthorizer` and grant syntax:

```ts
import { HttpIamAuthorizer } from '@aws-cdk/aws-apigatewayv2-authorizers';
import { HttpUrlIntegration } from '@aws-cdk/aws-apigatewayv2-integrations';

declare const principal: iam.AnyPrincipal;

const authorizer = new HttpIamAuthorizer();

const httpApi = new apigwv2.HttpApi(this, 'HttpApi', {
defaultAuthorizer: authorizer,
});

const routes = httpApi.addRoutes({
integration: new HttpUrlIntegration('BooksIntegration', 'https://get-books-proxy.myproxy.internal'),
path: '/books/{book}',
});

routes[0].grantInvoke(principal);
```

## WebSocket APIs

You can set an authorizer to your WebSocket API's `$connect` route to control access to your API.
Expand Down
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/iam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
HttpAuthorizerType,
HttpRouteAuthorizerBindOptions,
HttpRouteAuthorizerConfig,
IHttpRouteAuthorizer,
} from '@aws-cdk/aws-apigatewayv2';

/**
* Authorize HTTP API Routes with IAM
*/
export class HttpIamAuthorizer implements IHttpRouteAuthorizer {
public bind(_options: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig {
return {
authorizationType: HttpAuthorizerType.IAM,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './user-pool';
export * from './jwt';
export * from './lambda';
export * from './lambda';
export * from './iam';
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Construct } from 'constructs';
import { Duration, Stack } from '@aws-cdk/core';
import * as apigwv2 from '@aws-cdk/aws-apigatewayv2';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';

class Fixture extends Stack {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
{
"Resources": {
"User00B015A1": {
"Type": "AWS::IAM::User"
},
"UserDefaultPolicy1F97781E": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:execute-api:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "HttpApiF5A9A8A7"
},
"/*/*/foo"
]
]
}
},
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:execute-api:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "HttpApiF5A9A8A7"
},
"/*/*/books/*"
]
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "UserDefaultPolicy1F97781E",
"Users": [
{
"Ref": "User00B015A1"
}
]
}
},
"UserAccess": {
"Type": "AWS::IAM::AccessKey",
"Properties": {
"UserName": {
"Ref": "User00B015A1"
}
}
},
"HttpApiF5A9A8A7": {
"Type": "AWS::ApiGatewayV2::Api",
"Properties": {
"Name": "HttpApi",
"ProtocolType": "HTTP"
}
},
"HttpApiDefaultStage3EEB07D6": {
"Type": "AWS::ApiGatewayV2::Stage",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"StageName": "$default",
"AutoDeploy": true
}
},
"HttpApiANYfooexamplecom903F7A9F": {
"Type": "AWS::ApiGatewayV2::Integration",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"IntegrationType": "HTTP_PROXY",
"IntegrationMethod": "GET",
"IntegrationUri": "https://www.example.com/",
"PayloadFormatVersion": "1.0"
}
},
"HttpApiANYfooD178456F": {
"Type": "AWS::ApiGatewayV2::Route",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"RouteKey": "ANY /foo",
"AuthorizationType": "AWS_IAM",
"Target": {
"Fn::Join": [
"",
[
"integrations/",
{
"Ref": "HttpApiANYfooexamplecom903F7A9F"
}
]
]
}
}
},
"HttpApiANYbooksbookexamplecom5C333C98": {
"Type": "AWS::ApiGatewayV2::Integration",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"IntegrationType": "HTTP_PROXY",
"IntegrationMethod": "GET",
"IntegrationUri": "https://www.example.com/",
"PayloadFormatVersion": "1.0"
}
},
"HttpApiANYbooksbook2F78361C": {
"Type": "AWS::ApiGatewayV2::Route",
"Properties": {
"ApiId": {
"Ref": "HttpApiF5A9A8A7"
},
"RouteKey": "ANY /books/{book}",
"AuthorizationType": "AWS_IAM",
"Target": {
"Fn::Join": [
"",
[
"integrations/",
{
"Ref": "HttpApiANYbooksbookexamplecom5C333C98"
}
]
]
}
}
}
},
"Outputs": {
"API": {
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "HttpApiF5A9A8A7"
},
".execute-api.",
{
"Ref": "AWS::Region"
},
".",
{
"Ref": "AWS::URLSuffix"
},
"/"
]
]
}
},
"TESTACCESSKEYID": {
"Value": {
"Ref": "UserAccess"
}
},
"TESTSECRETACCESSKEY": {
"Value": {
"Fn::GetAtt": [
"UserAccess",
"SecretAccessKey"
]
}
},
"TESTREGION": {
"Value": {
"Ref": "AWS::Region"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as apigatewayv2 from '@aws-cdk/aws-apigatewayv2';
import * as iam from '@aws-cdk/aws-iam';
import * as cdk from '@aws-cdk/core';
import { HttpIamAuthorizer } from '../../lib';

class ExampleComIntegration extends apigatewayv2.HttpRouteIntegration {
public bind(): apigatewayv2.HttpRouteIntegrationConfig {
return {
type: apigatewayv2.HttpIntegrationType.HTTP_PROXY,
payloadFormatVersion: apigatewayv2.PayloadFormatVersion.VERSION_1_0,
method: apigatewayv2.HttpMethod.GET,
uri: 'https://www.example.com/',
};
}
}

const app = new cdk.App();
const stack = new cdk.Stack(app, 'IntegApiGatewayV2Iam');
const user = new iam.User(stack, 'User');
const userAccessKey = new iam.CfnAccessKey(stack, 'UserAccess', {
userName: user.userName,
});

const httpApi = new apigatewayv2.HttpApi(stack, 'HttpApi', {
defaultAuthorizer: new HttpIamAuthorizer(),
});

const [fooRoute] = httpApi.addRoutes({
integration: new ExampleComIntegration('examplecom'),
path: '/foo',
});

fooRoute.grantInvoke(user);

const [booksRoute] = httpApi.addRoutes({
integration: new ExampleComIntegration('examplecom'),
path: '/books/{book}',
});

booksRoute.grantInvoke(user);

new cdk.CfnOutput(stack, 'API', {
value: httpApi.url!,
});

new cdk.CfnOutput(stack, 'TESTACCESSKEYID', {
value: userAccessKey.ref,
});

new cdk.CfnOutput(stack, 'TESTSECRETACCESSKEY', {
value: userAccessKey.attrSecretAccessKey,
});

new cdk.CfnOutput(stack, 'TESTREGION', {
value: stack.region,
});

/*
* Stack verification steps:
* * Get cURL version 7.75.0 or later so you can use the --aws-sigv4 option
* * Curl <url>/foo without sigv4 and expect a 403
* * Curl <url>/books/something without sigv4 and expect a 403
* * Curl <url>/foo with sigv4 from the authorized user and expect 200
* * Curl <url>/books/something with sigv4 from the authorized user and expect 200
*
* Reference:
* * Using cURL 7.75.0 or later via the official docker image: docker run --rm curlimages/curl -s -o/dev/null -w"%{http_code}" <url>
* * Args to enable sigv4 with authorized credentials: --user "$TESTACCESSKEYID:$TESTSECRETACCESSKEY" --aws-sigv4 "aws:amz:$TESTREGION:execute-api"
*/
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/lib/http/authorizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { IHttpRoute } from './route';
* Supported Authorizer types
*/
export enum HttpAuthorizerType {
/** IAM Authorizer */
IAM = 'AWS_IAM',

/** JSON Web Tokens */
JWT = 'JWT',

Expand Down Expand Up @@ -221,6 +224,7 @@ export interface HttpRouteAuthorizerConfig {
* The type of authorization
*
* Possible values are:
* - AWS_IAM - IAM Authorizer
* - JWT - JSON Web Token Authorizer
* - CUSTOM - Lambda Authorizer
* - NONE - No Authorization
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigatewayv2/lib/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ export * from './route';
export * from './integration';
export * from './stage';
export * from './vpc-link';
export * from './authorizer';
export * from './authorizer';
Loading