@catladder/cli
Version:
Panter cli tool for cloud CI/CD and DevOps
72 lines • 3.88 kB
JavaScript
;
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