From a71e42efe72b0fc4411c51156e6b3861af17bff4 Mon Sep 17 00:00:00 2001 From: Conor Schaefer Date: Thu, 19 Sep 2024 12:49:11 -0700 Subject: [PATCH] feat: support CA_CERT env var override (#194) * feat: support CA_CERT env var override When connecting to remote databases that are SSL-required, the app will sometimes report cert errors. First, I tried to resolve this by pulling in `ca-certificates` in the container environment, but that wasn't sufficient. Turns out `node-postgres` in v8.x updated the ssl logic and that broke setups for many managed databases. As a workaround, one can now: 1. set the CA_CERT env var with the string contents of the db's CA 2. remove the `sslmode=require` from the connection auth starting The fact that 2 is necessary is a bit scary, but it's caused by the fact that the connectionString setting clobbers any manual `ssl` opts in the db config. * refactor: implement review feedback --- apps/web/src/lib/db.ts | 22 ++++++++++++++++++++-- justfile | 7 ++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/web/src/lib/db.ts b/apps/web/src/lib/db.ts index d502da9..bfb1d19 100644 --- a/apps/web/src/lib/db.ts +++ b/apps/web/src/lib/db.ts @@ -1,9 +1,27 @@ import pg from "pg"; const { Pool, types } = pg; -const pool = new Pool({ +// By default we assume that the `DATABASE_URL` connection string parsing is sufficient. +// It fails, however, when pointed out at URL for a managed Postgres db hosted by DigitalOcean. +// +// Therefore let's provide an opt-in method of providing a CA for the cert info. +// In order to use a DO managed DB URL, you must prune the `?sslmode=require` from the connection string! +// This is documented here: https://node-postgres.com/features/ssl#usage-with-connectionstring +const dbConfig = { connectionString: process.env.DATABASE_URL, -}); + ssl: {}, + // If a CA certificate was specified as an env var, pass that info to the database config. + // Be advised that if CA_CERT is set, then DATABASE_URL must *lack* an `sslmode` param! + ...(process.env.CA_CERT != null && { + ssl: { + rejectUnauthorized: true, + ca: process.env.CA_CERT, + }, + }), +}; + +// Construct the db connection. +const pool = new Pool(dbConfig); types.setTypeParser(types.builtins.DATE, (val: string) => val); types.setTypeParser(types.builtins.INT8, (val: string) => BigInt(val)); diff --git a/justfile b/justfile index f1817d7..e47e49a 100644 --- a/justfile +++ b/justfile @@ -25,8 +25,13 @@ pgtyped-cli: update-cometbft-schema: curl -o deploy/postgres-cometbft-schema.sql -sSf "https://raw.githubusercontent.com/cometbft/cometbft/v0.37.2/state/indexer/sink/psql/schema.sql" +# Build the webapp container image container: - podman build -t ghcr.io/penumbra-zone/cuiloa . + podman build -t ghcr.io/penumbra-zone/cuiloa -f apps/web/Containerfile . + +# Build, then run the webapp container image. Uses local env vars. +run-container: container + podman run -e CA_CERT -e DATABASE_URL -e APP_URL -e PENUMBRA_GRPC_ENDPOINT -p 3000:3000 -it ghcr.io/penumbra-zone/cuiloa compose: docker compose up