diff --git a/.github/workflows/cloud.yml b/.github/workflows/cloud.yml index c130ce63..2e39d3c4 100644 --- a/.github/workflows/cloud.yml +++ b/.github/workflows/cloud.yml @@ -15,7 +15,7 @@ defaults: working-directory: ./cloud jobs: - code-checks: + lint-format: runs-on: ubuntu-latest strategy: matrix: diff --git a/cloud/.eslintrc.cjs b/cloud/.eslintrc.cjs index ea2b2802..3df03390 100644 --- a/cloud/.eslintrc.cjs +++ b/cloud/.eslintrc.cjs @@ -16,7 +16,7 @@ module.exports = { }, plugins: ['@typescript-eslint'], root: true, - ignorePatterns: ['node_modules', 'cdk.out'], + ignorePatterns: ['node_modules', 'cdk*.out'], rules: { eqeqeq: 'error', 'func-style': ['error', 'expression', { allowArrowFunctions: true }], diff --git a/cloud/.gitignore b/cloud/.gitignore index 5d6598a3..1f9d1a27 100644 --- a/cloud/.gitignore +++ b/cloud/.gitignore @@ -5,4 +5,4 @@ node_modules # CDK asset staging directory .cdk.staging -cdk.out +cdk*.out diff --git a/cloud/cdk.context.json b/cloud/cdk.context.json index 369def1e..51de282d 100644 --- a/cloud/cdk.context.json +++ b/cloud/cdk.context.json @@ -5,5 +5,13 @@ "eu-north-1b", "eu-north-1c" ], - "ami:account=992382568770:filters.image-type.0=machine:filters.name.0=fck-nat-al2023-*-x86_64-ebs:filters.state.0=available:owners.0=568608671756:region=eu-north-1": "ami-0acc1d35233e84277" + "ami:account=992382568770:filters.image-type.0=machine:filters.name.0=fck-nat-al2023-*-x86_64-ebs:filters.state.0=available:owners.0=568608671756:region=eu-north-1": "ami-0acc1d35233e84277", + "cloudfront-prefix-list:account=992382568770:region=eu-north-1": "pl-fab65393", + "availability-zones:account=992382568770:region=eu-west-1": [ + "eu-west-1a", + "eu-west-1b", + "eu-west-1c" + ], + "ami:account=992382568770:filters.image-type.0=machine:filters.name.0=fck-nat-al2023-*-x86_64-ebs:filters.state.0=available:owners.0=568608671756:region=eu-west-1": "ami-085252d6cf1b51097", + "cloudfront-prefix-list:account=992382568770:region=eu-west-1": "pl-4fa04526" } diff --git a/cloud/lib/api-stack.ts b/cloud/lib/api-stack.ts index 4ff661a5..2274909b 100644 --- a/cloud/lib/api-stack.ts +++ b/cloud/lib/api-stack.ts @@ -70,9 +70,11 @@ export class ApiStack extends Stack { directory: join(__dirname, '../../backend/'), }); - // TODO Look into IPv6 Routing, so no need for NAT Gateway or Instance! + // Look into IPv6 Routing, so no need for NAT Instance: // https://www.turbogeek.co.uk/aws-cdk-ipv6-v/ // https://docs.aws.amazon.com/vpc/latest/userguide/egress-only-internet-gateway.html + // NOTE: api.openai.com does not have an IPv6 address yet :( + // https://community.openai.com/t/ipv6-address-for-api-openai-com/339025 // AMI courtesy of fck-nat: https://fck-nat.dev/stable/deploying/#cdk const natGatewayProvider = NatInstanceProviderV2.instanceV2({ @@ -175,7 +177,11 @@ export class ApiStack extends Stack { priority: 1, }); listener.connections.allowDefaultPortFrom( - Peer.prefixList('pl-fab65393'), + Peer.prefixList( + this.node.tryGetContext( + `cloudfront-prefix-list:account=${env.account}:region=${region}` + ) as string + ), 'Allow incoming traffic only from CloudFront' ); diff --git a/cloud/lib/auth-stack.ts b/cloud/lib/auth-stack.ts index 898981aa..0537bb09 100644 --- a/cloud/lib/auth-stack.ts +++ b/cloud/lib/auth-stack.ts @@ -10,6 +10,7 @@ import { import { StringParameter } from 'aws-cdk-lib/aws-ssm'; import { CfnOutput, Duration, RemovalPolicy, Stack, StackProps, Tags } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; +import { randomUUID } from 'node:crypto'; import { appName, resourceId, stageName } from './resourceNamingUtils'; @@ -19,7 +20,7 @@ type AuthStackProps = StackProps & { export class AuthStack extends Stack { public readonly customAuthHeaderName = 'X-Origin-Verified'; - public readonly customAuthHeaderValue = 'todo-generate-uuid-in-pipeline'; + public readonly customAuthHeaderValue: string; public readonly parameterNameUserPoolId: string; public readonly parameterNameUserPoolClient: string; public readonly userPoolId: CfnOutput; @@ -37,6 +38,9 @@ export class AuthStack extends Stack { throw new Error('Region not defined in stack env, cannot continue!'); } + // Regenerated each time we deploy the stacks: + this.customAuthHeaderValue = randomUUID(); + /* User Pool - including attribute claims and password policy */ diff --git a/cloud/lib/lambdas/verifyAuth/index.ts b/cloud/lib/lambdas/verifyAuth/index.ts index 6b55923b..e3f66ff6 100644 --- a/cloud/lib/lambdas/verifyAuth/index.ts +++ b/cloud/lib/lambdas/verifyAuth/index.ts @@ -6,6 +6,7 @@ import type { CognitoVerifyProperties, CognitoJwtVerifierSingleUserPool, } from 'aws-jwt-verify/cognito-verifier'; +import type { CognitoAccessTokenPayload } from 'aws-jwt-verify/jwt-model'; import type { CloudFrontRequestEvent, CloudFrontResponse } from 'aws-lambda'; // Leave these alone! They are replaced verbatim by esbuild, see ui-stack @@ -98,9 +99,16 @@ export const handler = async (event: CloudFrontRequestEvent) => { } try { - // Maybe change to using cookie for tokens? - const accessToken = request.headers.authorization[0].value; - await verifier.verify(accessToken, {} as CognitoVerifyProperties); + const accessToken = request.headers.authorization[0]?.value; + if (!accessToken) return unauthorizedResponse; + + const jwt = (await verifier.verify(accessToken, { + tokenUse: 'access', + } as CognitoVerifyProperties)) as CognitoAccessTokenPayload; + // Maybe insert custom header for username? We could then log that at ALB, + // and generate metrics for user access. + console.log(`Access verified for [${jwt.username}]`); + return request; } catch (err: unknown) { console.log('Unable to verify access token', err); diff --git a/cloud/package.json b/cloud/package.json index cf64a73d..5332dffa 100644 --- a/cloud/package.json +++ b/cloud/package.json @@ -6,7 +6,7 @@ }, "scripts": { "cdk:synth": "cdk synth -q \"*\"", - "cdk:synth:prod": "cdk synth --context STAGE=prod -q \"*\"", + "cdk:synth:prod": "cdk synth --context STAGE=prod", "cdk:diff": "cdk diff --app cdk.out", "cdk:deploy": "cdk deploy --app cdk.out", "cdk:deploy:all": "cdk deploy --app cdk.out --all", @@ -14,8 +14,10 @@ "cdk:destroy:all": "cdk destroy --app cdk.out --all", "cdk:clean": "rimraf cdk.out", "cdk:test:synth": "cdk synth -o cdk.test.out -a \"npx ts-node --prefer-ts-exts -r dotenv/config bin/application.ts\"", - "cdk:test:deploy": "cdk deploy --app cdk.test.out --all", - "cdk:test:destroy": "cdk destroy --app cdk.test.out --all", + "cdk:test:deploy": "cdk deploy --app cdk.test.out", + "cdk:test:deploy:all": "cdk deploy --app cdk.test.out --all", + "cdk:test:destroy": "cdk destroy --app cdk.test.out", + "cdk:test:destroy:all": "cdk destroy --app cdk.test.out --all", "cdk:test:clean": "rimraf cdk.test.out", "codecheck": "concurrently \"npm run lint:check\" \"npm run format:check\"", "format": "prettier . --write", diff --git a/frontend/src/models/overlay.ts b/frontend/src/models/overlay.ts deleted file mode 100644 index 49b07db1..00000000 --- a/frontend/src/models/overlay.ts +++ /dev/null @@ -1,11 +0,0 @@ -enum OVERLAY_TYPE { - WELCOME, - HANDBOOK, - INFORMATION, - LEVELS_COMPLETE, - DOCUMENTS, - RESET_LEVEL, - RESET_PROGRESS, -} - -export { OVERLAY_TYPE };