aquaman-proxy 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +69 -101
- package/dist/cli/index.js.map +1 -1
- package/dist/core/audit/logger.js +1 -1
- package/dist/core/audit/logger.js.map +1 -1
- package/dist/core/credentials/backends/onepassword.js +1 -1
- package/dist/core/credentials/backends/onepassword.js.map +1 -1
- package/dist/core/credentials/backends/systemd-creds.js +1 -1
- package/dist/core/credentials/backends/systemd-creds.js.map +1 -1
- package/dist/core/credentials/caching-store.d.ts +43 -0
- package/dist/core/credentials/caching-store.d.ts.map +1 -0
- package/dist/core/credentials/caching-store.js +77 -0
- package/dist/core/credentials/caching-store.js.map +1 -0
- package/dist/core/credentials/index.d.ts +1 -0
- package/dist/core/credentials/index.d.ts.map +1 -1
- package/dist/core/credentials/index.js +1 -0
- package/dist/core/credentials/index.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +9 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/utils/config.d.ts +17 -0
- package/dist/core/utils/config.d.ts.map +1 -1
- package/dist/core/utils/config.js +33 -1
- package/dist/core/utils/config.js.map +1 -1
- package/dist/core/utils/index.d.ts +1 -1
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +1 -1
- package/dist/core/utils/index.js.map +1 -1
- package/dist/hermes/config-writer.d.ts +10 -0
- package/dist/hermes/config-writer.d.ts.map +1 -1
- package/dist/hermes/config-writer.js +25 -0
- package/dist/hermes/config-writer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/openclaw/integration.d.ts.map +1 -1
- package/dist/openclaw/integration.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Agent / OpenClaw / Coding Agent Aquaman Proxy
|
|
|
18
18
|
│ No credentials. │ proxy.sock │ │
|
|
19
19
|
│ No open ports. │ (chmod 0o600) │ │
|
|
20
20
|
│ Nothing to steal. │ │ │
|
|
21
|
-
└──────────────────────┘
|
|
21
|
+
└──────────────────────┘ └──┬──────────┬────────┘
|
|
22
22
|
│ │
|
|
23
23
|
│ ▼
|
|
24
24
|
│ ~/.aquaman/audit/
|
package/dist/cli/index.js
CHANGED
|
@@ -12,12 +12,13 @@ import { Command, Help } from 'commander';
|
|
|
12
12
|
import * as path from 'node:path';
|
|
13
13
|
import * as fs from 'node:fs';
|
|
14
14
|
import * as http from 'node:http';
|
|
15
|
-
import { loadConfig, getConfigDir, ensureConfigDir, getDefaultConfig, expandPath, createAuditLogger, createCredentialStore, saveConfig, generateLoopbackToken, DEFAULT_LOOPBACK_PORT } from '../core/index.js';
|
|
15
|
+
import { loadConfig, getConfigDir, ensureConfigDir, getDefaultConfig, expandPath, createAuditLogger, createCredentialStore, saveConfig, generateLoopbackToken, DEFAULT_LOOPBACK_PORT, wrapWithCache, resolveCacheTtl } from '../core/index.js';
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
import { createCredentialProxy } from '../daemon.js';
|
|
18
18
|
import { createServiceRegistry, ServiceRegistry } from '../service-registry.js';
|
|
19
19
|
import { createOpenClawIntegration, authProfilesAreSqliteOnly } from '../openclaw/integration.js';
|
|
20
20
|
import { createHermesIntegration, detectHermes } from '../hermes/integration.js';
|
|
21
|
+
import { managedScopeShadowedKeys, HERMES_MANAGED_ENV_PATH } from '../hermes/config-writer.js';
|
|
21
22
|
import { loadPolicyFromConfig, validatePolicyConfig, getDefaultPolicyPresets, matchPolicy } from '../request-policy.js';
|
|
22
23
|
import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
|
|
23
24
|
// Read version from package.json (single source of truth)
|
|
@@ -38,6 +39,49 @@ function validateCredName(label, value) {
|
|
|
38
39
|
process.exit(1);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Soft hint for 1Password users running in biometric/desktop-app mode: every
|
|
44
|
+
* `op` spawn prompts, which makes unattended agents unusable. The daemon cache
|
|
45
|
+
* (v0.13.1+) bounds it to one prompt per TTL per credential; a service account
|
|
46
|
+
* removes prompts entirely. Printed by `aquaman doctor` and deep doctors.
|
|
47
|
+
*/
|
|
48
|
+
function printOnePasswordModeHint(config, indent = ' ') {
|
|
49
|
+
if (config.credentials.backend !== '1password')
|
|
50
|
+
return;
|
|
51
|
+
if (process.env['OP_SERVICE_ACCOUNT_TOKEN'] || process.env['OP_CONNECT_HOST'])
|
|
52
|
+
return;
|
|
53
|
+
const vault = config.credentials.onePasswordVault || 'aquaman';
|
|
54
|
+
const ttl = resolveCacheTtl(config);
|
|
55
|
+
const cacheNote = ttl > 0
|
|
56
|
+
? `the daemon cache bounds this to one per ${Math.round(ttl / 60)} min per credential`
|
|
57
|
+
: 'and the credential cache is disabled (cacheTtlSeconds: 0)';
|
|
58
|
+
console.log(`${indent}• 1Password is in biometric/desktop-app mode — each vault read prompts (${cacheNote}).`);
|
|
59
|
+
console.log(`${indent} For zero prompts, create a service account scoped to the "${vault}" vault (create the`);
|
|
60
|
+
console.log(`${indent} vault + credentials as a human first, or grant write_items) and start the daemon with`);
|
|
61
|
+
console.log(`${indent} OP_SERVICE_ACCOUNT_TOKEN. If OP_CONNECT_HOST/OP_CONNECT_TOKEN are set they take precedence.`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map config.credentials onto CredentialStoreOptions — the single source for
|
|
65
|
+
* every createCredentialStore() call in this CLI. Env fallbacks mirror
|
|
66
|
+
* applyEnvOverrides() (belt and braces for callers that build partial configs).
|
|
67
|
+
*/
|
|
68
|
+
function storeOptionsFromConfig(config) {
|
|
69
|
+
return {
|
|
70
|
+
backend: config.credentials.backend,
|
|
71
|
+
encryptionPassword: config.credentials.encryptionPassword || process.env['AQUAMAN_ENCRYPTION_PASSWORD'] || process.env['AQUAMAN_KEEPASS_PASSWORD'],
|
|
72
|
+
vaultAddress: config.credentials.vaultAddress || process.env['VAULT_ADDR'],
|
|
73
|
+
vaultToken: config.credentials.vaultToken || process.env['VAULT_TOKEN'],
|
|
74
|
+
vaultNamespace: config.credentials.vaultNamespace,
|
|
75
|
+
vaultMountPath: config.credentials.vaultMountPath,
|
|
76
|
+
onePasswordVault: config.credentials.onePasswordVault,
|
|
77
|
+
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
78
|
+
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
79
|
+
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
80
|
+
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
81
|
+
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
82
|
+
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
83
|
+
};
|
|
84
|
+
}
|
|
41
85
|
/**
|
|
42
86
|
* Build loopback listener options from config for the daemon. Returns undefined
|
|
43
87
|
* unless the loopback listener is explicitly enabled. If it's enabled but no
|
|
@@ -310,21 +354,10 @@ program
|
|
|
310
354
|
// Vault \u2014 backend + creds
|
|
311
355
|
try {
|
|
312
356
|
const config = loadConfig();
|
|
313
|
-
const store = await createCredentialStore(
|
|
314
|
-
backend: config.credentials.backend,
|
|
315
|
-
encryptionPassword: config.credentials.encryptionPassword,
|
|
316
|
-
vaultAddress: config.credentials.vaultAddress,
|
|
317
|
-
vaultToken: config.credentials.vaultToken,
|
|
318
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
319
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
320
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
321
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
322
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
323
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
324
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
325
|
-
});
|
|
357
|
+
const store = await createCredentialStore(storeOptionsFromConfig(config));
|
|
326
358
|
const creds = await store.list();
|
|
327
359
|
console.log(` \u2713 ${config.credentials.backend} backend (${creds.length} credential${creds.length !== 1 ? 's' : ''})`);
|
|
360
|
+
printOnePasswordModeHint(config);
|
|
328
361
|
}
|
|
329
362
|
catch (err) {
|
|
330
363
|
console.log(` \u2717 Backend not accessible: ${err.message}`);
|
|
@@ -528,19 +561,7 @@ async function runVaultSetup(opts) {
|
|
|
528
561
|
fs.mkdirSync(auditDir, { recursive: true, mode: 0o700 });
|
|
529
562
|
let store;
|
|
530
563
|
try {
|
|
531
|
-
store = await createCredentialStore(
|
|
532
|
-
backend: config.credentials.backend,
|
|
533
|
-
encryptionPassword: config.credentials.encryptionPassword || process.env['AQUAMAN_ENCRYPTION_PASSWORD'] || process.env['AQUAMAN_KEEPASS_PASSWORD'],
|
|
534
|
-
vaultAddress: config.credentials.vaultAddress || process.env['VAULT_ADDR'],
|
|
535
|
-
vaultToken: config.credentials.vaultToken || process.env['VAULT_TOKEN'],
|
|
536
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
537
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
538
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
539
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
540
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
541
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
542
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
543
|
-
});
|
|
564
|
+
store = await createCredentialStore(storeOptionsFromConfig(config));
|
|
544
565
|
}
|
|
545
566
|
catch (err) {
|
|
546
567
|
console.error(` Failed to initialize ${backend}: ${err instanceof Error ? err.message : err}`);
|
|
@@ -666,21 +687,7 @@ openclaw
|
|
|
666
687
|
// Initialize credential store
|
|
667
688
|
let credentialStore;
|
|
668
689
|
try {
|
|
669
|
-
credentialStore = await createCredentialStore(
|
|
670
|
-
backend: config.credentials.backend,
|
|
671
|
-
encryptionPassword: config.credentials.encryptionPassword,
|
|
672
|
-
vaultAddress: config.credentials.vaultAddress,
|
|
673
|
-
vaultToken: config.credentials.vaultToken,
|
|
674
|
-
vaultNamespace: config.credentials.vaultNamespace,
|
|
675
|
-
vaultMountPath: config.credentials.vaultMountPath,
|
|
676
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
677
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
678
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
679
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
680
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
681
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
682
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
683
|
-
});
|
|
690
|
+
credentialStore = wrapWithCache(await createCredentialStore(storeOptionsFromConfig(config)), resolveCacheTtl(config));
|
|
684
691
|
}
|
|
685
692
|
catch (err) {
|
|
686
693
|
console.error(`Credential backend "${config.credentials.backend}" failed to initialize: ${err instanceof Error ? err.message : err}`);
|
|
@@ -822,21 +829,7 @@ program
|
|
|
822
829
|
// Initialize credential store
|
|
823
830
|
let credentialStore;
|
|
824
831
|
try {
|
|
825
|
-
credentialStore = await createCredentialStore(
|
|
826
|
-
backend: config.credentials.backend,
|
|
827
|
-
encryptionPassword: config.credentials.encryptionPassword,
|
|
828
|
-
vaultAddress: config.credentials.vaultAddress,
|
|
829
|
-
vaultToken: config.credentials.vaultToken,
|
|
830
|
-
vaultNamespace: config.credentials.vaultNamespace,
|
|
831
|
-
vaultMountPath: config.credentials.vaultMountPath,
|
|
832
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
833
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
834
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
835
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
836
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
837
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
838
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
839
|
-
});
|
|
832
|
+
credentialStore = wrapWithCache(await createCredentialStore(storeOptionsFromConfig(config)), resolveCacheTtl(config));
|
|
840
833
|
}
|
|
841
834
|
catch (err) {
|
|
842
835
|
console.error(`Credential backend "${config.credentials.backend}" failed to initialize: ${err instanceof Error ? err.message : err}`);
|
|
@@ -896,21 +889,7 @@ openclaw
|
|
|
896
889
|
// Initialize credential store
|
|
897
890
|
let credentialStore;
|
|
898
891
|
try {
|
|
899
|
-
credentialStore = await createCredentialStore(
|
|
900
|
-
backend: config.credentials.backend,
|
|
901
|
-
encryptionPassword: config.credentials.encryptionPassword,
|
|
902
|
-
vaultAddress: config.credentials.vaultAddress,
|
|
903
|
-
vaultToken: config.credentials.vaultToken,
|
|
904
|
-
vaultNamespace: config.credentials.vaultNamespace,
|
|
905
|
-
vaultMountPath: config.credentials.vaultMountPath,
|
|
906
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
907
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
908
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
909
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
910
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
911
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
912
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
913
|
-
});
|
|
892
|
+
credentialStore = wrapWithCache(await createCredentialStore(storeOptionsFromConfig(config)), resolveCacheTtl(config));
|
|
914
893
|
}
|
|
915
894
|
catch (err) {
|
|
916
895
|
console.error(`Credential backend "${config.credentials.backend}" failed to initialize: ${err instanceof Error ? err.message : err}`);
|
|
@@ -1104,6 +1083,10 @@ hermes
|
|
|
1104
1083
|
}
|
|
1105
1084
|
catch { /* unreadable */ }
|
|
1106
1085
|
console.log(` ~/.hermes/.env: ${envWired ? aqua('wired') : 'not wired'} (${envPath})`);
|
|
1086
|
+
const shadowed = managedScopeShadowedKeys(integration.configureHermes());
|
|
1087
|
+
if (shadowed.length > 0) {
|
|
1088
|
+
console.log(` Managed scope: ⚠ ${HERMES_MANAGED_ENV_PATH} pins ${shadowed.join(', ')} — proxy bypassed for these keys`);
|
|
1089
|
+
}
|
|
1107
1090
|
const info = await detectHermes(config.hermes?.binaryPath || 'hermes');
|
|
1108
1091
|
console.log(` Hermes CLI: ${info.installed ? aqua(`v${info.version}`) : 'not found'}`);
|
|
1109
1092
|
// Live liveness probe of the loopback listener (no token needed for _health).
|
|
@@ -1162,6 +1145,16 @@ hermes
|
|
|
1162
1145
|
catch {
|
|
1163
1146
|
fail(`Could not read ${envPath}`);
|
|
1164
1147
|
}
|
|
1148
|
+
// 3b. Hermes >=0.17 managed scope: /etc/hermes/.env overrides ~/.hermes/.env
|
|
1149
|
+
{
|
|
1150
|
+
const shadowed = managedScopeShadowedKeys(integration.configureHermes());
|
|
1151
|
+
if (shadowed.length > 0) {
|
|
1152
|
+
fail(`Hermes managed scope (${HERMES_MANAGED_ENV_PATH}) pins ${shadowed.join(', ')} — it overrides ~/.hermes/.env, so the proxy is BYPASSED for these keys. Remove them from the managed file or point them at the proxy.`);
|
|
1153
|
+
}
|
|
1154
|
+
else {
|
|
1155
|
+
pass('No managed-scope override of aquaman env vars');
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1165
1158
|
// 4. Per-service vault credentials resolve
|
|
1166
1159
|
const wired = integration.wiredServices();
|
|
1167
1160
|
if (wired.length === 0) {
|
|
@@ -1169,21 +1162,7 @@ hermes
|
|
|
1169
1162
|
}
|
|
1170
1163
|
else {
|
|
1171
1164
|
try {
|
|
1172
|
-
const store = await createCredentialStore(
|
|
1173
|
-
backend: config.credentials.backend,
|
|
1174
|
-
encryptionPassword: config.credentials.encryptionPassword,
|
|
1175
|
-
vaultAddress: config.credentials.vaultAddress,
|
|
1176
|
-
vaultToken: config.credentials.vaultToken,
|
|
1177
|
-
vaultNamespace: config.credentials.vaultNamespace,
|
|
1178
|
-
vaultMountPath: config.credentials.vaultMountPath,
|
|
1179
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
1180
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
1181
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
1182
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
1183
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
1184
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
1185
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId,
|
|
1186
|
-
});
|
|
1165
|
+
const store = await createCredentialStore(storeOptionsFromConfig(config));
|
|
1187
1166
|
for (const svc of wired) {
|
|
1188
1167
|
const val = await store.get(svc, 'api_key');
|
|
1189
1168
|
if (val)
|
|
@@ -1191,6 +1170,7 @@ hermes
|
|
|
1191
1170
|
else
|
|
1192
1171
|
fail(`No credential for ${svc}/api_key — run: aquaman credentials add ${svc} api_key`);
|
|
1193
1172
|
}
|
|
1173
|
+
printOnePasswordModeHint(config, ' ');
|
|
1194
1174
|
}
|
|
1195
1175
|
catch (err) {
|
|
1196
1176
|
fail(`Vault backend "${config.credentials.backend}" failed: ${err instanceof Error ? err.message : err}`);
|
|
@@ -1379,7 +1359,7 @@ openclaw
|
|
|
1379
1359
|
process.exit(1);
|
|
1380
1360
|
}
|
|
1381
1361
|
}
|
|
1382
|
-
catch
|
|
1362
|
+
catch {
|
|
1383
1363
|
console.error(` Cannot reach Vault at ${vaultAddr}.`);
|
|
1384
1364
|
process.exit(1);
|
|
1385
1365
|
}
|
|
@@ -1459,19 +1439,7 @@ openclaw
|
|
|
1459
1439
|
// 3. Prompt for API keys (or read from env in non-interactive mode)
|
|
1460
1440
|
let store;
|
|
1461
1441
|
try {
|
|
1462
|
-
store = await createCredentialStore(
|
|
1463
|
-
backend: config.credentials.backend,
|
|
1464
|
-
encryptionPassword: config.credentials.encryptionPassword || process.env['AQUAMAN_ENCRYPTION_PASSWORD'] || process.env['AQUAMAN_KEEPASS_PASSWORD'],
|
|
1465
|
-
vaultAddress: config.credentials.vaultAddress || process.env['VAULT_ADDR'],
|
|
1466
|
-
vaultToken: config.credentials.vaultToken || process.env['VAULT_TOKEN'],
|
|
1467
|
-
onePasswordVault: config.credentials.onePasswordVault,
|
|
1468
|
-
onePasswordAccount: config.credentials.onePasswordAccount,
|
|
1469
|
-
keepassxcDatabasePath: config.credentials.keepassxcDatabasePath,
|
|
1470
|
-
keepassxcKeyFilePath: config.credentials.keepassxcKeyFilePath,
|
|
1471
|
-
bitwardenFolder: config.credentials.bitwardenFolder,
|
|
1472
|
-
bitwardenOrganizationId: config.credentials.bitwardenOrganizationId,
|
|
1473
|
-
bitwardenCollectionId: config.credentials.bitwardenCollectionId
|
|
1474
|
-
});
|
|
1442
|
+
store = await createCredentialStore(storeOptionsFromConfig(config));
|
|
1475
1443
|
}
|
|
1476
1444
|
catch (err) {
|
|
1477
1445
|
console.error(` Failed to initialize ${backend} credential store: ${err instanceof Error ? err.message : err}`);
|