From 704b7e93310a099844d28646f9f0f8111d775133 Mon Sep 17 00:00:00 2001 From: Ken Date: Mon, 16 Dec 2024 18:58:40 +0800 Subject: [PATCH 1/3] feat: expose .well-known --- .ebextensions/01env-file-aws-ssm.config | 1 + .../config/features/formsg-sdk-jwks.config.ts | 17 +++++++++++++ src/app/loaders/express/index.ts | 8 +++---- src/app/routes/.well-known/index.ts | 24 +++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 src/app/config/features/formsg-sdk-jwks.config.ts create mode 100644 src/app/routes/.well-known/index.ts diff --git a/.ebextensions/01env-file-aws-ssm.config b/.ebextensions/01env-file-aws-ssm.config index a7f16a54ad..d9bbde264e 100644 --- a/.ebextensions/01env-file-aws-ssm.config +++ b/.ebextensions/01env-file-aws-ssm.config @@ -46,6 +46,7 @@ files: aws ssm get-parameter --name "${ENV_TYPE}-verified-fields" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env aws ssm get-parameter --name "${ENV_TYPE}-webhook-verified-content" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env aws ssm get-parameter --name "${ENV_TYPE}-wogaa" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env + aws ssm get-parameter --name "/${ENV_TYPE}/formsg-sdk/jwks" --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env aws ssm get-parameter --name "${ENV_SITE_NAME}-sgid" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env aws ssm get-parameter --name "${ENV_SITE_NAME}-payment" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env aws ssm get-parameter --name "${ENV_SITE_NAME}-cron-payment" --with-decryption --region $AWS_REGION | jq -r '.Parameter.Value' >> $TARGET_DIR/.env diff --git a/src/app/config/features/formsg-sdk-jwks.config.ts b/src/app/config/features/formsg-sdk-jwks.config.ts new file mode 100644 index 0000000000..7c7f996a05 --- /dev/null +++ b/src/app/config/features/formsg-sdk-jwks.config.ts @@ -0,0 +1,17 @@ +import convict, { Schema } from 'convict' + +type FormSgSdkJwks = { + publicJwks: string +} + +const formSgSdkJwksSchema: Schema = { + publicJwks: { + doc: 'JSON Web Key Set for FormSG SDK', + format: String, + default: null, // required field + env: 'FORMSG_SDK_PUBLIC_JWKS', + }, +} +export const formSgSdkJwksConfig = convict(formSgSdkJwksSchema) + .validate({ allowed: 'strict' }) + .getProperties() diff --git a/src/app/loaders/express/index.ts b/src/app/loaders/express/index.ts index abfeada8b8..b7c9647bb6 100644 --- a/src/app/loaders/express/index.ts +++ b/src/app/loaders/express/index.ts @@ -12,6 +12,7 @@ import * as IntranetMiddleware from '../../modules/intranet/intranet.middleware' import { MYINFO_ROUTER_PREFIX } from '../../modules/myinfo/myinfo.constants' import { MyInfoRouter } from '../../modules/myinfo/myinfo.routes' import { SgidRouter } from '../../modules/sgid/sgid.routes' +import { WellKnownRouter } from '../../routes/./.well-known' import { ApiRouter } from '../../routes/api' import { LegacyRedirectRouter } from '../../routes/legacy-redirect' import { SpOidcJwksRouter } from '../../routes/singpass' @@ -123,6 +124,8 @@ const loadExpressApp = async (connection: Connection) => { app.use('/sgid', SgidRouter) app.use(MYINFO_ROUTER_PREFIX, MyInfoRouter) + app.use('/.well-known', WellKnownRouter) + // Legacy frontend routes which may still be in use app.use(LegacyRedirectRouter) @@ -135,10 +138,7 @@ const loadExpressApp = async (connection: Connection) => { // If requests for known static asset patterns were not served by // the static handlers above, middleware should try to fetch from s3 static bucket or else return 404s - app.get( - /^\/(public|static|\.well-known)\//, - catchNonExistentStaticRoutesMiddleware, - ) + app.get(/^\/(public|static)\//, catchNonExistentStaticRoutesMiddleware) // Requests for root files (e.g. /robots.txt or /favicon.ico) that were // not served statically above will also return 404 diff --git a/src/app/routes/.well-known/index.ts b/src/app/routes/.well-known/index.ts new file mode 100644 index 0000000000..eadd2b6277 --- /dev/null +++ b/src/app/routes/.well-known/index.ts @@ -0,0 +1,24 @@ +import { Router } from 'express' + +import { formSgSdkJwksConfig } from '../../config/features/formsg-sdk-jwks.config' +import { createLoggerWithLabel } from '../../config/logger' + +export const WellKnownRouter = Router() + +const logger = createLoggerWithLabel(module) +/** + * Returns the FormSG's public json web key set (JWKS) for communication with FormSG SDK + * @route GET /.well-known/formsg/jwks.json + * @returns 200 + */ +WellKnownRouter.get('/formsg/jwks.json', (req, res) => { + logger.info({ + message: 'Admin attempting to make changes', + meta: { + action: 'formsg/jwks.json', + publicJwks: formSgSdkJwksConfig.publicJwks, + }, + }) + + return res.send(formSgSdkJwksConfig.publicJwks) +}) From ef05a0871c87efa1180b73d19076b27239013e17 Mon Sep 17 00:00:00 2001 From: Ken Date: Mon, 16 Dec 2024 21:01:13 +0800 Subject: [PATCH 2/3] chore: add default jwks on local --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index ee7b758a11..c724b84c75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -131,6 +131,7 @@ services: - POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2 - DOWNLOAD_FORM_WHITELIST_RATE_LIMIT - UPLOAD_FORM_WHITELIST_RATE_LIMIT + - FORMSG_SDK_PUBLIC_JWKS={"keys":[{"kty":"RSA","kid":"old-key-id","use":"sig","alg":"RS256","n":"old-key-modulus","e":"old-key-exponent"},{"kty":"RSA","kid":"new-key-id","use":"sig","alg":"RS256","n":"new-key-modulus","e":"new-key-exponent"}]} mockpass: build: https://github.com/opengovsg/mockpass.git#v4.3.1 From 11e9e378584a84145147d6c513ac38f418dbcf63 Mon Sep 17 00:00:00 2001 From: Ken Date: Mon, 16 Dec 2024 21:23:07 +0800 Subject: [PATCH 3/3] fix: add missing test data --- __tests__/setup/.test-env | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/__tests__/setup/.test-env b/__tests__/setup/.test-env index 552f85f4b1..12d9b436a3 100644 --- a/__tests__/setup/.test-env +++ b/__tests__/setup/.test-env @@ -93,4 +93,5 @@ POSTMAN_MOP_CAMPAIGN_ID=campaign_tesst POSTMAN_MOP_CAMPAIGN_API_KEY=key_test_123 POSTMAN_INTERNAL_CAMPAIGN_ID=campaign_tesst POSTMAN_INTERNAL_CAMPAIGN_API_KEY=key_test_123 -POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2 \ No newline at end of file +POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2 +FORMSG_SDK_PUBLIC_JWKS={}