envilder
Version:
A CLI and GitHub Action that securely centralizes your environment variables from AWS SSM or Azure Key Vault as a single source of truth
120 lines • 4.62 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { spawn } from 'node:child_process';
import { createInterface } from 'node:readline';
import { SsoSessionExpiredError } from '../../../core/domain/errors/DomainErrors.js';
import { presentError } from '../errors/CliErrorPresenter.js';
import { SilentExitError } from '../errors/SilentExitError.js';
const AWS_CLI_NOT_FOUND = -1;
const LOGIN_FAILED = 1;
export function buildLoginArgs(profileName) {
if (profileName) {
return ['sso', 'login', '--profile', profileName];
}
return ['sso', 'login'];
}
function defaultIsInteractive() {
return [process.stdout.isTTY, process.stdin.isTTY].every(Boolean);
}
function defaultConfirm(question) {
const prompt = createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
prompt.question(`${question} `, (answer) => {
prompt.close();
resolve(answer.trim().toLowerCase() === 'y');
});
});
}
function defaultRunLogin(profileName) {
return new Promise((resolve) => {
const child = spawn('aws', buildLoginArgs(profileName), {
stdio: 'inherit',
});
child.on('error', (error) => {
resolve(error.code === 'ENOENT' ? AWS_CLI_NOT_FOUND : LOGIN_FAILED);
});
child.on('close', (code) => {
resolve(code !== null && code !== void 0 ? code : LOGIN_FAILED);
});
});
}
function defaultWrite(message) {
console.error(message);
}
const defaultDeps = {
isInteractive: defaultIsInteractive,
confirm: defaultConfirm,
runLogin: defaultRunLogin,
write: defaultWrite,
};
export function executeWithSsoRecovery(run_1) {
return __awaiter(this, arguments, void 0, function* (run, deps = {}) {
const resolved = Object.assign(Object.assign({}, defaultDeps), deps);
try {
return yield run();
}
catch (error) {
if (!(error instanceof SsoSessionExpiredError)) {
throw error;
}
if (!resolved.isInteractive()) {
throw error;
}
yield recoverInteractively(run, error, resolved);
}
});
}
function recoverInteractively(run, error, deps) {
return __awaiter(this, void 0, void 0, function* () {
deps.write(presentError(error));
const command = error.profileName
? `aws sso login --profile ${error.profileName}`
: 'aws sso login';
const accepted = yield deps.confirm(`Run '${command}' now? [y/N]`);
if (!accepted) {
deps.write('Skipped. Run the command above when ready, then re-run envilder.');
throw new SilentExitError(LOGIN_FAILED);
}
const exitCode = yield deps.runLogin(error.profileName);
ensureLoginSucceeded(exitCode, deps);
yield retryOnce(run, deps);
});
}
function ensureLoginSucceeded(exitCode, deps) {
if (exitCode === AWS_CLI_NOT_FOUND) {
deps.write('The AWS CLI was not found on your PATH. Install it, then run the command above.');
throw new SilentExitError(LOGIN_FAILED);
}
if (exitCode !== 0) {
deps.write('Login did not complete. Try again, then re-run envilder.');
throw new SilentExitError(LOGIN_FAILED);
}
}
function retryOnce(run, deps) {
return __awaiter(this, void 0, void 0, function* () {
deps.write('\uD83C\uDF44 1-UP! SSO session restored.');
deps.write('\u21bb Warping back for your secrets\u2026');
try {
yield run();
deps.write('\u2b50 Level cleared.');
}
catch (retryError) {
if (retryError instanceof SsoSessionExpiredError) {
deps.write(presentError(retryError));
throw new SilentExitError(LOGIN_FAILED);
}
throw retryError;
}
});
}
//# sourceMappingURL=SsoLoginRecovery.js.map