@jsenv/https-local 3.0.6 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -192
- package/package.json +19 -38
- package/src/certificate_authority.js +111 -110
- package/src/certificate_request.js +34 -35
- package/src/hosts_file_verif.js +34 -35
- package/src/https_local_cli.mjs +74 -0
- package/src/internal/authority_file_infos.js +12 -13
- package/src/internal/browser_detection.js +4 -4
- package/src/internal/certificate_authority_file_urls.js +23 -23
- package/src/internal/certificate_data_converter.js +39 -39
- package/src/internal/certificate_generator.js +39 -39
- package/src/internal/command.js +6 -6
- package/src/internal/exec.js +10 -10
- package/src/internal/forge.js +3 -3
- package/src/internal/hosts/hosts_utils.js +2 -2
- package/src/internal/hosts/parse_hosts.js +67 -66
- package/src/internal/hosts/read_hosts.js +5 -6
- package/src/internal/hosts/write_hosts.js +29 -31
- package/src/internal/hosts/write_line_hosts.js +30 -32
- package/src/internal/hosts.js +5 -5
- package/src/internal/linux/chrome_linux.js +21 -20
- package/src/internal/linux/firefox_linux.js +23 -20
- package/src/internal/linux/linux.js +8 -8
- package/src/internal/linux/linux_trust_store.js +58 -59
- package/src/internal/linux/nss_linux.js +21 -20
- package/src/internal/mac/chrome_mac.js +15 -16
- package/src/internal/mac/firefox_mac.js +20 -21
- package/src/internal/mac/mac.js +10 -10
- package/src/internal/mac/mac_keychain.js +46 -47
- package/src/internal/mac/nss_mac.js +29 -30
- package/src/internal/mac/safari.js +2 -2
- package/src/internal/memoize.js +14 -14
- package/src/internal/nssdb_browser.js +150 -145
- package/src/internal/platform.js +6 -6
- package/src/internal/search_certificate_in_command_output.js +4 -4
- package/src/internal/trust_query.js +4 -4
- package/src/internal/unsupported_platform/unsupported_platform.js +5 -5
- package/src/internal/validity_formatting.js +32 -32
- package/src/internal/windows/chrome_windows.js +26 -27
- package/src/internal/windows/edge.js +2 -2
- package/src/internal/windows/firefox_windows.js +31 -32
- package/src/internal/windows/windows.js +10 -10
- package/src/internal/windows/windows_certutil.js +41 -42
- package/src/jsenvParameters.js +2 -2
- package/src/main.js +5 -8
- package/src/validity_duration.js +12 -12
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
// https://ss64.com/osx/security.html
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import { searchCertificateInCommandOutput } from "../search_certificate_in_command_output.js"
|
|
3
|
+
import { createDetailedMessage, UNICODE } from "@jsenv/humanize";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { exec } from "../exec.js";
|
|
6
|
+
import { searchCertificateInCommandOutput } from "../search_certificate_in_command_output.js";
|
|
8
7
|
import {
|
|
9
|
-
VERB_CHECK_TRUST,
|
|
10
8
|
VERB_ADD_TRUST,
|
|
9
|
+
VERB_CHECK_TRUST,
|
|
11
10
|
VERB_ENSURE_TRUST,
|
|
12
11
|
VERB_REMOVE_TRUST,
|
|
13
|
-
} from "../trust_query.js"
|
|
12
|
+
} from "../trust_query.js";
|
|
14
13
|
|
|
15
14
|
const REASON_NEW_AND_TRY_TO_TRUST_DISABLED =
|
|
16
|
-
"certificate is new and tryToTrust is disabled"
|
|
17
|
-
const REASON_NOT_IN_KEYCHAIN = "certificate not found in mac keychain"
|
|
18
|
-
const REASON_IN_KEYCHAIN = "certificate found in mac keychain"
|
|
15
|
+
"certificate is new and tryToTrust is disabled";
|
|
16
|
+
const REASON_NOT_IN_KEYCHAIN = "certificate not found in mac keychain";
|
|
17
|
+
const REASON_IN_KEYCHAIN = "certificate found in mac keychain";
|
|
19
18
|
const REASON_ADD_TO_KEYCHAIN_COMMAND_FAILED =
|
|
20
|
-
"command to add certificate in mac keychain failed"
|
|
19
|
+
"command to add certificate in mac keychain failed";
|
|
21
20
|
const REASON_ADD_TO_KEYCHAIN_COMMAND_COMPLETED =
|
|
22
|
-
"command to add certificate in mac keychain completed"
|
|
21
|
+
"command to add certificate in mac keychain completed";
|
|
23
22
|
const REASON_REMOVE_FROM_KEYCHAIN_COMMAND_FAILED =
|
|
24
|
-
"command to remove certificate from mac keychain failed"
|
|
23
|
+
"command to remove certificate from mac keychain failed";
|
|
25
24
|
const REASON_REMOVE_FROM_KEYCHAIN_COMMAND_COMPLETED =
|
|
26
|
-
"command to remove certificate from mac keychain completed"
|
|
25
|
+
"command to remove certificate from mac keychain completed";
|
|
27
26
|
|
|
28
|
-
const systemKeychainPath = "/Library/Keychains/System.keychain"
|
|
27
|
+
const systemKeychainPath = "/Library/Keychains/System.keychain";
|
|
29
28
|
|
|
30
29
|
export const executeTrustQueryOnMacKeychain = async ({
|
|
31
30
|
logger,
|
|
@@ -36,35 +35,35 @@ export const executeTrustQueryOnMacKeychain = async ({
|
|
|
36
35
|
verb,
|
|
37
36
|
}) => {
|
|
38
37
|
if (verb === VERB_CHECK_TRUST && certificateIsNew) {
|
|
39
|
-
logger.info(`${UNICODE.INFO} You should add certificate to mac keychain`)
|
|
38
|
+
logger.info(`${UNICODE.INFO} You should add certificate to mac keychain`);
|
|
40
39
|
return {
|
|
41
40
|
status: "not_trusted",
|
|
42
41
|
reason: REASON_NEW_AND_TRY_TO_TRUST_DISABLED,
|
|
43
|
-
}
|
|
42
|
+
};
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
logger.info(`Check if certificate is in mac keychain...`)
|
|
45
|
+
logger.info(`Check if certificate is in mac keychain...`);
|
|
47
46
|
// https://ss64.com/osx/security-find-cert.html
|
|
48
|
-
const findCertificateCommand = `security find-certificate -a -p ${systemKeychainPath}
|
|
49
|
-
logger.debug(`${UNICODE.COMMAND} ${findCertificateCommand}`)
|
|
50
|
-
const findCertificateCommandOutput = await exec(findCertificateCommand)
|
|
47
|
+
const findCertificateCommand = `security find-certificate -a -p ${systemKeychainPath}`;
|
|
48
|
+
logger.debug(`${UNICODE.COMMAND} ${findCertificateCommand}`);
|
|
49
|
+
const findCertificateCommandOutput = await exec(findCertificateCommand);
|
|
51
50
|
const certificateFoundInCommandOutput = searchCertificateInCommandOutput(
|
|
52
51
|
findCertificateCommandOutput,
|
|
53
52
|
certificate,
|
|
54
|
-
)
|
|
53
|
+
);
|
|
55
54
|
|
|
56
55
|
const removeCert = async () => {
|
|
57
56
|
// https://ss64.com/osx/security-delete-cert.html
|
|
58
|
-
const removeTrustedCertCommand = `sudo security delete-certificate -c "${certificateCommonName}"
|
|
59
|
-
logger.info(`Removing certificate from mac keychain...`)
|
|
60
|
-
logger.info(`${UNICODE.COMMAND} ${removeTrustedCertCommand}`)
|
|
57
|
+
const removeTrustedCertCommand = `sudo security delete-certificate -c "${certificateCommonName}"`;
|
|
58
|
+
logger.info(`Removing certificate from mac keychain...`);
|
|
59
|
+
logger.info(`${UNICODE.COMMAND} ${removeTrustedCertCommand}`);
|
|
61
60
|
try {
|
|
62
|
-
await exec(removeTrustedCertCommand)
|
|
63
|
-
logger.info(`${UNICODE.OK} certificate removed from mac keychain`)
|
|
61
|
+
await exec(removeTrustedCertCommand);
|
|
62
|
+
logger.info(`${UNICODE.OK} certificate removed from mac keychain`);
|
|
64
63
|
return {
|
|
65
64
|
status: "not_trusted",
|
|
66
65
|
reason: REASON_REMOVE_FROM_KEYCHAIN_COMMAND_COMPLETED,
|
|
67
|
-
}
|
|
66
|
+
};
|
|
68
67
|
} catch (e) {
|
|
69
68
|
logger.error(
|
|
70
69
|
createDetailedMessage(
|
|
@@ -74,41 +73,41 @@ export const executeTrustQueryOnMacKeychain = async ({
|
|
|
74
73
|
"certificate file url": certificateFileUrl,
|
|
75
74
|
},
|
|
76
75
|
),
|
|
77
|
-
)
|
|
76
|
+
);
|
|
78
77
|
return {
|
|
79
78
|
status: "not_trusted",
|
|
80
79
|
reason: REASON_REMOVE_FROM_KEYCHAIN_COMMAND_FAILED,
|
|
81
|
-
}
|
|
80
|
+
};
|
|
82
81
|
}
|
|
83
|
-
}
|
|
82
|
+
};
|
|
84
83
|
|
|
85
84
|
if (!certificateFoundInCommandOutput) {
|
|
86
|
-
logger.info(`${UNICODE.INFO} certificate not found in mac keychain`)
|
|
85
|
+
logger.info(`${UNICODE.INFO} certificate not found in mac keychain`);
|
|
87
86
|
if (verb === VERB_CHECK_TRUST || verb === VERB_REMOVE_TRUST) {
|
|
88
87
|
return {
|
|
89
88
|
status: "not_trusted",
|
|
90
89
|
reason: REASON_NOT_IN_KEYCHAIN,
|
|
91
|
-
}
|
|
90
|
+
};
|
|
92
91
|
}
|
|
93
92
|
if (verb === VERB_ENSURE_TRUST) {
|
|
94
93
|
// It seems possible for certificate PEM representation to be different
|
|
95
94
|
// in mackeychain and in the one we have written on the filesystem
|
|
96
95
|
// When it happens the certificate is not found but actually exists on mackeychain
|
|
97
96
|
// and must be deleted first
|
|
98
|
-
await removeCert()
|
|
97
|
+
await removeCert();
|
|
99
98
|
}
|
|
100
|
-
const certificateFilePath = fileURLToPath(certificateFileUrl)
|
|
99
|
+
const certificateFilePath = fileURLToPath(certificateFileUrl);
|
|
101
100
|
// https://ss64.com/osx/security-cert.html
|
|
102
|
-
const addTrustedCertCommand = `sudo security add-trusted-cert -d -r trustRoot -k ${systemKeychainPath} "${certificateFilePath}"
|
|
103
|
-
logger.info(`Adding certificate to mac keychain...`)
|
|
104
|
-
logger.info(`${UNICODE.COMMAND} ${addTrustedCertCommand}`)
|
|
101
|
+
const addTrustedCertCommand = `sudo security add-trusted-cert -d -r trustRoot -k ${systemKeychainPath} "${certificateFilePath}"`;
|
|
102
|
+
logger.info(`Adding certificate to mac keychain...`);
|
|
103
|
+
logger.info(`${UNICODE.COMMAND} ${addTrustedCertCommand}`);
|
|
105
104
|
try {
|
|
106
|
-
await exec(addTrustedCertCommand)
|
|
107
|
-
logger.info(`${UNICODE.OK} certificate added to mac keychain`)
|
|
105
|
+
await exec(addTrustedCertCommand);
|
|
106
|
+
logger.info(`${UNICODE.OK} certificate added to mac keychain`);
|
|
108
107
|
return {
|
|
109
108
|
status: "trusted",
|
|
110
109
|
reason: REASON_ADD_TO_KEYCHAIN_COMMAND_COMPLETED,
|
|
111
|
-
}
|
|
110
|
+
};
|
|
112
111
|
} catch (e) {
|
|
113
112
|
logger.error(
|
|
114
113
|
createDetailedMessage(
|
|
@@ -118,11 +117,11 @@ export const executeTrustQueryOnMacKeychain = async ({
|
|
|
118
117
|
"certificate file": certificateFilePath,
|
|
119
118
|
},
|
|
120
119
|
),
|
|
121
|
-
)
|
|
120
|
+
);
|
|
122
121
|
return {
|
|
123
122
|
status: "not_trusted",
|
|
124
123
|
reason: REASON_ADD_TO_KEYCHAIN_COMMAND_FAILED,
|
|
125
|
-
}
|
|
124
|
+
};
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
127
|
|
|
@@ -130,7 +129,7 @@ export const executeTrustQueryOnMacKeychain = async ({
|
|
|
130
129
|
// people can still manually untrust the root cert
|
|
131
130
|
// but they shouldn't and I couldn't find an API to know if the cert is trusted or not
|
|
132
131
|
// just if it's in the keychain
|
|
133
|
-
logger.info(`${UNICODE.OK} certificate found in mac keychain`)
|
|
132
|
+
logger.info(`${UNICODE.OK} certificate found in mac keychain`);
|
|
134
133
|
if (
|
|
135
134
|
verb === VERB_CHECK_TRUST ||
|
|
136
135
|
verb === VERB_ADD_TRUST ||
|
|
@@ -139,8 +138,8 @@ export const executeTrustQueryOnMacKeychain = async ({
|
|
|
139
138
|
return {
|
|
140
139
|
status: "trusted",
|
|
141
140
|
reason: REASON_IN_KEYCHAIN,
|
|
142
|
-
}
|
|
141
|
+
};
|
|
143
142
|
}
|
|
144
143
|
|
|
145
|
-
return removeCert()
|
|
146
|
-
}
|
|
144
|
+
return removeCert();
|
|
145
|
+
};
|
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
|
|
2
|
+
import { UNICODE } from "@jsenv/humanize";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { commandExists } from "../command.js";
|
|
5
|
+
import { exec } from "../exec.js";
|
|
6
|
+
import { memoize } from "../memoize.js";
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
import { exec } from "../exec.js"
|
|
7
|
-
import { commandExists } from "../command.js"
|
|
8
|
-
|
|
9
|
-
export const nssCommandName = "nss"
|
|
8
|
+
export const nssCommandName = "nss";
|
|
10
9
|
|
|
11
10
|
export const detectIfNSSIsInstalled = async ({ logger }) => {
|
|
12
|
-
logger.debug(`Detecting if nss is installed....`)
|
|
13
|
-
const brewListCommand = `brew list --versions nss
|
|
11
|
+
logger.debug(`Detecting if nss is installed....`);
|
|
12
|
+
const brewListCommand = `brew list --versions nss`;
|
|
14
13
|
|
|
15
14
|
try {
|
|
16
|
-
await exec(brewListCommand)
|
|
17
|
-
logger.debug(`${UNICODE.OK} nss is installed`)
|
|
18
|
-
return true
|
|
19
|
-
} catch
|
|
20
|
-
logger.debug(`${UNICODE.INFO} nss not installed`)
|
|
21
|
-
return false
|
|
15
|
+
await exec(brewListCommand);
|
|
16
|
+
logger.debug(`${UNICODE.OK} nss is installed`);
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
logger.debug(`${UNICODE.INFO} nss not installed`);
|
|
20
|
+
return false;
|
|
22
21
|
}
|
|
23
|
-
}
|
|
22
|
+
};
|
|
24
23
|
|
|
25
24
|
export const getCertutilBinPath = memoize(async () => {
|
|
26
|
-
const brewCommand = `brew --prefix nss
|
|
27
|
-
const brewCommandOutput = await exec(brewCommand)
|
|
25
|
+
const brewCommand = `brew --prefix nss`;
|
|
26
|
+
const brewCommandOutput = await exec(brewCommand);
|
|
28
27
|
const nssCommandDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
29
28
|
brewCommandOutput.trim(),
|
|
30
|
-
)
|
|
31
|
-
const certutilBinUrl = new URL(`./bin/certutil`, nssCommandDirectoryUrl).href
|
|
32
|
-
const certutilBinPath = fileURLToPath(certutilBinUrl)
|
|
33
|
-
return certutilBinPath
|
|
34
|
-
})
|
|
29
|
+
);
|
|
30
|
+
const certutilBinUrl = new URL(`./bin/certutil`, nssCommandDirectoryUrl).href;
|
|
31
|
+
const certutilBinPath = fileURLToPath(certutilBinUrl);
|
|
32
|
+
return certutilBinPath;
|
|
33
|
+
});
|
|
35
34
|
|
|
36
35
|
export const getNSSDynamicInstallInfo = () => {
|
|
37
36
|
return {
|
|
@@ -39,12 +38,12 @@ export const getNSSDynamicInstallInfo = () => {
|
|
|
39
38
|
notInstallableReason: `"brew" is not available`,
|
|
40
39
|
suggestion: `install "brew" on this mac`,
|
|
41
40
|
install: async ({ logger }) => {
|
|
42
|
-
const brewInstallCommand = `brew install nss
|
|
41
|
+
const brewInstallCommand = `brew install nss`;
|
|
43
42
|
logger.info(
|
|
44
43
|
`"nss" is not installed, trying to install "nss" via Homebrew`,
|
|
45
|
-
)
|
|
46
|
-
logger.info(`${UNICODE.COMMAND} ${brewInstallCommand}`)
|
|
47
|
-
await exec(brewInstallCommand)
|
|
44
|
+
);
|
|
45
|
+
logger.info(`${UNICODE.COMMAND} ${brewInstallCommand}`);
|
|
46
|
+
await exec(brewInstallCommand);
|
|
48
47
|
},
|
|
49
|
-
}
|
|
50
|
-
}
|
|
48
|
+
};
|
|
49
|
+
};
|
package/src/internal/memoize.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
export const memoize = (compute) => {
|
|
2
|
-
let memoized = false
|
|
3
|
-
let memoizedValue
|
|
2
|
+
let memoized = false;
|
|
3
|
+
let memoizedValue;
|
|
4
4
|
|
|
5
5
|
const fnWithMemoization = (...args) => {
|
|
6
6
|
if (memoized) {
|
|
7
|
-
return memoizedValue
|
|
7
|
+
return memoizedValue;
|
|
8
8
|
}
|
|
9
9
|
// if compute is recursive wait for it to be fully done before storing the lockValue
|
|
10
10
|
// so set locked later
|
|
11
|
-
memoizedValue = compute(...args)
|
|
12
|
-
memoized = true
|
|
13
|
-
return memoizedValue
|
|
14
|
-
}
|
|
11
|
+
memoizedValue = compute(...args);
|
|
12
|
+
memoized = true;
|
|
13
|
+
return memoizedValue;
|
|
14
|
+
};
|
|
15
15
|
|
|
16
16
|
fnWithMemoization.forget = () => {
|
|
17
|
-
const value = memoizedValue
|
|
18
|
-
memoized = false
|
|
19
|
-
memoizedValue = undefined
|
|
20
|
-
return value
|
|
21
|
-
}
|
|
17
|
+
const value = memoizedValue;
|
|
18
|
+
memoized = false;
|
|
19
|
+
memoizedValue = undefined;
|
|
20
|
+
return value;
|
|
21
|
+
};
|
|
22
22
|
|
|
23
|
-
return fnWithMemoization
|
|
24
|
-
}
|
|
23
|
+
return fnWithMemoization;
|
|
24
|
+
};
|