This commit is contained in:
parent
c4ce80c5c2
commit
d6e9b1f489
@ -115,7 +115,7 @@ steps:
|
|||||||
gcloud secrets versions access latest --secret=WRAPPED_DEK_dev --project=$PROJECT > /tmp/dev_dek.enc; \
|
gcloud secrets versions access latest --secret=WRAPPED_DEK_dev --project=$PROJECT > /tmp/dev_dek.enc; \
|
||||||
if [ -s /tmp/dev_dek.enc ]; then \
|
if [ -s /tmp/dev_dek.enc ]; then \
|
||||||
docker volume ls -q | grep -qx aptiva_dek_staging || docker volume create aptiva_dek_staging >/dev/null; \
|
docker volume ls -q | grep -qx aptiva_dek_staging || docker volume create aptiva_dek_staging >/dev/null; \
|
||||||
sudo docker run --rm -v aptiva_dek_staging:/v -v /tmp:/host busybox sh -c 'set -e; mkdir -p /v/staging; cp -f /host/dev_dek.enc /v/staging/dek.enc; chown 1000:1000 /v/staging/dek.enc; chmod 400 /v/staging/dek.enc; rm -f /v/staging/dek.fpr; echo -n "staging dek.enc bytes: "; wc -c </v/staging/dek.enc; ls -l /v/staging'
|
sudo docker run --rm -v aptiva_dek_staging:/v -v /tmp:/host busybox sh -c 'set -e; mkdir -p /v/staging; cp -f /host/dev_dek.enc /v/staging/dek.enc; chown 1000:1000 /v/staging/dek.enc; chmod 400 /v/staging/dek.enc; rm -f /v/staging/dek.fpr; echo -n \"staging dek.enc bytes: \"; wc -c </v/staging/dek.enc; ls -l /v/staging'
|
||||||
else \
|
else \
|
||||||
echo \"⚠️ WRAPPED_DEK_dev returned empty; skipping copy\"; \
|
echo \"⚠️ WRAPPED_DEK_dev returned empty; skipping copy\"; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -4,15 +4,11 @@ import helmet from 'helmet';
|
|||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import bodyParser from 'body-parser';
|
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
import jwt from 'jsonwebtoken'; // For token-based authentication
|
import jwt from 'jsonwebtoken';
|
||||||
import { initEncryption, encrypt, decrypt, verifyCanary, SENTINEL } from './shared/crypto/encryption.js';
|
import { initEncryption, encrypt, decrypt, verifyCanary, SENTINEL } from './shared/crypto/encryption.js';
|
||||||
|
import pool from './config/mysqlPool.js';
|
||||||
import pool from './config/mysqlPool.js'; // adjust path if needed
|
// import sqlite3 from 'sqlite3'; // (unused here – safe to remove)
|
||||||
|
|
||||||
import sqlite3 from 'sqlite3';
|
|
||||||
|
|
||||||
|
|
||||||
const CANARY_SQL = `
|
const CANARY_SQL = `
|
||||||
CREATE TABLE IF NOT EXISTS encryption_canary (
|
CREATE TABLE IF NOT EXISTS encryption_canary (
|
||||||
@ -22,13 +18,11 @@ const CANARY_SQL = `
|
|||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
const rootPath = path.resolve(__dirname, '..');
|
||||||
const rootPath = path.resolve(__dirname, '..'); // Up one level
|
|
||||||
const env = process.env.NODE_ENV?.trim() || 'development';
|
const env = process.env.NODE_ENV?.trim() || 'development';
|
||||||
const envPath = path.resolve(rootPath, `.env.${env}`);
|
const envPath = path.resolve(rootPath, `.env.${env}`);
|
||||||
dotenv.config({ path: envPath }); // Load .env file
|
dotenv.config({ path: envPath, override: false });
|
||||||
|
|
||||||
// Grab secrets and config from ENV
|
|
||||||
const {
|
const {
|
||||||
JWT_SECRET,
|
JWT_SECRET,
|
||||||
CORS_ALLOWED_ORIGINS,
|
CORS_ALLOWED_ORIGINS,
|
||||||
@ -37,46 +31,48 @@ const {
|
|||||||
|
|
||||||
if (!JWT_SECRET) {
|
if (!JWT_SECRET) {
|
||||||
console.error('FATAL: JWT_SECRET missing – aborting startup');
|
console.error('FATAL: JWT_SECRET missing – aborting startup');
|
||||||
process.exit(1); // container exits, Docker marks it unhealthy
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CORS_ALLOWED_ORIGINS) {
|
if (!CORS_ALLOWED_ORIGINS) {
|
||||||
console.error('FATAL: CORS_ALLOWED_ORIGINS missing – aborting startup');
|
console.error('FATAL: CORS_ALLOWED_ORIGINS missing – aborting startup');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── unwrap / verify DEK before we serve requests ────────────── */
|
// Unwrap / verify DEK and seed canary before serving traffic
|
||||||
await initEncryption();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* quick connectivity smoke‑test (optional) */
|
await initEncryption(); // <-- wrap in try/catch
|
||||||
await pool.query('SELECT 1');
|
|
||||||
|
|
||||||
/* ① ensure table exists */
|
const db = pool.raw || pool; // <-- bypass DAO wrapper for canary ops
|
||||||
await pool.query(CANARY_SQL);
|
|
||||||
|
|
||||||
/* ② insert sentinel on first run */
|
// quick connectivity check
|
||||||
await pool.query(
|
await db.query('SELECT 1');
|
||||||
|
|
||||||
|
// ① ensure table
|
||||||
|
await db.query(CANARY_SQL);
|
||||||
|
|
||||||
|
// ② insert sentinel on first run (ignore if exists)
|
||||||
|
await db.query(
|
||||||
'INSERT IGNORE INTO encryption_canary (id, value) VALUES (1, ?)',
|
'INSERT IGNORE INTO encryption_canary (id, value) VALUES (1, ?)',
|
||||||
[encrypt(SENTINEL)]
|
[encrypt(SENTINEL)]
|
||||||
);
|
);
|
||||||
|
|
||||||
/* ③ read back & verify */
|
// ③ read back & verify
|
||||||
const [rows] = await pool.query(
|
const [rows] = await db.query(
|
||||||
'SELECT value FROM encryption_canary WHERE id = 1 LIMIT 1'
|
'SELECT value FROM encryption_canary WHERE id = 1 LIMIT 1'
|
||||||
);
|
);
|
||||||
|
|
||||||
const plaintext = decrypt(rows[0]?.value || '');
|
const plaintext = decrypt(rows[0]?.value || '');
|
||||||
if (plaintext !== SENTINEL) {
|
if (plaintext !== SENTINEL) {
|
||||||
throw new Error('DEK mismatch with database sentinel');
|
throw new Error('DEK mismatch with database sentinel');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[ENCRYPT] DEK verified against canary – proceeding');
|
console.log('[ENCRYPT] DEK verified against canary – proceeding');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('FATAL:', err.message || err);
|
console.error('FATAL:', err?.message || err);
|
||||||
process.exit(1); // container restarts → alert
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// …the rest of your server: app = express(), middlewares, routes, app.listen()
|
||||||
|
|
||||||
/* ────────────────────────────────────────────────────────────────
|
/* ────────────────────────────────────────────────────────────────
|
||||||
Express app & middleware
|
Express app & middleware
|
||||||
---------------------------------------------------------------- */
|
---------------------------------------------------------------- */
|
||||||
|
Loading…
Reference in New Issue
Block a user