You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
8.0 KiB
150 lines
8.0 KiB
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.checkSpecForSecrets = exports.handleSecretParams = void 0;
|
|
const clc = require("colorette");
|
|
const secretUtils = require("../../extensions/secretsUtils");
|
|
const secretManager = require("../../gcp/secretManager");
|
|
const planner_1 = require("./planner");
|
|
const askUserForParam_1 = require("../../extensions/askUserForParam");
|
|
const types_1 = require("../../extensions/types");
|
|
const error_1 = require("../../error");
|
|
const logger_1 = require("../../logger");
|
|
const utils_1 = require("../../utils");
|
|
async function handleSecretParams(payload, have, nonInteractive) {
|
|
var _a, _b, _c;
|
|
for (const i of (_a = payload.instancesToCreate) !== null && _a !== void 0 ? _a : []) {
|
|
if (await checkSpecForSecrets(i)) {
|
|
(0, utils_1.logLabeledBullet)("extensions", `Verifying secret params for ${clc.bold(i.instanceId)}`);
|
|
await handleSecretsCreateInstance(i, nonInteractive);
|
|
}
|
|
}
|
|
const updates = [...((_b = payload.instancesToUpdate) !== null && _b !== void 0 ? _b : []), ...((_c = payload.instancesToConfigure) !== null && _c !== void 0 ? _c : [])];
|
|
for (const i of updates) {
|
|
if (await checkSpecForSecrets(i)) {
|
|
(0, utils_1.logLabeledBullet)("extensions", `Verifying secret params for ${clc.bold(i.instanceId)}`);
|
|
const previousSpec = have.find((h) => h.instanceId === i.instanceId);
|
|
await handleSecretsUpdateInstance(i, previousSpec, nonInteractive);
|
|
}
|
|
}
|
|
}
|
|
exports.handleSecretParams = handleSecretParams;
|
|
async function checkSpecForSecrets(i) {
|
|
const extensionSpec = await (0, planner_1.getExtensionSpec)(i);
|
|
return secretUtils.usesSecrets(extensionSpec);
|
|
}
|
|
exports.checkSpecForSecrets = checkSpecForSecrets;
|
|
const secretsInSpec = (spec) => {
|
|
return spec.params.filter((p) => p.type === types_1.ParamType.SECRET);
|
|
};
|
|
async function handleSecretsCreateInstance(i, nonInteractive) {
|
|
const extensionVersion = await (0, planner_1.getExtensionVersion)(i);
|
|
const secretParams = secretsInSpec(extensionVersion.spec);
|
|
for (const s of secretParams) {
|
|
await handleSecretParamForCreate(s, i, nonInteractive);
|
|
}
|
|
}
|
|
async function handleSecretsUpdateInstance(i, prevSpec, nonInteractive) {
|
|
const extensionVersion = await (0, planner_1.getExtensionVersion)(i);
|
|
const prevExtensionVersion = await (0, planner_1.getExtensionVersion)(prevSpec);
|
|
const secretParams = secretsInSpec(extensionVersion.spec);
|
|
for (const s of secretParams) {
|
|
const prevParam = prevExtensionVersion.spec.params.find((p) => p.param === s.param);
|
|
if ((prevParam === null || prevParam === void 0 ? void 0 : prevParam.type) === types_1.ParamType.SECRET && prevSpec.params[prevParam === null || prevParam === void 0 ? void 0 : prevParam.param]) {
|
|
await handleSecretParamForUpdate(s, i, prevSpec.params[prevParam === null || prevParam === void 0 ? void 0 : prevParam.param], nonInteractive);
|
|
}
|
|
else {
|
|
await handleSecretParamForCreate(s, i, nonInteractive);
|
|
}
|
|
}
|
|
}
|
|
async function handleSecretParamForCreate(secretParam, i, nonInteractive) {
|
|
var _a;
|
|
const providedValue = i.params[secretParam.param];
|
|
if (!providedValue) {
|
|
return;
|
|
}
|
|
const [, projectId, , secretName, , version] = providedValue.split("/");
|
|
if (!projectId || !secretName || !version) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}, but expected a secret version.`);
|
|
}
|
|
const secretInfo = await getSecretInfo(projectId, secretName, version);
|
|
if (!secretInfo.secret) {
|
|
await promptForCreateSecret({
|
|
projectId,
|
|
secretName,
|
|
instanceId: i.instanceId,
|
|
secretParam,
|
|
nonInteractive,
|
|
});
|
|
return;
|
|
}
|
|
else if (!secretInfo.secretVersion) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}. ` +
|
|
`projects/${projectId}/secrets/${secretName} exists, but version ${version} does not. ` +
|
|
`See more information about this secret at ${secretManager.secretManagerConsoleUri(projectId)}`);
|
|
}
|
|
if (!!((_a = secretInfo === null || secretInfo === void 0 ? void 0 : secretInfo.secret) === null || _a === void 0 ? void 0 : _a.labels) &&
|
|
!!(secretInfo === null || secretInfo === void 0 ? void 0 : secretInfo.secret.labels[secretUtils.SECRET_LABEL]) &&
|
|
secretInfo.secret.labels[secretUtils.SECRET_LABEL] !== i.instanceId) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}. ` +
|
|
`projects/${projectId}/secrets/${secretName} is managed by a different extension instance (${secretInfo.secret.labels[secretUtils.SECRET_LABEL]}), so reusing it here can lead to unexpected behavior. ` +
|
|
"Please choose a different name for this secret, and rerun this command.");
|
|
}
|
|
await secretUtils.grantFirexServiceAgentSecretAdminRole(secretInfo.secret);
|
|
}
|
|
async function handleSecretParamForUpdate(secretParam, i, prevValue, nonInteractive) {
|
|
const providedValue = i.params[secretParam.param];
|
|
if (!providedValue) {
|
|
return;
|
|
}
|
|
const [, projectId, , secretName, , version] = providedValue.split("/");
|
|
if (!projectId || !secretName || !version) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}, but expected a secret version.`);
|
|
}
|
|
const [, prevProjectId, , prevSecretName] = prevValue.split("/");
|
|
if (prevSecretName !== secretName) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}, ` +
|
|
`but this instance was previously using a different secret projects/${prevProjectId}/secrets/${prevSecretName}.\n` +
|
|
`Changing secrets is not supported. If you want to change the value of this secret, ` +
|
|
`use a new version of projects/${prevProjectId}/secrets/${prevSecretName}.` +
|
|
`You can create a new version at ${secretManager.secretManagerConsoleUri(projectId)}`);
|
|
}
|
|
const secretInfo = await getSecretInfo(projectId, secretName, version);
|
|
if (!secretInfo.secret) {
|
|
i.params[secretParam.param] = await promptForCreateSecret({
|
|
projectId,
|
|
secretName,
|
|
instanceId: i.instanceId,
|
|
secretParam,
|
|
nonInteractive,
|
|
});
|
|
return;
|
|
}
|
|
else if (!secretInfo.secretVersion) {
|
|
throw new error_1.FirebaseError(`${clc.bold(i.instanceId)}: Found '${providedValue}' for secret param ${secretParam.param}. ` +
|
|
`projects/${projectId}/secrets/${secretName} exists, but version ${version} does not. ` +
|
|
`See more information about this secret at ${secretManager.secretManagerConsoleUri(projectId)}`);
|
|
}
|
|
i.params[secretParam.param] = secretManager.toSecretVersionResourceName(secretInfo.secretVersion);
|
|
await secretUtils.grantFirexServiceAgentSecretAdminRole(secretInfo.secret);
|
|
}
|
|
async function getSecretInfo(projectId, secretName, version) {
|
|
const secretInfo = {};
|
|
try {
|
|
secretInfo.secret = await secretManager.getSecret(projectId, secretName);
|
|
secretInfo.secretVersion = await secretManager.getSecretVersion(projectId, secretName, version);
|
|
}
|
|
catch (err) {
|
|
if (err.status !== 404) {
|
|
throw err;
|
|
}
|
|
}
|
|
return secretInfo;
|
|
}
|
|
async function promptForCreateSecret(args) {
|
|
logger_1.logger.info(`${clc.bold(args.instanceId)}: Secret ${args.projectId}/${args.secretName} doesn't exist yet.`);
|
|
if (args.nonInteractive) {
|
|
throw new error_1.FirebaseError(`To create this secret, run this command in interactive mode, or go to ${secretManager.secretManagerConsoleUri(args.projectId)}`);
|
|
}
|
|
return (0, askUserForParam_1.promptCreateSecret)(args.projectId, args.instanceId, args.secretParam, args.secretName);
|
|
}
|