Skip to content

Commit 9d79712

Browse files
authored
Generalize secrets prefix for Flexion sandbox (#13)
1 parent 5ad2a72 commit 9d79712

15 files changed

Lines changed: 73 additions & 64 deletions

File tree

apps/cli/src/cli-controller/secrets.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ import { promises as fs } from 'fs';
22
import path from 'path';
33
import { Command } from 'commander';
44

5-
import {
6-
type DeployEnv,
7-
commands,
8-
getSecretsVault,
9-
} from '@flexion/forms-infra-core';
5+
import { commands, getSecretsVault } from '@flexion/forms-infra-core';
106
import { type Context } from './types.js';
117

128
export const addSecretCommands = (ctx: Context, cli: Command) => {
@@ -79,17 +75,20 @@ export const addSecretCommands = (ctx: Context, cli: Command) => {
7975
.command('set-login-gov-keys')
8076
.description(
8177
'generate and save login.gov keypair; if it already exists, it is not ' +
82-
'updated (future work might include adding key rotation)',
78+
'updated (future work might include adding key rotation)'
8379
)
84-
.argument('<deploy-env>', 'deployment environment (dev, demo)')
85-
.argument('<app-key>', 'application key')
86-
.action(async (env: DeployEnv, appKey: string) => {
80+
.argument(
81+
'<root-key>',
82+
'root key for secrets (e.g., flexion-forms-demo, tts-10x-forms-dev)'
83+
)
84+
.argument('<app-key>', 'application key (e.g., server-doj, server-kansas)')
85+
.action(async (rootKey: string, appKey: string) => {
8786
const vault = await getSecretsVault(ctx.file);
8887
const secretsDir = path.resolve(__dirname, '../../../infra/secrets');
8988
const loginResult = await commands.setLoginGovSecrets(
9089
{ vault, secretsDir },
91-
env,
92-
appKey,
90+
rootKey,
91+
appKey
9392
);
9493
if (loginResult.preexisting) {
9594
console.log('Keypair already exists.');

apps/sandbox/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"build": "tsup src/* --format esm",
1414
"clean": "rimraf dist tsconfig.tsbuildinfo coverage",
1515
"dev": "tsup src/* --watch --format esm",
16-
"start": "VCAP_SERVICES='{\"aws-rds\": [{ \"credentials\": { \"uri\": \"\" }}]}' node dist/index.js",
16+
"start": "node dist/index.js",
1717
"test": "vitest run --coverage"
1818
},
1919
"dependencies": {

apps/sandbox/src/index.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,16 @@ import { createCustomServer } from './server.js';
55

66
const port = process.env.PORT || 4321;
77

8-
const getCloudGovServerSecrets = () => {
9-
if (process.env.VCAP_SERVICES === undefined) {
10-
return;
11-
}
12-
const services = JSON.parse(process.env.VCAP_SERVICES || '{}');
13-
return {
14-
//loginGovClientSecret: services['user-provided']?.credentials?.SECRET_LOGIN_GOV_PRIVATE_KEY,
15-
dbUri: services['aws-rds'][0].credentials.uri as string,
16-
};
17-
};
18-
198
const getAppRunnerSecrets = async () => {
209
const dbSecretArn = process.env.DB_SECRET_ARN;
2110
const dbHost = process.env.DB_HOST;
2211
const dbPort = process.env.DB_PORT;
2312
const dbName = process.env.DB_NAME;
2413

2514
if (!dbSecretArn || !dbHost || !dbPort || !dbName) {
15+
console.error(
16+
'Missing required environment variables: DB_SECRET_ARN, DB_HOST, DB_PORT, DB_NAME'
17+
);
2618
return;
2719
}
2820

@@ -35,11 +27,11 @@ const getAppRunnerSecrets = async () => {
3527

3628
const dbSecret = JSON.parse(dbSecretString);
3729
return {
38-
dbUri: `postgresql://${dbSecret.username}:${dbSecret.password}@${dbHost}:${dbPort}/${dbName}`
30+
dbUri: `postgresql://${dbSecret.username}:${dbSecret.password}@${dbHost}:${dbPort}/${dbName}`,
3931
};
4032
};
4133

42-
const secrets = getCloudGovServerSecrets() || (await getAppRunnerSecrets());
34+
const secrets = await getAppRunnerSecrets();
4335
if (secrets === undefined) {
4436
console.error('Error getting secrets');
4537
process.exit(1);

infra/cdktf/src/spaces/aws/demo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AwsDemoStack extends TerraformStack {
1818

1919
// Create the sandbox infrastructure
2020
new SandboxStack(this, stackName, {
21-
environment: 'demo-aws',
21+
environment: 'flexion-forms-demo',
2222
});
2323
}
2424
}

infra/cdktf/src/spaces/aws/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AwsMainStack extends TerraformStack {
1818

1919
// Create the sandbox infrastructure
2020
new SandboxStack(this, stackName, {
21-
environment: 'main-aws',
21+
environment: 'flexion-forms-main',
2222
});
2323
}
2424
}

infra/core/src/commands/set-login-gov-secrets.test.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@ describe('set-login-gov-secrets command', () => {
2525
}),
2626
};
2727
const appKey = randomUUID();
28-
const result = await setLoginGovSecrets(context, 'dev', appKey);
28+
const result = await setLoginGovSecrets(
29+
context,
30+
'flexion-forms-dev',
31+
appKey
32+
);
2933
expect(result.preexisting).toEqual(false);
3034
expect(
3135
await context.vault.getSecrets(await context.vault.getSecretKeys())
3236
).toEqual({
33-
[`/tts-10x-forms-dev/${appKey}/login.gov/public-key`]: 'mock public key',
34-
[`/tts-10x-forms-dev/${appKey}/login.gov/private-key`]: 'mock private key',
37+
[`/flexion-forms-dev/${appKey}/login.gov/public-key`]: 'mock public key',
38+
[`/flexion-forms-dev/${appKey}/login.gov/private-key`]:
39+
'mock private key',
3540
});
3641
});
3742

@@ -50,7 +55,7 @@ describe('set-login-gov-secrets command', () => {
5055
privateKey: 'mock private key - 1',
5156
}),
5257
},
53-
'dev',
58+
'flexion-forms-dev',
5459
appKey
5560
);
5661
const secondResult = await setLoginGovSecrets(
@@ -61,17 +66,17 @@ describe('set-login-gov-secrets command', () => {
6166
privateKey: 'mock private key - 2',
6267
}),
6368
},
64-
'dev',
69+
'flexion-forms-dev',
6570
appKey
6671
);
6772

6873
expect(secondResult.preexisting).toEqual(true);
6974
expect(
7075
await context.vault.getSecrets(await context.vault.getSecretKeys())
7176
).toEqual({
72-
[`/tts-10x-forms-dev/${appKey}/login.gov/public-key`]:
77+
[`/flexion-forms-dev/${appKey}/login.gov/public-key`]:
7378
'mock public key - 1',
74-
[`/tts-10x-forms-dev/${appKey}/login.gov/private-key`]:
79+
[`/flexion-forms-dev/${appKey}/login.gov/private-key`]:
7580
'mock private key - 1',
7681
});
7782
});

