Skip to content

Commit 8b1b091

Browse files
fix(aggregator): read the OpenSearch credential from a file, not launchd env
Follow-up to the ship-auth fix: injecting OFFGRID_OPENSEARCH_USER/PASSWORD via the daemon plist proved fragile — a KeepAlive respawn kept the old job definition's env, so the process still shipped unauthenticated. The script now reads the credential ITSELF from a root-only file (/etc/offgrid/opensearch-basic, override with OFFGRID_OPENSEARCH_CRED_FILE), env still taking precedence. Works regardless of which launchd job or wrapper starts it. Verified live end to end: offgrid-gateway 2899 -> 2900 docs, org_bharat 57 -> 58, newest doc {"org":"org_bharat","model":"gemma-local","gateway":"g5"}.
1 parent 05f977b commit 8b1b091

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

scripts/gateway-aggregator.mjs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// JWT (OFFGRID_KEYCLOAK_URL + _REALM). Keys are ISSUED by Keycloak (a service-account
1313
// client → client_credentials → JWT) — we don't run our own key store. If neither is
1414
// configured the endpoint is open (LAN-only dev default).
15+
import { readFileSync } from 'node:fs';
1516
import http from 'node:http';
1617
import crypto from 'node:crypto';
1718
import { execFile } from 'node:child_process';
@@ -230,8 +231,22 @@ const OS_INDEX = process.env.OFFGRID_GATEWAY_INDEX || 'offgrid-gateway';
230231
// silently LOST. This standalone script can't use the console's credential broker, so it authenticates
231232
// with the internal break-glass basic user that the security config deliberately keeps enabled.
232233
// Absent credentials ⇒ no header (correct for a security-OFF cluster), so both deployments work.
233-
const OS_USER = process.env.OFFGRID_OPENSEARCH_USER || '';
234-
const OS_PASS = process.env.OFFGRID_OPENSEARCH_PASSWORD || '';
234+
// Credentials come from the env when the launcher provides them, else from a root-only credential
235+
// file the script reads ITSELF (line 1 = user, line 2 = password). Reading the file directly means the
236+
// ship path works no matter which launchd job/wrapper started the process — depending on plist
237+
// EnvironmentVariables proved fragile (a KeepAlive respawn kept the old job definition's env).
238+
function readOsCredFile() {
239+
try {
240+
const path = process.env.OFFGRID_OPENSEARCH_CRED_FILE || '/etc/offgrid/opensearch-basic';
241+
const [u, p] = readFileSync(path, 'utf8').split('\n');
242+
return { user: (u || '').trim(), pass: (p || '').trim() };
243+
} catch {
244+
return { user: '', pass: '' };
245+
}
246+
}
247+
const OS_FILE_CRED = readOsCredFile();
248+
const OS_USER = process.env.OFFGRID_OPENSEARCH_USER || OS_FILE_CRED.user;
249+
const OS_PASS = process.env.OFFGRID_OPENSEARCH_PASSWORD || OS_FILE_CRED.pass;
235250
function osAuthHeaders() {
236251
if (!OS_USER || !OS_PASS) return {};
237252
return { authorization: `Basic ${Buffer.from(`${OS_USER}:${OS_PASS}`).toString('base64')}` };

0 commit comments

Comments
 (0)