UNPKG

@catladder/cli

Version:

Panter cli tool for cloud CI/CD and DevOps

72 lines 3.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.upsertGcloudServiceAccountAndSaveSecret = exports.accountExists = void 0; const child_process_promise_1 = require("child-process-promise"); const crypto_1 = require("crypto"); const gitlab_1 = require("../utils/gitlab"); const accountExists = async (fullIdentifier) => { try { await (0, child_process_promise_1.exec)(`gcloud iam service-accounts describe ${fullIdentifier}`); return true; } catch (_a) { return false; } }; exports.accountExists = accountExists; const upsertGcloudServiceAccount = async (context, account) => { const { projectId, name, displayName, roles, description } = account; // name has limit of 30 const namePrefix = `${name}`; const nameSuffixRaw = `${context.env}-${context.name}`; const nameMiddleRaw = `${context.fullConfig.customerName}-${context.fullConfig.appName}`; const MAX_LENGTH = 30; const NUM_SEPARATORS = 2; // we want to first hash middle, then suffix // if for middle we have at least 1 char left, its ok, so we don't hash nameSuffix, otherwise we need to hash that as well const middleMaxLength = MAX_LENGTH - namePrefix.length - nameSuffixRaw.length - NUM_SEPARATORS; let nameMiddle; let nameSuffix; if (middleMaxLength < 1) { nameMiddle = hashIfNessecary(nameMiddleRaw, 1); nameSuffix = hashIfNessecary(nameSuffixRaw, MAX_LENGTH - namePrefix.length - 1 - NUM_SEPARATORS); } else { nameMiddle = hashIfNessecary(nameMiddleRaw, middleMaxLength); nameSuffix = nameSuffixRaw; } const fullName = `${namePrefix}-${nameMiddle}-${nameSuffix}`; const fullDisplayName = `${context.fullConfig.customerName}-${context.fullConfig.appName} ${context.env}:${context.name} | ${displayName}`; const fullIdentifier = `${fullName}@${projectId}.iam.gserviceaccount.com`; const existing = await (0, exports.accountExists)(fullIdentifier); if (!existing) { await (0, child_process_promise_1.exec)(`gcloud iam service-accounts create ${fullName} --display-name="${fullDisplayName}" --project="${projectId}" --description="${description}"`); } const memberName = `serviceAccount:${fullIdentifier}`; for (const role of roles) { await (0, child_process_promise_1.exec)(`gcloud projects add-iam-policy-binding ${projectId} --member=${memberName} --role=${role} --condition=None`); } // create key // delete first all keys const keys = await (0, child_process_promise_1.exec)(`gcloud iam service-accounts keys list --iam-account=${fullIdentifier} --managed-by=user --format=json`).then((o) => JSON.parse(o.stdout)); for (const key of keys) { await (0, child_process_promise_1.exec)(`gcloud iam service-accounts keys delete ${key.name} --quiet --iam-account=${fullIdentifier}`); } return await (0, child_process_promise_1.exec)( // on some platforms /dev/stdout is not available without the pipe `gcloud iam service-accounts keys create /dev/stdout --iam-account=${fullIdentifier} | cat`).then((o) => o.stdout); }; const upsertGcloudServiceAccountAndSaveSecret = async (instance, context, account, secretName) => { instance.log("upserting service account " + account.name + "..."); const key = await upsertGcloudServiceAccount(context, account); await (0, gitlab_1.upsertAllVariables)(instance, { [secretName]: key, }, context.env, context.name); instance.log("done!"); }; exports.upsertGcloudServiceAccountAndSaveSecret = upsertGcloudServiceAccountAndSaveSecret; const hashIfNessecary = (str, maxLength) => str.length > maxLength ? hash(str, maxLength) : str; const hash = (str, length) => { return (0, crypto_1.createHmac)("sha256", str).digest("hex").substring(0, length); }; //# sourceMappingURL=serviceAccounts.js.map