infra/core/src/commands/set-login-gov-secrets.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { promises as fs } from 'fs';
33
import { promisify } from 'util';
44

55
import { type SecretsVault } from '../lib/types.js';
6-
import { type DeployEnv, getAppLoginGovKeys } from '../values.js';
6+
import { getAppLoginGovKeys } from '../values.js';
77

88
const execPromise = promisify(exec);
99

@@ -24,13 +24,17 @@ type Context = {
2424
/**
2525
* Sets or retrieves Login.gov secrets for the given application key. It retrieves and returns the
2626
* existing key pair or generates, stores, and returns new key pair if one didn't exist previously.
27+
*
28+
* @param ctx Context with vault and secrets directory
29+
* @param rootKey The root key for secrets (e.g., 'flexion-forms-demo', 'tts-10x-forms-dev')
30+
* @param appKey The application key (e.g., 'server-doj', 'server-kansas')
2731
*/
2832
export const setLoginGovSecrets = async (
2933
ctx: Context,
30-
env: DeployEnv,
34+
rootKey: string,
3135
appKey: string
3236
) => {
33-
const loginKeys = getAppLoginGovKeys(env, appKey);
37+
const loginKeys = getAppLoginGovKeys(rootKey, appKey);
3438

3539
// If the keypair is already set, do nothing and return it.
3640
const existingPublicKey = await ctx.vault.getSecret(loginKeys.publicKey);

infra/core/src/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type SecretMap, type SecretsVault } from './types.js';
22

33
export { getSecretMapFromJsonString } from './types.js';
44
export * from './adapters/index.js';
5+
export * from './secrets/index.js';
56

67
export const getSecretMap = async (vault: SecretsVault): Promise<SecretMap> => {
78
const secretKeys = await vault.getSecretKeys();
Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
export const getSecretKeys = (env: string) => [
2-
`/tts-10x-forms-${env}/cloudfoundry/password`,
3-
`/tts-10x-forms-${env}/cloudfoundry/username`,
4-
`/tts-10x-forms-${env}/server-doj/leidos-intranet-quorum/password`,
5-
`/tts-10x-forms-${env}/server-doj/leidos-intranet-quorum/username`,
6-
`/tts-10x-forms-${env}/server-doj/login.gov/private-key`,
7-
`/tts-10x-forms-${env}/server-doj/login.gov/public-key`,
8-
`/tts-10x-forms-${env}/server-kansas/login.gov/private-key`,
9-
`/tts-10x-forms-${env}/server-kansas/login.gov/public-key`,
1+
export const getSecretKeys = (rootKey: string) => [
2+
`/${rootKey}/cloudfoundry/password`,
3+
`/${rootKey}/cloudfoundry/username`,
4+
`/${rootKey}/server-doj/leidos-intranet-quorum/password`,
5+
`/${rootKey}/server-doj/leidos-intranet-quorum/username`,
6+
`/${rootKey}/server-doj/login.gov/private-key`,
7+
`/${rootKey}/server-doj/login.gov/public-key`,
8+
`/${rootKey}/server-kansas/login.gov/private-key`,
9+
`/${rootKey}/server-kansas/login.gov/public-key`,
10+
`/${rootKey}/database`,
1011
];
1112

12-
const secretPrefix = (env: string) => `/tts-10x-forms-${env}`;
13-
14-
export const getDatabaseSecretKey = (env: string) =>
15-
`${secretPrefix(env)}/database`;
13+
export const getDatabaseSecretKey = (rootKey: string) => `/${rootKey}/database`;

infra/core/src/values.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
export type DeployEnv = 'dev' | 'demo';
22

3-
const getPathPrefix = (env: DeployEnv) => `/tts-10x-forms-${env}`;
4-
53
/**
64
* Generates an object containing the paths for private/public keys pairs
75
* associated with login.gov for an application in the specified
86
* deployment environment.
7+
*
8+
* @param rootKey The root key for secrets (e.g., 'flexion-forms-demo', 'tts-10x-forms-dev')
9+
* @param appKey The application key (e.g., 'server-doj', 'server-kansas')
910
*/
10-
export const getAppLoginGovKeys = (env: DeployEnv, appKey: string) => {
11-
const prefix = getPathPrefix(env);
11+
export const getAppLoginGovKeys = (rootKey: string, appKey: string) => {
1212
return {
13-
privateKey: `${prefix}/${appKey}/login.gov/private-key`,
14-
publicKey: `${prefix}/${appKey}/login.gov/public-key`,
13+
privateKey: `/${rootKey}/${appKey}/login.gov/private-key`,
14+
publicKey: `/${rootKey}/${appKey}/login.gov/public-key`,
1515
};
1616
};

0 commit comments

Comments
 (0)