@capraconsulting/cals-cli 3.5.2 → 3.7.0
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/lib/{cals-cli.js → cals-cli.mjs} +230 -309
- package/lib/{cals-cli.js.map → cals-cli.mjs.map} +1 -1
- package/lib/definition/index.d.ts +1 -1
- package/lib/github/index.d.ts +3 -2
- package/lib/index.d.ts +0 -1
- package/lib/index.es.js +91 -427
- package/lib/index.es.js.map +1 -1
- package/lib/index.js +163 -563
- package/lib/index.js.map +1 -1
- package/lib/snyk/index.d.ts +1 -1
- package/lib/sonarcloud/index.d.ts +2 -1
- package/package.json +21 -17
- package/lib/load-secrets/index.d.ts +0 -2
- package/lib/load-secrets/load-secrets.d.ts +0 -7
- package/lib/load-secrets/types.d.ts +0 -34
package/lib/index.es.js
CHANGED
|
@@ -9,28 +9,27 @@ import https from 'https';
|
|
|
9
9
|
import os from 'os';
|
|
10
10
|
import AJV from 'ajv';
|
|
11
11
|
import yaml from 'js-yaml';
|
|
12
|
-
import { uniq } from 'lodash';
|
|
12
|
+
import { uniq } from 'lodash-es';
|
|
13
13
|
import { Octokit } from '@octokit/rest';
|
|
14
14
|
import fetch from 'node-fetch';
|
|
15
15
|
import pLimit from 'p-limit';
|
|
16
16
|
import keytar from 'keytar';
|
|
17
17
|
import * as process$1 from 'process';
|
|
18
18
|
import { performance } from 'perf_hooks';
|
|
19
|
-
import { SecretsManagerClient, DescribeSecretCommand, UntagResourceCommand, TagResourceCommand, GetSecretValueCommand, CreateSecretCommand, RestoreSecretCommand, PutSecretValueCommand, ReplicateSecretToRegionsCommand, RemoveRegionsFromReplicationCommand } from '@aws-sdk/client-secrets-manager';
|
|
20
|
-
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
|
21
|
-
import read from 'read';
|
|
22
19
|
import { strict } from 'assert';
|
|
23
20
|
import execa from 'execa';
|
|
21
|
+
import read from 'read';
|
|
24
22
|
import { Transform } from 'stream';
|
|
25
23
|
|
|
26
|
-
var version = "3.
|
|
24
|
+
var version = "3.7.0";
|
|
27
25
|
|
|
28
26
|
class CacheProvider {
|
|
29
27
|
constructor(config) {
|
|
30
|
-
this.mustValidate = false;
|
|
31
|
-
this.defaultCacheTime = 1800;
|
|
32
28
|
this.config = config;
|
|
33
29
|
}
|
|
30
|
+
mustValidate = false;
|
|
31
|
+
config;
|
|
32
|
+
defaultCacheTime = 1800;
|
|
34
33
|
/**
|
|
35
34
|
* Retrieve cache if existent, ignoring the time.
|
|
36
35
|
*
|
|
@@ -84,15 +83,17 @@ function clearLine(stdout) {
|
|
|
84
83
|
}
|
|
85
84
|
class Reporter {
|
|
86
85
|
constructor(opts = {}) {
|
|
87
|
-
this.stdout = process.stdout;
|
|
88
|
-
this.stderr = process.stderr;
|
|
89
|
-
this.stdin = process.stdin;
|
|
90
|
-
this.isTTY = this.stdout.isTTY;
|
|
91
|
-
this.format = chalk;
|
|
92
|
-
this.startTime = Date.now();
|
|
93
86
|
this.nonInteractive = !!opts.nonInteractive;
|
|
94
87
|
this.isVerbose = !!opts.verbose;
|
|
95
88
|
}
|
|
89
|
+
stdout = process.stdout;
|
|
90
|
+
stderr = process.stderr;
|
|
91
|
+
stdin = process.stdin;
|
|
92
|
+
isTTY = this.stdout.isTTY;
|
|
93
|
+
nonInteractive;
|
|
94
|
+
isVerbose;
|
|
95
|
+
format = chalk;
|
|
96
|
+
startTime = Date.now();
|
|
96
97
|
error(msg) {
|
|
97
98
|
clearLine(this.stderr);
|
|
98
99
|
this.stderr.write(`${this.format.red("error")} ${msg}\n`);
|
|
@@ -116,15 +117,13 @@ class Reporter {
|
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
class Config {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.configCached = undefined;
|
|
127
|
-
}
|
|
120
|
+
cwd = path.resolve(process.cwd());
|
|
121
|
+
configFile = path.join(os.homedir(), ".cals-config.json");
|
|
122
|
+
cacheDir = cachedir("cals-cli");
|
|
123
|
+
agent = new https.Agent({
|
|
124
|
+
keepAlive: true,
|
|
125
|
+
});
|
|
126
|
+
configCached = undefined;
|
|
128
127
|
get config() {
|
|
129
128
|
const existingConfig = this.configCached;
|
|
130
129
|
if (existingConfig !== undefined) {
|
|
@@ -468,12 +467,11 @@ function getRepoId(orgName, repoName) {
|
|
|
468
467
|
return `${orgName}/${repoName}`;
|
|
469
468
|
}
|
|
470
469
|
function checkAgainstSchema(value) {
|
|
471
|
-
var _a;
|
|
472
470
|
const ajv = new AJV({ allErrors: true });
|
|
473
471
|
const valid = ajv.validate(schema, value);
|
|
474
472
|
return valid
|
|
475
473
|
? { definition: value }
|
|
476
|
-
: { error:
|
|
474
|
+
: { error: ajv.errorsText() ?? "Unknown error" };
|
|
477
475
|
}
|
|
478
476
|
function requireValidDefinition(definition) {
|
|
479
477
|
// Verify no duplicates in users and extract known logins.
|
|
@@ -518,7 +516,8 @@ function requireValidDefinition(definition) {
|
|
|
518
516
|
if (!teamIdList.includes(id)) {
|
|
519
517
|
throw new Error(`Project team ${id} in project ${project.name} is not registered in team list`);
|
|
520
518
|
}
|
|
521
|
-
})
|
|
519
|
+
}) // Verify repo teams exists as teams.
|
|
520
|
+
;
|
|
522
521
|
(org.repos || []).forEach((repo) => {
|
|
523
522
|
(repo.teams || []).forEach((team) => {
|
|
524
523
|
const id = getTeamId(org.organization, team.name);
|
|
@@ -542,6 +541,7 @@ function requireValidDefinition(definition) {
|
|
|
542
541
|
}, []);
|
|
543
542
|
}
|
|
544
543
|
class DefinitionFile {
|
|
544
|
+
path;
|
|
545
545
|
constructor(path) {
|
|
546
546
|
this.path = path;
|
|
547
547
|
}
|
|
@@ -587,10 +587,8 @@ function createReporter(argv) {
|
|
|
587
587
|
}
|
|
588
588
|
|
|
589
589
|
class GitHubTokenCliProvider {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
this.keyringAccount = "github-token";
|
|
593
|
-
}
|
|
590
|
+
keyringService = "cals";
|
|
591
|
+
keyringAccount = "github-token";
|
|
594
592
|
async getToken() {
|
|
595
593
|
if (process.env.CALS_GITHUB_TOKEN) {
|
|
596
594
|
return process.env.CALS_GITHUB_TOKEN;
|
|
@@ -626,8 +624,12 @@ async function undefinedForNotFound(value) {
|
|
|
626
624
|
}
|
|
627
625
|
|
|
628
626
|
class GitHubService {
|
|
627
|
+
config;
|
|
628
|
+
octokit;
|
|
629
|
+
cache;
|
|
630
|
+
tokenProvider;
|
|
631
|
+
semaphore;
|
|
629
632
|
constructor(props) {
|
|
630
|
-
this._requestCount = 0;
|
|
631
633
|
this.config = props.config;
|
|
632
634
|
this.octokit = props.octokit;
|
|
633
635
|
this.cache = props.cache;
|
|
@@ -639,7 +641,6 @@ class GitHubService {
|
|
|
639
641
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
640
642
|
this._requestCount++;
|
|
641
643
|
if (options.method !== "GET") {
|
|
642
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
643
644
|
return this.semaphore(() => request(options));
|
|
644
645
|
}
|
|
645
646
|
// Try to cache ETag for GET requests to save on rate limiting.
|
|
@@ -663,7 +664,6 @@ class GitHubService {
|
|
|
663
664
|
}
|
|
664
665
|
const getResponse = async (allowRetry = true) => {
|
|
665
666
|
try {
|
|
666
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
667
667
|
return await request(options);
|
|
668
668
|
}
|
|
669
669
|
catch (e) {
|
|
@@ -702,6 +702,7 @@ class GitHubService {
|
|
|
702
702
|
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
703
703
|
});
|
|
704
704
|
}
|
|
705
|
+
_requestCount = 0;
|
|
705
706
|
get requestCount() {
|
|
706
707
|
return this._requestCount;
|
|
707
708
|
}
|
|
@@ -792,7 +793,6 @@ class GitHubService {
|
|
|
792
793
|
if (res.organization.repositories.nodes == null) {
|
|
793
794
|
throw new Error("Missing organization nodes");
|
|
794
795
|
}
|
|
795
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
796
796
|
repos.push(...res.organization.repositories.nodes);
|
|
797
797
|
if (!res.organization.repositories.pageInfo.hasNextPage) {
|
|
798
798
|
break;
|
|
@@ -821,15 +821,12 @@ class GitHubService {
|
|
|
821
821
|
login: it.login,
|
|
822
822
|
data: it,
|
|
823
823
|
})),
|
|
824
|
-
...(await this.getOrgMembersInvitedList(org)).map((it) => {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
data: it,
|
|
831
|
-
});
|
|
832
|
-
}),
|
|
824
|
+
...(await this.getOrgMembersInvitedList(org)).map((it) => ({
|
|
825
|
+
type: "invited",
|
|
826
|
+
// TODO: Fix ?? case properly
|
|
827
|
+
login: it.login ?? "invalid",
|
|
828
|
+
data: it,
|
|
829
|
+
})),
|
|
833
830
|
];
|
|
834
831
|
}
|
|
835
832
|
async getRepository(owner, repo) {
|
|
@@ -898,15 +895,12 @@ class GitHubService {
|
|
|
898
895
|
login: it.login,
|
|
899
896
|
data: it,
|
|
900
897
|
})),
|
|
901
|
-
...(await this.getTeamMemberInvitedList(org, team)).map((it) => {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
data: it,
|
|
908
|
-
});
|
|
909
|
-
}),
|
|
898
|
+
...(await this.getTeamMemberInvitedList(org, team)).map((it) => ({
|
|
899
|
+
type: "invited",
|
|
900
|
+
// TODO: Fix ?? case properly
|
|
901
|
+
login: it.login ?? "invalid",
|
|
902
|
+
data: it,
|
|
903
|
+
})),
|
|
910
904
|
];
|
|
911
905
|
}
|
|
912
906
|
async getSearchedPullRequestList(owner) {
|
|
@@ -1031,17 +1025,16 @@ class GitHubService {
|
|
|
1031
1025
|
}
|
|
1032
1026
|
}`;
|
|
1033
1027
|
return this.cache.json(`vulnerability-alerts-${owner}-${repo}`, async () => {
|
|
1034
|
-
var _a, _b, _c, _d, _e;
|
|
1035
1028
|
const result = [];
|
|
1036
1029
|
let after = null;
|
|
1037
1030
|
while (true) {
|
|
1038
1031
|
const query = getQuery(after);
|
|
1039
1032
|
const res = await this.runGraphqlQuery(query);
|
|
1040
|
-
result.push(...(
|
|
1041
|
-
if (!
|
|
1033
|
+
result.push(...(res.repository?.vulnerabilityAlerts.edges?.map((it) => it.node) ?? []));
|
|
1034
|
+
if (!res.repository?.vulnerabilityAlerts.pageInfo.hasNextPage) {
|
|
1042
1035
|
break;
|
|
1043
1036
|
}
|
|
1044
|
-
after =
|
|
1037
|
+
after = res.repository?.vulnerabilityAlerts.pageInfo.endCursor;
|
|
1045
1038
|
}
|
|
1046
1039
|
return result;
|
|
1047
1040
|
});
|
|
@@ -1083,27 +1076,23 @@ class GitHubService {
|
|
|
1083
1076
|
}
|
|
1084
1077
|
}`;
|
|
1085
1078
|
const issues = await this.cache.json(`renovate-bot-issues-${owner}-${repo}`, async () => {
|
|
1086
|
-
var _a, _b, _c, _d, _e;
|
|
1087
1079
|
const result = [];
|
|
1088
1080
|
let after = null;
|
|
1089
1081
|
while (true) {
|
|
1090
1082
|
const query = getQuery(after);
|
|
1091
1083
|
const res = await this.runGraphqlQuery(query);
|
|
1092
|
-
const nodes =
|
|
1084
|
+
const nodes = res.repository?.issues.edges?.map((it) => it.node) ?? [];
|
|
1093
1085
|
result.push(...nodes
|
|
1094
1086
|
.filter((it) => it.title === "Dependency Dashboard")
|
|
1095
|
-
.map((it) => {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
});
|
|
1102
|
-
}));
|
|
1103
|
-
if (!((_d = res.repository) === null || _d === void 0 ? void 0 : _d.issues.pageInfo.hasNextPage)) {
|
|
1087
|
+
.map((it) => ({
|
|
1088
|
+
number: it.number,
|
|
1089
|
+
body: it.body,
|
|
1090
|
+
lastUpdatedByRenovate: it.userContentEdits?.nodes?.filter((it) => it.editor?.login === "renovate")?.[0]?.createdAt ?? null,
|
|
1091
|
+
})));
|
|
1092
|
+
if (!res.repository?.issues.pageInfo.hasNextPage) {
|
|
1104
1093
|
break;
|
|
1105
1094
|
}
|
|
1106
|
-
after =
|
|
1095
|
+
after = res.repository?.issues.pageInfo.endCursor;
|
|
1107
1096
|
}
|
|
1108
1097
|
return result;
|
|
1109
1098
|
});
|
|
@@ -1122,8 +1111,7 @@ async function createOctokit(config, tokenProvider) {
|
|
|
1122
1111
|
});
|
|
1123
1112
|
}
|
|
1124
1113
|
async function createGitHubService(props) {
|
|
1125
|
-
|
|
1126
|
-
const tokenProvider = (_a = props.tokenProvider) !== null && _a !== void 0 ? _a : new GitHubTokenCliProvider();
|
|
1114
|
+
const tokenProvider = props.tokenProvider ?? new GitHubTokenCliProvider();
|
|
1127
1115
|
return new GitHubService({
|
|
1128
1116
|
config: props.config,
|
|
1129
1117
|
octokit: await createOctokit(props.config, tokenProvider),
|
|
@@ -1132,7 +1120,7 @@ async function createGitHubService(props) {
|
|
|
1132
1120
|
});
|
|
1133
1121
|
}
|
|
1134
1122
|
|
|
1135
|
-
var index$
|
|
1123
|
+
var index$3 = /*#__PURE__*/Object.freeze({
|
|
1136
1124
|
__proto__: null,
|
|
1137
1125
|
DefinitionFile: DefinitionFile,
|
|
1138
1126
|
getGitHubOrgs: getGitHubOrgs,
|
|
@@ -1141,341 +1129,15 @@ var index$4 = /*#__PURE__*/Object.freeze({
|
|
|
1141
1129
|
parseDefinition: parseDefinition
|
|
1142
1130
|
});
|
|
1143
1131
|
|
|
1144
|
-
var index$
|
|
1132
|
+
var index$2 = /*#__PURE__*/Object.freeze({
|
|
1145
1133
|
__proto__: null,
|
|
1146
1134
|
createGitHubService: createGitHubService,
|
|
1147
1135
|
GitHubService: GitHubService
|
|
1148
1136
|
});
|
|
1149
1137
|
|
|
1150
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
1151
|
-
class LoadSecrets {
|
|
1152
|
-
constructor(props) {
|
|
1153
|
-
this.smClientForRegions = {};
|
|
1154
|
-
this.stsClient = new STSClient({
|
|
1155
|
-
region: "eu-west-1",
|
|
1156
|
-
});
|
|
1157
|
-
this.reporter = props.reporter;
|
|
1158
|
-
this.silent = props.silent;
|
|
1159
|
-
}
|
|
1160
|
-
getSmClient(region) {
|
|
1161
|
-
if (!this.smClientForRegions[region]) {
|
|
1162
|
-
this.smClientForRegions[region] = new SecretsManagerClient({
|
|
1163
|
-
region,
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
return this.smClientForRegions[region];
|
|
1167
|
-
}
|
|
1168
|
-
async getInput(options) {
|
|
1169
|
-
return new Promise((resolve, reject) => {
|
|
1170
|
-
read(options, (err, answer) => {
|
|
1171
|
-
if (err) {
|
|
1172
|
-
reject(err);
|
|
1173
|
-
}
|
|
1174
|
-
resolve(answer);
|
|
1175
|
-
});
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
async getSecretDetails(client, secretId) {
|
|
1179
|
-
try {
|
|
1180
|
-
return await client.send(new DescribeSecretCommand({ SecretId: secretId }));
|
|
1181
|
-
}
|
|
1182
|
-
catch (e) {
|
|
1183
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1184
|
-
if (e.name && e.name === "ResourceNotFoundException") {
|
|
1185
|
-
return null;
|
|
1186
|
-
}
|
|
1187
|
-
throw e;
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
async handleStringUpdate() {
|
|
1191
|
-
return await this.getInput({
|
|
1192
|
-
prompt: "Enter value (Ctrl+C to abort): ",
|
|
1193
|
-
silent: this.silent,
|
|
1194
|
-
});
|
|
1195
|
-
}
|
|
1196
|
-
async handleJsonUpdate(secret) {
|
|
1197
|
-
this.reporter.log("The secret is of type JSON with these expected fields:");
|
|
1198
|
-
for (const field of secret.fields) {
|
|
1199
|
-
const key = typeof field === "string" ? field : field.key;
|
|
1200
|
-
const desc = typeof field === "string"
|
|
1201
|
-
? ""
|
|
1202
|
-
: field.description
|
|
1203
|
-
? ` (${field.description})`
|
|
1204
|
-
: "";
|
|
1205
|
-
this.reporter.log(` - ${key}${desc}`);
|
|
1206
|
-
}
|
|
1207
|
-
this.reporter.log("");
|
|
1208
|
-
// TODO: Ability to specify full json value as one line.
|
|
1209
|
-
const collectedValues = {};
|
|
1210
|
-
for (const field of secret.fields) {
|
|
1211
|
-
const key = typeof field === "string" ? field : field.key;
|
|
1212
|
-
this.reporter.log(`Field: ${this.reporter.format.greenBright(key)}`);
|
|
1213
|
-
if (typeof field !== "string" && field.example != null) {
|
|
1214
|
-
this.reporter.log(`Example: ${this.reporter.format.magentaBright(field.example)}`);
|
|
1215
|
-
}
|
|
1216
|
-
const value = await this.getInput({
|
|
1217
|
-
prompt: "Enter value (Ctrl+C to abort): ",
|
|
1218
|
-
silent: this.silent,
|
|
1219
|
-
});
|
|
1220
|
-
collectedValues[key] = value;
|
|
1221
|
-
this.reporter.log("");
|
|
1222
|
-
}
|
|
1223
|
-
return JSON.stringify(collectedValues, undefined, " ");
|
|
1224
|
-
}
|
|
1225
|
-
getFullName(secretGroup, secret) {
|
|
1226
|
-
return `${secretGroup.namePrefix}${secret.name}`;
|
|
1227
|
-
}
|
|
1228
|
-
async syncTags(client, secret, tags) {
|
|
1229
|
-
const keysToRemove = secret
|
|
1230
|
-
.Tags.filter((existingTag) => !tags.some((it) => it.Key === existingTag.Key))
|
|
1231
|
-
.map((it) => it.Key);
|
|
1232
|
-
if (keysToRemove.length > 0) {
|
|
1233
|
-
this.reporter.log(`Removing obsolete tags: ${keysToRemove.join(", ")}`);
|
|
1234
|
-
await client.send(new UntagResourceCommand({
|
|
1235
|
-
SecretId: secret.ARN,
|
|
1236
|
-
TagKeys: keysToRemove,
|
|
1237
|
-
}));
|
|
1238
|
-
}
|
|
1239
|
-
const tagsToUpdate = tags.filter((expectedTag) => {
|
|
1240
|
-
const existing = secret.Tags.find((it) => it.Key === expectedTag.Key);
|
|
1241
|
-
return existing == null || existing.Value != expectedTag.Value;
|
|
1242
|
-
});
|
|
1243
|
-
if (tagsToUpdate.length > 0) {
|
|
1244
|
-
this.reporter.log(`Storing tags: ${tagsToUpdate.map((it) => it.Key).join(", ")}`);
|
|
1245
|
-
await client.send(new TagResourceCommand({
|
|
1246
|
-
SecretId: secret.ARN,
|
|
1247
|
-
Tags: tagsToUpdate,
|
|
1248
|
-
}));
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
async getSecretValue(client, secretId) {
|
|
1252
|
-
const result = await client.send(new GetSecretValueCommand({
|
|
1253
|
-
SecretId: secretId,
|
|
1254
|
-
}));
|
|
1255
|
-
if (result.SecretString == null) {
|
|
1256
|
-
throw new Error("Missing SecretString (is it a binary?)");
|
|
1257
|
-
}
|
|
1258
|
-
return result.SecretString;
|
|
1259
|
-
}
|
|
1260
|
-
async handleUpdate(secretGroup, secret) {
|
|
1261
|
-
var _a, _b, _c, _d, _e;
|
|
1262
|
-
const client = this.getSmClient(secretGroup.region);
|
|
1263
|
-
const fullName = this.getFullName(secretGroup, secret);
|
|
1264
|
-
const describeSecret = await this.getSecretDetails(client, fullName);
|
|
1265
|
-
this.reporter.log(`Secret: ${this.reporter.format.greenBright(fullName)}`);
|
|
1266
|
-
if (describeSecret == null) {
|
|
1267
|
-
this.reporter.log("The secret does not already exist and will be created");
|
|
1268
|
-
}
|
|
1269
|
-
else {
|
|
1270
|
-
this.reporter.log("Current value:");
|
|
1271
|
-
this.reporter.log(this.reporter.format.yellowBright((await this.getSecretValue(client, fullName)).replace(/^/gm, " ")));
|
|
1272
|
-
}
|
|
1273
|
-
this.reporter.log("");
|
|
1274
|
-
let secretValue;
|
|
1275
|
-
if (secret.type === "json") {
|
|
1276
|
-
try {
|
|
1277
|
-
secretValue = await this.handleJsonUpdate(secret);
|
|
1278
|
-
}
|
|
1279
|
-
catch (e) {
|
|
1280
|
-
if (e instanceof Error && e.message === "canceled") {
|
|
1281
|
-
this.reporter.log("Aborted");
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1284
|
-
throw e;
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
else if (secret.type === "string") {
|
|
1288
|
-
secretValue = await this.handleStringUpdate();
|
|
1289
|
-
}
|
|
1290
|
-
else {
|
|
1291
|
-
throw new Error(`Unsupported type`);
|
|
1292
|
-
}
|
|
1293
|
-
this.reporter.log("Storing secret value:");
|
|
1294
|
-
this.reporter.log(this.reporter.format.yellowBright(secretValue.replace(/^/gm, " ")));
|
|
1295
|
-
const tags = [
|
|
1296
|
-
{
|
|
1297
|
-
Key: "Source",
|
|
1298
|
-
Value: "load-secrets script",
|
|
1299
|
-
},
|
|
1300
|
-
];
|
|
1301
|
-
let arn;
|
|
1302
|
-
let version;
|
|
1303
|
-
let newReplicaRegions = [];
|
|
1304
|
-
let removedReplicaRegions = [];
|
|
1305
|
-
if (describeSecret == null) {
|
|
1306
|
-
newReplicaRegions = (_a = secret.replicaRegions) !== null && _a !== void 0 ? _a : [];
|
|
1307
|
-
const createResult = await client.send(new CreateSecretCommand({
|
|
1308
|
-
Name: fullName,
|
|
1309
|
-
AddReplicaRegions: secret.replicaRegions
|
|
1310
|
-
? secret.replicaRegions.map((replicaRegion) => ({
|
|
1311
|
-
Region: replicaRegion,
|
|
1312
|
-
}))
|
|
1313
|
-
: undefined,
|
|
1314
|
-
Description: "Created by load-secrets",
|
|
1315
|
-
SecretString: secretValue,
|
|
1316
|
-
Tags: tags,
|
|
1317
|
-
}));
|
|
1318
|
-
if (createResult.VersionId == null) {
|
|
1319
|
-
throw new Error("Expected versionId");
|
|
1320
|
-
}
|
|
1321
|
-
arn = createResult.ARN;
|
|
1322
|
-
version = createResult.VersionId;
|
|
1323
|
-
}
|
|
1324
|
-
else {
|
|
1325
|
-
if (describeSecret.DeletedDate != null) {
|
|
1326
|
-
await client.send(new RestoreSecretCommand({
|
|
1327
|
-
SecretId: fullName,
|
|
1328
|
-
}));
|
|
1329
|
-
}
|
|
1330
|
-
const updateResult = await client.send(new PutSecretValueCommand({
|
|
1331
|
-
SecretId: fullName,
|
|
1332
|
-
SecretString: secretValue,
|
|
1333
|
-
}));
|
|
1334
|
-
const currentReplicaRegions = (_c = (_b = describeSecret.ReplicationStatus) === null || _b === void 0 ? void 0 : _b.map((replicationStatus) => replicationStatus.Region)) !== null && _c !== void 0 ? _c : [];
|
|
1335
|
-
newReplicaRegions =
|
|
1336
|
-
(_e = (_d = secret.replicaRegions) === null || _d === void 0 ? void 0 : _d.filter((region) => !currentReplicaRegions.includes(region))) !== null && _e !== void 0 ? _e : [];
|
|
1337
|
-
removedReplicaRegions = currentReplicaRegions
|
|
1338
|
-
.filter((region) => !!region && typeof region === "string")
|
|
1339
|
-
.filter((region) => !(secret.replicaRegions || []).includes(region));
|
|
1340
|
-
if (newReplicaRegions.length > 0) {
|
|
1341
|
-
await client.send(new ReplicateSecretToRegionsCommand({
|
|
1342
|
-
SecretId: fullName,
|
|
1343
|
-
AddReplicaRegions: newReplicaRegions.map((region) => ({
|
|
1344
|
-
Region: region,
|
|
1345
|
-
})),
|
|
1346
|
-
}));
|
|
1347
|
-
}
|
|
1348
|
-
if (removedReplicaRegions.length > 0) {
|
|
1349
|
-
await client.send(new RemoveRegionsFromReplicationCommand({
|
|
1350
|
-
SecretId: fullName,
|
|
1351
|
-
RemoveReplicaRegions: removedReplicaRegions,
|
|
1352
|
-
}));
|
|
1353
|
-
}
|
|
1354
|
-
if (updateResult.VersionId == null) {
|
|
1355
|
-
throw new Error("Expected versionId");
|
|
1356
|
-
}
|
|
1357
|
-
await this.syncTags(client, describeSecret, tags);
|
|
1358
|
-
arn = updateResult.ARN;
|
|
1359
|
-
version = updateResult.VersionId;
|
|
1360
|
-
}
|
|
1361
|
-
this.reporter.log("");
|
|
1362
|
-
this.reporter.log("Secret stored:");
|
|
1363
|
-
this.reporter.log(`ARN: ${this.reporter.format.greenBright(arn)}`);
|
|
1364
|
-
this.reporter.log(`Version: ${this.reporter.format.greenBright(version)}`);
|
|
1365
|
-
if (newReplicaRegions.length > 0) {
|
|
1366
|
-
this.reporter.log(`Read replicas added to regions: ${newReplicaRegions
|
|
1367
|
-
.map((r) => this.reporter.format.greenBright(r))
|
|
1368
|
-
.join(", ")}`);
|
|
1369
|
-
}
|
|
1370
|
-
if (removedReplicaRegions.length > 0) {
|
|
1371
|
-
this.reporter.log(`Read replicas removed from regions: ${removedReplicaRegions
|
|
1372
|
-
.map((r) => this.reporter.format.redBright(r))
|
|
1373
|
-
.join(", ")}`);
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
checkSecretGroup(secretGroup) {
|
|
1377
|
-
if (!secretGroup.namePrefix.startsWith("/") ||
|
|
1378
|
-
!secretGroup.namePrefix.endsWith("/")) {
|
|
1379
|
-
throw new Error(`namePrefix should start and end with /. Current value: ${secretGroup.namePrefix}`);
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
getSecretDescription(details) {
|
|
1383
|
-
var _a, _b;
|
|
1384
|
-
return details == null
|
|
1385
|
-
? "not yet created"
|
|
1386
|
-
: (details === null || details === void 0 ? void 0 : details.DeletedDate) != null
|
|
1387
|
-
? `scheduled for deletion ${details.DeletedDate.toISOString()}`
|
|
1388
|
-
: `last changed ${(_b = (_a = details.LastChangedDate) === null || _a === void 0 ? void 0 : _a.toISOString()) !== null && _b !== void 0 ? _b : "unknown"}`;
|
|
1389
|
-
}
|
|
1390
|
-
/**
|
|
1391
|
-
* Returns false if aborted.
|
|
1392
|
-
*/
|
|
1393
|
-
async selectAndUpdate(secretGroups) {
|
|
1394
|
-
const secrets = [];
|
|
1395
|
-
this.reporter.log("Select secret to write:");
|
|
1396
|
-
this.reporter.log("");
|
|
1397
|
-
for (const secretGroup of secretGroups) {
|
|
1398
|
-
this.reporter.log(`${secretGroup.description} (prefix: ${secretGroup.namePrefix})`);
|
|
1399
|
-
for (let i = 0; i < secretGroup.secrets.length; i++) {
|
|
1400
|
-
const offset = secrets.length;
|
|
1401
|
-
const secret = secretGroup.secrets[i];
|
|
1402
|
-
secrets.push({
|
|
1403
|
-
secret: secret,
|
|
1404
|
-
secretGroup,
|
|
1405
|
-
});
|
|
1406
|
-
const client = this.getSmClient(secretGroup.region);
|
|
1407
|
-
const details = await this.getSecretDetails(client, this.getFullName(secretGroup, secret));
|
|
1408
|
-
const desc = this.getSecretDescription(details);
|
|
1409
|
-
this.reporter.log(` (${offset}) ${secret.name} (${desc})`);
|
|
1410
|
-
}
|
|
1411
|
-
this.reporter.log("");
|
|
1412
|
-
}
|
|
1413
|
-
let index;
|
|
1414
|
-
try {
|
|
1415
|
-
const answer = await this.getInput({
|
|
1416
|
-
prompt: "Enter index (or enter to quit): ",
|
|
1417
|
-
});
|
|
1418
|
-
if (answer.trim() === "") {
|
|
1419
|
-
return false;
|
|
1420
|
-
}
|
|
1421
|
-
index = parseInt(answer);
|
|
1422
|
-
if (!secrets[index]) {
|
|
1423
|
-
throw new Error();
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
catch (e) {
|
|
1427
|
-
this.reporter.warn("Secret not found - aborting");
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
this.reporter.log("");
|
|
1431
|
-
await this.handleUpdate(secrets[index].secretGroup, secrets[index].secret);
|
|
1432
|
-
this.reporter.log("");
|
|
1433
|
-
return true;
|
|
1434
|
-
}
|
|
1435
|
-
async process(secretGroups) {
|
|
1436
|
-
this.reporter.info("Checking account for current credentials");
|
|
1437
|
-
this.reporter.info("If any error is given, make sure you have valid credentials active");
|
|
1438
|
-
const currentAccount = await this.stsClient.send(new GetCallerIdentityCommand({}));
|
|
1439
|
-
this.reporter.info(`Running for account ${currentAccount.Account}`);
|
|
1440
|
-
this.reporter.log("");
|
|
1441
|
-
const matchedSecretGroups = secretGroups.filter((it) => it.accountId === currentAccount.Account);
|
|
1442
|
-
if (matchedSecretGroups.length === 0) {
|
|
1443
|
-
this.reporter.error(`No secrets specified for this account - aborting`);
|
|
1444
|
-
return;
|
|
1445
|
-
}
|
|
1446
|
-
for (const secretGroup of matchedSecretGroups) {
|
|
1447
|
-
this.checkSecretGroup(secretGroup);
|
|
1448
|
-
}
|
|
1449
|
-
while (await this.selectAndUpdate(matchedSecretGroups)) { }
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
/**
|
|
1453
|
-
* Load secrets interactively into Secrets Manager.
|
|
1454
|
-
*/
|
|
1455
|
-
function loadSecretsCli(props) {
|
|
1456
|
-
const loadSecrets = new LoadSecrets({
|
|
1457
|
-
reporter: createReporter({}),
|
|
1458
|
-
// For now we show the secrets, so that we get positive feedback that the value
|
|
1459
|
-
// is correctly entered.
|
|
1460
|
-
silent: false,
|
|
1461
|
-
});
|
|
1462
|
-
loadSecrets.process(props.secretGroups).catch((error) => {
|
|
1463
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1464
|
-
console.error(error.stack || error.message || error);
|
|
1465
|
-
process.exitCode = 1;
|
|
1466
|
-
});
|
|
1467
|
-
}
|
|
1468
|
-
|
|
1469
|
-
var index$2 = /*#__PURE__*/Object.freeze({
|
|
1470
|
-
__proto__: null,
|
|
1471
|
-
loadSecretsCli: loadSecretsCli
|
|
1472
|
-
});
|
|
1473
|
-
|
|
1474
1138
|
class SnykTokenCliProvider {
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
this.keyringAccount = "snyk-token";
|
|
1478
|
-
}
|
|
1139
|
+
keyringService = "cals";
|
|
1140
|
+
keyringAccount = "snyk-token";
|
|
1479
1141
|
async getToken() {
|
|
1480
1142
|
if (process.env.CALS_SNYK_TOKEN) {
|
|
1481
1143
|
return process.env.CALS_SNYK_TOKEN;
|
|
@@ -1496,13 +1158,14 @@ class SnykTokenCliProvider {
|
|
|
1496
1158
|
}
|
|
1497
1159
|
|
|
1498
1160
|
class SnykService {
|
|
1161
|
+
config;
|
|
1162
|
+
tokenProvider;
|
|
1499
1163
|
constructor(props) {
|
|
1500
1164
|
this.config = props.config;
|
|
1501
1165
|
this.tokenProvider = props.tokenProvider;
|
|
1502
1166
|
}
|
|
1503
1167
|
async getProjects(definition) {
|
|
1504
|
-
|
|
1505
|
-
const snykAccountId = (_a = definition.snyk) === null || _a === void 0 ? void 0 : _a.accountId;
|
|
1168
|
+
const snykAccountId = definition.snyk?.accountId;
|
|
1506
1169
|
if (snykAccountId === undefined) {
|
|
1507
1170
|
return [];
|
|
1508
1171
|
}
|
|
@@ -1567,7 +1230,7 @@ class SnykService {
|
|
|
1567
1230
|
totalDependencies: project.meta.latest_dependency_total.total,
|
|
1568
1231
|
issueCountsBySeverity: project.meta.latest_issue_counts,
|
|
1569
1232
|
lastTestedDate: project.meta.latest_dependency_total.updated_at,
|
|
1570
|
-
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId
|
|
1233
|
+
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId ?? "it"}/project/${project.id}`,
|
|
1571
1234
|
};
|
|
1572
1235
|
}),
|
|
1573
1236
|
];
|
|
@@ -1579,10 +1242,9 @@ class SnykService {
|
|
|
1579
1242
|
}
|
|
1580
1243
|
}
|
|
1581
1244
|
function createSnykService(props) {
|
|
1582
|
-
var _a;
|
|
1583
1245
|
return new SnykService({
|
|
1584
1246
|
config: props.config,
|
|
1585
|
-
tokenProvider:
|
|
1247
|
+
tokenProvider: props.tokenProvider ?? new SnykTokenCliProvider(),
|
|
1586
1248
|
});
|
|
1587
1249
|
}
|
|
1588
1250
|
|
|
@@ -1640,6 +1302,8 @@ class SonarCloudTokenCliProvider {
|
|
|
1640
1302
|
}
|
|
1641
1303
|
|
|
1642
1304
|
class SonarCloudService {
|
|
1305
|
+
config;
|
|
1306
|
+
tokenProvider;
|
|
1643
1307
|
constructor(props) {
|
|
1644
1308
|
this.config = props.config;
|
|
1645
1309
|
this.tokenProvider = props.tokenProvider;
|
|
@@ -1676,10 +1340,9 @@ class SonarCloudService {
|
|
|
1676
1340
|
}
|
|
1677
1341
|
}
|
|
1678
1342
|
function createSonarCloudService(props) {
|
|
1679
|
-
var _a;
|
|
1680
1343
|
return new SonarCloudService({
|
|
1681
1344
|
config: props.config,
|
|
1682
|
-
tokenProvider:
|
|
1345
|
+
tokenProvider: props.tokenProvider ?? new SonarCloudTokenCliProvider(),
|
|
1683
1346
|
});
|
|
1684
1347
|
}
|
|
1685
1348
|
|
|
@@ -1691,12 +1354,10 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1691
1354
|
});
|
|
1692
1355
|
|
|
1693
1356
|
class TestExecutor {
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
this.tasks = [];
|
|
1699
|
-
}
|
|
1357
|
+
shutdown = false;
|
|
1358
|
+
cleanupTask = null;
|
|
1359
|
+
usingWithCleanupTasks = false;
|
|
1360
|
+
tasks = [];
|
|
1700
1361
|
/**
|
|
1701
1362
|
* Check if we are currently in shutdown state due to user
|
|
1702
1363
|
* asking to abort (Ctrl+C).
|
|
@@ -1878,7 +1539,7 @@ async function pollForCondition({ container, attempts, waitIntervalSec, conditio
|
|
|
1878
1539
|
log(`Took ${duration()} seconds for condition`);
|
|
1879
1540
|
return;
|
|
1880
1541
|
}
|
|
1881
|
-
catch
|
|
1542
|
+
catch {
|
|
1882
1543
|
log("Still waiting...");
|
|
1883
1544
|
await new Promise((resolve) => setTimeout(resolve, waitIntervalSec * 1000));
|
|
1884
1545
|
}
|
|
@@ -1926,7 +1587,7 @@ async function isRunning(executor, container) {
|
|
|
1926
1587
|
await execa("docker", ["inspect", container.name]);
|
|
1927
1588
|
return true;
|
|
1928
1589
|
}
|
|
1929
|
-
catch
|
|
1590
|
+
catch {
|
|
1930
1591
|
return false;
|
|
1931
1592
|
}
|
|
1932
1593
|
}
|
|
@@ -1958,16 +1619,19 @@ class OutputPrefixTransform extends Transform {
|
|
|
1958
1619
|
}
|
|
1959
1620
|
}
|
|
1960
1621
|
function pipeToConsole(result, name) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1622
|
+
result.stdout
|
|
1623
|
+
?.pipe(new OutputPrefixTransform(`${name}: `))
|
|
1624
|
+
.pipe(process.stdout);
|
|
1625
|
+
result.stderr
|
|
1626
|
+
?.pipe(new OutputPrefixTransform(`${name} (stderr): `))
|
|
1627
|
+
.pipe(process.stderr);
|
|
1964
1628
|
}
|
|
1965
1629
|
function checkPidRunning(pid) {
|
|
1966
1630
|
try {
|
|
1967
1631
|
process.kill(pid, 0);
|
|
1968
1632
|
return true;
|
|
1969
1633
|
}
|
|
1970
|
-
catch
|
|
1634
|
+
catch {
|
|
1971
1635
|
return false;
|
|
1972
1636
|
}
|
|
1973
1637
|
}
|
|
@@ -1981,7 +1645,7 @@ async function getContainerId({ executor, name, hasFailed, pid, }) {
|
|
|
1981
1645
|
result = (await execa("docker", ["inspect", name, "-f", "{{.Id}}"]))
|
|
1982
1646
|
.stdout;
|
|
1983
1647
|
}
|
|
1984
|
-
catch
|
|
1648
|
+
catch {
|
|
1985
1649
|
result = null;
|
|
1986
1650
|
}
|
|
1987
1651
|
// Debugging to help us solve CALS-366.
|
|
@@ -2060,7 +1724,7 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2060
1724
|
args.push(imageId);
|
|
2061
1725
|
console.log(`Starting ${imageId}`);
|
|
2062
1726
|
const process = execa("docker", args);
|
|
2063
|
-
pipeToConsole(process, alias
|
|
1727
|
+
pipeToConsole(process, alias ?? containerName);
|
|
2064
1728
|
let failed = false;
|
|
2065
1729
|
process.catch(() => {
|
|
2066
1730
|
failed = true;
|
|
@@ -2077,7 +1741,7 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2077
1741
|
executor.registerCleanupTask(async () => {
|
|
2078
1742
|
console.log(`Stopping container ${containerName}`);
|
|
2079
1743
|
const r = execa("docker", ["stop", containerName]);
|
|
2080
|
-
pipeToConsole(r, (alias
|
|
1744
|
+
pipeToConsole(r, (alias ?? containerName) + " (stop)");
|
|
2081
1745
|
try {
|
|
2082
1746
|
await r;
|
|
2083
1747
|
}
|
|
@@ -2098,7 +1762,7 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2098
1762
|
}
|
|
2099
1763
|
async function runNpmRunScript(name, options) {
|
|
2100
1764
|
const result = execa("npm", ["run", name], {
|
|
2101
|
-
env: options
|
|
1765
|
+
env: options?.env,
|
|
2102
1766
|
});
|
|
2103
1767
|
pipeToConsole(result, `npm run ${name}`);
|
|
2104
1768
|
await result;
|
|
@@ -2115,13 +1779,12 @@ async function getDockerHostAddress() {
|
|
|
2115
1779
|
pipeToConsole(process, "ip route");
|
|
2116
1780
|
const res = await process;
|
|
2117
1781
|
try {
|
|
2118
|
-
return
|
|
1782
|
+
return res.stdout
|
|
2119
1783
|
.split("\n")
|
|
2120
1784
|
.filter((it) => it.includes("default via"))
|
|
2121
|
-
|
|
2122
|
-
.map((it) => /default via ([\d\.]+) /.exec(it)[1])[0]);
|
|
1785
|
+
.map((it) => /default via ([\d\.]+) /.exec(it)[1])[0];
|
|
2123
1786
|
}
|
|
2124
|
-
catch
|
|
1787
|
+
catch {
|
|
2125
1788
|
throw new Error("Failed to extract docker host address");
|
|
2126
1789
|
}
|
|
2127
1790
|
}
|
|
@@ -2134,6 +1797,7 @@ async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
|
2134
1797
|
silent: true,
|
|
2135
1798
|
}, (err) => {
|
|
2136
1799
|
if (err) {
|
|
1800
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
|
2137
1801
|
reject(err);
|
|
2138
1802
|
}
|
|
2139
1803
|
resolve();
|
|
@@ -2143,5 +1807,5 @@ async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
|
2143
1807
|
|
|
2144
1808
|
const VERSION = version;
|
|
2145
1809
|
|
|
2146
|
-
export { CacheProvider, Config, DefinitionFile, GitHubService, Reporter, TestExecutor, VERSION, createGitHubService, createNetwork, createReporter, createTestExecutor, curl, index$
|
|
1810
|
+
export { CacheProvider, Config, DefinitionFile, GitHubService, Reporter, TestExecutor, VERSION, createGitHubService, createNetwork, createReporter, createTestExecutor, curl, index$3 as definition, getDockerHostAddress, index$2 as github, pollForCondition, runNpmRunScript, index$1 as snyk, index as sonarCloud, startContainer, waitForEnterToContinue, waitForHttpOk, waitForPostgresAvailable };
|
|
2147
1811
|
//# sourceMappingURL=index.es.js.map
|