@rushstack/debug-certificate-manager 1.4.37 → 1.5.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/CHANGELOG.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "@rushstack/debug-certificate-manager",
3
3
  "entries": [
4
+ {
5
+ "version": "1.5.0",
6
+ "tag": "@rushstack/debug-certificate-manager_v1.5.0",
7
+ "date": "Wed, 23 Jul 2025 20:55:57 GMT",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "comment": "CertificateStore - Add params to support custom paths and filenames"
12
+ },
13
+ {
14
+ "comment": "CertificateManager - Update `untrustCertificateAsync` to clear `caCertificateData`"
15
+ },
16
+ {
17
+ "comment": "CertificateManager - Use osascript (applescript) to run elevated command on macOS instead of sudo package."
18
+ },
19
+ {
20
+ "comment": "CertificateManager - Expose `getCertificateExpirationAsync` method to retrieve certificate expiration date"
21
+ }
22
+ ],
23
+ "dependency": [
24
+ {
25
+ "comment": "Updating dependency \"@rushstack/node-core-library\" to `5.14.0`"
26
+ },
27
+ {
28
+ "comment": "Updating dependency \"@rushstack/terminal\" to `0.15.4`"
29
+ },
30
+ {
31
+ "comment": "Updating dependency \"@rushstack/heft\" to `0.74.1`"
32
+ }
33
+ ]
34
+ }
35
+ },
4
36
  {
5
37
  "version": "1.4.37",
6
38
  "tag": "@rushstack/debug-certificate-manager_v1.4.37",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Change Log - @rushstack/debug-certificate-manager
2
2
 
3
- This log was last generated on Sat, 21 Jun 2025 00:13:15 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 23 Jul 2025 20:55:57 GMT and should not be manually modified.
4
+
5
+ ## 1.5.0
6
+ Wed, 23 Jul 2025 20:55:57 GMT
7
+
8
+ ### Minor changes
9
+
10
+ - CertificateStore - Add params to support custom paths and filenames
11
+ - CertificateManager - Update `untrustCertificateAsync` to clear `caCertificateData`
12
+ - CertificateManager - Use osascript (applescript) to run elevated command on macOS instead of sudo package.
13
+ - CertificateManager - Expose `getCertificateExpirationAsync` method to retrieve certificate expiration date
4
14
 
5
15
  ## 1.4.37
6
16
  Sat, 21 Jun 2025 00:13:15 GMT
@@ -22,8 +22,12 @@ import type { ITerminal } from '@rushstack/terminal';
22
22
  * @public
23
23
  */
24
24
  export declare class CertificateManager {
25
- private _certificateStore;
26
- constructor();
25
+ /**
26
+ * Get the certificate store used by this manager.
27
+ * @public
28
+ */
29
+ readonly certificateStore: CertificateStore;
30
+ constructor(options?: ICertificateManagerOptions);
27
31
  /**
28
32
  * Get a development certificate from the store, or optionally, generate a new one
29
33
  * and trust it if one doesn't exist in the store.
@@ -43,6 +47,12 @@ export declare class CertificateManager {
43
47
  private _detectIfCertificateIsTrustedAsync;
44
48
  private _trySetFriendlyNameAsync;
45
49
  private _ensureCertificateInternalAsync;
50
+ /**
51
+ * Validate existing certificates to check if they are usable.
52
+ *
53
+ * @public
54
+ */
55
+ validateCertificateAsync(terminal: ITerminal, options?: ICertificateGenerationOptions): Promise<ICertificateValidationResult>;
46
56
  private _parseMacOsMatchingCertificateHash;
47
57
  }
48
58
 
@@ -54,10 +64,15 @@ export declare class CertificateStore {
54
64
  private readonly _caCertificatePath;
55
65
  private readonly _certificatePath;
56
66
  private readonly _keyPath;
67
+ private readonly _storePath;
57
68
  private _caCertificateData;
58
69
  private _certificateData;
59
70
  private _keyData;
60
- constructor();
71
+ constructor(options?: ICertificateStoreOptions);
72
+ /**
73
+ * Path to the directory where the debug certificates are stored.
74
+ */
75
+ get storePath(): string;
61
76
  /**
62
77
  * Path to the saved debug CA certificate
63
78
  */
@@ -66,6 +81,10 @@ export declare class CertificateStore {
66
81
  * Path to the saved debug TLS certificate
67
82
  */
68
83
  get certificatePath(): string;
84
+ /**
85
+ * Path to the saved debug TLS key
86
+ */
87
+ get keyPath(): string;
69
88
  /**
70
89
  * Debug Certificate Authority certificate pem file contents.
71
90
  */
@@ -136,4 +155,57 @@ export declare interface ICertificateGenerationOptions {
136
155
  skipCertificateTrust?: boolean;
137
156
  }
138
157
 
158
+ /**
159
+ * Options for configuring the `CertificateManager`.
160
+ * @public
161
+ */
162
+ export declare interface ICertificateManagerOptions extends ICertificateStoreOptions {
163
+ }
164
+
165
+ /**
166
+ * Options for configuring paths and filenames used by the `CertificateStore`.
167
+ * @public
168
+ */
169
+ export declare interface ICertificateStoreOptions {
170
+ /**
171
+ * Path to the directory where the certificate store will be created.
172
+ * If not provided, it defaults to `<homedir>/.rushstack`.
173
+ */
174
+ storePath?: string;
175
+ /**
176
+ * Filename of the CA certificate file within the store directory.
177
+ * If not provided, it defaults to `rushstack-ca.pem`.
178
+ */
179
+ caCertificateFilename?: string;
180
+ /**
181
+ * Filename of the TLS certificate file within the store directory.
182
+ * If not provided, it defaults to `rushstack-serve.pem`.
183
+ */
184
+ certificateFilename?: string;
185
+ /**
186
+ * Filename of the TLS key file within the store directory.
187
+ * If not provided, it defaults to `rushstack-serve.key`.
188
+ */
189
+ keyFilename?: string;
190
+ }
191
+
192
+ /**
193
+ * Information about certificate validation results
194
+ * @public
195
+ */
196
+ export declare interface ICertificateValidationResult {
197
+ /**
198
+ * Whether valid certificates exist and are usable
199
+ */
200
+ isValid: boolean;
201
+ /**
202
+ * List of validation messages/issues found
203
+ */
204
+ validationMessages: string[];
205
+ /**
206
+ * The existing certificate if it exists and is valid
207
+ */
208
+ certificate?: ICertificate;
209
+ }
210
+
139
211
  export { }
@@ -1,4 +1,5 @@
1
1
  import type { ITerminal } from '@rushstack/terminal';
2
+ import { CertificateStore, type ICertificateStoreOptions } from './CertificateStore';
2
3
  /**
3
4
  * The set of names the certificate should be generated for, by default.
4
5
  * @public
@@ -32,6 +33,24 @@ export interface ICertificate {
32
33
  */
33
34
  subjectAltNames: readonly string[] | undefined;
34
35
  }
36
+ /**
37
+ * Information about certificate validation results
38
+ * @public
39
+ */
40
+ export interface ICertificateValidationResult {
41
+ /**
42
+ * Whether valid certificates exist and are usable
43
+ */
44
+ isValid: boolean;
45
+ /**
46
+ * List of validation messages/issues found
47
+ */
48
+ validationMessages: string[];
49
+ /**
50
+ * The existing certificate if it exists and is valid
51
+ */
52
+ certificate?: ICertificate;
53
+ }
35
54
  /**
36
55
  * Options to use if needing to generate a new certificate
37
56
  * @public
@@ -54,14 +73,24 @@ export interface ICertificateGenerationOptions {
54
73
  */
55
74
  skipCertificateTrust?: boolean;
56
75
  }
76
+ /**
77
+ * Options for configuring the `CertificateManager`.
78
+ * @public
79
+ */
80
+ export interface ICertificateManagerOptions extends ICertificateStoreOptions {
81
+ }
57
82
  /**
58
83
  * A utility class to handle generating, trusting, and untrustring a debug certificate.
59
84
  * Contains two public methods to `ensureCertificate` and `untrustCertificate`.
60
85
  * @public
61
86
  */
62
87
  export declare class CertificateManager {
63
- private _certificateStore;
64
- constructor();
88
+ /**
89
+ * Get the certificate store used by this manager.
90
+ * @public
91
+ */
92
+ readonly certificateStore: CertificateStore;
93
+ constructor(options?: ICertificateManagerOptions);
65
94
  /**
66
95
  * Get a development certificate from the store, or optionally, generate a new one
67
96
  * and trust it if one doesn't exist in the store.
@@ -81,6 +110,12 @@ export declare class CertificateManager {
81
110
  private _detectIfCertificateIsTrustedAsync;
82
111
  private _trySetFriendlyNameAsync;
83
112
  private _ensureCertificateInternalAsync;
113
+ /**
114
+ * Validate existing certificates to check if they are usable.
115
+ *
116
+ * @public
117
+ */
118
+ validateCertificateAsync(terminal: ITerminal, options?: ICertificateGenerationOptions): Promise<ICertificateValidationResult>;
84
119
  private _parseMacOsMatchingCertificateHash;
85
120
  }
86
121
  //# sourceMappingURL=CertificateManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CertificateManager.d.ts","sourceRoot":"","sources":["../src/CertificateManager.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAarD;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAAE,aAAa,CAAC,MAAM,CAAiB,CAAC;AAEtF;;;GAGG;AACH,eAAO,MAAM,wCAAwC,EAAE,aAAa,CAAC,MAAM,CAAiB,CAAC;AAK7F;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC;;OAEG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3B;;OAEG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAChD;AAmCD;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC;;OAEG;IACH,kBAAkB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAID;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,iBAAiB,CAAmB;;IAM5C;;;;;OAKG;IACU,sBAAsB,CACjC,yBAAyB,EAAE,OAAO,EAClC,QAAQ,EAAE,SAAS,EACnB,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,YAAY,CAAC;IAwHxB;;;;OAIG;IACU,uBAAuB,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YA6E7D,yBAAyB;YA2EzB,kCAAkC;YAsGlC,yBAAyB;YA0FzB,kCAAkC;YAwElC,wBAAwB;YAsCxB,+BAA+B;IAkD7C,OAAO,CAAC,kCAAkC;CAe3C"}
1
+ {"version":3,"file":"CertificateManager.d.ts","sourceRoot":"","sources":["../src/CertificateManager.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,gBAAgB,EAAE,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAUrF;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAAE,aAAa,CAAC,MAAM,CAAiB,CAAC;AAEtF;;;GAGG;AACH,eAAO,MAAM,wCAAwC,EAAE,aAAa,CAAC,MAAM,CAAiB,CAAC;AAK7F;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC;;OAEG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3B;;OAEG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAChD;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAE7B;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B;AAmCD;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC;;OAEG;IACH,kBAAkB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB;CAAG;AAI/E;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B;;;OAGG;IACH,SAAgB,gBAAgB,EAAE,gBAAgB,CAAC;gBAEhC,OAAO,GAAE,0BAA+B;IAI3D;;;;;OAKG;IACU,sBAAsB,CACjC,yBAAyB,EAAE,OAAO,EAClC,QAAQ,EAAE,SAAS,EACnB,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,YAAY,CAAC;IAkDxB;;;;OAIG;IACU,uBAAuB,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YA8E7D,yBAAyB;YA2EzB,kCAAkC;YAsGlC,yBAAyB;YA0FzB,kCAAkC;YAwElC,wBAAwB;YAsCxB,+BAA+B;IAmD7C;;;;OAIG;IACU,wBAAwB,CACnC,QAAQ,EAAE,SAAS,EACnB,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,4BAA4B,CAAC;IAsGxC,OAAO,CAAC,kCAAkC;CAe3C"}
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  })();
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.CertificateManager = exports.DEFAULT_CERTIFICATE_SUBJECT_IP_ADDRESSES = exports.DEFAULT_CERTIFICATE_SUBJECT_NAMES = void 0;
39
- const path = __importStar(require("path"));
40
- const os_1 = require("os");
39
+ const path = __importStar(require("node:path"));
40
+ const node_os_1 = require("node:os");
41
41
  const node_core_library_1 = require("@rushstack/node-core-library");
42
42
  const runCommand_1 = require("./runCommand");
43
43
  const CertificateStore_1 = require("./CertificateStore");
@@ -66,8 +66,8 @@ const MAX_CERTIFICATE_VALIDITY_DAYS = 365;
66
66
  * @public
67
67
  */
