From e49922e188574ecfe43cde4aa9f8663ea6d3e83d Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sun, 12 Jul 2026 00:28:13 +0900 Subject: [PATCH] fix(security): Remove hardcoded DB password from release artifact Production incident: quant.taxbaik.com/login threw 28P01 (password authentication failed) after the July 7 deployment's appsettings.Production.json carried a stale DB password. Root cause chain: 1. The DB password for quantengine_app had been rotated at some point; the new password was saved to /home/kjh2064/.config/quantengine.env on the server, but that file was never wired into the quantengine.service systemd unit (no EnvironmentFile= directive), so it was silently unused. 2. Every appsettings.Production.json we've generated in CI (including tonight's prepare-release.yml) baked in a PLACEHOLDER password ("quantengine_app") that was never the real credential to begin with -- copied forward from an earlier debugging session without ever being verified against the live DB. Immediate production fix (out of band, via SSH): patched the active deployment's appsettings.Production.json with the current working password (verified via direct psql connection) and restarted the service. Login confirmed HTTP 200 with a clean journalctl afterward. This commit fixes the root cause in the pipeline: prepare-release.yml no longer writes a ConnectionStrings block into the artifact at all. Baking any DB password (even a correct one) into a build artifact that ships as a downloadable Gitea Release asset is unsafe and goes stale on every credential rotation. The correct fix is for quantengine.service to load ConnectionStrings__DefaultConnection from /home/kjh2064/.config/quantengine.env via systemd's EnvironmentFile=, which overrides appsettings.Production.json at runtime per standard ASP.NET Core configuration precedence. That unit-file edit requires interactive sudo and must be applied by hand on the server (tracked separately, not part of this commit). IMPORTANT: the release quant_20260711.1.6ab270f already published tonight was built before this fix and still lacks any DB config -- do not deploy it via deploy-prod.yml until the systemd EnvironmentFile wiring is confirmed on the server, or the login outage will recur. --- .gitea/workflows/prepare-release.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/prepare-release.yml b/.gitea/workflows/prepare-release.yml index a04980e6..c4a321c3 100644 --- a/.gitea/workflows/prepare-release.yml +++ b/.gitea/workflows/prepare-release.yml @@ -79,10 +79,13 @@ jobs: import json import pathlib + # NOTE: No ConnectionStrings here on purpose. The real DB + # password lives only in /home/kjh2064/.config/quantengine.env + # on the production server and is injected via systemd + # EnvironmentFile (ConnectionStrings__DefaultConnection), + # which overrides this file at runtime. Never bake secrets + # into a build artifact that ends up in a Gitea Release. config = { - "ConnectionStrings": { - "DefaultConnection": "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=quantengine_app;Search Path=quantengine;" - }, "Logging": { "LogLevel": { "Default": "Information" @@ -96,7 +99,7 @@ jobs: )' test -s ./publish/appsettings.Production.json || { echo "ERROR: appsettings.Production.json is empty"; exit 1; } - echo "✓ Production config created" + echo "✓ Production config created (no secrets included)" - name: Package Artifact run: |