@mongodb-js/signing-utils 0.2.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/LICENSE +557 -0
- package/dist/.esm-wrapper.mjs +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/signing-clients/index.d.ts +28 -0
- package/dist/signing-clients/index.d.ts.map +1 -0
- package/dist/signing-clients/index.js +59 -0
- package/dist/signing-clients/index.js.map +1 -0
- package/dist/signing-clients/local-signing-client.d.ts +7 -0
- package/dist/signing-clients/local-signing-client.d.ts.map +1 -0
- package/dist/signing-clients/local-signing-client.js +38 -0
- package/dist/signing-clients/local-signing-client.js.map +1 -0
- package/dist/signing-clients/remote-signing-client.d.ts +16 -0
- package/dist/signing-clients/remote-signing-client.d.ts.map +1 -0
- package/dist/signing-clients/remote-signing-client.js +93 -0
- package/dist/signing-clients/remote-signing-client.js.map +1 -0
- package/dist/ssh-client.d.ts +14 -0
- package/dist/ssh-client.d.ts.map +1 -0
- package/dist/ssh-client.js +80 -0
- package/dist/ssh-client.js.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +19 -0
- package/dist/utils.js.map +1 -0
- package/package.json +74 -0
- package/src/garasign.sh +62 -0
- package/src/index.ts +27 -0
- package/src/signing-clients/index.ts +82 -0
- package/src/signing-clients/local-signing-client.spec.ts +44 -0
- package/src/signing-clients/local-signing-client.ts +44 -0
- package/src/signing-clients/remote-signing-client.spec.ts +96 -0
- package/src/signing-clients/remote-signing-client.ts +119 -0
- package/src/ssh-client.spec.ts +186 -0
- package/src/ssh-client.ts +92 -0
- package/src/utils.ts +21 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getSigningClient = exports.RemoteSigningClient = exports.LocalSigningClient = void 0;
|
|
27
|
+
const path = __importStar(require("path"));
|
|
28
|
+
const ssh_client_1 = require("../ssh-client");
|
|
29
|
+
const local_signing_client_1 = require("./local-signing-client");
|
|
30
|
+
const remote_signing_client_1 = require("./remote-signing-client");
|
|
31
|
+
var local_signing_client_2 = require("./local-signing-client");
|
|
32
|
+
Object.defineProperty(exports, "LocalSigningClient", { enumerable: true, get: function () { return local_signing_client_2.LocalSigningClient; } });
|
|
33
|
+
var remote_signing_client_2 = require("./remote-signing-client");
|
|
34
|
+
Object.defineProperty(exports, "RemoteSigningClient", { enumerable: true, get: function () { return remote_signing_client_2.RemoteSigningClient; } });
|
|
35
|
+
async function getSigningClient(options) {
|
|
36
|
+
async function getSshClient(sshOptions) {
|
|
37
|
+
const sshClient = new ssh_client_1.SSHClient(sshOptions);
|
|
38
|
+
await sshClient.connect();
|
|
39
|
+
return sshClient;
|
|
40
|
+
}
|
|
41
|
+
const signingScript = path.join(__dirname, '../..', 'src', './garasign.sh');
|
|
42
|
+
if (options.client === 'remote') {
|
|
43
|
+
const sshClient = await getSshClient(options);
|
|
44
|
+
return new remote_signing_client_1.RemoteSigningClient(sshClient, {
|
|
45
|
+
workingDirectory: options.workingDirectory ?? '/home/ubuntu/garasign',
|
|
46
|
+
signingScript,
|
|
47
|
+
signingMethod: options.signingMethod,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (options.client === 'local') {
|
|
51
|
+
return new local_signing_client_1.LocalSigningClient({
|
|
52
|
+
signingScript,
|
|
53
|
+
signingMethod: options.signingMethod,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Unknown client type: ${options.client}`);
|
|
57
|
+
}
|
|
58
|
+
exports.getSigningClient = getSigningClient;
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signing-clients/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,2CAA6B;AAC7B,8CAA0C;AAC1C,iEAA4D;AAC5D,mEAA8D;AAE9D,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAC3B,iEAA8D;AAArD,4HAAA,mBAAmB,OAAA;AA4CrB,KAAK,UAAU,gBAAgB,CACpC,OAAsB;IAEtB,KAAK,UAAU,YAAY,CAAC,UAAyB;QACnD,MAAM,SAAS,GAAG,IAAI,sBAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IAE5E,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;QAE9C,OAAO,IAAI,2CAAmB,CAAC,SAAS,EAAE;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,uBAAuB;YACrE,aAAa;YACb,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC/B,OAAO,IAAI,yCAAkB,CAAC;YAC5B,aAAa;YACb,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC,CAAC;IACL,CAAC;IAGD,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5D,CAAC;AA7BD,4CA6BC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SigningClient, SigningClientOptions } from '.';
|
|
2
|
+
export declare class LocalSigningClient implements SigningClient {
|
|
3
|
+
private options;
|
|
4
|
+
constructor(options: Omit<SigningClientOptions, 'workingDirectory'>);
|
|
5
|
+
sign(file: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=local-signing-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-signing-client.d.ts","sourceRoot":"","sources":["../../src/signing-clients/local-signing-client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,GAAG,CAAC;AAU7D,qBAAa,kBAAmB,YAAW,aAAa;IAEpD,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;IAGjE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAyBlC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LocalSigningClient = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const utils_1 = require("../utils");
|
|
10
|
+
const localClientDebug = utils_1.debug.extend('LocalSigningClient');
|
|
11
|
+
class LocalSigningClient {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
sign(file) {
|
|
16
|
+
localClientDebug(`Signing ${file}`);
|
|
17
|
+
const directoryOfFileToSign = path_1.default.dirname(file);
|
|
18
|
+
try {
|
|
19
|
+
const env = {
|
|
20
|
+
...(0, utils_1.getEnv)(),
|
|
21
|
+
method: this.options.signingMethod,
|
|
22
|
+
};
|
|
23
|
+
(0, child_process_1.spawnSync)('bash', [this.options.signingScript, path_1.default.basename(file)], {
|
|
24
|
+
cwd: directoryOfFileToSign,
|
|
25
|
+
env,
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
});
|
|
28
|
+
localClientDebug(`Signed file ${file}`);
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
localClientDebug({ error });
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.LocalSigningClient = LocalSigningClient;
|
|
38
|
+
//# sourceMappingURL=local-signing-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-signing-client.js","sourceRoot":"","sources":["../../src/signing-clients/local-signing-client.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,iDAA0C;AAC1C,oCAAyC;AAGzC,MAAM,gBAAgB,GAAG,aAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAQ5D,MAAa,kBAAkB;IAC7B,YACU,OAAuD;QAAvD,YAAO,GAAP,OAAO,CAAgD;IAC9D,CAAC;IAEJ,IAAI,CAAC,IAAY;QACf,gBAAgB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAEpC,MAAM,qBAAqB,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG;gBACV,GAAG,IAAA,cAAM,GAAE;gBACX,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;aACnC,CAAC;YAEF,IAAA,yBAAS,EAAC,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,cAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE;gBACnE,GAAG,EAAE,qBAAqB;gBAC1B,GAAG;gBACH,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;YAEH,gBAAgB,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;YAExC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AA9BD,gDA8BC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SSHClient } from '../ssh-client';
|
|
2
|
+
import type { SigningClient, SigningClientOptions } from '.';
|
|
3
|
+
export declare class RemoteSigningClient implements SigningClient {
|
|
4
|
+
private sshClient;
|
|
5
|
+
private options;
|
|
6
|
+
private sftpConnection;
|
|
7
|
+
constructor(sshClient: SSHClient, options: SigningClientOptions);
|
|
8
|
+
private init;
|
|
9
|
+
private getRemoteFilePath;
|
|
10
|
+
private copyFile;
|
|
11
|
+
private downloadFile;
|
|
12
|
+
private removeFile;
|
|
13
|
+
private signRemoteFile;
|
|
14
|
+
sign(file: string): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=remote-signing-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-signing-client.d.ts","sourceRoot":"","sources":["../../src/signing-clients/remote-signing-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,GAAG,CAAC;AAE7D,qBAAa,mBAAoB,YAAW,aAAa;IAIrD,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IAJjB,OAAO,CAAC,cAAc,CAAe;gBAG3B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,oBAAoB;YASzB,IAAI;IAYlB,OAAO,CAAC,iBAAiB;YAMX,QAAQ;YAWR,YAAY;YAWZ,UAAU;YAWV,cAAc;IAyBtB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAsBxC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RemoteSigningClient = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
class RemoteSigningClient {
|
|
10
|
+
constructor(sshClient, options) {
|
|
11
|
+
this.sshClient = sshClient;
|
|
12
|
+
this.options = options;
|
|
13
|
+
}
|
|
14
|
+
async init() {
|
|
15
|
+
this.sftpConnection = await this.sshClient.getSftpConnection();
|
|
16
|
+
await this.sshClient.exec(`mkdir -p ${this.options.workingDirectory}`);
|
|
17
|
+
{
|
|
18
|
+
const remoteScript = `${this.options.workingDirectory}/garasign.sh`;
|
|
19
|
+
await this.copyFile(this.options.signingScript, remoteScript);
|
|
20
|
+
await this.sshClient.exec(`chmod +x ${remoteScript}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
getRemoteFilePath(file) {
|
|
24
|
+
return `${this.options.workingDirectory}/temp-${Date.now()}-${path_1.default.basename(file)}`;
|
|
25
|
+
}
|
|
26
|
+
async copyFile(file, remotePath) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
this.sftpConnection.fastPut(file, remotePath, (err) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
return reject(err);
|
|
31
|
+
}
|
|
32
|
+
return resolve();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async downloadFile(remotePath, file) {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
this.sftpConnection.fastGet(remotePath, file, (err) => {
|
|
39
|
+
if (err) {
|
|
40
|
+
return reject(err);
|
|
41
|
+
}
|
|
42
|
+
return resolve();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async removeFile(remotePath) {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
this.sftpConnection.unlink(remotePath, (err) => {
|
|
49
|
+
if (err) {
|
|
50
|
+
return reject(err);
|
|
51
|
+
}
|
|
52
|
+
return resolve();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async signRemoteFile(file) {
|
|
57
|
+
const env = (0, utils_1.getEnv)();
|
|
58
|
+
const cmds = [
|
|
59
|
+
`cd '${this.options.workingDirectory}'`,
|
|
60
|
+
`export garasign_username=${env.garasign_username}`,
|
|
61
|
+
`export garasign_password=${env.garasign_password}`,
|
|
62
|
+
`export artifactory_username=${env.artifactory_username}`,
|
|
63
|
+
`export artifactory_password=${env.artifactory_password}`,
|
|
64
|
+
`export method=${this.options.signingMethod}`,
|
|
65
|
+
`./garasign.sh '${file}'`,
|
|
66
|
+
];
|
|
67
|
+
const command = cmds.join(' && ');
|
|
68
|
+
const res = await this.sshClient.exec(command);
|
|
69
|
+
(0, utils_1.debug)('Sign remote file response\n', res.trim());
|
|
70
|
+
}
|
|
71
|
+
async sign(file) {
|
|
72
|
+
const remotePath = this.getRemoteFilePath(file);
|
|
73
|
+
try {
|
|
74
|
+
await this.init();
|
|
75
|
+
await this.copyFile(file, remotePath);
|
|
76
|
+
(0, utils_1.debug)(`SFTP: Copied file ${file} to ${remotePath}`);
|
|
77
|
+
await this.signRemoteFile(path_1.default.basename(remotePath));
|
|
78
|
+
(0, utils_1.debug)(`SFTP: Signed file ${file}`);
|
|
79
|
+
await this.downloadFile(remotePath, file);
|
|
80
|
+
(0, utils_1.debug)(`SFTP: Downloaded signed file to ${file}`);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
(0, utils_1.debug)({ error });
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await this.removeFile(remotePath);
|
|
87
|
+
(0, utils_1.debug)(`SFTP: Removed remote file ${remotePath}`);
|
|
88
|
+
this.sshClient.disconnect();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.RemoteSigningClient = RemoteSigningClient;
|
|
93
|
+
//# sourceMappingURL=remote-signing-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-signing-client.js","sourceRoot":"","sources":["../../src/signing-clients/remote-signing-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConnectConfig, SFTPWrapper } from 'ssh2';
|
|
2
|
+
export declare class SSHClient {
|
|
3
|
+
private sshClientOptions;
|
|
4
|
+
private sshConnection;
|
|
5
|
+
private sftpConnection?;
|
|
6
|
+
private connected;
|
|
7
|
+
constructor(sshClientOptions: ConnectConfig);
|
|
8
|
+
setupEventListeners(): void;
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
exec(command: string): Promise<string>;
|
|
12
|
+
getSftpConnection(): Promise<SFTPWrapper>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ssh-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh-client.d.ts","sourceRoot":"","sources":["../src/ssh-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAOtE,qBAAa,SAAS;IAMR,OAAO,CAAC,gBAAgB;IALpC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAc;IAErC,OAAO,CAAC,SAAS,CAAS;gBAEN,gBAAgB,EAAE,aAAa;IAKnD,mBAAmB;IAgBb,OAAO;IAgBb,UAAU;IAKJ,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BtC,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC;CAUhD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SSHClient = void 0;
|
|
4
|
+
const ssh2_1 = require("ssh2");
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const util_1 = require("util");
|
|
8
|
+
const events_1 = require("events");
|
|
9
|
+
class SSHClient {
|
|
10
|
+
constructor(sshClientOptions) {
|
|
11
|
+
this.sshClientOptions = sshClientOptions;
|
|
12
|
+
this.connected = false;
|
|
13
|
+
this.sshConnection = new ssh2_1.Client();
|
|
14
|
+
this.setupEventListeners();
|
|
15
|
+
}
|
|
16
|
+
setupEventListeners() {
|
|
17
|
+
this.sshConnection.on('ready', () => {
|
|
18
|
+
(0, utils_1.debug)('SSH: Connection established');
|
|
19
|
+
this.connected = true;
|
|
20
|
+
});
|
|
21
|
+
this.sshConnection.on('error', (err) => {
|
|
22
|
+
(0, utils_1.debug)('SSH: Connection error', err);
|
|
23
|
+
this.connected = false;
|
|
24
|
+
});
|
|
25
|
+
this.sshConnection.on('close', () => {
|
|
26
|
+
(0, utils_1.debug)('SSH: Connection closed');
|
|
27
|
+
this.connected = false;
|
|
28
|
+
this.sshConnection.destroy();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async connect() {
|
|
32
|
+
if (this.connected) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const privateKey = this.sshClientOptions.privateKey
|
|
36
|
+
? await (0, promises_1.readFile)(this.sshClientOptions.privateKey)
|
|
37
|
+
: undefined;
|
|
38
|
+
const ready = (0, events_1.once)(this.sshConnection, 'ready');
|
|
39
|
+
this.sshConnection.connect({
|
|
40
|
+
...this.sshClientOptions,
|
|
41
|
+
privateKey,
|
|
42
|
+
});
|
|
43
|
+
await ready;
|
|
44
|
+
}
|
|
45
|
+
disconnect() {
|
|
46
|
+
this.sshConnection.end();
|
|
47
|
+
this.connected = false;
|
|
48
|
+
}
|
|
49
|
+
async exec(command) {
|
|
50
|
+
if (!this.connected) {
|
|
51
|
+
throw new Error('Not connected to ssh server');
|
|
52
|
+
}
|
|
53
|
+
const stream = await (0, util_1.promisify)(this.sshConnection.exec.bind(this.sshConnection))(command);
|
|
54
|
+
let data = '';
|
|
55
|
+
stream.setEncoding('utf-8');
|
|
56
|
+
stream.stderr.setEncoding('utf-8');
|
|
57
|
+
stream.on('data', (chunk) => {
|
|
58
|
+
data += chunk;
|
|
59
|
+
});
|
|
60
|
+
stream.stderr.on('data', (chunk) => {
|
|
61
|
+
data += chunk;
|
|
62
|
+
});
|
|
63
|
+
const [code] = await (0, events_1.once)(stream, 'close');
|
|
64
|
+
if (code !== 0) {
|
|
65
|
+
throw new Error(`Command failed with code ${code}. Error: ${data}`);
|
|
66
|
+
}
|
|
67
|
+
return data;
|
|
68
|
+
}
|
|
69
|
+
async getSftpConnection() {
|
|
70
|
+
if (!this.connected) {
|
|
71
|
+
throw new Error('Not connected to ssh server');
|
|
72
|
+
}
|
|
73
|
+
this.sftpConnection =
|
|
74
|
+
this.sftpConnection ??
|
|
75
|
+
(await (0, util_1.promisify)(this.sshConnection.sftp.bind(this.sshConnection))());
|
|
76
|
+
return this.sftpConnection;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.SSHClient = SSHClient;
|
|
80
|
+
//# sourceMappingURL=ssh-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh-client.js","sourceRoot":"","sources":["../src/ssh-client.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="debug" />
|
|
2
|
+
export declare const debug: import("debug").Debugger;
|
|
3
|
+
export declare function getEnv(): {
|
|
4
|
+
garasign_username: string | undefined;
|
|
5
|
+
garasign_password: string | undefined;
|
|
6
|
+
artifactory_username: string | undefined;
|
|
7
|
+
artifactory_password: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAEA,eAAO,MAAM,KAAK,0BAA2B,CAAC;AAE9C,wBAAgB,MAAM;;;;;EAgBrB"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEnv = exports.debug = void 0;
|
|
4
|
+
const debug_1 = require("debug");
|
|
5
|
+
exports.debug = (0, debug_1.debug)('signing-utils');
|
|
6
|
+
function getEnv() {
|
|
7
|
+
const garasign_username = process.env['GARASIGN_USERNAME'] ?? process.env['garasign_username'];
|
|
8
|
+
const garasign_password = process.env['GARASIGN_PASSWORD'] ?? process.env['garasign_password'];
|
|
9
|
+
const artifactory_username = process.env['ARTIFACTORY_USERNAME'] ?? process.env['artifactory_username'];
|
|
10
|
+
const artifactory_password = process.env['ARTIFACTORY_PASSWORD'] ?? process.env['artifactory_password'];
|
|
11
|
+
return {
|
|
12
|
+
garasign_username,
|
|
13
|
+
garasign_password,
|
|
14
|
+
artifactory_username,
|
|
15
|
+
artifactory_password,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
exports.getEnv = getEnv;
|
|
19
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAA,iCAAyC;AAE5B,QAAA,KAAK,GAAG,IAAA,aAAO,EAAC,eAAe,CAAC,CAAC;AAE9C,SAAgB,MAAM;IACpB,MAAM,iBAAiB,GACrB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACvE,MAAM,iBAAiB,GACrB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACvE,MAAM,oBAAoB,GACxB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC7E,MAAM,oBAAoB,GACxB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAE7E,OAAO;QACL,iBAAiB;QACjB,iBAAiB;QACjB,oBAAoB;QACpB,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAhBD,wBAgBC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mongodb-js/signing-utils",
|
|
3
|
+
"description": "Utilities for signing packages in CI with Garasign.",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "MongoDB Inc",
|
|
6
|
+
"email": "compass@mongodb.com"
|
|
7
|
+
},
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://jira.mongodb.org/projects/COMPASS/issues",
|
|
13
|
+
"email": "compass@mongodb.com"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/mongodb-js/devtools-shared",
|
|
16
|
+
"version": "0.2.0",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/mongodb-js/devtools-shared.git"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"license": "SSPL",
|
|
26
|
+
"main": "dist/index.js",
|
|
27
|
+
"exports": {
|
|
28
|
+
"require": "./dist/index.js",
|
|
29
|
+
"import": "./dist/.esm-wrapper.mjs"
|
|
30
|
+
},
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"bootstrap": "npm run compile",
|
|
34
|
+
"prepublishOnly": "npm run compile",
|
|
35
|
+
"compile": "tsc -p tsconfig.json && gen-esm-wrapper . ./dist/.esm-wrapper.mjs",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"eslint": "eslint",
|
|
38
|
+
"prettier": "prettier",
|
|
39
|
+
"lint": "npm run eslint . && npm run prettier -- --check .",
|
|
40
|
+
"depcheck": "depcheck",
|
|
41
|
+
"check": "npm run typecheck && npm run lint && npm run depcheck",
|
|
42
|
+
"check-ci": "npm run check",
|
|
43
|
+
"test": "mocha",
|
|
44
|
+
"test-cov": "nyc -x \"**/*.spec.*\" --reporter=lcov --reporter=text --reporter=html npm run test",
|
|
45
|
+
"test-watch": "npm run test -- --watch",
|
|
46
|
+
"test-ci": "npm run test-cov",
|
|
47
|
+
"reformat": "npm run prettier -- --write ."
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@mongodb-js/eslint-config-devtools": "0.9.10",
|
|
51
|
+
"@mongodb-js/mocha-config-devtools": "^1.0.2",
|
|
52
|
+
"@mongodb-js/prettier-config-devtools": "^1.0.1",
|
|
53
|
+
"@mongodb-js/tsconfig-devtools": "^1.0.1",
|
|
54
|
+
"@types/chai": "^4.2.21",
|
|
55
|
+
"@types/mocha": "^9.1.1",
|
|
56
|
+
"@types/node": "^17.0.35",
|
|
57
|
+
"@types/sinon-chai": "^3.2.5",
|
|
58
|
+
"@types/ssh2": "^1.11.18",
|
|
59
|
+
"chai": "^4.3.6",
|
|
60
|
+
"depcheck": "^1.4.1",
|
|
61
|
+
"eslint": "^7.25.0",
|
|
62
|
+
"gen-esm-wrapper": "^1.1.0",
|
|
63
|
+
"mocha": "^8.4.0",
|
|
64
|
+
"nyc": "^15.1.0",
|
|
65
|
+
"prettier": "^2.3.2",
|
|
66
|
+
"sinon": "^9.2.3",
|
|
67
|
+
"typescript": "^5.0.4"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"debug": "^4.3.4",
|
|
71
|
+
"ssh2": "^1.15.0"
|
|
72
|
+
},
|
|
73
|
+
"gitHead": "ad497d997a5164646475261232687c8d0ace8722"
|
|
74
|
+
}
|
package/src/garasign.sh
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#! /usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
if [ -z "$1" ]; then
|
|
4
|
+
echo "Usage: garasign.sh <file>"
|
|
5
|
+
exit 1
|
|
6
|
+
fi
|
|
7
|
+
|
|
8
|
+
if [ -z ${garasign_username+omitted} ]; then echo "garasign_username is unset" && exit 1; fi
|
|
9
|
+
if [ -z ${garasign_password+omitted} ]; then echo "garasign_password is unset" && exit 1; fi
|
|
10
|
+
if [ -z ${artifactory_username+omitted} ]; then echo "artifactory_username is unset" && exit 1; fi
|
|
11
|
+
if [ -z ${artifactory_password+omitted} ]; then echo "artifactory_password is unset" && exit 1; fi
|
|
12
|
+
if [ -z ${method+omitted} ]; then echo "method must either be gpg or jsign" && exit 1; fi
|
|
13
|
+
|
|
14
|
+
ARTIFACTORY_HOST="artifactory.corp.mongodb.com"
|
|
15
|
+
|
|
16
|
+
logout_artifactory() {
|
|
17
|
+
docker logout "${ARTIFACTORY_HOST}" > /dev/null 2>&1
|
|
18
|
+
echo "Logged out from artifactory"
|
|
19
|
+
}
|
|
20
|
+
trap logout_artifactory EXIT
|
|
21
|
+
|
|
22
|
+
echo "Logging into docker artifactory"
|
|
23
|
+
echo "${artifactory_password}" | docker login --password-stdin --username ${artifactory_username} ${ARTIFACTORY_HOST} > /dev/null 2>&1
|
|
24
|
+
|
|
25
|
+
# If the docker login failed, exit
|
|
26
|
+
[ $? -ne 0 ] && exit $?
|
|
27
|
+
|
|
28
|
+
directory=$(pwd)
|
|
29
|
+
file=$1
|
|
30
|
+
|
|
31
|
+
echo "File to be signed: $file"
|
|
32
|
+
echo "Working directory: $directory"
|
|
33
|
+
|
|
34
|
+
gpg_sign() {
|
|
35
|
+
docker run \
|
|
36
|
+
-e GRS_CONFIG_USER1_USERNAME="${garasign_username}" \
|
|
37
|
+
-e GRS_CONFIG_USER1_PASSWORD="${garasign_password}" \
|
|
38
|
+
--rm \
|
|
39
|
+
-v $directory:$directory \
|
|
40
|
+
-w $directory \
|
|
41
|
+
${ARTIFACTORY_HOST}/release-tools-container-registry-local/garasign-gpg \
|
|
42
|
+
/bin/bash -c "gpgloader && gpg --yes -v --armor -o '$file.sig' --detach-sign '$file'"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
jsign_sign() {
|
|
46
|
+
docker run \
|
|
47
|
+
-e GRS_CONFIG_USER1_USERNAME="${garasign_username}" \
|
|
48
|
+
-e GRS_CONFIG_USER1_PASSWORD="${garasign_password}" \
|
|
49
|
+
--rm \
|
|
50
|
+
-v $directory:$directory \
|
|
51
|
+
-w $directory \
|
|
52
|
+
artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-jsign \
|
|
53
|
+
/bin/bash -c "jsign --tsaurl "timestamp.url" -a mongo-authenticode-2021 '$file'"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if [[ "$method" -eq "gpg" ]]; then
|
|
57
|
+
gpg_sign
|
|
58
|
+
elif [[ "$method" -eq "jsign" ]]; then
|
|
59
|
+
jsign_sign
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
echo "Finished signing $file"
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ClientOptions } from './signing-clients';
|
|
2
|
+
|
|
3
|
+
import { getSigningClient } from './signing-clients';
|
|
4
|
+
import { debug } from './utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Signs a file using Garasign.
|
|
8
|
+
*
|
|
9
|
+
* @param file the name of the file to sign
|
|
10
|
+
* @param options options to sign with - see the docs for `SigningOptions`
|
|
11
|
+
*/
|
|
12
|
+
export async function sign(
|
|
13
|
+
file: string,
|
|
14
|
+
options: ClientOptions
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
debug(
|
|
17
|
+
`Signing file: ${file} with client ${options.client} and options:`,
|
|
18
|
+
options
|
|
19
|
+
);
|
|
20
|
+
try {
|
|
21
|
+
const signingClient = await getSigningClient(options);
|
|
22
|
+
await signingClient.sign(file);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
debug(`Error signing file: ${file}`, err);
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ConnectConfig } from 'ssh2';
|
|
2
|
+
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { SSHClient } from '../ssh-client';
|
|
5
|
+
import { LocalSigningClient } from './local-signing-client';
|
|
6
|
+
import { RemoteSigningClient } from './remote-signing-client';
|
|
7
|
+
|
|
8
|
+
export { LocalSigningClient } from './local-signing-client';
|
|
9
|
+
export { RemoteSigningClient } from './remote-signing-client';
|
|
10
|
+
|
|
11
|
+
export type SigningMethod = 'gpg' | 'jsign';
|
|
12
|
+
|
|
13
|
+
export type SigningClientOptions = {
|
|
14
|
+
workingDirectory: string;
|
|
15
|
+
signingScript: string;
|
|
16
|
+
signingMethod: SigningMethod;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Options for signing a file remotely over an SSH connection. */
|
|
20
|
+
export type RemoteSigningOptions = {
|
|
21
|
+
/** Username for authentication. */
|
|
22
|
+
username?: string;
|
|
23
|
+
/** Password for password-based user authentication. */
|
|
24
|
+
password?: string;
|
|
25
|
+
/** Port number of the ssh server. */
|
|
26
|
+
port?: number;
|
|
27
|
+
/** Buffer or string that contains a private key for either key-based or hostbased user authentication (OpenSSH format). */
|
|
28
|
+
privateKey?: Buffer | string;
|
|
29
|
+
/** The method to sign with. Use gpg on linux and jsign on windows. */
|
|
30
|
+
signingMethod: SigningMethod;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The path of the working directory in which to sign files **on the remote ssh server**. Defaults to `/home/ubuntu/garasign`.
|
|
34
|
+
*/
|
|
35
|
+
workingDirectory?: string;
|
|
36
|
+
client: 'remote';
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** Options for signing a file locally. */
|
|
40
|
+
export type LocalSigningOptions = {
|
|
41
|
+
/** The method to sign with. Use gpg on linux and jsign on windows. */
|
|
42
|
+
signingMethod: SigningMethod;
|
|
43
|
+
|
|
44
|
+
client: 'local';
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type ClientOptions = RemoteSigningOptions | LocalSigningOptions;
|
|
48
|
+
|
|
49
|
+
export interface SigningClient {
|
|
50
|
+
sign(file: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function getSigningClient(
|
|
54
|
+
options: ClientOptions
|
|
55
|
+
): Promise<SigningClient> {
|
|
56
|
+
async function getSshClient(sshOptions: ConnectConfig) {
|
|
57
|
+
const sshClient = new SSHClient(sshOptions);
|
|
58
|
+
await sshClient.connect();
|
|
59
|
+
return sshClient;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const signingScript = path.join(__dirname, '../..', 'src', './garasign.sh');
|
|
63
|
+
|
|
64
|
+
if (options.client === 'remote') {
|
|
65
|
+
const sshClient = await getSshClient(options);
|
|
66
|
+
// Currently only linux remote is supported to sign the artifacts
|
|
67
|
+
return new RemoteSigningClient(sshClient, {
|
|
68
|
+
workingDirectory: options.workingDirectory ?? '/home/ubuntu/garasign',
|
|
69
|
+
signingScript,
|
|
70
|
+
signingMethod: options.signingMethod,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (options.client === 'local') {
|
|
74
|
+
return new LocalSigningClient({
|
|
75
|
+
signingScript,
|
|
76
|
+
signingMethod: options.signingMethod,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// @ts-expect-error `client` is a discriminated union - we should never reach here but we throw on the off-chance we do.
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
81
|
+
throw new Error(`Unknown client type: ${options.client}`);
|
|
82
|
+
}
|