Skip to content

Commit d08f16f

Browse files
committed
feat: support env suffixed encryption env var keys
1 parent 6b7575a commit d08f16f

File tree

2 files changed

+70
-19
lines changed

2 files changed

+70
-19
lines changed

app-config-cli/src/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,8 @@ export const cli = yargs
601601
async (opts) => {
602602
const environmentOptions = await loadEnvironmentOptions(opts);
603603

604-
const myKey = await loadPublicKeyLazy();
605-
const privateKey = await loadPrivateKeyLazy();
604+
const myKey = await loadPublicKeyLazy(environmentOptions);
605+
const privateKey = await loadPrivateKeyLazy(environmentOptions);
606606

607607
// we trust ourselves, essentially
608608
await trustTeamMember(myKey, privateKey, environmentOptions);
@@ -717,7 +717,7 @@ export const cli = yargs
717717

718718
await trustTeamMember(
719719
await loadKey(publicKeyArmored),
720-
await loadPrivateKeyLazy(),
720+
await loadPrivateKeyLazy(environmentOptions),
721721
environmentOptions,
722722
);
723723

@@ -761,7 +761,7 @@ export const cli = yargs
761761
const environmentOptions = await loadEnvironmentOptions(opts);
762762

763763
const key = await loadKey(await readFile(opts.keyPath));
764-
const privateKey = await loadPrivateKeyLazy();
764+
const privateKey = await loadPrivateKeyLazy(environmentOptions);
765765
await trustTeamMember(key, privateKey, environmentOptions);
766766

767767
logger.info(`Trusted ${key.getUserIds().join(', ')}`);
@@ -793,7 +793,7 @@ export const cli = yargs
793793
},
794794
async (opts) => {
795795
const environmentOptions = await loadEnvironmentOptions(opts);
796-
const privateKey = await loadPrivateKeyLazy();
796+
const privateKey = await loadPrivateKeyLazy(environmentOptions);
797797

798798
// TODO: by default, untrust for all envs?
799799
await untrustTeamMember(opts.email, privateKey, environmentOptions);
@@ -828,7 +828,7 @@ export const cli = yargs
828828
shouldUseSecretAgent(opts.agent);
829829

830830
// load these right away, so user unlocks asap
831-
if (!shouldUseSecretAgent()) await loadPrivateKeyLazy();
831+
if (!shouldUseSecretAgent()) await loadPrivateKeyLazy(environmentOptions);
832832

833833
let { secretValue }: { secretValue?: Json } = opts;
834834

@@ -896,7 +896,7 @@ export const cli = yargs
896896
shouldUseSecretAgent(opts.agent);
897897

898898
// load these right away, so user unlocks asap
899-
if (!shouldUseSecretAgent()) await loadPrivateKeyLazy();
899+
if (!shouldUseSecretAgent()) await loadPrivateKeyLazy(environmentOptions);
900900

901901
let { encryptedText } = opts;
902902

app-config-encryption/src/encryption.ts

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,20 @@ export async function loadKey(contents: string | Buffer): Promise<Key> {
147147
}
148148

149149
export async function loadPrivateKey(
150-
override: string | Buffer | undefined = process.env.APP_CONFIG_SECRETS_KEY,
150+
override: string | Buffer | undefined = undefined,
151+
environmentOptions?: EnvironmentOptions,
151152
): Promise<Key> {
152153
let key: Key;
154+
let overrideKey;
153155

154156
if (override) {
155-
key = await loadKey(override);
157+
overrideKey = override;
158+
} else {
159+
overrideKey = getKeyFromEnv('public', environmentOptions);
160+
}
161+
162+
if (overrideKey) {
163+
key = await loadKey(overrideKey);
156164
} else {
157165
if (process.env.CI) {
158166
logger.info('Warning! Trying to load encryption keys from home folder in a CI environment');
@@ -183,12 +191,20 @@ export async function loadPrivateKey(
183191
}
184192

185193
export async function loadPublicKey(
186-
override: string | Buffer | undefined = process.env.APP_CONFIG_SECRETS_PUBLIC_KEY,
194+
override: string | Buffer | undefined = undefined,
195+
environmentOptions?: EnvironmentOptions,
187196
): Promise<Key> {
188197
let key: Key;
198+
let overrideKey;
189199

190200
if (override) {
191-
key = await loadKey(override);
201+
overrideKey = override;
202+
} else {
203+
overrideKey = getKeyFromEnv('public', environmentOptions);
204+
}
205+
206+
if (overrideKey) {
207+
key = await loadKey(overrideKey);
192208
} else {
193209
if (process.env.CI) {
194210
logger.warn('Warning! Trying to load encryption keys from home folder in a CI environment');
@@ -203,17 +219,47 @@ export async function loadPublicKey(
203219
return key;
204220
}
205221

222+
function getKeyFromEnv(keyType: 'private' | 'public', envOptions?: EnvironmentOptions) {
223+
const env = currentEnvironment(envOptions);
224+
225+
const envVarPrefix =
226+
keyType === 'private' ? 'APP_CONFIG_SECRETS_KEY' : 'APP_CONFIG_SECRETS_PUBLIC_KEY';
227+
228+
if (!envOptions || !env) {
229+
return process.env[envVarPrefix];
230+
}
231+
232+
let key = process.env[`${envVarPrefix}_${env.toUpperCase()}`];
233+
234+
// try an alias if we didn't find the key first try
235+
if (!key) {
236+
const aliases = aliasesFor(env, envOptions.aliases);
237+
238+
for (const alias of aliases) {
239+
key = process.env[`${envVarPrefix}_${alias.toUpperCase()}`];
240+
241+
if (key) {
242+
break;
243+
}
244+
}
245+
}
246+
247+
return key;
248+
}
249+
206250
let loadedPrivateKey: Promise<Key> | undefined;
207251

208-
export async function loadPrivateKeyLazy(): Promise<Key> {
252+
export async function loadPrivateKeyLazy(environmentOptions?: EnvironmentOptions): Promise<Key> {
209253
if (!loadedPrivateKey) {
210254
logger.verbose('Loading local private key');
211255

212256
if (checkTTY()) {
213257
// help the end user, if they haven't initialized their local keys yet
214-
loadedPrivateKey = initializeLocalKeys().then(() => loadPrivateKey());
258+
loadedPrivateKey = initializeLocalKeys().then(() =>
259+
loadPrivateKey(undefined, environmentOptions),
260+
);
215261
} else {
216-
loadedPrivateKey = loadPrivateKey();
262+
loadedPrivateKey = loadPrivateKey(undefined, environmentOptions);
217263
}
218264
}
219265

@@ -222,15 +268,17 @@ export async function loadPrivateKeyLazy(): Promise<Key> {
222268

223269
let loadedPublicKey: Promise<Key> | undefined;
224270

225-
export async function loadPublicKeyLazy(): Promise<Key> {
271+
export async function loadPublicKeyLazy(environmentOptions?: EnvironmentOptions): Promise<Key> {
226272
if (!loadedPublicKey) {
227273
logger.verbose('Loading local public key');
228274

229275
if (checkTTY()) {
230276
// help the end user, if they haven't initialized their local keys yet
231-
loadedPublicKey = initializeLocalKeys().then(() => loadPublicKey());
277+
loadedPublicKey = initializeLocalKeys().then(() =>
278+
loadPublicKey(undefined, environmentOptions),
279+
);
232280
} else {
233-
loadedPublicKey = loadPublicKey();
281+
loadedPublicKey = loadPublicKey(undefined, environmentOptions);
234282
}
235283
}
236284

@@ -393,7 +441,10 @@ export async function encryptValue(
393441
if (symmetricKeyOverride) {
394442
symmetricKey = symmetricKeyOverride;
395443
} else {
396-
symmetricKey = await loadLatestSymmetricKeyLazy(await loadPrivateKeyLazy(), environmentOptions);
444+
symmetricKey = await loadLatestSymmetricKeyLazy(
445+
await loadPrivateKeyLazy(environmentOptions),
446+
environmentOptions,
447+
);
397448
}
398449

399450
// all encrypted data is JSON encoded
@@ -447,7 +498,7 @@ export async function decryptValue(
447498

448499
symmetricKey = await loadSymmetricKeyLazy(
449500
revisionNumber,
450-
await loadPrivateKeyLazy(),
501+
await loadPrivateKeyLazy(environmentOptions),
451502
environmentOptions,
452503
);
453504
}

0 commit comments

Comments
 (0)