@govuk-pay/cli 0.0.27 → 0.0.29
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/package.json
CHANGED
|
@@ -65,6 +65,7 @@ pay-low-pass:
|
|
|
65
65
|
master_db_password: aws/rds/superuser/deploy-tooling/pact-broker/password # pragma: allowlist secret
|
|
66
66
|
db_user: aws/rds/application_users/deploy/pact_broker_db_username
|
|
67
67
|
db_password: aws/rds/application_users/deploy/pact_broker_db_password # pragma: allowlist secret
|
|
68
|
+
DB_SUPPORT_PASSWORD_READONLY: aws/rds/support_readonly_users/deploy/pact_broker_support_readonly # pragma: allowlist secret
|
|
68
69
|
stubs:
|
|
69
70
|
smartpay-expected-password: pay-stubs/smartpay/expected-password
|
|
70
71
|
smartpay-expected-user: pay-stubs/smartpay/expected-user
|
|
@@ -498,6 +499,9 @@ value:
|
|
|
498
499
|
LEDGER_RDS_PASSWORD: "/" # pragma: allowlist secret
|
|
499
500
|
PRODUCTS_RDS_PASSWORD: "/" # pragma: allowlist secret
|
|
500
501
|
PUBLICAUTH_RDS_PASSWORD: "/" # pragma: allowlist secret
|
|
502
|
+
deploy-tooling:
|
|
503
|
+
pact-broker:
|
|
504
|
+
DB_SUPPORT_USER_READONLY: "pact_broker_support_readonly"
|
|
501
505
|
test-12:
|
|
502
506
|
adminusers:
|
|
503
507
|
DB_USER: "adminusers1"
|
package/src/commands/tunnel.js
CHANGED
|
@@ -10,6 +10,7 @@ const client_ecs_1 = require("@aws-sdk/client-ecs");
|
|
|
10
10
|
const client_rds_1 = require("@aws-sdk/client-rds");
|
|
11
11
|
const client_ssm_1 = require("@aws-sdk/client-ssm");
|
|
12
12
|
const readline_1 = __importDefault(require("readline"));
|
|
13
|
+
const promises_1 = __importDefault(require("node:readline/promises"));
|
|
13
14
|
const child_process_1 = require("child_process");
|
|
14
15
|
const constants_js_1 = require("../core/constants.js");
|
|
15
16
|
let ec2;
|
|
@@ -29,6 +30,30 @@ function logTunnelCommands() {
|
|
|
29
30
|
pay tunnel help # Describe tunnel command`);
|
|
30
31
|
}
|
|
31
32
|
exports.logTunnelCommands = logTunnelCommands;
|
|
33
|
+
async function readInputForReadOrWriteDBAccess() {
|
|
34
|
+
const rl = promises_1.default.createInterface({
|
|
35
|
+
input: process.stdin,
|
|
36
|
+
output: process.stdout
|
|
37
|
+
});
|
|
38
|
+
let answer = await rl.question('Do you require read-only access, or write-access to the database? [R/w]: ');
|
|
39
|
+
rl.close();
|
|
40
|
+
if (answer === undefined || answer === '') {
|
|
41
|
+
answer = 'R';
|
|
42
|
+
console.log('No option entered. Defaulting to read-only');
|
|
43
|
+
}
|
|
44
|
+
if (answer === 'R' || answer === 'r') {
|
|
45
|
+
printGreen('Database read-only access requested');
|
|
46
|
+
return 'read-only';
|
|
47
|
+
}
|
|
48
|
+
else if (answer === 'w') {
|
|
49
|
+
printGreen('Database write access requested');
|
|
50
|
+
return 'write';
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
printError('Invalid option entered. Exiting..');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
32
57
|
async function tunnelHandler(options) {
|
|
33
58
|
await (0, standardContent_js_1.showHeader)();
|
|
34
59
|
const { environment, application } = parseArguments(options);
|
|
@@ -39,10 +64,11 @@ async function tunnelHandler(options) {
|
|
|
39
64
|
let bastionTask = null;
|
|
40
65
|
try {
|
|
41
66
|
printWarningToUser();
|
|
67
|
+
const dbAccessType = await readInputForReadOrWriteDBAccess();
|
|
42
68
|
const database = await getDatabaseDetails(environment, application);
|
|
43
69
|
bastionTask = await startBastion(environment);
|
|
44
70
|
openTunnel(bastionTask, database, environment);
|
|
45
|
-
printHowToTunnelText(application, environment, database.EngineVersion);
|
|
71
|
+
await printHowToTunnelText(application, environment, database.EngineVersion, dbAccessType);
|
|
46
72
|
await waitForExit();
|
|
47
73
|
await shutdown(environment, bastionTask);
|
|
48
74
|
}
|
|
@@ -345,10 +371,10 @@ async function terminateSession(task, environment) {
|
|
|
345
371
|
}
|
|
346
372
|
}
|
|
347
373
|
}
|
|
348
|
-
function printHowToTunnelText(application, environment, dbEngineVersion) {
|
|
349
|
-
const dbUser = getDbUser(application);
|
|
350
|
-
const payLowPassDbSecretName =
|
|
351
|
-
const paySecretsPasswordName = getPaySecretsPasswordName();
|
|
374
|
+
async function printHowToTunnelText(application, environment, dbEngineVersion, dbAccessType) {
|
|
375
|
+
const dbUser = await getDbUser(environment, application, dbAccessType);
|
|
376
|
+
const payLowPassDbSecretName = getPayLowPassDbSecretName(environment, dbUser, dbAccessType);
|
|
377
|
+
const paySecretsPasswordName = getPaySecretsPasswordName(dbAccessType);
|
|
352
378
|
printGreen(`\nConnected tunnel to ${application} RDS database in ${environment} on port 65432\n`);
|
|
353
379
|
printGreen('Copy DB credentials to clipboard (in another window) using pay-low-pass:');
|
|
354
380
|
printGreen(` pay-low-pass ${payLowPassDbSecretName} | pbcopy`);
|
|
@@ -361,15 +387,42 @@ function printHowToTunnelText(application, environment, dbEngineVersion) {
|
|
|
361
387
|
printGreen('Or even more conveniently connect using a docker container and set the password automatically using pay-low-pass:');
|
|
362
388
|
printGreen(` docker run -e "PGPASSWORD=$(pay-low-pass ${payLowPassDbSecretName})" --rm -ti postgres:${dbEngineVersion}-alpine psql --host docker.for.mac.localhost --port 65432 --user ${dbUser} --dbname ${application}\n`);
|
|
363
389
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
390
|
+
async function getDbUser(environment, application, dbAccessType) {
|
|
391
|
+
let paramName;
|
|
392
|
+
if (dbAccessType === 'write') {
|
|
393
|
+
paramName = `${environment}_${application}.db_user`;
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
paramName = `${environment}_${application}.db_support_user_readonly`;
|
|
397
|
+
}
|
|
398
|
+
const ssmClient = new client_ssm_1.SSMClient();
|
|
399
|
+
const input = { Names: [paramName], WithDecryption: true };
|
|
400
|
+
const command = new client_ssm_1.GetParametersCommand(input);
|
|
401
|
+
const response = await ssmClient.send(command);
|
|
402
|
+
if (response?.Parameters?.length !== undefined && response?.Parameters?.length > 0 &&
|
|
403
|
+
response?.Parameters[0]?.Value !== undefined) {
|
|
404
|
+
return response.Parameters[0].Value;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
printError('Unable to get database username from Parameter Store');
|
|
408
|
+
return '';
|
|
409
|
+
}
|
|
367
410
|
}
|
|
368
|
-
function
|
|
369
|
-
|
|
411
|
+
function getPayLowPassDbSecretName(environment, user, dbAccessType) {
|
|
412
|
+
if (dbAccessType === 'write') {
|
|
413
|
+
return `aws/rds/application_users/${environment.split('-')[0]}/${user}`;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
return `aws/rds/support_readonly_users/${environment.split('-')[0]}/${user}`;
|
|
417
|
+
}
|
|
370
418
|
}
|
|
371
|
-
function getPaySecretsPasswordName() {
|
|
372
|
-
|
|
419
|
+
function getPaySecretsPasswordName(dbAccessType) {
|
|
420
|
+
if (dbAccessType === 'write') {
|
|
421
|
+
return 'DB_PASSWORD';
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
return 'DB_SUPPORT_PASSWORD_READONLY';
|
|
425
|
+
}
|
|
373
426
|
}
|
|
374
427
|
function printWarningToUser() {
|
|
375
428
|
console.log(FORMAT.yellow, '⚠️ WARNING: When using SSM, any and all activity you perform may be getting logged for security auditing purposes (think PCI).', FORMAT.reset);
|