68
68
  class CertificateManager {
69
- constructor() {
70
- this._certificateStore = new CertificateStore_1.CertificateStore();
69
+ constructor(options = {}) {
70
+ this.certificateStore = new CertificateStore_1.CertificateStore(options);
71
71
  }
72
72
  /**
73
73
  * Get a development certificate from the store, or optionally, generate a new one
@@ -77,80 +77,31 @@ class CertificateManager {
77
77
  */
78
78
  async ensureCertificateAsync(canGenerateNewCertificate, terminal, options) {
79
79
  const optionsWithDefaults = applyDefaultOptions(options);
80
- const { certificateData: existingCert, keyData: existingKey } = this._certificateStore;
81
80
  if (process.env[DISABLE_CERT_GENERATION_VARIABLE_NAME] === '1') {
82
81
  // Allow the environment (e.g. GitHub codespaces) to forcibly disable dev cert generation
83
82
  terminal.writeLine(`Found environment variable ${DISABLE_CERT_GENERATION_VARIABLE_NAME}=1, disabling certificate generation.`);
84
83
  canGenerateNewCertificate = false;
85
84
  }
86
- if (existingCert && existingKey) {
87
- const messages = [];
88
- const forge = await Promise.resolve().then(() => __importStar(require('node-forge')));
89
- const certificate = forge.pki.certificateFromPem(existingCert);
90
- const altNamesExtension = certificate.getExtension('subjectAltName');
91
- if (!altNamesExtension) {
92
- messages.push('The existing development certificate is missing the subjectAltName ' +
93
- 'property and will not work with the latest versions of some browsers.');
94
- }
95
- else {
96
- const missingSubjectNames = new Set(optionsWithDefaults.subjectAltNames);
97
- for (const altName of altNamesExtension.altNames) {
98
- missingSubjectNames.delete(isIPAddress(altName) ? altName.ip : altName.value);
99
- }
100
- if (missingSubjectNames.size) {
101
- messages.push(`The existing development certificate does not include the following expected subjectAltName values: ` +
102
- Array.from(missingSubjectNames, (name) => `"${name}"`).join(', '));
103
- }
104
- }
105
- const { notBefore, notAfter } = certificate.validity;
106
- const now = new Date();
107
- if (now < notBefore) {
108
- messages.push(`The existing development certificate's validity period does not start until ${notBefore}. It is currently ${now}.`);
109
- }
110
- if (now > notAfter) {
111
- messages.push(`The existing development certificate's validity period ended ${notAfter}. It is currently ${now}.`);
112
- }
113
- now.setUTCDate(now.getUTCDate() + optionsWithDefaults.validityInDays);
114
- if (notAfter > now) {
115
- messages.push(`The existing development certificate's expiration date ${notAfter} exceeds the allowed limit ${now}. ` +
116
- `This will be rejected by many browsers.`);
117
- }
118
- if (notBefore.getTime() - notAfter.getTime() >
119
- optionsWithDefaults.validityInDays * ONE_DAY_IN_MILLISECONDS) {
120
- messages.push("The existing development certificate's validity period is longer " +
121
- `than ${optionsWithDefaults.validityInDays} days.`);
122
- }
123
- const { caCertificateData } = this._certificateStore;
124
- if (!caCertificateData) {
125
- messages.push('The existing development certificate is missing a separate CA cert as the root ' +
126
- 'of trust and will not work with the latest versions of some browsers.');
127
- }
128
- const isTrusted = await this._detectIfCertificateIsTrustedAsync(terminal);
129
- if (!isTrusted) {
130
- messages.push('The existing development certificate is not currently trusted by your system.');
131
- }
132
- if (messages.length > 0) {
133
- if (canGenerateNewCertificate) {
134
- messages.push('Attempting to untrust the certificate and generate a new one.');
135
- terminal.writeWarningLine(messages.join(' '));
136
- if (!(options === null || options === void 0 ? void 0 : options.skipCertificateTrust)) {
137
- await this.untrustCertificateAsync(terminal);
138
- }
139
- return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);
140
- }
141
- else {
142
- messages.push('Untrust the certificate and generate a new one, or set the ' +
143
- '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.');
144
- throw new Error(messages.join(' '));
85
+ // Validate existing certificates
86
+ const validationResult = await this.validateCertificateAsync(terminal, options);
87
+ if (validationResult.isValid && validationResult.certificate) {
88
+ // Existing certificate is valid, return it
89
+ return validationResult.certificate;
90
+ }
91
+ // Certificate is invalid or doesn't exist
92
+ if (validationResult.validationMessages.length > 0) {
93
+ if (canGenerateNewCertificate) {
94
+ validationResult.validationMessages.push('Attempting to untrust the certificate and generate a new one.');
95
+ terminal.writeWarningLine(validationResult.validationMessages.join(' '));
96
+ if (!(options === null || options === void 0 ? void 0 : options.skipCertificateTrust)) {
97
+ await this.untrustCertificateAsync(terminal);
145
98
  }
99
+ return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);
146
100
  }
147
101
  else {
148
- return {
149
- pemCaCertificate: caCertificateData,
150
- pemCertificate: existingCert,
151
- pemKey: existingKey,
152
- subjectAltNames: altNamesExtension.altNames.map((entry) => isIPAddress(entry) ? entry.ip : entry.value)
153
- };
102
+ validationResult.validationMessages.push('Untrust the certificate and generate a new one, or set the ' +
103
+ '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.');
104
+ throw new Error(validationResult.validationMessages.join(' '));
154
105
  }
155
106
  }
156
107
  else if (canGenerateNewCertificate) {
@@ -167,8 +118,9 @@ class CertificateManager {
167
118
  * @public
168
119
  */
169
120
  async untrustCertificateAsync(terminal) {
170
- this._certificateStore.certificateData = undefined;
171
- this._certificateStore.keyData = undefined;
121
+ this.certificateStore.certificateData = undefined;
122
+ this.certificateStore.keyData = undefined;
123
+ this.certificateStore.caCertificateData = undefined;
172
124
  switch (process.platform) {
173
125
  case 'win32':
174
126
  const winUntrustResult = await (0, runCommand_1.runAsync)(CERTUTIL_EXE_NAME, [
@@ -190,7 +142,7 @@ class CertificateManager {
190
142
  const macFindCertificateResult = await (0, runCommand_1.runAsync)('security', [
191
143
  'find-certificate',
192
144
  '-c',
193
- 'localhost',
145
+ CA_ALT_NAME,
194
146
  '-a',
195
147
  '-Z',
196
148
  MAC_KEYCHAIN
@@ -199,7 +151,7 @@ class CertificateManager {
199
151
  terminal.writeErrorLine(`Error finding the development certificate: ${macFindCertificateResult.stderr.join(' ')}`);
200
152
  return false;
201
153
  }
202
- const shaHash = this._parseMacOsMatchingCertificateHash(macFindCertificateResult.stdout.join(os_1.EOL));
154
+ const shaHash = this._parseMacOsMatchingCertificateHash(macFindCertificateResult.stdout.join(node_os_1.EOL));
203
155
  if (!shaHash) {
204
156
  terminal.writeErrorLine('Unable to find the development certificate.');
205
157
  return false;
@@ -207,7 +159,7 @@ class CertificateManager {
207
159
  else {
208
160
  terminal.writeVerboseLine(`Found the development certificate. SHA is ${shaHash}`);
209
161
  }
210
- const macUntrustResult = await (0, runCommand_1.runSudoAsync)('security', [
162
+ const macUntrustResult = await (0, runCommand_1.darwinRunSudoAsync)(terminal, 'security', [
211
163
  'delete-certificate',
212
164
  '-Z',
213
165
  shaHash,
@@ -225,7 +177,7 @@ class CertificateManager {
225
177
  // Linux + others: Have the user manually untrust the cert
226
178
  terminal.writeLine('Automatic certificate untrust is only implemented for debug-certificate-manager on Windows ' +
227
179
  'and macOS. To untrust the development certificate, remove this certificate from your trusted ' +
228
- `root certification authorities: "${this._certificateStore.certificatePath}". The ` +
180
+ `root certification authorities: "${this.certificateStore.certificatePath}". The ` +
229
181
  `certificate has serial number "${CA_SERIAL_NUMBER}".`);
230
182
  return false;
231
183
  }
@@ -393,7 +345,7 @@ class CertificateManager {
393
345
  terminal.writeErrorLine(`Error: ${winTrustResult.stdout.toString()}`);
394
346
  const errorLines = winTrustResult.stdout
395
347
  .toString()
396
- .split(os_1.EOL)
348
+ .split(node_os_1.EOL)
397
349
  .map((line) => line.trim());
398
350
  // Not sure if this is always the status code for "cancelled" - should confirm.
399
351
  if (winTrustResult.exitCode === 2147943623 ||
@@ -414,7 +366,7 @@ class CertificateManager {
414
366
  'and will be stored in your local user profile to be used by other instances of ' +
415
367
  'debug-certificate-manager. If you do not consent to trust this certificate, do not enter your ' +
416
368
  'root password in the prompt.');
417
- const result = await (0, runCommand_1.runSudoAsync)('security', [
369
+ const result = await (0, runCommand_1.darwinRunSudoAsync)(terminal, 'security', [
418
370
  'add-trusted-cert',
419
371
  '-d',
420
372
  '-r',
@@ -468,7 +420,7 @@ class CertificateManager {
468
420
  const macFindCertificateResult = await (0, runCommand_1.runAsync)('security', [
469
421
  'find-certificate',
470
422
  '-c',
471
- 'localhost',
423
+ CA_ALT_NAME,
472
424
  '-a',
473
425
  '-Z',
474
426
  MAC_KEYCHAIN
@@ -477,7 +429,7 @@ class CertificateManager {
477
429
  terminal.writeVerboseLine('The development certificate was not found in keychain. Find certificate error: ', macFindCertificateResult.stderr.join(' '));
478
430
  return false;
479
431
  }
480
- const shaHash = this._parseMacOsMatchingCertificateHash(macFindCertificateResult.stdout.join(os_1.EOL));
432
+ const shaHash = this._parseMacOsMatchingCertificateHash(macFindCertificateResult.stdout.join(node_os_1.EOL));
481
433
  if (!shaHash) {
482
434
  terminal.writeVerboseLine('The development certificate was not found in keychain. Find certificate output:\n', macFindCertificateResult.stdout.join(' '));
483
435
  return false;
@@ -488,7 +440,7 @@ class CertificateManager {
488
440
  // Linux + others: Have the user manually verify the cert is trusted
489
441
  terminal.writeVerboseLine('Automatic certificate trust validation is only implemented for debug-certificate-manager on Windows ' +
490
442
  'and macOS. Manually verify this development certificate is present in your trusted ' +
491
- `root certification authorities: "${this._certificateStore.certificatePath}". ` +
443
+ `root certification authorities: "${this.certificateStore.certificatePath}". ` +
492
444
  `The certificate has serial number "${CA_SERIAL_NUMBER}".`);
493
445
  // Always return true on Linux to prevent breaking flow.
494
446
  return true;
@@ -505,7 +457,7 @@ class CertificateManager {
505
457
  '[Properties]',
506
458
  `11 = "{text}${FRIENDLY_NAME}"`,
507
459
  ''
508
- ].join(os_1.EOL);
460
+ ].join(node_os_1.EOL);
509
461
  await node_core_library_1.FileSystem.writeFileAsync(friendlyNamePath, friendlyNameFile);
510
462
  const repairStoreResult = await (0, runCommand_1.runAsync)(CERTUTIL_EXE_NAME, [
511
463
  '-repairstore',
@@ -530,10 +482,11 @@ class CertificateManager {
530
482
  }
531
483
  }
532
484
  async _ensureCertificateInternalAsync(options, terminal) {
533
- const certificateStore = this._certificateStore;
485
+ const certificateStore = this.certificateStore;
534
486
  const generatedCertificate = await this._createDevelopmentCertificateAsync(options);
535
487
  const certificateName = Date.now().toString();
536
- const tempDirName = path.join(__dirname, '..', 'temp');
488
+ const tempDirName = (0, runCommand_1.randomTmpPath)('rushstack', 'temp');
489
+ await node_core_library_1.FileSystem.ensureFolderAsync(tempDirName);
537
490
  const tempCertificatePath = path.join(tempDirName, `${certificateName}.pem`);
538
491
  const pemFileContents = generatedCertificate.pemCaCertificate;
539
492
  if (pemFileContents) {
@@ -569,9 +522,83 @@ class CertificateManager {
569
522
  subjectAltNames
570
523
  };
571
524
  }
525
+ /**
526
+ * Validate existing certificates to check if they are usable.
527
+ *
528
+ * @public
529
+ */
530
+ async validateCertificateAsync(terminal, options) {
531
+ const optionsWithDefaults = applyDefaultOptions(options);
532
+ const { certificateData: existingCert, keyData: existingKey } = this.certificateStore;
533
+ if (!existingCert || !existingKey) {
534
+ return {
535
+ isValid: false,
536
+ validationMessages: ['No development certificate found.']
537
+ };
538
+ }
539
+ const messages = [];
540
+ const forge = await Promise.resolve().then(() => __importStar(require('node-forge')));
541
+ const parsedCertificate = forge.pki.certificateFromPem(existingCert);
542
+ const altNamesExtension = parsedCertificate.getExtension('subjectAltName');
543
+ if (!altNamesExtension) {
544
+ messages.push('The existing development certificate is missing the subjectAltName ' +
545
+ 'property and will not work with the latest versions of some browsers.');
546
+ }
547
+ else {
548
+ const missingSubjectNames = new Set(optionsWithDefaults.subjectAltNames);
549
+ for (const altName of altNamesExtension.altNames) {
550
+ missingSubjectNames.delete(isIPAddress(altName) ? altName.ip : altName.value);
551
+ }
552
+ if (missingSubjectNames.size) {
553
+ messages.push(`The existing development certificate does not include the following expected subjectAltName values: ` +
554
+ Array.from(missingSubjectNames, (name) => `"${name}"`).join(', '));
555
+ }
556
+ }
557
+ const { notBefore, notAfter } = parsedCertificate.validity;
558
+ const now = new Date();
559
+ if (now < notBefore) {
560
+ messages.push(`The existing development certificate's validity period does not start until ${notBefore}. It is currently ${now}.`);
561
+ }
562
+ if (now > notAfter) {
563
+ messages.push(`The existing development certificate's validity period ended ${notAfter}. It is currently ${now}.`);
564
+ }
565
+ now.setUTCDate(now.getUTCDate() + optionsWithDefaults.validityInDays);
566
+ if (notAfter > now) {
567
+ messages.push(`The existing development certificate's expiration date ${notAfter} exceeds the allowed limit ${now}. ` +
568
+ `This will be rejected by many browsers.`);
569
+ }
570
+ if (notBefore.getTime() - notAfter.getTime() >
571
+ optionsWithDefaults.validityInDays * ONE_DAY_IN_MILLISECONDS) {
572
+ messages.push("The existing development certificate's validity period is longer " +
573
+ `than ${optionsWithDefaults.validityInDays} days.`);
574
+ }
575
+ const { caCertificateData } = this.certificateStore;
576
+ if (!caCertificateData) {
577
+ messages.push('The existing development certificate is missing a separate CA cert as the root ' +
578
+ 'of trust and will not work with the latest versions of some browsers.');
579
+ }
580
+ const isTrusted = await this._detectIfCertificateIsTrustedAsync(terminal);
581
+ if (!isTrusted) {
582
+ messages.push('The existing development certificate is not currently trusted by your system.');
583
+ }
584
+ const isValid = messages.length === 0;
585
+ const validCertificate = isValid
586
+ ? {
587
+ pemCaCertificate: caCertificateData,
588
+ pemCertificate: existingCert,
589
+ pemKey: existingKey,
590
+ subjectAltNames: altNamesExtension === null || altNamesExtension === void 0 ? void 0 : altNamesExtension.altNames.map((entry) => isIPAddress(entry) ? entry.ip : entry.value)
591
+ }
592
+ : undefined;
593
+ return {
594
+ isValid,
595
+ validationMessages: messages,
596
+ certificate: validCertificate
597
+ };
598
+ }
572
599
  _parseMacOsMatchingCertificateHash(findCertificateOuput) {
573
600
  let shaHash = undefined;
574
- for (const line of findCertificateOuput.split(os_1.EOL)) {
601
+ for (const line of findCertificateOuput.split(node_os_1.EOL)) {
575
602
  // Sets `shaHash` to the current certificate SHA-1 as we progress through the lines of certificate text.
576
603
  const shaHashMatch = line.match(/^SHA-1 hash: (.+)$/);
577
604
  if (shaHashMatch) {
@@ -1 +1 @@
1
- {"version":3,"file":"CertificateManager.js","sourceRoot":"","sources":["../src/CertificateManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { pki } from 'node-forge';\nimport * as path from 'path';\nimport { EOL } from 'os';\nimport { FileSystem } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { runSudoAsync, type IRunResult, runAsync } from './runCommand';\nimport { CertificateStore } from './CertificateStore';\n\nconst CA_SERIAL_NUMBER: string = '731c321744e34650a202e3ef91c3c1b0';\nconst TLS_SERIAL_NUMBER: string = '731c321744e34650a202e3ef00000001';\nconst FRIENDLY_NAME: string = 'debug-certificate-manager Development Certificate';\nconst MAC_KEYCHAIN: string = '/Library/Keychains/System.keychain';\nconst CERTUTIL_EXE_NAME: string = 'certutil';\nconst CA_ALT_NAME: string = 'rushstack-certificate-manager.localhost';\nconst ONE_DAY_IN_MILLISECONDS: number = 24 * 60 * 60 * 1000;\n\n/**\n * The set of names the certificate should be generated for, by default.\n * @public\n */\nexport const DEFAULT_CERTIFICATE_SUBJECT_NAMES: ReadonlyArray<string> = ['localhost'];\n\n/**\n * The set of ip addresses the certificate should be generated for, by default.\n * @public\n */\nexport const DEFAULT_CERTIFICATE_SUBJECT_IP_ADDRESSES: ReadonlyArray<string> = ['127.0.0.1'];\n\nconst DISABLE_CERT_GENERATION_VARIABLE_NAME: 'RUSHSTACK_DISABLE_DEV_CERT_GENERATION' =\n 'RUSHSTACK_DISABLE_DEV_CERT_GENERATION';\n\n/**\n * The interface for a debug certificate instance\n *\n * @public\n */\nexport interface ICertificate {\n /**\n * Generated pem Certificate Authority certificate contents\n */\n pemCaCertificate: string | undefined;\n\n /**\n * Generated pem TLS Server certificate contents\n */\n pemCertificate: string | undefined;\n\n /**\n * Private key for the TLS server certificate, used to sign TLS communications\n */\n pemKey: string | undefined;\n\n /**\n * The subject names the TLS server certificate is valid for\n */\n subjectAltNames: readonly string[] | undefined;\n}\n\ninterface ICaCertificate {\n /**\n * Certificate\n */\n certificate: pki.Certificate;\n\n /**\n * Private key for the CA cert. Delete after signing the TLS cert.\n */\n privateKey: pki.PrivateKey;\n}\n\ninterface ISubjectAltNameExtension {\n altNames: readonly IAltName[];\n}\n\n/**\n * Fields for a Subject Alternative Name of type DNS Name\n */\ninterface IDnsAltName {\n type: 2;\n value: string;\n}\n/**\n * Fields for a Subject Alternative Name of type IP Address\n * `node-forge` requires the field name to be \"ip\" instead of \"value\", likely due to subtle encoding differences.\n */\ninterface IIPAddressAltName {\n type: 7;\n ip: string;\n}\ntype IAltName = IDnsAltName | IIPAddressAltName;\n\n/**\n * Options to use if needing to generate a new certificate\n * @public\n */\nexport interface ICertificateGenerationOptions {\n /**\n * The DNS Subject names to issue the certificate for. Defaults to ['localhost'].\n */\n subjectAltNames?: ReadonlyArray<string>;\n /**\n * The IP Address Subject names to issue the certificate for. Defaults to ['127.0.0.1'].\n */\n subjectIPAddresses?: ReadonlyArray<string>;\n /**\n * How many days the certificate should be valid for.\n */\n validityInDays?: number;\n /**\n * Skip trusting a certificate. Defaults to false.\n */\n skipCertificateTrust?: boolean;\n}\n\nconst MAX_CERTIFICATE_VALIDITY_DAYS: 365 = 365;\n\n/**\n * A utility class to handle generating, trusting, and untrustring a debug certificate.\n * Contains two public methods to `ensureCertificate` and `untrustCertificate`.\n * @public\n */\nexport class CertificateManager {\n private _certificateStore: CertificateStore;\n\n public constructor() {\n this._certificateStore = new CertificateStore();\n }\n\n /**\n * Get a development certificate from the store, or optionally, generate a new one\n * and trust it if one doesn't exist in the store.\n *\n * @public\n */\n public async ensureCertificateAsync(\n canGenerateNewCertificate: boolean,\n terminal: ITerminal,\n options?: ICertificateGenerationOptions\n ): Promise<ICertificate> {\n const optionsWithDefaults: Required<ICertificateGenerationOptions> = applyDefaultOptions(options);\n\n const { certificateData: existingCert, keyData: existingKey } = this._certificateStore;\n\n if (process.env[DISABLE_CERT_GENERATION_VARIABLE_NAME] === '1') {\n // Allow the environment (e.g. GitHub codespaces) to forcibly disable dev cert generation\n terminal.writeLine(\n `Found environment variable ${DISABLE_CERT_GENERATION_VARIABLE_NAME}=1, disabling certificate generation.`\n );\n canGenerateNewCertificate = false;\n }\n\n if (existingCert && existingKey) {\n const messages: string[] = [];\n\n const forge: typeof import('node-forge') = await import('node-forge');\n const certificate: pki.Certificate = forge.pki.certificateFromPem(existingCert);\n const altNamesExtension: ISubjectAltNameExtension | undefined = certificate.getExtension(\n 'subjectAltName'\n ) as ISubjectAltNameExtension;\n if (!altNamesExtension) {\n messages.push(\n 'The existing development certificate is missing the subjectAltName ' +\n 'property and will not work with the latest versions of some browsers.'\n );\n } else {\n const missingSubjectNames: Set<string> = new Set(optionsWithDefaults.subjectAltNames);\n for (const altName of altNamesExtension.altNames) {\n missingSubjectNames.delete(isIPAddress(altName) ? altName.ip : altName.value);\n }\n if (missingSubjectNames.size) {\n messages.push(\n `The existing development certificate does not include the following expected subjectAltName values: ` +\n Array.from(missingSubjectNames, (name: string) => `\"${name}\"`).join(', ')\n );\n }\n }\n\n const { notBefore, notAfter } = certificate.validity;\n const now: Date = new Date();\n if (now < notBefore) {\n messages.push(\n `The existing development certificate's validity period does not start until ${notBefore}. It is currently ${now}.`\n );\n }\n\n if (now > notAfter) {\n messages.push(\n `The existing development certificate's validity period ended ${notAfter}. It is currently ${now}.`\n );\n }\n\n now.setUTCDate(now.getUTCDate() + optionsWithDefaults.validityInDays);\n if (notAfter > now) {\n messages.push(\n `The existing development certificate's expiration date ${notAfter} exceeds the allowed limit ${now}. ` +\n `This will be rejected by many browsers.`\n );\n }\n\n if (\n notBefore.getTime() - notAfter.getTime() >\n optionsWithDefaults.validityInDays * ONE_DAY_IN_MILLISECONDS\n ) {\n messages.push(\n \"The existing development certificate's validity period is longer \" +\n `than ${optionsWithDefaults.validityInDays} days.`\n );\n }\n\n const { caCertificateData } = this._certificateStore;\n\n if (!caCertificateData) {\n messages.push(\n 'The existing development certificate is missing a separate CA cert as the root ' +\n 'of trust and will not work with the latest versions of some browsers.'\n );\n }\n\n const isTrusted: boolean = await this._detectIfCertificateIsTrustedAsync(terminal);\n if (!isTrusted) {\n messages.push('The existing development certificate is not currently trusted by your system.');\n }\n\n if (messages.length > 0) {\n if (canGenerateNewCertificate) {\n messages.push('Attempting to untrust the certificate and generate a new one.');\n terminal.writeWarningLine(messages.join(' '));\n if (!options?.skipCertificateTrust) {\n await this.untrustCertificateAsync(terminal);\n }\n return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);\n } else {\n messages.push(\n 'Untrust the certificate and generate a new one, or set the ' +\n '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.'\n );\n throw new Error(messages.join(' '));\n }\n } else {\n return {\n pemCaCertificate: caCertificateData,\n pemCertificate: existingCert,\n pemKey: existingKey,\n subjectAltNames: altNamesExtension.altNames.map((entry) =>\n isIPAddress(entry) ? entry.ip : entry.value\n )\n };\n }\n } else if (canGenerateNewCertificate) {\n return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);\n } else {\n throw new Error(\n 'No development certificate found. Generate a new certificate manually, or set the ' +\n '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.'\n );\n }\n }\n\n /**\n * Attempt to locate a previously generated debug certificate and untrust it.\n *\n * @public\n */\n public async untrustCertificateAsync(terminal: ITerminal): Promise<boolean> {\n this._certificateStore.certificateData = undefined;\n this._certificateStore.keyData = undefined;\n\n switch (process.platform) {\n case 'win32':\n const winUntrustResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-delstore',\n 'root',\n CA_SERIAL_NUMBER\n ]);\n\n if (winUntrustResult.exitCode !== 0) {\n terminal.writeErrorLine(`Error: ${winUntrustResult.stderr.join(' ')}`);\n return false;\n } else {\n terminal.writeVerboseLine('Successfully untrusted development certificate.');\n return true;\n }\n\n case 'darwin':\n terminal.writeVerboseLine('Trying to find the signature of the development certificate.');\n\n const macFindCertificateResult: IRunResult = await runAsync('security', [\n 'find-certificate',\n '-c',\n 'localhost',\n '-a',\n '-Z',\n MAC_KEYCHAIN\n ]);\n if (macFindCertificateResult.exitCode !== 0) {\n terminal.writeErrorLine(\n `Error finding the development certificate: ${macFindCertificateResult.stderr.join(' ')}`\n );\n return false;\n }\n\n const shaHash: string | undefined = this._parseMacOsMatchingCertificateHash(\n macFindCertificateResult.stdout.join(EOL)\n );\n\n if (!shaHash) {\n terminal.writeErrorLine('Unable to find the development certificate.');\n return false;\n } else {\n terminal.writeVerboseLine(`Found the development certificate. SHA is ${shaHash}`);\n }\n\n const macUntrustResult: IRunResult = await runSudoAsync('security', [\n 'delete-certificate',\n '-Z',\n shaHash,\n MAC_KEYCHAIN\n ]);\n\n if (macUntrustResult.exitCode === 0) {\n terminal.writeVerboseLine('Successfully untrusted development certificate.');\n return true;\n } else {\n terminal.writeErrorLine(macUntrustResult.stderr.join(' '));\n return false;\n }\n\n default:\n // Linux + others: Have the user manually untrust the cert\n terminal.writeLine(\n 'Automatic certificate untrust is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. To untrust the development certificate, remove this certificate from your trusted ' +\n `root certification authorities: \"${this._certificateStore.certificatePath}\". The ` +\n `certificate has serial number \"${CA_SERIAL_NUMBER}\".`\n );\n return false;\n }\n }\n\n private async _createCACertificateAsync(\n validityInDays: number,\n forge: typeof import('node-forge')\n ): Promise<ICaCertificate> {\n const keys: pki.KeyPair = forge.pki.rsa.generateKeyPair(2048);\n const certificate: pki.Certificate = forge.pki.createCertificate();\n certificate.publicKey = keys.publicKey;\n\n certificate.serialNumber = CA_SERIAL_NUMBER;\n\n const notBefore: Date = new Date();\n const notAfter: Date = new Date(notBefore);\n notAfter.setUTCDate(notBefore.getUTCDate() + validityInDays);\n certificate.validity.notBefore = notBefore;\n certificate.validity.notAfter = notAfter;\n\n const attrs: pki.CertificateField[] = [\n {\n name: 'commonName',\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setSubject(attrs);\n certificate.setIssuer(attrs);\n\n const altNames: readonly IAltName[] = [\n {\n type: 2, // DNS\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setExtensions([\n {\n name: 'basicConstraints',\n cA: true,\n pathLenConstraint: 0,\n critical: true\n },\n {\n name: 'subjectAltName',\n altNames,\n critical: true\n },\n {\n name: 'issuerAltName',\n altNames,\n critical: false\n },\n {\n name: 'keyUsage',\n keyCertSign: true,\n critical: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n critical: true\n },\n {\n name: 'friendlyName',\n value: FRIENDLY_NAME\n }\n ]);\n\n // self-sign certificate\n certificate.sign(keys.privateKey, forge.md.sha256.create());\n\n return {\n certificate,\n privateKey: keys.privateKey\n };\n }\n\n private async _createDevelopmentCertificateAsync(\n options: Required<ICertificateGenerationOptions>\n ): Promise<ICertificate> {\n const forge: typeof import('node-forge') = await import('node-forge');\n const keys: pki.KeyPair = forge.pki.rsa.generateKeyPair(2048);\n const certificate: pki.Certificate = forge.pki.createCertificate();\n\n certificate.publicKey = keys.publicKey;\n certificate.serialNumber = TLS_SERIAL_NUMBER;\n\n const { subjectAltNames: subjectNames, subjectIPAddresses: subjectIpAddresses, validityInDays } = options;\n\n const { certificate: caCertificate, privateKey: caPrivateKey } = await this._createCACertificateAsync(\n validityInDays,\n forge\n );\n\n const notBefore: Date = new Date();\n const notAfter: Date = new Date(notBefore);\n notAfter.setUTCDate(notBefore.getUTCDate() + validityInDays);\n certificate.validity.notBefore = notBefore;\n certificate.validity.notAfter = notAfter;\n\n const subjectAttrs: pki.CertificateField[] = [\n {\n name: 'commonName',\n value: subjectNames[0]\n }\n ];\n const issuerAttrs: pki.CertificateField[] = caCertificate.subject.attributes;\n\n certificate.setSubject(subjectAttrs);\n certificate.setIssuer(issuerAttrs);\n\n const subjectAltNames: IAltName[] = [\n ...subjectNames.map<IDnsAltName>((subjectName) => ({\n type: 2, // DNS\n value: subjectName\n })),\n ...subjectIpAddresses.map<IIPAddressAltName>((ip) => ({\n type: 7, // IP\n ip\n }))\n ];\n\n const issuerAltNames: readonly IAltName[] = [\n {\n type: 2, // DNS\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setExtensions([\n {\n name: 'basicConstraints',\n cA: false,\n critical: true\n },\n {\n name: 'subjectAltName',\n altNames: subjectAltNames,\n critical: true\n },\n {\n name: 'issuerAltName',\n altNames: issuerAltNames,\n critical: false\n },\n {\n name: 'keyUsage',\n digitalSignature: true,\n keyEncipherment: true,\n dataEncipherment: true,\n critical: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n critical: true\n },\n {\n name: 'friendlyName',\n value: FRIENDLY_NAME\n }\n ]);\n\n // Sign certificate with CA\n certificate.sign(caPrivateKey, forge.md.sha256.create());\n\n // convert a Forge certificate to PEM\n const caPem: string = forge.pki.certificateToPem(caCertificate);\n const pem: string = forge.pki.certificateToPem(certificate);\n const pemKey: string = forge.pki.privateKeyToPem(keys.privateKey);\n\n return {\n pemCaCertificate: caPem,\n pemCertificate: pem,\n pemKey: pemKey,\n subjectAltNames: options.subjectAltNames\n };\n }\n\n private async _tryTrustCertificateAsync(certificatePath: string, terminal: ITerminal): Promise<boolean> {\n switch (process.platform) {\n case 'win32':\n terminal.writeLine(\n 'Attempting to trust a development certificate. This self-signed certificate only points to localhost ' +\n 'and will be stored in your local user profile to be used by other instances of ' +\n 'debug-certificate-manager. If you do not consent to trust this certificate, click \"NO\" in the dialog.'\n );\n\n const winTrustResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-addstore',\n 'root',\n certificatePath\n ]);\n\n if (winTrustResult.exitCode !== 0) {\n terminal.writeErrorLine(`Error: ${winTrustResult.stdout.toString()}`);\n\n const errorLines: string[] = winTrustResult.stdout\n .toString()\n .split(EOL)\n .map((line: string) => line.trim());\n\n // Not sure if this is always the status code for \"cancelled\" - should confirm.\n if (\n winTrustResult.exitCode === 2147943623 ||\n errorLines[errorLines.length - 1].indexOf('The operation was canceled by the user.') > 0\n ) {\n terminal.writeLine('Certificate trust cancelled.');\n } else {\n terminal.writeErrorLine('Certificate trust failed with an unknown error.');\n }\n\n return false;\n } else {\n terminal.writeVerboseLine('Successfully trusted development certificate.');\n\n return true;\n }\n\n case 'darwin':\n terminal.writeLine(\n 'Attempting to trust a development certificate. This self-signed certificate only points to localhost ' +\n 'and will be stored in your local user profile to be used by other instances of ' +\n 'debug-certificate-manager. If you do not consent to trust this certificate, do not enter your ' +\n 'root password in the prompt.'\n );\n\n const result: IRunResult = await runSudoAsync('security', [\n 'add-trusted-cert',\n '-d',\n '-r',\n 'trustRoot',\n '-k',\n MAC_KEYCHAIN,\n certificatePath\n ]);\n\n if (result.exitCode === 0) {\n terminal.writeVerboseLine('Successfully trusted development certificate.');\n return true;\n } else {\n if (\n result.stderr.some(\n (value: string) => !!value.match(/The authorization was cancelled by the user\\./)\n )\n ) {\n terminal.writeLine('Certificate trust cancelled.');\n return false;\n } else {\n terminal.writeErrorLine(\n `Certificate trust failed with an unknown error. Exit code: ${result.exitCode}. ` +\n `Error: ${result.stderr.join(' ')}`\n );\n return false;\n }\n }\n\n default:\n // Linux + others: Have the user manually trust the cert if they want to\n terminal.writeLine(\n 'Automatic certificate trust is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. To trust the development certificate, add this certificate to your trusted root ' +\n `certification authorities: \"${certificatePath}\".`\n );\n return true;\n }\n }\n\n private async _detectIfCertificateIsTrustedAsync(terminal: ITerminal): Promise<boolean> {\n switch (process.platform) {\n case 'win32':\n const winVerifyStoreResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-verifystore',\n 'root',\n CA_SERIAL_NUMBER\n ]);\n\n if (winVerifyStoreResult.exitCode !== 0) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in the store. CertUtil error: ',\n winVerifyStoreResult.stderr.join(' ')\n );\n return false;\n } else {\n terminal.writeVerboseLine(\n 'The development certificate was found in the store. CertUtil output: ',\n winVerifyStoreResult.stdout.join(' ')\n );\n return true;\n }\n\n case 'darwin':\n terminal.writeVerboseLine('Trying to find the signature of the development certificate.');\n\n const macFindCertificateResult: IRunResult = await runAsync('security', [\n 'find-certificate',\n '-c',\n 'localhost',\n '-a',\n '-Z',\n MAC_KEYCHAIN\n ]);\n\n if (macFindCertificateResult.exitCode !== 0) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in keychain. Find certificate error: ',\n macFindCertificateResult.stderr.join(' ')\n );\n return false;\n }\n\n const shaHash: string | undefined = this._parseMacOsMatchingCertificateHash(\n macFindCertificateResult.stdout.join(EOL)\n );\n\n if (!shaHash) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in keychain. Find certificate output:\\n',\n macFindCertificateResult.stdout.join(' ')\n );\n return false;\n }\n\n terminal.writeVerboseLine(`The development certificate was found in keychain.`);\n return true;\n\n default:\n // Linux + others: Have the user manually verify the cert is trusted\n terminal.writeVerboseLine(\n 'Automatic certificate trust validation is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. Manually verify this development certificate is present in your trusted ' +\n `root certification authorities: \"${this._certificateStore.certificatePath}\". ` +\n `The certificate has serial number \"${CA_SERIAL_NUMBER}\".`\n );\n // Always return true on Linux to prevent breaking flow.\n return true;\n }\n }\n\n private async _trySetFriendlyNameAsync(certificatePath: string, terminal: ITerminal): Promise<boolean> {\n if (process.platform === 'win32') {\n const basePath: string = path.dirname(certificatePath);\n const fileName: string = path.basename(certificatePath, path.extname(certificatePath));\n const friendlyNamePath: string = path.join(basePath, `${fileName}.inf`);\n\n const friendlyNameFile: string = [\n '[Version]',\n 'Signature = \"$Windows NT$\"',\n '[Properties]',\n `11 = \"{text}${FRIENDLY_NAME}\"`,\n ''\n ].join(EOL);\n\n await FileSystem.writeFileAsync(friendlyNamePath, friendlyNameFile);\n\n const repairStoreResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-repairstore',\n '-user',\n 'root',\n CA_SERIAL_NUMBER,\n friendlyNamePath\n ]);\n\n if (repairStoreResult.exitCode !== 0) {\n terminal.writeVerboseLine(`CertUtil Error: ${repairStoreResult.stderr.join('')}`);\n terminal.writeVerboseLine(`CertUtil: ${repairStoreResult.stdout.join('')}`);\n return false;\n } else {\n terminal.writeVerboseLine('Successfully set certificate name.');\n return true;\n }\n } else {\n // No equivalent concept outside of Windows\n return true;\n }\n }\n\n private async _ensureCertificateInternalAsync(\n options: Required<ICertificateGenerationOptions>,\n terminal: ITerminal\n ): Promise<ICertificate> {\n const certificateStore: CertificateStore = this._certificateStore;\n const generatedCertificate: ICertificate = await this._createDevelopmentCertificateAsync(options);\n\n const certificateName: string = Date.now().toString();\n const tempDirName: string = path.join(__dirname, '..', 'temp');\n\n const tempCertificatePath: string = path.join(tempDirName, `${certificateName}.pem`);\n const pemFileContents: string | undefined = generatedCertificate.pemCaCertificate;\n if (pemFileContents) {\n await FileSystem.writeFileAsync(tempCertificatePath, pemFileContents, {\n ensureFolderExists: true\n });\n }\n\n const trustCertificateResult: boolean = options.skipCertificateTrust\n ? true\n : await this._tryTrustCertificateAsync(tempCertificatePath, terminal);\n\n let subjectAltNames: readonly string[] | undefined;\n if (trustCertificateResult) {\n certificateStore.caCertificateData = generatedCertificate.pemCaCertificate;\n certificateStore.certificateData = generatedCertificate.pemCertificate;\n certificateStore.keyData = generatedCertificate.pemKey;\n subjectAltNames = generatedCertificate.subjectAltNames;\n\n // Try to set the friendly name, and warn if we can't\n if (!(await this._trySetFriendlyNameAsync(tempCertificatePath, terminal))) {\n terminal.writeWarningLine(\"Unable to set the certificate's friendly name.\");\n }\n } else {\n // Clear out the existing store data, if any exists\n certificateStore.caCertificateData = undefined;\n certificateStore.certificateData = undefined;\n certificateStore.keyData = undefined;\n }\n\n await FileSystem.deleteFileAsync(tempCertificatePath);\n\n return {\n pemCaCertificate: certificateStore.caCertificateData,\n pemCertificate: certificateStore.certificateData,\n pemKey: certificateStore.keyData,\n subjectAltNames\n };\n }\n\n private _parseMacOsMatchingCertificateHash(findCertificateOuput: string): string | undefined {\n let shaHash: string | undefined = undefined;\n for (const line of findCertificateOuput.split(EOL)) {\n // Sets `shaHash` to the current certificate SHA-1 as we progress through the lines of certificate text.\n const shaHashMatch: string[] | null = line.match(/^SHA-1 hash: (.+)$/);\n if (shaHashMatch) {\n shaHash = shaHashMatch[1];\n }\n\n const snbrMatch: string[] | null = line.match(/^\\s*\"snbr\"<blob>=0x([^\\s]+).+$/);\n if (snbrMatch && (snbrMatch[1] || '').toLowerCase() === CA_SERIAL_NUMBER) {\n return shaHash;\n }\n }\n }\n}\n\nfunction applyDefaultOptions(\n options: ICertificateGenerationOptions | undefined\n): Required<ICertificateGenerationOptions> {\n const subjectNames: ReadonlyArray<string> | undefined = options?.subjectAltNames;\n const subjectIpAddresses: ReadonlyArray<string> | undefined = options?.subjectIPAddresses;\n const skipCertificateTrust: boolean | undefined = options?.skipCertificateTrust || false;\n return {\n subjectAltNames: subjectNames?.length ? subjectNames : DEFAULT_CERTIFICATE_SUBJECT_NAMES,\n subjectIPAddresses: subjectIpAddresses?.length\n ? subjectIpAddresses\n : DEFAULT_CERTIFICATE_SUBJECT_IP_ADDRESSES,\n validityInDays: Math.min(\n MAX_CERTIFICATE_VALIDITY_DAYS,\n options?.validityInDays ?? MAX_CERTIFICATE_VALIDITY_DAYS\n ),\n skipCertificateTrust: skipCertificateTrust\n };\n}\n\nfunction isIPAddress(altName: IAltName): altName is IIPAddressAltName {\n return altName.type === 7;\n}\n"]}
1
+ {"version":3,"file":"CertificateManager.js","sourceRoot":"","sources":["../src/CertificateManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { pki } from 'node-forge';\nimport * as path from 'node:path';\nimport { EOL } from 'node:os';\nimport { FileSystem } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { darwinRunSudoAsync, type IRunResult, randomTmpPath, runAsync } from './runCommand';\nimport { CertificateStore, type ICertificateStoreOptions } from './CertificateStore';\n\nconst CA_SERIAL_NUMBER: string = '731c321744e34650a202e3ef91c3c1b0';\nconst TLS_SERIAL_NUMBER: string = '731c321744e34650a202e3ef00000001';\nconst FRIENDLY_NAME: string = 'debug-certificate-manager Development Certificate';\nconst MAC_KEYCHAIN: string = '/Library/Keychains/System.keychain';\nconst CERTUTIL_EXE_NAME: string = 'certutil';\nconst CA_ALT_NAME: string = 'rushstack-certificate-manager.localhost';\nconst ONE_DAY_IN_MILLISECONDS: number = 24 * 60 * 60 * 1000;\n\n/**\n * The set of names the certificate should be generated for, by default.\n * @public\n */\nexport const DEFAULT_CERTIFICATE_SUBJECT_NAMES: ReadonlyArray<string> = ['localhost'];\n\n/**\n * The set of ip addresses the certificate should be generated for, by default.\n * @public\n */\nexport const DEFAULT_CERTIFICATE_SUBJECT_IP_ADDRESSES: ReadonlyArray<string> = ['127.0.0.1'];\n\nconst DISABLE_CERT_GENERATION_VARIABLE_NAME: 'RUSHSTACK_DISABLE_DEV_CERT_GENERATION' =\n 'RUSHSTACK_DISABLE_DEV_CERT_GENERATION';\n\n/**\n * The interface for a debug certificate instance\n *\n * @public\n */\nexport interface ICertificate {\n /**\n * Generated pem Certificate Authority certificate contents\n */\n pemCaCertificate: string | undefined;\n\n /**\n * Generated pem TLS Server certificate contents\n */\n pemCertificate: string | undefined;\n\n /**\n * Private key for the TLS server certificate, used to sign TLS communications\n */\n pemKey: string | undefined;\n\n /**\n * The subject names the TLS server certificate is valid for\n */\n subjectAltNames: readonly string[] | undefined;\n}\n\n/**\n * Information about certificate validation results\n * @public\n */\nexport interface ICertificateValidationResult {\n /**\n * Whether valid certificates exist and are usable\n */\n isValid: boolean;\n\n /**\n * List of validation messages/issues found\n */\n validationMessages: string[];\n\n /**\n * The existing certificate if it exists and is valid\n */\n certificate?: ICertificate;\n}\n\ninterface ICaCertificate {\n /**\n * Certificate\n */\n certificate: pki.Certificate;\n\n /**\n * Private key for the CA cert. Delete after signing the TLS cert.\n */\n privateKey: pki.PrivateKey;\n}\n\ninterface ISubjectAltNameExtension {\n altNames: readonly IAltName[];\n}\n\n/**\n * Fields for a Subject Alternative Name of type DNS Name\n */\ninterface IDnsAltName {\n type: 2;\n value: string;\n}\n/**\n * Fields for a Subject Alternative Name of type IP Address\n * `node-forge` requires the field name to be \"ip\" instead of \"value\", likely due to subtle encoding differences.\n */\ninterface IIPAddressAltName {\n type: 7;\n ip: string;\n}\ntype IAltName = IDnsAltName | IIPAddressAltName;\n\n/**\n * Options to use if needing to generate a new certificate\n * @public\n */\nexport interface ICertificateGenerationOptions {\n /**\n * The DNS Subject names to issue the certificate for. Defaults to ['localhost'].\n */\n subjectAltNames?: ReadonlyArray<string>;\n /**\n * The IP Address Subject names to issue the certificate for. Defaults to ['127.0.0.1'].\n */\n subjectIPAddresses?: ReadonlyArray<string>;\n /**\n * How many days the certificate should be valid for.\n */\n validityInDays?: number;\n /**\n * Skip trusting a certificate. Defaults to false.\n */\n skipCertificateTrust?: boolean;\n}\n\n/**\n * Options for configuring the `CertificateManager`.\n * @public\n */\nexport interface ICertificateManagerOptions extends ICertificateStoreOptions {}\n\nconst MAX_CERTIFICATE_VALIDITY_DAYS: 365 = 365;\n\n/**\n * A utility class to handle generating, trusting, and untrustring a debug certificate.\n * Contains two public methods to `ensureCertificate` and `untrustCertificate`.\n * @public\n */\nexport class CertificateManager {\n /**\n * Get the certificate store used by this manager.\n * @public\n */\n public readonly certificateStore: CertificateStore;\n\n public constructor(options: ICertificateManagerOptions = {}) {\n this.certificateStore = new CertificateStore(options);\n }\n\n /**\n * Get a development certificate from the store, or optionally, generate a new one\n * and trust it if one doesn't exist in the store.\n *\n * @public\n */\n public async ensureCertificateAsync(\n canGenerateNewCertificate: boolean,\n terminal: ITerminal,\n options?: ICertificateGenerationOptions\n ): Promise<ICertificate> {\n const optionsWithDefaults: Required<ICertificateGenerationOptions> = applyDefaultOptions(options);\n\n if (process.env[DISABLE_CERT_GENERATION_VARIABLE_NAME] === '1') {\n // Allow the environment (e.g. GitHub codespaces) to forcibly disable dev cert generation\n terminal.writeLine(\n `Found environment variable ${DISABLE_CERT_GENERATION_VARIABLE_NAME}=1, disabling certificate generation.`\n );\n canGenerateNewCertificate = false;\n }\n\n // Validate existing certificates\n const validationResult: ICertificateValidationResult = await this.validateCertificateAsync(\n terminal,\n options\n );\n\n if (validationResult.isValid && validationResult.certificate) {\n // Existing certificate is valid, return it\n return validationResult.certificate;\n }\n\n // Certificate is invalid or doesn't exist\n if (validationResult.validationMessages.length > 0) {\n if (canGenerateNewCertificate) {\n validationResult.validationMessages.push(\n 'Attempting to untrust the certificate and generate a new one.'\n );\n terminal.writeWarningLine(validationResult.validationMessages.join(' '));\n if (!options?.skipCertificateTrust) {\n await this.untrustCertificateAsync(terminal);\n }\n return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);\n } else {\n validationResult.validationMessages.push(\n 'Untrust the certificate and generate a new one, or set the ' +\n '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.'\n );\n throw new Error(validationResult.validationMessages.join(' '));\n }\n } else if (canGenerateNewCertificate) {\n return await this._ensureCertificateInternalAsync(optionsWithDefaults, terminal);\n } else {\n throw new Error(\n 'No development certificate found. Generate a new certificate manually, or set the ' +\n '`canGenerateNewCertificate` parameter to `true` when calling `ensureCertificateAsync`.'\n );\n }\n }\n\n /**\n * Attempt to locate a previously generated debug certificate and untrust it.\n *\n * @public\n */\n public async untrustCertificateAsync(terminal: ITerminal): Promise<boolean> {\n this.certificateStore.certificateData = undefined;\n this.certificateStore.keyData = undefined;\n this.certificateStore.caCertificateData = undefined;\n\n switch (process.platform) {\n case 'win32':\n const winUntrustResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-delstore',\n 'root',\n CA_SERIAL_NUMBER\n ]);\n\n if (winUntrustResult.exitCode !== 0) {\n terminal.writeErrorLine(`Error: ${winUntrustResult.stderr.join(' ')}`);\n return false;\n } else {\n terminal.writeVerboseLine('Successfully untrusted development certificate.');\n return true;\n }\n\n case 'darwin':\n terminal.writeVerboseLine('Trying to find the signature of the development certificate.');\n\n const macFindCertificateResult: IRunResult = await runAsync('security', [\n 'find-certificate',\n '-c',\n CA_ALT_NAME,\n '-a',\n '-Z',\n MAC_KEYCHAIN\n ]);\n if (macFindCertificateResult.exitCode !== 0) {\n terminal.writeErrorLine(\n `Error finding the development certificate: ${macFindCertificateResult.stderr.join(' ')}`\n );\n return false;\n }\n\n const shaHash: string | undefined = this._parseMacOsMatchingCertificateHash(\n macFindCertificateResult.stdout.join(EOL)\n );\n\n if (!shaHash) {\n terminal.writeErrorLine('Unable to find the development certificate.');\n return false;\n } else {\n terminal.writeVerboseLine(`Found the development certificate. SHA is ${shaHash}`);\n }\n\n const macUntrustResult: IRunResult = await darwinRunSudoAsync(terminal, 'security', [\n 'delete-certificate',\n '-Z',\n shaHash,\n MAC_KEYCHAIN\n ]);\n\n if (macUntrustResult.exitCode === 0) {\n terminal.writeVerboseLine('Successfully untrusted development certificate.');\n return true;\n } else {\n terminal.writeErrorLine(macUntrustResult.stderr.join(' '));\n return false;\n }\n\n default:\n // Linux + others: Have the user manually untrust the cert\n terminal.writeLine(\n 'Automatic certificate untrust is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. To untrust the development certificate, remove this certificate from your trusted ' +\n `root certification authorities: \"${this.certificateStore.certificatePath}\". The ` +\n `certificate has serial number \"${CA_SERIAL_NUMBER}\".`\n );\n return false;\n }\n }\n\n private async _createCACertificateAsync(\n validityInDays: number,\n forge: typeof import('node-forge')\n ): Promise<ICaCertificate> {\n const keys: pki.KeyPair = forge.pki.rsa.generateKeyPair(2048);\n const certificate: pki.Certificate = forge.pki.createCertificate();\n certificate.publicKey = keys.publicKey;\n\n certificate.serialNumber = CA_SERIAL_NUMBER;\n\n const notBefore: Date = new Date();\n const notAfter: Date = new Date(notBefore);\n notAfter.setUTCDate(notBefore.getUTCDate() + validityInDays);\n certificate.validity.notBefore = notBefore;\n certificate.validity.notAfter = notAfter;\n\n const attrs: pki.CertificateField[] = [\n {\n name: 'commonName',\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setSubject(attrs);\n certificate.setIssuer(attrs);\n\n const altNames: readonly IAltName[] = [\n {\n type: 2, // DNS\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setExtensions([\n {\n name: 'basicConstraints',\n cA: true,\n pathLenConstraint: 0,\n critical: true\n },\n {\n name: 'subjectAltName',\n altNames,\n critical: true\n },\n {\n name: 'issuerAltName',\n altNames,\n critical: false\n },\n {\n name: 'keyUsage',\n keyCertSign: true,\n critical: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n critical: true\n },\n {\n name: 'friendlyName',\n value: FRIENDLY_NAME\n }\n ]);\n\n // self-sign certificate\n certificate.sign(keys.privateKey, forge.md.sha256.create());\n\n return {\n certificate,\n privateKey: keys.privateKey\n };\n }\n\n private async _createDevelopmentCertificateAsync(\n options: Required<ICertificateGenerationOptions>\n ): Promise<ICertificate> {\n const forge: typeof import('node-forge') = await import('node-forge');\n const keys: pki.KeyPair = forge.pki.rsa.generateKeyPair(2048);\n const certificate: pki.Certificate = forge.pki.createCertificate();\n\n certificate.publicKey = keys.publicKey;\n certificate.serialNumber = TLS_SERIAL_NUMBER;\n\n const { subjectAltNames: subjectNames, subjectIPAddresses: subjectIpAddresses, validityInDays } = options;\n\n const { certificate: caCertificate, privateKey: caPrivateKey } = await this._createCACertificateAsync(\n validityInDays,\n forge\n );\n\n const notBefore: Date = new Date();\n const notAfter: Date = new Date(notBefore);\n notAfter.setUTCDate(notBefore.getUTCDate() + validityInDays);\n certificate.validity.notBefore = notBefore;\n certificate.validity.notAfter = notAfter;\n\n const subjectAttrs: pki.CertificateField[] = [\n {\n name: 'commonName',\n value: subjectNames[0]\n }\n ];\n const issuerAttrs: pki.CertificateField[] = caCertificate.subject.attributes;\n\n certificate.setSubject(subjectAttrs);\n certificate.setIssuer(issuerAttrs);\n\n const subjectAltNames: IAltName[] = [\n ...subjectNames.map<IDnsAltName>((subjectName) => ({\n type: 2, // DNS\n value: subjectName\n })),\n ...subjectIpAddresses.map<IIPAddressAltName>((ip) => ({\n type: 7, // IP\n ip\n }))\n ];\n\n const issuerAltNames: readonly IAltName[] = [\n {\n type: 2, // DNS\n value: CA_ALT_NAME\n }\n ];\n\n certificate.setExtensions([\n {\n name: 'basicConstraints',\n cA: false,\n critical: true\n },\n {\n name: 'subjectAltName',\n altNames: subjectAltNames,\n critical: true\n },\n {\n name: 'issuerAltName',\n altNames: issuerAltNames,\n critical: false\n },\n {\n name: 'keyUsage',\n digitalSignature: true,\n keyEncipherment: true,\n dataEncipherment: true,\n critical: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n critical: true\n },\n {\n name: 'friendlyName',\n value: FRIENDLY_NAME\n }\n ]);\n\n // Sign certificate with CA\n certificate.sign(caPrivateKey, forge.md.sha256.create());\n\n // convert a Forge certificate to PEM\n const caPem: string = forge.pki.certificateToPem(caCertificate);\n const pem: string = forge.pki.certificateToPem(certificate);\n const pemKey: string = forge.pki.privateKeyToPem(keys.privateKey);\n\n return {\n pemCaCertificate: caPem,\n pemCertificate: pem,\n pemKey: pemKey,\n subjectAltNames: options.subjectAltNames\n };\n }\n\n private async _tryTrustCertificateAsync(certificatePath: string, terminal: ITerminal): Promise<boolean> {\n switch (process.platform) {\n case 'win32':\n terminal.writeLine(\n 'Attempting to trust a development certificate. This self-signed certificate only points to localhost ' +\n 'and will be stored in your local user profile to be used by other instances of ' +\n 'debug-certificate-manager. If you do not consent to trust this certificate, click \"NO\" in the dialog.'\n );\n\n const winTrustResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-addstore',\n 'root',\n certificatePath\n ]);\n\n if (winTrustResult.exitCode !== 0) {\n terminal.writeErrorLine(`Error: ${winTrustResult.stdout.toString()}`);\n\n const errorLines: string[] = winTrustResult.stdout\n .toString()\n .split(EOL)\n .map((line: string) => line.trim());\n\n // Not sure if this is always the status code for \"cancelled\" - should confirm.\n if (\n winTrustResult.exitCode === 2147943623 ||\n errorLines[errorLines.length - 1].indexOf('The operation was canceled by the user.') > 0\n ) {\n terminal.writeLine('Certificate trust cancelled.');\n } else {\n terminal.writeErrorLine('Certificate trust failed with an unknown error.');\n }\n\n return false;\n } else {\n terminal.writeVerboseLine('Successfully trusted development certificate.');\n\n return true;\n }\n\n case 'darwin':\n terminal.writeLine(\n 'Attempting to trust a development certificate. This self-signed certificate only points to localhost ' +\n 'and will be stored in your local user profile to be used by other instances of ' +\n 'debug-certificate-manager. If you do not consent to trust this certificate, do not enter your ' +\n 'root password in the prompt.'\n );\n\n const result: IRunResult = await darwinRunSudoAsync(terminal, 'security', [\n 'add-trusted-cert',\n '-d',\n '-r',\n 'trustRoot',\n '-k',\n MAC_KEYCHAIN,\n certificatePath\n ]);\n\n if (result.exitCode === 0) {\n terminal.writeVerboseLine('Successfully trusted development certificate.');\n return true;\n } else {\n if (\n result.stderr.some(\n (value: string) => !!value.match(/The authorization was cancelled by the user\\./)\n )\n ) {\n terminal.writeLine('Certificate trust cancelled.');\n return false;\n } else {\n terminal.writeErrorLine(\n `Certificate trust failed with an unknown error. Exit code: ${result.exitCode}. ` +\n `Error: ${result.stderr.join(' ')}`\n );\n return false;\n }\n }\n\n default:\n // Linux + others: Have the user manually trust the cert if they want to\n terminal.writeLine(\n 'Automatic certificate trust is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. To trust the development certificate, add this certificate to your trusted root ' +\n `certification authorities: \"${certificatePath}\".`\n );\n return true;\n }\n }\n\n private async _detectIfCertificateIsTrustedAsync(terminal: ITerminal): Promise<boolean> {\n switch (process.platform) {\n case 'win32':\n const winVerifyStoreResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-user',\n '-verifystore',\n 'root',\n CA_SERIAL_NUMBER\n ]);\n\n if (winVerifyStoreResult.exitCode !== 0) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in the store. CertUtil error: ',\n winVerifyStoreResult.stderr.join(' ')\n );\n return false;\n } else {\n terminal.writeVerboseLine(\n 'The development certificate was found in the store. CertUtil output: ',\n winVerifyStoreResult.stdout.join(' ')\n );\n return true;\n }\n\n case 'darwin':\n terminal.writeVerboseLine('Trying to find the signature of the development certificate.');\n\n const macFindCertificateResult: IRunResult = await runAsync('security', [\n 'find-certificate',\n '-c',\n CA_ALT_NAME,\n '-a',\n '-Z',\n MAC_KEYCHAIN\n ]);\n\n if (macFindCertificateResult.exitCode !== 0) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in keychain. Find certificate error: ',\n macFindCertificateResult.stderr.join(' ')\n );\n return false;\n }\n\n const shaHash: string | undefined = this._parseMacOsMatchingCertificateHash(\n macFindCertificateResult.stdout.join(EOL)\n );\n\n if (!shaHash) {\n terminal.writeVerboseLine(\n 'The development certificate was not found in keychain. Find certificate output:\\n',\n macFindCertificateResult.stdout.join(' ')\n );\n return false;\n }\n\n terminal.writeVerboseLine(`The development certificate was found in keychain.`);\n return true;\n\n default:\n // Linux + others: Have the user manually verify the cert is trusted\n terminal.writeVerboseLine(\n 'Automatic certificate trust validation is only implemented for debug-certificate-manager on Windows ' +\n 'and macOS. Manually verify this development certificate is present in your trusted ' +\n `root certification authorities: \"${this.certificateStore.certificatePath}\". ` +\n `The certificate has serial number \"${CA_SERIAL_NUMBER}\".`\n );\n // Always return true on Linux to prevent breaking flow.\n return true;\n }\n }\n\n private async _trySetFriendlyNameAsync(certificatePath: string, terminal: ITerminal): Promise<boolean> {\n if (process.platform === 'win32') {\n const basePath: string = path.dirname(certificatePath);\n const fileName: string = path.basename(certificatePath, path.extname(certificatePath));\n const friendlyNamePath: string = path.join(basePath, `${fileName}.inf`);\n\n const friendlyNameFile: string = [\n '[Version]',\n 'Signature = \"$Windows NT$\"',\n '[Properties]',\n `11 = \"{text}${FRIENDLY_NAME}\"`,\n ''\n ].join(EOL);\n\n await FileSystem.writeFileAsync(friendlyNamePath, friendlyNameFile);\n\n const repairStoreResult: IRunResult = await runAsync(CERTUTIL_EXE_NAME, [\n '-repairstore',\n '-user',\n 'root',\n CA_SERIAL_NUMBER,\n friendlyNamePath\n ]);\n\n if (repairStoreResult.exitCode !== 0) {\n terminal.writeVerboseLine(`CertUtil Error: ${repairStoreResult.stderr.join('')}`);\n terminal.writeVerboseLine(`CertUtil: ${repairStoreResult.stdout.join('')}`);\n return false;\n } else {\n terminal.writeVerboseLine('Successfully set certificate name.');\n return true;\n }\n } else {\n // No equivalent concept outside of Windows\n return true;\n }\n }\n\n private async _ensureCertificateInternalAsync(\n options: Required<ICertificateGenerationOptions>,\n terminal: ITerminal\n ): Promise<ICertificate> {\n const certificateStore: CertificateStore = this.certificateStore;\n const generatedCertificate: ICertificate = await this._createDevelopmentCertificateAsync(options);\n\n const certificateName: string = Date.now().toString();\n const tempDirName: string = randomTmpPath('rushstack', 'temp');\n await FileSystem.ensureFolderAsync(tempDirName);\n\n const tempCertificatePath: string = path.join(tempDirName, `${certificateName}.pem`);\n const pemFileContents: string | undefined = generatedCertificate.pemCaCertificate;\n if (pemFileContents) {\n await FileSystem.writeFileAsync(tempCertificatePath, pemFileContents, {\n ensureFolderExists: true\n });\n }\n\n const trustCertificateResult: boolean = options.skipCertificateTrust\n ? true\n : await this._tryTrustCertificateAsync(tempCertificatePath, terminal);\n\n let subjectAltNames: readonly string[] | undefined;\n if (trustCertificateResult) {\n certificateStore.caCertificateData = generatedCertificate.pemCaCertificate;\n certificateStore.certificateData = generatedCertificate.pemCertificate;\n certificateStore.keyData = generatedCertificate.pemKey;\n subjectAltNames = generatedCertificate.subjectAltNames;\n\n // Try to set the friendly name, and warn if we can't\n if (!(await this._trySetFriendlyNameAsync(tempCertificatePath, terminal))) {\n terminal.writeWarningLine(\"Unable to set the certificate's friendly name.\");\n }\n } else {\n // Clear out the existing store data, if any exists\n certificateStore.caCertificateData = undefined;\n certificateStore.certificateData = undefined;\n certificateStore.keyData = undefined;\n }\n\n await FileSystem.deleteFileAsync(tempCertificatePath);\n\n return {\n pemCaCertificate: certificateStore.caCertificateData,\n pemCertificate: certificateStore.certificateData,\n pemKey: certificateStore.keyData,\n subjectAltNames\n };\n }\n\n /**\n * Validate existing certificates to check if they are usable.\n *\n * @public\n */\n public async validateCertificateAsync(\n terminal: ITerminal,\n options?: ICertificateGenerationOptions\n ): Promise<ICertificateValidationResult> {\n const optionsWithDefaults: Required<ICertificateGenerationOptions> = applyDefaultOptions(options);\n const { certificateData: existingCert, keyData: existingKey } = this.certificateStore;\n\n if (!existingCert || !existingKey) {\n return {\n isValid: false,\n validationMessages: ['No development certificate found.']\n };\n }\n\n const messages: string[] = [];\n\n const forge: typeof import('node-forge') = await import('node-forge');\n const parsedCertificate: pki.Certificate = forge.pki.certificateFromPem(existingCert);\n const altNamesExtension: ISubjectAltNameExtension | undefined = parsedCertificate.getExtension(\n 'subjectAltName'\n ) as ISubjectAltNameExtension;\n\n if (!altNamesExtension) {\n messages.push(\n 'The existing development certificate is missing the subjectAltName ' +\n 'property and will not work with the latest versions of some browsers.'\n );\n } else {\n const missingSubjectNames: Set<string> = new Set(optionsWithDefaults.subjectAltNames);\n for (const altName of altNamesExtension.altNames) {\n missingSubjectNames.delete(isIPAddress(altName) ? altName.ip : altName.value);\n }\n if (missingSubjectNames.size) {\n messages.push(\n `The existing development certificate does not include the following expected subjectAltName values: ` +\n Array.from(missingSubjectNames, (name: string) => `\"${name}\"`).join(', ')\n );\n }\n }\n\n const { notBefore, notAfter } = parsedCertificate.validity;\n const now: Date = new Date();\n if (now < notBefore) {\n messages.push(\n `The existing development certificate's validity period does not start until ${notBefore}. It is currently ${now}.`\n );\n }\n\n if (now > notAfter) {\n messages.push(\n `The existing development certificate's validity period ended ${notAfter}. It is currently ${now}.`\n );\n }\n\n now.setUTCDate(now.getUTCDate() + optionsWithDefaults.validityInDays);\n if (notAfter > now) {\n messages.push(\n `The existing development certificate's expiration date ${notAfter} exceeds the allowed limit ${now}. ` +\n `This will be rejected by many browsers.`\n );\n }\n\n if (\n notBefore.getTime() - notAfter.getTime() >\n optionsWithDefaults.validityInDays * ONE_DAY_IN_MILLISECONDS\n ) {\n messages.push(\n \"The existing development certificate's validity period is longer \" +\n `than ${optionsWithDefaults.validityInDays} days.`\n );\n }\n\n const { caCertificateData } = this.certificateStore;\n\n if (!caCertificateData) {\n messages.push(\n 'The existing development certificate is missing a separate CA cert as the root ' +\n 'of trust and will not work with the latest versions of some browsers.'\n );\n }\n\n const isTrusted: boolean = await this._detectIfCertificateIsTrustedAsync(terminal);\n if (!isTrusted) {\n messages.push('The existing development certificate is not currently trusted by your system.');\n }\n\n const isValid: boolean = messages.length === 0;\n const validCertificate: ICertificate | undefined = isValid\n ? {\n pemCaCertificate: caCertificateData,\n pemCertificate: existingCert,\n pemKey: existingKey,\n subjectAltNames: altNamesExtension?.altNames.map((entry) =>\n isIPAddress(entry) ? entry.ip : entry.value\n )\n }\n : undefined;\n\n return {\n isValid,\n validationMessages: messages,\n certificate: validCertificate\n };\n }\n\n private _parseMacOsMatchingCertificateHash(findCertificateOuput: string): string | undefined {\n let shaHash: string | undefined = undefined;\n for (const line of findCertificateOuput.split(EOL)) {\n // Sets `shaHash` to the current certificate SHA-1 as we progress through the lines of certificate text.\n const shaHashMatch: string[] | null = line.match(/^SHA-1 hash: (.+)$/);\n if (shaHashMatch) {\n shaHash = shaHashMatch[1];\n }\n\n const snbrMatch: string[] | null = line.match(/^\\s*\"snbr\"<blob>=0x([^\\s]+).+$/);\n if (snbrMatch && (snbrMatch[1] || '').toLowerCase() === CA_SERIAL_NUMBER) {\n return shaHash;\n }\n }\n }\n}\n\nfunction applyDefaultOptions(\n options: ICertificateGenerationOptions | undefined\n): Required<ICertificateGenerationOptions> {\n const subjectNames: ReadonlyArray<string> | undefined = options?.subjectAltNames;\n const subjectIpAddresses: ReadonlyArray<string> | undefined = options?.subjectIPAddresses;\n const skipCertificateTrust: boolean | undefined = options?.skipCertificateTrust || false;\n return {\n subjectAltNames: subjectNames?.length ? subjectNames : DEFAULT_CERTIFICATE_SUBJECT_NAMES,\n subjectIPAddresses: subjectIpAddresses?.length\n ? subjectIpAddresses\n : DEFAULT_CERTIFICATE_SUBJECT_IP_ADDRESSES,\n validityInDays: Math.min(\n MAX_CERTIFICATE_VALIDITY_DAYS,\n options?.validityInDays ?? MAX_CERTIFICATE_VALIDITY_DAYS\n ),\n skipCertificateTrust: skipCertificateTrust\n };\n}\n\nfunction isIPAddress(altName: IAltName): altName is IIPAddressAltName {\n return altName.type === 7;\n}\n"]}
@@ -1,3 +1,29 @@
1
+ /**
2
+ * Options for configuring paths and filenames used by the `CertificateStore`.
3
+ * @public
4
+ */
5
+ export interface ICertificateStoreOptions {
6
+ /**
7
+ * Path to the directory where the certificate store will be created.
8
+ * If not provided, it defaults to `<homedir>/.rushstack`.
9
+ */
10
+ storePath?: string;
11
+ /**
12
+ * Filename of the CA certificate file within the store directory.
13
+ * If not provided, it defaults to `rushstack-ca.pem`.
14
+ */
15
+ caCertificateFilename?: string;
16
+ /**
17
+ * Filename of the TLS certificate file within the store directory.
18
+ * If not provided, it defaults to `rushstack-serve.pem`.
19
+ */
20
+ certificateFilename?: string;
21
+ /**
22
+ * Filename of the TLS key file within the store directory.
23
+ * If not provided, it defaults to `rushstack-serve.key`.
24
+ */
25
+ keyFilename?: string;
26
+ }
1
27
  /**
2
28
  * Store to retrieve and save debug certificate data.
3
29
  * @public
@@ -6,10 +32,15 @@ export declare class CertificateStore {
6
32
  private readonly _caCertificatePath;
7
33
  private readonly _certificatePath;
8
34
  private readonly _keyPath;
35
+ private readonly _storePath;
9
36
  private _caCertificateData;
10
37
  private _certificateData;
11
38
  private _keyData;
12
- constructor();
39
+ constructor(options?: ICertificateStoreOptions);
40
+ /**
41
+ * Path to the directory where the debug certificates are stored.
42
+ */
43
+ get storePath(): string;
13
44
  /**
14
45
  * Path to the saved debug CA certificate
15
46
  */
@@ -18,6 +49,10 @@ export declare class CertificateStore {
18
49
  * Path to the saved debug TLS certificate
19
50
  */
20
51
  get certificatePath(): string;
52
+ /**
53
+ * Path to the saved debug TLS key
54
+ */
55
+ get keyPath(): string;
21
56
  /**
22
57
  * Debug Certificate Authority certificate pem file contents.
23
58
  */
@@ -1 +1 @@
1
- {"version":3,"file":"CertificateStore.d.ts","sourceRoot":"","sources":["../src/CertificateStore.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAqB;;IAiBrC;;OAEG;IACH,IAAW,iBAAiB,IAAI,MAAM,CAErC;IAED;;OAEG;IACH,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED;;OAEG;IACH,IAAW,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAYjD;IAED,IAAW,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAQ3D;IAED;;OAEG;IACH,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAY/C;IAED,IAAW,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAQzD;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,MAAM,GAAG,SAAS,CAYvC;IAED,IAAW,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAQzC;CACF"}
1
+ {"version":3,"file":"CertificateStore.d.ts","sourceRoot":"","sources":["../src/CertificateStore.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAqB;gBAElB,OAAO,GAAE,wBAA6B;IAsBzD;;OAEG;IACH,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED;;OAEG;IACH,IAAW,iBAAiB,IAAI,MAAM,CAErC;IAED;;OAEG;IACH,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED;;OAEG;IACH,IAAW,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAYjD;IAED,IAAW,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAQ3D;IAED;;OAEG;IACH,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAY/C;IAED,IAAW,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAQzD;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,MAAM,GAAG,SAAS,CAYvC;IAED,IAAW,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAQzC;CACF"}
@@ -44,17 +44,33 @@ const node_core_library_1 = require("@rushstack/node-core-library");
44
44
  * @public
45
45
  */
46
46
  class CertificateStore {
47
- constructor() {
48
- const unresolvedUserFolder = (0, os_1.homedir)();
49
- const userProfilePath = path.resolve(unresolvedUserFolder);
50
- if (!node_core_library_1.FileSystem.exists(userProfilePath)) {
51
- throw new Error("Unable to determine the current user's home directory");
47
+ constructor(options = {}) {
48
+ var _a, _b, _c;
49
+ const requestedStorePath = options.storePath;
50
+ let storePath;
51
+ if (requestedStorePath) {
52
+ storePath = path.resolve(requestedStorePath);
52
53
  }
53
- const serveDataPath = path.join(userProfilePath, '.rushstack');
54
- node_core_library_1.FileSystem.ensureFolder(serveDataPath);
55
- this._caCertificatePath = path.join(serveDataPath, 'rushstack-ca.pem');
56
- this._certificatePath = path.join(serveDataPath, 'rushstack-serve.pem');
57
- this._keyPath = path.join(serveDataPath, 'rushstack-serve.key');
54
+ else {
55
+ // Default to the user's home directory under `.rushstack`
56
+ const unresolvedUserFolder = (0, os_1.homedir)();
57
+ const userProfilePath = path.resolve(unresolvedUserFolder);
58
+ if (!node_core_library_1.FileSystem.exists(userProfilePath)) {
59
+ throw new Error("Unable to determine the current user's home directory");
60
+ }
61
+ storePath = path.join(userProfilePath, '.rushstack');
62
+ }
63
+ this._storePath = storePath;
64
+ node_core_library_1.FileSystem.ensureFolder(storePath);
65
+ this._caCertificatePath = path.join(storePath, (_a = options.caCertificateFilename) !== null && _a !== void 0 ? _a : 'rushstack-ca.pem');
66
+ this._certificatePath = path.join(storePath, (_b = options.certificateFilename) !== null && _b !== void 0 ? _b : 'rushstack-serve.pem');
67
+ this._keyPath = path.join(storePath, (_c = options.keyFilename) !== null && _c !== void 0 ? _c : 'rushstack-serve.key');
68
+ }
69
+ /**
70
+ * Path to the directory where the debug certificates are stored.
71
+ */
72
+ get storePath() {
73
+ return this._storePath;
58
74
  }
59
75
  /**
60
76
  * Path to the saved debug CA certificate
@@ -68,6 +84,12 @@ class CertificateStore {
68
84
  get certificatePath() {
69
85
  return this._certificatePath;
70
86
  }
87
+ /**
88
+ * Path to the saved debug TLS key
89
+ */
90
+ get keyPath() {
91
+ return this._keyPath;
92
+ }
71
93
  /**
72
94
  * Debug Certificate Authority certificate pem file contents.
73
95
  */
@@ -1 +1 @@
1
- {"version":3,"file":"CertificateStore.js","sourceRoot":"","sources":["../src/CertificateStore.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as path from 'path';\nimport { homedir } from 'os';\n\nimport { FileSystem } from '@rushstack/node-core-library';\n\n/**\n * Store to retrieve and save debug certificate data.\n * @public\n */\nexport class CertificateStore {\n private readonly _caCertificatePath: string;\n private readonly _certificatePath: string;\n private readonly _keyPath: string;\n\n private _caCertificateData: string | undefined;\n private _certificateData: string | undefined;\n private _keyData: string | undefined;\n\n public constructor() {\n const unresolvedUserFolder: string = homedir();\n const userProfilePath: string = path.resolve(unresolvedUserFolder);\n if (!FileSystem.exists(userProfilePath)) {\n throw new Error(\"Unable to determine the current user's home directory\");\n }\n\n const serveDataPath: string = path.join(userProfilePath, '.rushstack');\n FileSystem.ensureFolder(serveDataPath);\n\n this._caCertificatePath = path.join(serveDataPath, 'rushstack-ca.pem');\n this._certificatePath = path.join(serveDataPath, 'rushstack-serve.pem');\n this._keyPath = path.join(serveDataPath, 'rushstack-serve.key');\n }\n\n /**\n * Path to the saved debug CA certificate\n */\n public get caCertificatePath(): string {\n return this._caCertificatePath;\n }\n\n /**\n * Path to the saved debug TLS certificate\n */\n public get certificatePath(): string {\n return this._certificatePath;\n }\n\n /**\n * Debug Certificate Authority certificate pem file contents.\n */\n public get caCertificateData(): string | undefined {\n if (!this._caCertificateData) {\n try {\n this._caCertificateData = FileSystem.readFile(this._caCertificatePath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._caCertificateData;\n }\n\n public set caCertificateData(certificate: string | undefined) {\n if (certificate) {\n FileSystem.writeFile(this._caCertificatePath, certificate);\n } else if (FileSystem.exists(this._caCertificatePath)) {\n FileSystem.deleteFile(this._caCertificatePath);\n }\n\n this._caCertificateData = certificate;\n }\n\n /**\n * Debug TLS Server certificate pem file contents.\n */\n public get certificateData(): string | undefined {\n if (!this._certificateData) {\n try {\n this._certificateData = FileSystem.readFile(this._certificatePath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._certificateData;\n }\n\n public set certificateData(certificate: string | undefined) {\n if (certificate) {\n FileSystem.writeFile(this._certificatePath, certificate);\n } else if (FileSystem.exists(this._certificatePath)) {\n FileSystem.deleteFile(this._certificatePath);\n }\n\n this._certificateData = certificate;\n }\n\n /**\n * Key used to sign the debug pem certificate.\n */\n public get keyData(): string | undefined {\n if (!this._keyData) {\n try {\n this._keyData = FileSystem.readFile(this._keyPath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._keyData;\n }\n\n public set keyData(key: string | undefined) {\n if (key) {\n FileSystem.writeFile(this._keyPath, key);\n } else if (FileSystem.exists(this._keyPath)) {\n FileSystem.deleteFile(this._keyPath);\n }\n\n this._keyData = key;\n }\n}\n"]}
1
+ {"version":3,"file":"CertificateStore.js","sourceRoot":"","sources":["../src/CertificateStore.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as path from 'path';\nimport { homedir } from 'os';\n\nimport { FileSystem } from '@rushstack/node-core-library';\n\n/**\n * Options for configuring paths and filenames used by the `CertificateStore`.\n * @public\n */\nexport interface ICertificateStoreOptions {\n /**\n * Path to the directory where the certificate store will be created.\n * If not provided, it defaults to `<homedir>/.rushstack`.\n */\n storePath?: string;\n /**\n * Filename of the CA certificate file within the store directory.\n * If not provided, it defaults to `rushstack-ca.pem`.\n */\n caCertificateFilename?: string;\n /**\n * Filename of the TLS certificate file within the store directory.\n * If not provided, it defaults to `rushstack-serve.pem`.\n */\n certificateFilename?: string;\n /**\n * Filename of the TLS key file within the store directory.\n * If not provided, it defaults to `rushstack-serve.key`.\n */\n keyFilename?: string;\n}\n\n/**\n * Store to retrieve and save debug certificate data.\n * @public\n */\nexport class CertificateStore {\n private readonly _caCertificatePath: string;\n private readonly _certificatePath: string;\n private readonly _keyPath: string;\n private readonly _storePath: string;\n\n private _caCertificateData: string | undefined;\n private _certificateData: string | undefined;\n private _keyData: string | undefined;\n\n public constructor(options: ICertificateStoreOptions = {}) {\n const requestedStorePath: string | undefined = options.storePath;\n let storePath: string | undefined;\n if (requestedStorePath) {\n storePath = path.resolve(requestedStorePath);\n } else {\n // Default to the user's home directory under `.rushstack`\n const unresolvedUserFolder: string = homedir();\n const userProfilePath: string = path.resolve(unresolvedUserFolder);\n if (!FileSystem.exists(userProfilePath)) {\n throw new Error(\"Unable to determine the current user's home directory\");\n }\n storePath = path.join(userProfilePath, '.rushstack');\n }\n this._storePath = storePath;\n FileSystem.ensureFolder(storePath);\n\n this._caCertificatePath = path.join(storePath, options.caCertificateFilename ?? 'rushstack-ca.pem');\n this._certificatePath = path.join(storePath, options.certificateFilename ?? 'rushstack-serve.pem');\n this._keyPath = path.join(storePath, options.keyFilename ?? 'rushstack-serve.key');\n }\n\n /**\n * Path to the directory where the debug certificates are stored.\n */\n public get storePath(): string {\n return this._storePath;\n }\n\n /**\n * Path to the saved debug CA certificate\n */\n public get caCertificatePath(): string {\n return this._caCertificatePath;\n }\n\n /**\n * Path to the saved debug TLS certificate\n */\n public get certificatePath(): string {\n return this._certificatePath;\n }\n\n /**\n * Path to the saved debug TLS key\n */\n public get keyPath(): string {\n return this._keyPath;\n }\n\n /**\n * Debug Certificate Authority certificate pem file contents.\n */\n public get caCertificateData(): string | undefined {\n if (!this._caCertificateData) {\n try {\n this._caCertificateData = FileSystem.readFile(this._caCertificatePath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._caCertificateData;\n }\n\n public set caCertificateData(certificate: string | undefined) {\n if (certificate) {\n FileSystem.writeFile(this._caCertificatePath, certificate);\n } else if (FileSystem.exists(this._caCertificatePath)) {\n FileSystem.deleteFile(this._caCertificatePath);\n }\n\n this._caCertificateData = certificate;\n }\n\n /**\n * Debug TLS Server certificate pem file contents.\n */\n public get certificateData(): string | undefined {\n if (!this._certificateData) {\n try {\n this._certificateData = FileSystem.readFile(this._certificatePath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._certificateData;\n }\n\n public set certificateData(certificate: string | undefined) {\n if (certificate) {\n FileSystem.writeFile(this._certificatePath, certificate);\n } else if (FileSystem.exists(this._certificatePath)) {\n FileSystem.deleteFile(this._certificatePath);\n }\n\n this._certificateData = certificate;\n }\n\n /**\n * Key used to sign the debug pem certificate.\n */\n public get keyData(): string | undefined {\n if (!this._keyData) {\n try {\n this._keyData = FileSystem.readFile(this._keyPath);\n } catch (err) {\n if (!FileSystem.isNotExistError(err)) {\n throw err;\n }\n }\n }\n\n return this._keyData;\n }\n\n public set keyData(key: string | undefined) {\n if (key) {\n FileSystem.writeFile(this._keyPath, key);\n } else if (FileSystem.exists(this._keyPath)) {\n FileSystem.deleteFile(this._keyPath);\n }\n\n this._keyData = key;\n }\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -13,6 +13,6 @@
13
13
  *
14
14
  * @packageDocumentation
15
15
  */
16
- export { type ICertificate, CertificateManager, type ICertificateGenerationOptions, DEFAULT_CERTIFICATE_SUBJECT_NAMES } from './CertificateManager';
17
- export { CertificateStore } from './CertificateStore';
16
+ export { type ICertificate, CertificateManager, type ICertificateGenerationOptions, type ICertificateManagerOptions, type ICertificateValidationResult, DEFAULT_CERTIFICATE_SUBJECT_NAMES } from './CertificateManager';
17
+ export { CertificateStore, type ICertificateStoreOptions } from './CertificateStore';
18
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,6BAA6B,EAClC,iCAAiC,EAClC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,iCAAiC,EAClC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC"}
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D;;;;;;;;;;;;;;GAcG;AAEH,2DAK8B;AAH5B,wHAAA,kBAAkB,OAAA;AAElB,uIAAA,iCAAiC,OAAA;AAEnC,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * This package is used to manage debug certificates for development servers.\n *\n * This package provides the following utilities:\n *\n * - `CertificateStore` to handle retrieving and saving a debug certificate.\n *\n * - `CertificateManager` is a utility class containing the following public methods:\n *\n * - `ensureCertificate` will find or optionally create a debug certificate and trust it.\n *\n * - `untrustCertificate` will untrust a debug certificate.\n *\n * @packageDocumentation\n */\n\nexport {\n type ICertificate,\n CertificateManager,\n type ICertificateGenerationOptions,\n DEFAULT_CERTIFICATE_SUBJECT_NAMES\n} from './CertificateManager';\nexport { CertificateStore } from './CertificateStore';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D;;;;;;;;;;;;;;GAcG;AAEH,2DAO8B;AAL5B,wHAAA,kBAAkB,OAAA;AAIlB,uIAAA,iCAAiC,OAAA;AAEnC,uDAAqF;AAA5E,oHAAA,gBAAgB,OAAA","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * This package is used to manage debug certificates for development servers.\n *\n * This package provides the following utilities:\n *\n * - `CertificateStore` to handle retrieving and saving a debug certificate.\n *\n * - `CertificateManager` is a utility class containing the following public methods:\n *\n * - `ensureCertificate` will find or optionally create a debug certificate and trust it.\n *\n * - `untrustCertificate` will untrust a debug certificate.\n *\n * @packageDocumentation\n */\n\nexport {\n type ICertificate,\n CertificateManager,\n type ICertificateGenerationOptions,\n type ICertificateManagerOptions,\n type ICertificateValidationResult,\n DEFAULT_CERTIFICATE_SUBJECT_NAMES\n} from './CertificateManager';\nexport { CertificateStore, type ICertificateStoreOptions } from './CertificateStore';\n"]}
@@ -1,3 +1,4 @@
1
+ import type { ITerminal } from '@rushstack/terminal';
1
2
  export interface IRunResult {
2
3
  stdout: string[];
3
4
  stderr: string[];
@@ -6,11 +7,7 @@ export interface IRunResult {
6
7
  */
7
8
  exitCode: number;
8
9
  }
9
- export interface ISudoOptions {
10
- cachePassword?: boolean;
11
- prompt?: string;
12
- spawnOptions?: object;
13
- }
14
- export declare function runSudoAsync(command: string, params: string[]): Promise<IRunResult>;
10
+ export declare function randomTmpPath(prefix?: string, suffix?: string): string;
11
+ export declare function darwinRunSudoAsync(terminal: ITerminal, command: string, params: string[]): Promise<IRunResult>;
15
12
  export declare function runAsync(command: string, params: string[]): Promise<IRunResult>;
16
13
  //# sourceMappingURL=runCommand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runCommand.d.ts","sourceRoot":"","sources":["../src/runCommand.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAOzF;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGrF"}
1
+ {"version":3,"file":"runCommand.d.ts","sourceRoot":"","sources":["../src/runCommand.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAKrD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,UAAU,CAAC,CAiErB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGrF"}
package/lib/runCommand.js CHANGED
@@ -1,17 +1,102 @@
1
1
  "use strict";
2
2
  // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
3
  // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
4
37
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.runSudoAsync = runSudoAsync;
38
+ exports.randomTmpPath = randomTmpPath;
39
+ exports.darwinRunSudoAsync = darwinRunSudoAsync;
6
40
  exports.runAsync = runAsync;
7
41
  const node_core_library_1 = require("@rushstack/node-core-library");
8
- async function runSudoAsync(command, params) {
9
- const sudo = require('sudo');
10
- const result = sudo([command, ...params], {
11
- cachePassword: false,
12
- prompt: 'Enter your password: '
13
- });
14
- return await _handleChildProcess(result);
42
+ const path = __importStar(require("node:path"));
43
+ const os = __importStar(require("node:os"));
44
+ function randomTmpPath(prefix, suffix) {
45
+ return path.join(os.tmpdir(), `${prefix || 'tmp-'}${Math.random().toString(36).slice(2)}${suffix || ''}`);
46
+ }
47
+ async function darwinRunSudoAsync(terminal, command, params) {
48
+ if (process.platform !== 'darwin') {
49
+ throw new Error('This function is only supported on macOS.');
50
+ }
51
+ const basename = randomTmpPath('sudo-runner-');
52
+ const stdoutFile = `${basename}.stdout`;
53
+ const stderrFile = `${basename}.stderr`;
54
+ const exitFile = `${basename}.exit`;
55
+ const scriptFile = `${basename}.script`;
56
+ const commandStr = `${command} ${params.join(' ')}`;
57
+ terminal.writeLine(`Running command with elevated privileges: ${commandStr}`);
58
+ // Wrap the shell command in a bash command and capture stdout, stderr, and exit code
59
+ const shellScript = `#!/bin/bash
60
+ set -v
61
+ echo "\\n\\nRunning command with elevated privileges: ${commandStr}";
62
+ sudo ${commandStr} > >(tee -a ${stdoutFile}) 2> >(tee -a ${stderrFile} >&2)
63
+ echo $? > "${exitFile}"
64
+ `;
65
+ node_core_library_1.FileSystem.writeFile(scriptFile, shellScript);
66
+ // This AppleScript opens a new Terminal window, runs the shell script, waits for it to finish and then closes the Terminal window.
67
+ const appleScript = `
68
+ tell application "Terminal"
69
+ activate
70
+ set win to do script "bash '${scriptFile}'"
71
+ repeat
72
+ delay 0.5
73
+ if not busy of window 1 then exit repeat
74
+ end repeat
75
+ close window 1
76
+ end tell
77
+ `;
78
+ terminal.writeLine(`Running AppleScript: ${appleScript}`);
79
+ const child = node_core_library_1.Executable.spawn('osascript', ['-e', appleScript]);
80
+ await node_core_library_1.Executable.waitForExitAsync(child);
81
+ const [stdoutContent, stderrContent, exitCodeStr] = await Promise.all([
82
+ node_core_library_1.FileSystem.readFileAsync(stdoutFile),
83
+ node_core_library_1.FileSystem.readFileAsync(stderrFile),
84
+ node_core_library_1.FileSystem.readFileAsync(exitFile)
85
+ ]);
86
+ const stdout = node_core_library_1.Text.splitByNewLines(stdoutContent);
87
+ const stderr = node_core_library_1.Text.splitByNewLines(stderrContent);
88
+ const exitCode = exitCodeStr ? Number(exitCodeStr) : -1;
89
+ await Promise.all([
90
+ node_core_library_1.FileSystem.deleteFileAsync(stdoutFile),
91
+ node_core_library_1.FileSystem.deleteFileAsync(stderrFile),
92
+ node_core_library_1.FileSystem.deleteFileAsync(exitFile),
93
+ node_core_library_1.FileSystem.deleteFileAsync(scriptFile)
94
+ ]);
95
+ return {
96
+ stdout,
97
+ stderr,
98
+ exitCode
99
+ };
15
100
  }
16
101
  async function runAsync(command, params) {
17
102
  const result = node_core_library_1.Executable.spawn(command, params);
@@ -1 +1 @@
1
- {"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../src/runCommand.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;AAoB3D,oCAOC;AAED,4BAGC;AA9BD,oEAA0D;AAkBnD,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,MAAgB;IAClE,MAAM,IAAI,GAA0E,OAAO,CAAC,MAAM,CAAC,CAAC;IACpG,MAAM,MAAM,GAA+B,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,EAAE;QACpE,aAAa,EAAE,KAAK;QACpB,MAAM,EAAE,uBAAuB;KAChC,CAAC,CAAC;IACH,OAAO,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,MAAgB;IAC9D,MAAM,MAAM,GAA+B,8BAAU,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7E,OAAO,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,YAAwC;IACzE,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAqC,EAAE,EAAE;;QACjE,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAA,YAAY,CAAC,MAAM,0CAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC/C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAA,YAAY,CAAC,MAAM,0CAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC/C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAuB,EAAE,MAA6B,EAAE,EAAE;YAClF,MAAM,kBAAkB,GAAW,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7F,OAAO,CAAC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Executable } from '@rushstack/node-core-library';\nimport type * as child_process from 'child_process';\n\nexport interface IRunResult {\n stdout: string[];\n stderr: string[];\n /**\n * The exit code, or -1 if the child process was terminated by a signal\n */\n exitCode: number;\n}\n\nexport interface ISudoOptions {\n cachePassword?: boolean;\n prompt?: string;\n spawnOptions?: object;\n}\n\nexport async function runSudoAsync(command: string, params: string[]): Promise<IRunResult> {\n const sudo: (args: string[], options: ISudoOptions) => child_process.ChildProcess = require('sudo');\n const result: child_process.ChildProcess = sudo([command, ...params], {\n cachePassword: false,\n prompt: 'Enter your password: '\n });\n return await _handleChildProcess(result);\n}\n\nexport async function runAsync(command: string, params: string[]): Promise<IRunResult> {\n const result: child_process.ChildProcess = Executable.spawn(command, params);\n return await _handleChildProcess(result);\n}\n\nasync function _handleChildProcess(childProcess: child_process.ChildProcess): Promise<IRunResult> {\n return await new Promise((resolve: (result: IRunResult) => void) => {\n const stderr: string[] = [];\n childProcess.stderr?.on('data', (data: Buffer) => {\n stderr.push(data.toString());\n });\n\n const stdout: string[] = [];\n childProcess.stdout?.on('data', (data: Buffer) => {\n stdout.push(data.toString());\n });\n\n childProcess.on('close', (exitCode: number | null, signal: NodeJS.Signals | null) => {\n const normalizedExitCode: number = typeof exitCode === 'number' ? exitCode : signal ? -1 : 0;\n resolve({ exitCode: normalizedExitCode, stdout, stderr });\n });\n });\n}\n"]}
1
+ {"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../src/runCommand.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Executable, FileSystem, Text } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\nimport type * as child_process from 'node:child_process';\nimport * as path from 'node:path';\nimport * as os from 'node:os';\n\nexport interface IRunResult {\n stdout: string[];\n stderr: string[];\n /**\n * The exit code, or -1 if the child process was terminated by a signal\n */\n exitCode: number;\n}\n\nexport function randomTmpPath(prefix?: string, suffix?: string): string {\n return path.join(os.tmpdir(), `${prefix || 'tmp-'}${Math.random().toString(36).slice(2)}${suffix || ''}`);\n}\n\nexport async function darwinRunSudoAsync(\n terminal: ITerminal,\n command: string,\n params: string[]\n): Promise<IRunResult> {\n if (process.platform !== 'darwin') {\n throw new Error('This function is only supported on macOS.');\n }\n\n const basename: string = randomTmpPath('sudo-runner-');\n const stdoutFile: string = `${basename}.stdout`;\n const stderrFile: string = `${basename}.stderr`;\n const exitFile: string = `${basename}.exit`;\n const scriptFile: string = `${basename}.script`;\n\n const commandStr: string = `${command} ${params.join(' ')}`;\n terminal.writeLine(`Running command with elevated privileges: ${commandStr}`);\n\n // Wrap the shell command in a bash command and capture stdout, stderr, and exit code\n const shellScript: string = `#!/bin/bash\nset -v\necho \"\\\\n\\\\nRunning command with elevated privileges: ${commandStr}\";\nsudo ${commandStr} > >(tee -a ${stdoutFile}) 2> >(tee -a ${stderrFile} >&2)\necho $? > \"${exitFile}\"\n`;\n\n FileSystem.writeFile(scriptFile, shellScript);\n\n // This AppleScript opens a new Terminal window, runs the shell script, waits for it to finish and then closes the Terminal window.\n const appleScript: string = `\n tell application \"Terminal\"\n activate\n set win to do script \"bash '${scriptFile}'\"\n repeat\n delay 0.5\n if not busy of window 1 then exit repeat\n end repeat\n close window 1\n end tell\n `;\n\n terminal.writeLine(`Running AppleScript: ${appleScript}`);\n\n const child: child_process.ChildProcess = Executable.spawn('osascript', ['-e', appleScript]);\n\n await Executable.waitForExitAsync(child);\n\n const [stdoutContent, stderrContent, exitCodeStr] = await Promise.all([\n FileSystem.readFileAsync(stdoutFile),\n FileSystem.readFileAsync(stderrFile),\n FileSystem.readFileAsync(exitFile)\n ]);\n\n const stdout: string[] = Text.splitByNewLines(stdoutContent);\n const stderr: string[] = Text.splitByNewLines(stderrContent);\n const exitCode: number = exitCodeStr ? Number(exitCodeStr) : -1;\n\n await Promise.all([\n FileSystem.deleteFileAsync(stdoutFile),\n FileSystem.deleteFileAsync(stderrFile),\n FileSystem.deleteFileAsync(exitFile),\n FileSystem.deleteFileAsync(scriptFile)\n ]);\n\n return {\n stdout,\n stderr,\n exitCode\n };\n}\n\nexport async function runAsync(command: string, params: string[]): Promise<IRunResult> {\n const result: child_process.ChildProcess = Executable.spawn(command, params);\n return await _handleChildProcess(result);\n}\n\nasync function _handleChildProcess(childProcess: child_process.ChildProcess): Promise<IRunResult> {\n return await new Promise((resolve: (result: IRunResult) => void) => {\n const stderr: string[] = [];\n childProcess.stderr?.on('data', (data: Buffer) => {\n stderr.push(data.toString());\n });\n\n const stdout: string[] = [];\n childProcess.stdout?.on('data', (data: Buffer) => {\n stdout.push(data.toString());\n });\n\n childProcess.on('close', (exitCode: number | null, signal: NodeJS.Signals | null) => {\n const normalizedExitCode: number = typeof exitCode === 'number' ? exitCode : signal ? -1 : 0;\n resolve({ exitCode: normalizedExitCode, stdout, stderr });\n });\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/debug-certificate-manager",
3
- "version": "1.4.37",
3
+ "version": "1.5.0",
4
4
  "description": "Cross-platform functionality to create debug ssl certificates.",
5
5
  "main": "lib/index.js",
6
6
  "typings": "dist/debug-certificate-manager.d.ts",
@@ -12,14 +12,14 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "node-forge": "~1.3.1",
15
- "sudo": "~1.0.3",
16
- "@rushstack/node-core-library": "5.13.1",
17
- "@rushstack/terminal": "0.15.3"
15
+ "@rushstack/node-core-library": "5.14.0",
16
+ "@rushstack/terminal": "0.15.4"
18
17
  },
19
18
  "devDependencies": {
20
19
  "@types/node-forge": "1.0.4",
21
- "@rushstack/heft": "0.74.0",
22
- "local-node-rig": "1.0.0"
20
+ "eslint": "~9.25.1",
21
+ "local-node-rig": "1.0.0",
22
+ "@rushstack/heft": "0.74.1"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "heft build --clean",