@celonis/content-cli 1.7.0 → 1.8.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/README.md +5 -5
- package/commands/configuration-management/api/package-version-api.js +9 -0
- package/commands/configuration-management/interfaces/package-version.interfaces.js +6 -0
- package/commands/configuration-management/module.js +22 -0
- package/commands/configuration-management/package-version-command.service.js +5 -0
- package/commands/configuration-management/package-version.service.js +32 -0
- package/commands/profile/module.js +9 -0
- package/commands/profile/profile-command.service.js +18 -1
- package/core/profile/profile.service.js +45 -11
- package/core/profile/secret-storage.service.js +115 -0
- package/lib/commands/configuration-management/api/package-version-api.d.ts +2 -1
- package/lib/commands/configuration-management/interfaces/package-version.interfaces.d.ts +21 -0
- package/lib/commands/configuration-management/module.d.ts +1 -0
- package/lib/commands/configuration-management/package-version-command.service.d.ts +1 -0
- package/lib/commands/configuration-management/package-version.service.d.ts +2 -0
- package/lib/commands/profile/module.d.ts +1 -0
- package/lib/commands/profile/profile-command.service.d.ts +1 -0
- package/lib/core/profile/profile.interface.d.ts +7 -4
- package/lib/core/profile/profile.service.d.ts +2 -2
- package/lib/core/profile/secret-storage.service.d.ts +7 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -72,8 +72,8 @@ Example, if you want to push a package from zipped file "interesting-package.zip
|
|
|
72
72
|
content-cli push package -p my-dev-profile --spaceKey my-cool-space -f interesting-package.zip
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
A
|
|
76
|
-
[documentation](https://github.com/celonis/content-cli/
|
|
75
|
+
A comprehensive list of Content CLI capabilities can be found in the
|
|
76
|
+
[documentation](https://github.com/celonis/content-cli/tree/main/docs).
|
|
77
77
|
|
|
78
78
|
You can still explore the full capabilities of Content CLI and the list of options for the different commands
|
|
79
79
|
by using the `-h` option in your command.
|
|
@@ -159,14 +159,14 @@ npm i -g @celonis/content-cli
|
|
|
159
159
|
## Contributing
|
|
160
160
|
|
|
161
161
|
We encourage public contributions! Please check
|
|
162
|
-
[CONTRIBUTING.md](https://github.com/celonis/content-cli/blob/
|
|
162
|
+
[CONTRIBUTING.md](https://github.com/celonis/content-cli/blob/main/CONTRIBUTING.md) for details on our
|
|
163
163
|
code of conduct.
|
|
164
164
|
|
|
165
|
-
For details on command development, refer to the [How to Add a Command](https://github.com/celonis/content-cli/blob/
|
|
165
|
+
For details on command development, refer to the [How to Add a Command](https://github.com/celonis/content-cli/blob/main/docs/how-to-add-command.md) guide.
|
|
166
166
|
|
|
167
167
|
## License
|
|
168
168
|
|
|
169
169
|
Copyright (c) 2021 Celonis SE
|
|
170
170
|
|
|
171
171
|
This project is licensed under the MIT License -
|
|
172
|
-
see [LICENSE](https://github.com/celonis/content-cli/blob/
|
|
172
|
+
see [LICENSE](https://github.com/celonis/content-cli/blob/main/LICENSE) file for details.
|
|
@@ -33,6 +33,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
createVersion(packageKey, request) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
return this.httpClient()
|
|
39
|
+
.post(`/pacman/api/core/packages/${packageKey}/versions`, request)
|
|
40
|
+
.catch(e => {
|
|
41
|
+
throw new logger_1.FatalError(`Problem creating version for package '${packageKey}': ${e}`);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
exports.PackageVersionApi = PackageVersionApi;
|
|
38
47
|
});
|
|
@@ -9,4 +9,10 @@
|
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.VersionBumpOption = void 0;
|
|
13
|
+
var VersionBumpOption;
|
|
14
|
+
(function (VersionBumpOption) {
|
|
15
|
+
VersionBumpOption["NONE"] = "NONE";
|
|
16
|
+
VersionBumpOption["PATCH"] = "PATCH";
|
|
17
|
+
})(VersionBumpOption || (exports.VersionBumpOption = VersionBumpOption = {}));
|
|
12
18
|
});
|
|
@@ -79,6 +79,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
79
79
|
.requiredOption("--packageVersion <packageVersion>", "Version of the package. Can be a specific version or \"LATEST\" keyword, which will return the most recently created version.")
|
|
80
80
|
.option("--json", "Return the response as a JSON file")
|
|
81
81
|
.action(this.getPackageVersion);
|
|
82
|
+
configVersionCommand.command("create")
|
|
83
|
+
.description("Create a new version for a package")
|
|
84
|
+
.requiredOption("--packageKey <packageKey>", "Identifier of the package")
|
|
85
|
+
.option("--packageVersion <packageVersion>", "Version string (required if versionBumpOption is NONE)")
|
|
86
|
+
.option("--versionBumpOption <versionBumpOption>", "Version bump option: NONE or PATCH", "NONE")
|
|
87
|
+
.option("--summaryOfChanges <summaryOfChanges>", "Summary of changes for this version")
|
|
88
|
+
.option("--nodeFilterKeys <nodeFilterKeys...>", "Node keys to include in the version. If omitted, all nodes of the package are included.")
|
|
89
|
+
.option("--json", "Return the response as a JSON file")
|
|
90
|
+
.action(this.createPackageVersion);
|
|
82
91
|
const variablesCommand = configCommand.command("variables")
|
|
83
92
|
.description("Commands related to variable configs");
|
|
84
93
|
variablesCommand.command("list")
|
|
@@ -162,6 +171,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
162
171
|
yield new package_version_command_service_1.PackageVersionCommandService(context).getPackageVersion(options.packageKey, options.packageVersion, options.json);
|
|
163
172
|
});
|
|
164
173
|
}
|
|
174
|
+
createPackageVersion(context, command, options) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
const hasExplicitVersion = !!options.packageVersion;
|
|
177
|
+
const hasVersionBump = options.versionBumpOption && options.versionBumpOption !== "NONE";
|
|
178
|
+
if (hasExplicitVersion && hasVersionBump) {
|
|
179
|
+
throw new Error("Please provide either --packageVersion or --versionBumpOption, but not both.");
|
|
180
|
+
}
|
|
181
|
+
if (!hasExplicitVersion && !hasVersionBump) {
|
|
182
|
+
throw new Error("Please provide either --packageVersion or --versionBumpOption PATCH.");
|
|
183
|
+
}
|
|
184
|
+
yield new package_version_command_service_1.PackageVersionCommandService(context).createPackageVersion(options.packageKey, options.packageVersion, options.versionBumpOption, options.summaryOfChanges, options.nodeFilterKeys, options.json);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
165
187
|
batchImportPackages(context, command, options) {
|
|
166
188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
167
189
|
if (options.gitProfile && !options.gitBranch) {
|
|
@@ -29,6 +29,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
29
29
|
yield this.packageVersionService.findPackageVersion(packageKey, version, jsonResponse);
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
createPackageVersion(packageKey, version, versionBumpOption, summaryOfChanges, nodeFilterKeys, jsonResponse) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
yield this.packageVersionService.createPackageVersion(packageKey, version, versionBumpOption, summaryOfChanges, nodeFilterKeys, jsonResponse);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
32
37
|
}
|
|
33
38
|
exports.PackageVersionCommandService = PackageVersionCommandService;
|
|
34
39
|
});
|
|
@@ -40,6 +40,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
+
createPackageVersion(packageKey, version, versionBumpOption, summaryOfChanges, nodeFilterKeys, jsonResponse) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const request = {
|
|
46
|
+
version: version,
|
|
47
|
+
versionBumpOption: versionBumpOption,
|
|
48
|
+
summaryOfChanges: summaryOfChanges,
|
|
49
|
+
};
|
|
50
|
+
if (nodeFilterKeys && nodeFilterKeys.length > 0) {
|
|
51
|
+
request.nodeFilter = {
|
|
52
|
+
filterType: "INCLUDE",
|
|
53
|
+
keys: nodeFilterKeys,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const created = yield this.packageVersionApi.createVersion(packageKey, request);
|
|
57
|
+
if (jsonResponse) {
|
|
58
|
+
const filename = (0, uuid_1.v4)() + ".json";
|
|
59
|
+
file_service_1.fileService.writeToFileWithGivenName(JSON.stringify(created, null, 2), filename);
|
|
60
|
+
logger_1.logger.info(file_service_1.FileService.fileDownloadedMessage + filename);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.printPackageVersionCreatedTransport(created);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
43
67
|
printPackageVersionTransport(packageVersionTransport) {
|
|
44
68
|
logger_1.logger.info(`Package Key: ${packageVersionTransport.packageKey}`);
|
|
45
69
|
logger_1.logger.info(`Version: ${packageVersionTransport.version}`);
|
|
@@ -50,6 +74,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
50
74
|
logger_1.logger.info(`Deployed: ${packageVersionTransport.deployed}`);
|
|
51
75
|
logger_1.logger.info(`Published By: ${packageVersionTransport.publishedBy}`);
|
|
52
76
|
}
|
|
77
|
+
printPackageVersionCreatedTransport(transport) {
|
|
78
|
+
logger_1.logger.info(`Successfully created version ${transport.version} for package ${transport.packageKey}`);
|
|
79
|
+
logger_1.logger.info(`Version: ${transport.version}`);
|
|
80
|
+
logger_1.logger.info(`Package Key: ${transport.packageKey}`);
|
|
81
|
+
logger_1.logger.info(`Summary of Changes: ${transport.summaryOfChanges}`);
|
|
82
|
+
logger_1.logger.info(`Creation Date: ${new Date(transport.creationDate).toISOString()}`);
|
|
83
|
+
logger_1.logger.info(`Created By: ${transport.createdBy}`);
|
|
84
|
+
}
|
|
53
85
|
}
|
|
54
86
|
exports.PackageVersionService = PackageVersionService;
|
|
55
87
|
});
|
|
@@ -37,6 +37,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
37
37
|
command.command("default <profile>")
|
|
38
38
|
.description("Command to set a profile as default")
|
|
39
39
|
.action(this.defaultProfile);
|
|
40
|
+
command.command("secure <profile>")
|
|
41
|
+
.description("Migrate a profile's secrets to secure system keychain storage")
|
|
42
|
+
.action(this.secureProfile);
|
|
40
43
|
}
|
|
41
44
|
defaultProfile(context, command) {
|
|
42
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -55,6 +58,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
55
58
|
yield new profile_command_service_1.ProfileCommandService().listProfiles();
|
|
56
59
|
});
|
|
57
60
|
}
|
|
61
|
+
secureProfile(context, command) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
const profile = command.args[0];
|
|
64
|
+
yield new profile_command_service_1.ProfileCommandService().secureProfile(profile);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
return Module;
|
|
60
69
|
});
|
|
@@ -55,7 +55,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
55
55
|
}
|
|
56
56
|
profile.authenticationType = yield profile_validator_1.ProfileValidator.validateProfile(profile);
|
|
57
57
|
yield this.profileService.authorizeProfile(profile);
|
|
58
|
-
this.profileService.storeProfile(profile);
|
|
58
|
+
yield this.profileService.storeProfile(profile);
|
|
59
59
|
if (setAsDefault) {
|
|
60
60
|
yield this.makeDefaultProfile(profile.name);
|
|
61
61
|
}
|
|
@@ -89,6 +89,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
89
89
|
logger_1.logger.info("Default profile: " + profile);
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
|
+
secureProfile(profileName) {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
const profile = yield this.profileService.findProfile(profileName);
|
|
95
|
+
if (profile.secretsStoredSecurely) {
|
|
96
|
+
logger_1.logger.info(`Profile "${profileName}" is already using secure storage.`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
yield this.profileService.storeProfile(profile);
|
|
100
|
+
const updatedProfile = yield this.profileService.findProfile(profileName);
|
|
101
|
+
if (updatedProfile.secretsStoredSecurely) {
|
|
102
|
+
logger_1.logger.info(`Profile "${profileName}" secrets have been migrated to secure storage.`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
logger_1.logger.warn(`Failed to migrate profile "${profileName}" to secure storage. Secrets remain in plaintext.`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
92
109
|
}
|
|
93
110
|
exports.ProfileCommandService = ProfileCommandService;
|
|
94
111
|
});
|
|
@@ -13,12 +13,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
13
13
|
if (v !== undefined) module.exports = v;
|
|
14
14
|
}
|
|
15
15
|
else if (typeof define === "function" && define.amd) {
|
|
16
|
-
define(["require", "exports", "./profile.interface", "./profile.validator", "path", "fs", "../utils/logger", "openid-client", "axios", "os"], factory);
|
|
16
|
+
define(["require", "exports", "./profile.interface", "./profile.validator", "path", "fs", "../utils/logger", "openid-client", "axios", "os", "./secret-storage.service"], factory);
|
|
17
17
|
}
|
|
18
18
|
})(function (require, exports) {
|
|
19
19
|
"use strict";
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
21
|
+
exports.ProfileService = void 0;
|
|
22
22
|
const profile_interface_1 = require("./profile.interface");
|
|
23
23
|
const profile_validator_1 = require("./profile.validator");
|
|
24
24
|
const path = require("path");
|
|
@@ -27,6 +27,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
27
|
const openid_client_1 = require("openid-client");
|
|
28
28
|
const axios_1 = require("axios");
|
|
29
29
|
const os = require("os");
|
|
30
|
+
const secret_storage_service_1 = require("./secret-storage.service");
|
|
30
31
|
const homedir = os.homedir();
|
|
31
32
|
// use 5 seconds buffer to avoid rare cases when accessToken is just about to expire before the command is sent
|
|
32
33
|
const expiryBuffer = 5000;
|
|
@@ -38,6 +39,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
38
39
|
constructor() {
|
|
39
40
|
this.profileContainerPath = path.resolve(homedir, ".celonis-content-cli-profiles");
|
|
40
41
|
this.configContainer = path.resolve(this.profileContainerPath, "config.json");
|
|
42
|
+
this.secureSecretStorageService = new secret_storage_service_1.SecureSecretStorageService();
|
|
41
43
|
}
|
|
42
44
|
findProfile(profileName) {
|
|
43
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -46,8 +48,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
46
48
|
if (!this.checkIfMissingProfile(profileName)) {
|
|
47
49
|
const file = fs.readFileSync(path.resolve(this.profileContainerPath, this.constructProfileFileName(profileName)), { encoding: "utf-8" });
|
|
48
50
|
const profile = JSON.parse(file);
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
+
if (profile.secretsStoredSecurely) {
|
|
52
|
+
this.secureSecretStorageService.getSecrets(profileName)
|
|
53
|
+
.then(profileSecureSecrets => {
|
|
54
|
+
if (profileSecureSecrets) {
|
|
55
|
+
profile.apiToken = profileSecureSecrets.apiToken;
|
|
56
|
+
profile.refreshToken = profileSecureSecrets.refreshToken;
|
|
57
|
+
profile.clientSecret = profileSecureSecrets.clientSecret;
|
|
58
|
+
this.refreshProfile(profile)
|
|
59
|
+
.then(() => resolve(profile))
|
|
60
|
+
.catch(() => reject(`The profile ${profileName} couldn't be resolved.`));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
reject("Failed to read secrets from system keychain.");
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
.catch(() => reject(`The profile ${profileName} couldn't be resolved.`));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.refreshProfile(profile)
|
|
70
|
+
.then(() => resolve(profile))
|
|
71
|
+
.catch(() => reject(`The profile ${profileName} couldn't be resolved.`));
|
|
72
|
+
}
|
|
51
73
|
}
|
|
52
74
|
else if (process.env.TEAM_URL && process.env.API_TOKEN) {
|
|
53
75
|
resolve(this.buildProfileFromEnvVariables());
|
|
@@ -92,11 +114,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
92
114
|
}
|
|
93
115
|
}
|
|
94
116
|
storeProfile(profile) {
|
|
95
|
-
this
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
this.createProfileContainerIfNotExists();
|
|
119
|
+
const newProfileFileName = this.constructProfileFileName(profile.name);
|
|
120
|
+
profile.team = this.getBaseTeamUrl(profile.team);
|
|
121
|
+
const secretsStoredInKeychain = yield this.secureSecretStorageService.storeSecrets(profile);
|
|
122
|
+
const profileToStore = Object.assign({}, profile);
|
|
123
|
+
if (secretsStoredInKeychain) {
|
|
124
|
+
profileToStore.secretsStoredSecurely = true;
|
|
125
|
+
delete profileToStore.apiToken;
|
|
126
|
+
delete profileToStore.refreshToken;
|
|
127
|
+
delete profileToStore.clientSecret;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
profileToStore.secretsStoredSecurely = false;
|
|
131
|
+
}
|
|
132
|
+
fs.writeFileSync(path.resolve(this.profileContainerPath, newProfileFileName), JSON.stringify(profileToStore), {
|
|
133
|
+
encoding: "utf-8",
|
|
134
|
+
});
|
|
100
135
|
});
|
|
101
136
|
}
|
|
102
137
|
buildProfileFromEnvVariables() {
|
|
@@ -263,7 +298,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
263
298
|
logger_1.logger.error(new logger_1.FatalError("The profile cannot be refreshed. Please retry or recreate profile."));
|
|
264
299
|
}
|
|
265
300
|
}
|
|
266
|
-
this.storeProfile(profile);
|
|
301
|
+
yield this.storeProfile(profile);
|
|
267
302
|
});
|
|
268
303
|
}
|
|
269
304
|
getProfileEnvVariables() {
|
|
@@ -394,5 +429,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
394
429
|
}
|
|
395
430
|
}
|
|
396
431
|
exports.ProfileService = ProfileService;
|
|
397
|
-
exports.profileService = new ProfileService();
|
|
398
432
|
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
(function (factory) {
|
|
11
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
12
|
+
var v = factory(require, exports);
|
|
13
|
+
if (v !== undefined) module.exports = v;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof define === "function" && define.amd) {
|
|
16
|
+
define(["require", "exports", "../utils/logger"], factory);
|
|
17
|
+
}
|
|
18
|
+
})(function (require, exports) {
|
|
19
|
+
"use strict";
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.SecureSecretStorageService = void 0;
|
|
22
|
+
const logger_1 = require("../utils/logger");
|
|
23
|
+
var PROFILE_SECRET_TYPE;
|
|
24
|
+
(function (PROFILE_SECRET_TYPE) {
|
|
25
|
+
PROFILE_SECRET_TYPE["API_TOKEN"] = "apiToken";
|
|
26
|
+
PROFILE_SECRET_TYPE["CLIENT_SECRET"] = "clientSecret";
|
|
27
|
+
PROFILE_SECRET_TYPE["REFRESH_TOKEN"] = "refreshToken";
|
|
28
|
+
})(PROFILE_SECRET_TYPE || (PROFILE_SECRET_TYPE = {}));
|
|
29
|
+
const CONTENT_CLI_SERVICE_NAME = "celonis-content-cli";
|
|
30
|
+
// Lazy load keytar to handle cases where native dependencies are not available
|
|
31
|
+
let keytar = null;
|
|
32
|
+
let keytarLoadError = null;
|
|
33
|
+
function getKeytar() {
|
|
34
|
+
if (keytar !== null) {
|
|
35
|
+
return keytar;
|
|
36
|
+
}
|
|
37
|
+
if (keytarLoadError !== null) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
keytar = require("@github/keytar");
|
|
42
|
+
return keytar;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
keytarLoadError = error;
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
class SecureSecretStorageService {
|
|
50
|
+
storeSecrets(profile) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
let secretsStoredInKeychain = true;
|
|
53
|
+
const secretEntries = [
|
|
54
|
+
{ type: PROFILE_SECRET_TYPE.API_TOKEN, value: profile.apiToken },
|
|
55
|
+
{ type: PROFILE_SECRET_TYPE.CLIENT_SECRET, value: profile.clientSecret },
|
|
56
|
+
{ type: PROFILE_SECRET_TYPE.REFRESH_TOKEN, value: profile.refreshToken },
|
|
57
|
+
];
|
|
58
|
+
for (const secretEntry of secretEntries) {
|
|
59
|
+
if (secretEntry.value) {
|
|
60
|
+
const stored = yield this.storeSecret(this.getSecretServiceName(profile.name), secretEntry.type, secretEntry.value);
|
|
61
|
+
if (!stored) {
|
|
62
|
+
secretsStoredInKeychain = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!secretsStoredInKeychain) {
|
|
67
|
+
logger_1.logger.warn("⚠️ Failed to store secrets securely. They will be stored in plain text file.");
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
getSecrets(profileName) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const keytarModule = getKeytar();
|
|
76
|
+
if (!keytarModule) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const secrets = yield keytarModule.findCredentials(this.getSecretServiceName(profileName));
|
|
81
|
+
if (!secrets.length) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const profileSecrets = {};
|
|
85
|
+
for (const secret of secrets) {
|
|
86
|
+
profileSecrets[secret.account] = secret.password;
|
|
87
|
+
}
|
|
88
|
+
return profileSecrets;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
getSecretServiceName(profileName) {
|
|
96
|
+
return `${CONTENT_CLI_SERVICE_NAME}:${profileName}`;
|
|
97
|
+
}
|
|
98
|
+
storeSecret(service, account, secret) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
const keytarModule = getKeytar();
|
|
101
|
+
if (!keytarModule) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
yield keytarModule.setPassword(service, account, secret);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.SecureSecretStorageService = SecureSecretStorageService;
|
|
115
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Context } from "../../../core/command/cli-context";
|
|
2
|
-
import { PackageVersionTransport } from "../interfaces/package-version.interfaces";
|
|
2
|
+
import { PackageVersionCreatedTransport, PackageVersionTransport, SavePackageVersionTransport } from "../interfaces/package-version.interfaces";
|
|
3
3
|
export declare class PackageVersionApi {
|
|
4
4
|
private httpClient;
|
|
5
5
|
constructor(context: Context);
|
|
6
6
|
findOne(packageKey: string, version: string): Promise<PackageVersionTransport>;
|
|
7
|
+
createVersion(packageKey: string, request: SavePackageVersionTransport): Promise<PackageVersionCreatedTransport>;
|
|
7
8
|
}
|
|
@@ -8,3 +8,24 @@ export interface PackageVersionTransport {
|
|
|
8
8
|
deployed: boolean;
|
|
9
9
|
publishedBy: string;
|
|
10
10
|
}
|
|
11
|
+
export interface SavePackageVersionTransport {
|
|
12
|
+
version?: string;
|
|
13
|
+
versionBumpOption?: VersionBumpOption;
|
|
14
|
+
summaryOfChanges?: string;
|
|
15
|
+
nodeFilter?: NodeFilterTransport;
|
|
16
|
+
}
|
|
17
|
+
export declare enum VersionBumpOption {
|
|
18
|
+
NONE = "NONE",
|
|
19
|
+
PATCH = "PATCH"
|
|
20
|
+
}
|
|
21
|
+
export interface NodeFilterTransport {
|
|
22
|
+
filterType: "INCLUDE";
|
|
23
|
+
keys: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface PackageVersionCreatedTransport {
|
|
26
|
+
packageKey: string;
|
|
27
|
+
version: string;
|
|
28
|
+
summaryOfChanges: string;
|
|
29
|
+
creationDate: string;
|
|
30
|
+
createdBy: string;
|
|
31
|
+
}
|
|
@@ -3,4 +3,5 @@ export declare class PackageVersionCommandService {
|
|
|
3
3
|
private packageVersionService;
|
|
4
4
|
constructor(context: Context);
|
|
5
5
|
getPackageVersion(packageKey: string, version: string, jsonResponse: boolean): Promise<void>;
|
|
6
|
+
createPackageVersion(packageKey: string, version: string | undefined, versionBumpOption: string, summaryOfChanges: string | undefined, nodeFilterKeys: string[] | undefined, jsonResponse: boolean): Promise<void>;
|
|
6
7
|
}
|
|
@@ -3,5 +3,7 @@ export declare class PackageVersionService {
|
|
|
3
3
|
private packageVersionApi;
|
|
4
4
|
constructor(context: Context);
|
|
5
5
|
findPackageVersion(packageKey: string, version: string, jsonResponse: boolean): Promise<void>;
|
|
6
|
+
createPackageVersion(packageKey: string, version: string | undefined, versionBumpOption: string, summaryOfChanges: string | undefined, nodeFilterKeys: string[] | undefined, jsonResponse: boolean): Promise<void>;
|
|
6
7
|
private printPackageVersionTransport;
|
|
8
|
+
private printPackageVersionCreatedTransport;
|
|
7
9
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface ProfileSecrets {
|
|
2
|
+
apiToken: string;
|
|
3
|
+
clientSecret?: string;
|
|
4
|
+
refreshToken?: string;
|
|
5
|
+
secretsStoredSecurely?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface Profile extends ProfileSecrets {
|
|
2
8
|
name: string;
|
|
3
9
|
team: string;
|
|
4
10
|
type: ProfileType;
|
|
5
|
-
apiToken: string;
|
|
6
11
|
authenticationType: AuthenticationType;
|
|
7
12
|
clientId?: string;
|
|
8
|
-
clientSecret?: string;
|
|
9
13
|
scopes?: string[];
|
|
10
14
|
clientAuthenticationMethod?: ClientAuthenticationMethod;
|
|
11
|
-
refreshToken?: string;
|
|
12
15
|
expiresAt?: number;
|
|
13
16
|
}
|
|
14
17
|
export type AuthenticationType = "Bearer" | "AppKey";
|
|
@@ -5,10 +5,11 @@ export interface Config {
|
|
|
5
5
|
export declare class ProfileService {
|
|
6
6
|
private profileContainerPath;
|
|
7
7
|
private configContainer;
|
|
8
|
+
private secureSecretStorageService;
|
|
8
9
|
findProfile(profileName: string): Promise<Profile>;
|
|
9
10
|
makeDefaultProfile(profileName: string): Promise<Profile>;
|
|
10
11
|
getDefaultProfile(): string;
|
|
11
|
-
storeProfile(profile: Profile): void
|
|
12
|
+
storeProfile(profile: Profile): Promise<void>;
|
|
12
13
|
private buildProfileFromEnvVariables;
|
|
13
14
|
private storeConfig;
|
|
14
15
|
private createProfileContainerIfNotExists;
|
|
@@ -40,4 +41,3 @@ export declare class ProfileService {
|
|
|
40
41
|
*/
|
|
41
42
|
private extractScopesFromTokenSet;
|
|
42
43
|
}
|
|
43
|
-
export declare const profileService: ProfileService;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Profile, ProfileSecrets } from "./profile.interface";
|
|
2
|
+
export declare class SecureSecretStorageService {
|
|
3
|
+
storeSecrets(profile: Profile): Promise<boolean>;
|
|
4
|
+
getSecrets(profileName: string): Promise<ProfileSecrets | undefined>;
|
|
5
|
+
private getSecretServiceName;
|
|
6
|
+
private storeSecret;
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@celonis/content-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "CLI Tool to help manage content in Celonis Platform",
|
|
5
5
|
"main": "content-cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"form-data": "4.0.4",
|
|
27
27
|
"openid-client": "5.6.1",
|
|
28
28
|
"hpagent": "1.2.0",
|
|
29
|
+
"@github/keytar": "7.10.6",
|
|
29
30
|
"semver": "7.6.3",
|
|
30
|
-
"simple-git": "3.
|
|
31
|
+
"simple-git": "3.32.3",
|
|
31
32
|
"valid-url": "1.0.9",
|
|
32
33
|
"winston": "3.17.0",
|
|
33
34
|
"yaml": "2.7.0"
|