-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi-stack.ts
More file actions
81 lines (72 loc) · 3.58 KB
/
Copy pathapi-stack.ts
File metadata and controls
81 lines (72 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { CfnOutput, Duration, Stack, StackProps, Tags } from 'aws-cdk-lib';
import { CorsHttpMethod, HttpApi, HttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpUserPoolAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import { IUserPool, IUserPoolClient } from 'aws-cdk-lib/aws-cognito';
import { ITable } from 'aws-cdk-lib/aws-dynamodb';
import { Code, Function as LambdaFunction, Runtime } from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
import * as path from 'path';
import { EnvName } from './env';
export interface ApiStackProps extends StackProps {
readonly envName: EnvName;
readonly tenantTable: ITable;
readonly userPool: IUserPool;
readonly userPoolClient: IUserPoolClient;
}
/**
* The first real request path (roadmap architecture diagram's `web_api`; ADR-0024): an HTTP API
* behind a Cognito JWT authorizer, one Lambda handler, `GET /me`.
*
* `GET /me` exists to prove the chain end to end, not as a feature: Cognito issues a JWT (ADR-
* 0022) → the HTTP API's `HttpUserPoolAuthorizer` verifies it before the Lambda ever runs → the
* handler (`openjobradar.lambda_handlers.me`) reads `sub` from the verified claims, builds a
* `TenantContext`, and calls `ProvisioningService`/`EntitlementsService` against a real
* `DynamoStore` (ADR-0023) — every one of those pieces already existed and was already tested;
* this stack is the wiring, not new logic.
*
* **No Docker bundling.** The handler only imports `openjobradar.tenancy`/`openjobradar.control`
* (`boto3` only — ships pre-installed in every Lambda Python runtime); `Code.fromAsset` zips
* `src/` verbatim with no dependency-install step, so `cdk synth`/`cdk deploy` need nothing this
* repo's CI doesn't already have. `openjobradar.config` (which needs `PyYAML`/`jsonschema`,
* neither bundled) stays unreachable from this handler — see `docs/adr/0024-first-api-lambda.md`
* for what that constrains for any handler added here later.
*/
export class ApiStack extends Stack {
public readonly httpApi: HttpApi;
public readonly meFunction: LambdaFunction;
constructor(scope: Construct, id: string, props: ApiStackProps) {
super(scope, id, props);
this.meFunction = new LambdaFunction(this, 'MeFunction', {
runtime: Runtime.PYTHON_3_12,
handler: 'openjobradar.lambda_handlers.me.handler',
code: Code.fromAsset(path.join(__dirname, '..', '..', 'src'), {
exclude: ['**/__pycache__/**', '**/*.pyc'],
}),
environment: { TENANT_TABLE_NAME: props.tenantTable.tableName },
timeout: Duration.seconds(10),
memorySize: 256,
});
props.tenantTable.grantReadWriteData(this.meFunction);
const authorizer = new HttpUserPoolAuthorizer('CognitoAuthorizer', props.userPool, {
userPoolClients: [props.userPoolClient],
});
this.httpApi = new HttpApi(this, 'HttpApi', {
apiName: `openjobradar-${props.envName}`,
corsPreflight: {
allowMethods: [CorsHttpMethod.GET],
allowOrigins: props.envName === 'dev' ? ['*'] : [], // stage/prod: tighten to the real web origin when it exists
allowHeaders: ['Authorization', 'Content-Type'],
},
});
this.httpApi.addRoutes({
path: '/me',
methods: [HttpMethod.GET],
integration: new HttpLambdaIntegration('MeIntegration', this.meFunction),
authorizer,
});
Tags.of(this).add('openjobradar:env', props.envName);
Tags.of(this).add('openjobradar:stack', 'api');
new CfnOutput(this, 'HttpApiUrl', { value: this.httpApi.apiEndpoint });
}
}