@jsenv/https-local 3.0.7 → 3.1.1

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.
Files changed (46) hide show
  1. package/README.md +160 -192
  2. package/package.json +10 -30
  3. package/src/certificate_authority.js +111 -110
  4. package/src/certificate_request.js +37 -36
  5. package/src/hosts_file_verif.js +34 -35
  6. package/src/https_local_cli.mjs +74 -0
  7. package/src/internal/authority_file_infos.js +12 -13
  8. package/src/internal/browser_detection.js +4 -4
  9. package/src/internal/certificate_authority_file_urls.js +23 -23
  10. package/src/internal/certificate_data_converter.js +39 -39
  11. package/src/internal/certificate_generator.js +39 -39
  12. package/src/internal/command.js +6 -6
  13. package/src/internal/exec.js +10 -10
  14. package/src/internal/forge.js +3 -3
  15. package/src/internal/hosts/hosts_utils.js +2 -2
  16. package/src/internal/hosts/parse_hosts.js +67 -66
  17. package/src/internal/hosts/read_hosts.js +5 -6
  18. package/src/internal/hosts/write_hosts.js +29 -31
  19. package/src/internal/hosts/write_line_hosts.js +30 -32
  20. package/src/internal/hosts.js +5 -5
  21. package/src/internal/linux/chrome_linux.js +19 -20
  22. package/src/internal/linux/firefox_linux.js +19 -20
  23. package/src/internal/linux/linux.js +8 -8
  24. package/src/internal/linux/linux_trust_store.js +58 -59
  25. package/src/internal/linux/nss_linux.js +20 -21
  26. package/src/internal/mac/chrome_mac.js +15 -16
  27. package/src/internal/mac/firefox_mac.js +20 -21
  28. package/src/internal/mac/mac.js +10 -10
  29. package/src/internal/mac/mac_keychain.js +46 -47
  30. package/src/internal/mac/nss_mac.js +29 -30
  31. package/src/internal/mac/safari.js +2 -2
  32. package/src/internal/memoize.js +14 -14
  33. package/src/internal/nssdb_browser.js +150 -145
  34. package/src/internal/platform.js +6 -6
  35. package/src/internal/search_certificate_in_command_output.js +4 -4
  36. package/src/internal/trust_query.js +4 -4
  37. package/src/internal/unsupported_platform/unsupported_platform.js +5 -5
  38. package/src/internal/validity_formatting.js +32 -32
  39. package/src/internal/windows/chrome_windows.js +26 -27
  40. package/src/internal/windows/edge.js +2 -2
  41. package/src/internal/windows/firefox_windows.js +31 -32
  42. package/src/internal/windows/windows.js +10 -10
  43. package/src/internal/windows/windows_certutil.js +41 -42
  44. package/src/jsenvParameters.js +2 -2
  45. package/src/main.js +5 -8
  46. package/src/validity_duration.js +12 -12
@@ -1,6 +1,6 @@
1
- import { executeTrustQueryOnLinux } from "./linux_trust_store.js"
2
- import { executeTrustQueryOnChrome } from "./chrome_linux.js"
3
- import { executeTrustQueryOnFirefox } from "./firefox_linux.js"
1
+ import { executeTrustQueryOnChrome } from "./chrome_linux.js";
2
+ import { executeTrustQueryOnFirefox } from "./firefox_linux.js";
3
+ import { executeTrustQueryOnLinux } from "./linux_trust_store.js";
4
4
 
5
5
  export const executeTrustQuery = async ({
6
6
  logger,
@@ -18,7 +18,7 @@ export const executeTrustQuery = async ({
18
18
  certificateIsNew,
19
19
  certificate,
20
20
  verb,
21
- })
21
+ });
22
22
 
23
23
  const chromeTrustInfo = await executeTrustQueryOnChrome({
24
24
  logger,
@@ -28,7 +28,7 @@ export const executeTrustQuery = async ({
28
28
  certificate,
29
29
  verb,
30
30
  NSSDynamicInstall,
31
- })
31
+ });
32
32
 
33
33
  const firefoxTrustInfo = await executeTrustQueryOnFirefox({
34
34
  logger,
@@ -38,11 +38,11 @@ export const executeTrustQuery = async ({
38
38
  certificate,
39
39
  verb,
40
40
  NSSDynamicInstall,
41
- })
41
+ });
42
42
 
43
43
  return {
44
44
  linux: linuxTrustInfo,
45
45
  chrome: chromeTrustInfo,
46
46
  firefox: firefoxTrustInfo,
47
- }
48
- }
47
+ };
48
+ };
@@ -2,34 +2,33 @@
2
2
  * see https://github.com/davewasmer/devcert/blob/master/src/platforms/linux.ts
3
3
  */
4
4
 
5
- import { existsSync } from "node:fs"
6
- import { fileURLToPath } from "node:url"
7
- import { readFile } from "@jsenv/filesystem"
8
- import { createDetailedMessage, UNICODE } from "@jsenv/log"
9
-
5
+ import { readFile } from "@jsenv/filesystem";
6
+ import { createDetailedMessage, UNICODE } from "@jsenv/humanize";
7
+ import { existsSync } from "node:fs";
8
+ import { fileURLToPath } from "node:url";
9
+ import { exec } from "../exec.js";
10
10
  import {
11
- VERB_CHECK_TRUST,
12
11
  VERB_ADD_TRUST,
12
+ VERB_CHECK_TRUST,
13
13
  VERB_ENSURE_TRUST,
14
14
  VERB_REMOVE_TRUST,
15
- } from "../trust_query.js"
16
- import { exec } from "../exec.js"
15
+ } from "../trust_query.js";
17
16
 
18
17
  const REASON_NEW_AND_TRY_TO_TRUST_DISABLED =
19
- "certificate is new and tryToTrust is disabled"
20
- const REASON_NOT_FOUND_IN_LINUX = `not found in linux store`
21
- const REASON_OUTDATED_IN_LINUX = "certificate in linux store is outdated"
22
- const REASON_FOUND_IN_LINUX = "found in linux store"
23
- const REASON_ADD_COMMAND_FAILED = "command to add certificate to linux failed"
18
+ "certificate is new and tryToTrust is disabled";
19
+ const REASON_NOT_FOUND_IN_LINUX = `not found in linux store`;
20
+ const REASON_OUTDATED_IN_LINUX = "certificate in linux store is outdated";
21
+ const REASON_FOUND_IN_LINUX = "found in linux store";
22
+ const REASON_ADD_COMMAND_FAILED = "command to add certificate to linux failed";
24
23
  const REASON_ADD_COMMAND_COMPLETED =
25
- "command to add certificate to linux completed"
24
+ "command to add certificate to linux completed";
26
25
  const REASON_REMOVE_COMMAND_FAILED =
27
- "command to remove certificate from linux failed"
26
+ "command to remove certificate from linux failed";
28
27
  const REASON_REMOVE_COMMAND_COMPLETED =
29
- "command to remove certificate from linux completed"
28
+ "command to remove certificate from linux completed";
30
29
 
31
- const LINUX_CERTIFICATE_AUTHORITIES_DIRECTORY_PATH = `/usr/local/share/ca-certificates/`
32
- const JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH = `${LINUX_CERTIFICATE_AUTHORITIES_DIRECTORY_PATH}https_local_root_certificate.crt`
30
+ const LINUX_CERTIFICATE_AUTHORITIES_DIRECTORY_PATH = `/usr/local/share/ca-certificates/`;
31
+ const JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH = `${LINUX_CERTIFICATE_AUTHORITIES_DIRECTORY_PATH}https_local_root_certificate.crt`;
33
32
 
34
33
  export const executeTrustQueryOnLinux = async ({
35
34
  logger,
@@ -40,25 +39,25 @@ export const executeTrustQueryOnLinux = async ({
40
39
  verb,
41
40
  }) => {
42
41
  if (verb === VERB_CHECK_TRUST && certificateIsNew) {
43
- logger.info(`${UNICODE.INFO} You should add certificate to linux`)
42
+ logger.info(`${UNICODE.INFO} You should add certificate to linux`);
44
43
  return {
45
44
  status: "not_trusted",
46
45
  reason: REASON_NEW_AND_TRY_TO_TRUST_DISABLED,
47
- }
46
+ };
48
47
  }
49
48
 
50
- logger.info(`Check if certificate is in linux...`)
49
+ logger.info(`Check if certificate is in linux...`);
51
50
  logger.debug(
52
51
  `Searching certificate file at ${JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH}...`,
53
- )
54
- const certificateFilePath = fileURLToPath(certificateFileUrl)
55
- const certificateStatus = await getCertificateStatus({ certificate })
52
+ );
53
+ const certificateFilePath = fileURLToPath(certificateFileUrl);
54
+ const certificateStatus = await getCertificateStatus({ certificate });
56
55
 
57
56
  if (certificateStatus === "missing" || certificateStatus === "outdated") {
58
57
  if (certificateStatus === "missing") {
59
- logger.info(`${UNICODE.INFO} certificate not in linux`)
58
+ logger.info(`${UNICODE.INFO} certificate not in linux`);
60
59
  } else {
61
- logger.info(`${UNICODE.INFO} certificate in linux is outdated`)
60
+ logger.info(`${UNICODE.INFO} certificate in linux is outdated`);
62
61
  }
63
62
  if (verb === VERB_CHECK_TRUST || verb === VERB_REMOVE_TRUST) {
64
63
  return {
@@ -67,24 +66,24 @@ export const executeTrustQueryOnLinux = async ({
67
66
  certificateStatus === "missing"
68
67
  ? REASON_NOT_FOUND_IN_LINUX
69
68
  : REASON_OUTDATED_IN_LINUX,
70
- }
69
+ };
71
70
  }
72
71
 
73
- const copyCertificateCommand = `sudo /bin/cp -f "${certificateFilePath}" ${JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH}`
74
- const updateCertificateCommand = `sudo update-ca-certificates`
75
- logger.info(`Adding certificate to linux...`)
72
+ const copyCertificateCommand = `sudo /bin/cp -f "${certificateFilePath}" ${JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH}`;
73
+ const updateCertificateCommand = `sudo update-ca-certificates`;
74
+ logger.info(`Adding certificate to linux...`);
76
75
  try {
77
- logger.info(`${UNICODE.COMMAND} ${copyCertificateCommand}`)
78
- await exec(copyCertificateCommand)
79
- logger.info(`${UNICODE.COMMAND} ${updateCertificateCommand}`)
80
- await exec(updateCertificateCommand)
81
- logger.info(`${UNICODE.OK} certificate added to linux`)
76
+ logger.info(`${UNICODE.COMMAND} ${copyCertificateCommand}`);
77
+ await exec(copyCertificateCommand);
78
+ logger.info(`${UNICODE.COMMAND} ${updateCertificateCommand}`);
79
+ await exec(updateCertificateCommand);
80
+ logger.info(`${UNICODE.OK} certificate added to linux`);
82
81
  return {
83
82
  status: "trusted",
84
83
  reason: REASON_ADD_COMMAND_COMPLETED,
85
- }
84
+ };
86
85
  } catch (e) {
87
- console.error(e)
86
+ console.error(e);
88
87
  logger.error(
89
88
  createDetailedMessage(
90
89
  `${UNICODE.FAILURE} failed to add certificate to linux`,
@@ -92,15 +91,15 @@ export const executeTrustQueryOnLinux = async ({
92
91
  "certificate file": certificateFilePath,
93
92
  },
94
93
  ),
95
- )
94
+ );
96
95
  return {
97
96
  status: "not_trusted",
98
97
  reason: REASON_ADD_COMMAND_FAILED,
99
- }
98
+ };
100
99
  }
101
100
  }
102
101
 
103
- logger.info(`${UNICODE.OK} certificate found in linux`)
102
+ logger.info(`${UNICODE.OK} certificate found in linux`);
104
103
  if (
105
104
  verb === VERB_CHECK_TRUST ||
106
105
  verb === VERB_ADD_TRUST ||
@@ -109,22 +108,22 @@ export const executeTrustQueryOnLinux = async ({
109
108
  return {
110
109
  status: "trusted",
111
110
  reason: REASON_FOUND_IN_LINUX,
112
- }
111
+ };
113
112
  }
114
113
 
115
- logger.info(`Removing certificate from linux...`)
116
- const removeCertificateCommand = `sudo rm ${JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH}`
117
- const updateCertificateCommand = `sudo update-ca-certificates`
114
+ logger.info(`Removing certificate from linux...`);
115
+ const removeCertificateCommand = `sudo rm ${JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH}`;
116
+ const updateCertificateCommand = `sudo update-ca-certificates`;
118
117
  try {
119
- logger.info(`${UNICODE.COMMAND} ${removeCertificateCommand}`)
120
- await exec(removeCertificateCommand)
121
- logger.info(`${UNICODE.COMMAND} ${updateCertificateCommand}`)
122
- await exec(updateCertificateCommand)
123
- logger.info(`${UNICODE.OK} certificate removed from linux`)
118
+ logger.info(`${UNICODE.COMMAND} ${removeCertificateCommand}`);
119
+ await exec(removeCertificateCommand);
120
+ logger.info(`${UNICODE.COMMAND} ${updateCertificateCommand}`);
121
+ await exec(updateCertificateCommand);
122
+ logger.info(`${UNICODE.OK} certificate removed from linux`);
124
123
  return {
125
124
  status: "not_trusted",
126
125
  reason: REASON_REMOVE_COMMAND_COMPLETED,
127
- }
126
+ };
128
127
  } catch (e) {
129
128
  logger.error(
130
129
  createDetailedMessage(
@@ -134,25 +133,25 @@ export const executeTrustQueryOnLinux = async ({
134
133
  "certificate file": JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH,
135
134
  },
136
135
  ),
137
- )
136
+ );
138
137
  return {
139
138
  status: "unknown",
140
139
  reason: REASON_REMOVE_COMMAND_FAILED,
141
- }
140
+ };
142
141
  }
143
- }
142
+ };
144
143
 
145
144
  const getCertificateStatus = async ({ certificate }) => {
146
- const certificateInStore = existsSync(JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH)
145
+ const certificateInStore = existsSync(JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH);
147
146
  if (!certificateInStore) {
148
- return "missing"
147
+ return "missing";
149
148
  }
150
149
  const certificateInLinuxStore = await readFile(
151
150
  JSENV_AUTHORITY_ROOT_CERTIFICATE_PATH,
152
151
  { as: "string" },
153
- )
152
+ );
154
153
  if (certificateInLinuxStore !== certificate) {
155
- return "outdated"
154
+ return "outdated";
156
155
  }
157
- return "found"
158
- }
156
+ return "found";
157
+ };
@@ -1,40 +1,39 @@
1
1
  // https://github.com/FiloSottile/mkcert/issues/447
2
2
 
3
- import { UNICODE } from "@jsenv/log"
3
+ import { UNICODE } from "@jsenv/humanize";
4
+ import { exec } from "../exec.js";
5
+ import { memoize } from "../memoize.js";
4
6
 
5
- import { memoize } from "../memoize.js"
6
- import { exec } from "../exec.js"
7
-
8
- export const nssCommandName = "libnss3-tools"
7
+ export const nssCommandName = "libnss3-tools";
9
8
 
10
9
  export const detectIfNSSIsInstalled = memoize(async ({ logger }) => {
11
- logger.debug(`Detect if nss installed....`)
10
+ logger.debug(`Detect if nss installed....`);
12
11
 
13
- const aptCommand = `apt list libnss3-tools --installed`
14
- logger.debug(`${UNICODE.COMMAND} ${aptCommand}`)
15
- const aptCommandOutput = await exec(aptCommand)
12
+ const aptCommand = `apt list libnss3-tools --installed`;
13
+ logger.debug(`${UNICODE.COMMAND} ${aptCommand}`);
14
+ const aptCommandOutput = await exec(aptCommand);
16
15
 
17
16
  if (aptCommandOutput.includes("libnss3-tools")) {
18
- logger.debug(`${UNICODE.OK} libnss3-tools is installed`)
19
- return true
17
+ logger.debug(`${UNICODE.OK} libnss3-tools is installed`);
18
+ return true;
20
19
  }
21
20
 
22
- logger.debug(`${UNICODE.INFO} libnss3-tools not installed`)
23
- return false
24
- })
21
+ logger.debug(`${UNICODE.INFO} libnss3-tools not installed`);
22
+ return false;
23
+ });
25
24
 
26
- export const getCertutilBinPath = () => "certutil"
25
+ export const getCertutilBinPath = () => "certutil";
27
26
 
28
27
  export const getNSSDynamicInstallInfo = ({ logger }) => {
29
28
  return {
30
29
  isInstallable: true,
31
30
  install: async () => {
32
- const aptInstallCommand = `sudo apt install libnss3-tools`
31
+ const aptInstallCommand = `sudo apt install libnss3-tools`;
33
32
  logger.info(
34
33
  `"libnss3-tools" is not installed, trying to install "libnss3-tools"`,
35
- )
36
- logger.info(`${UNICODE.COMMAND} ${aptInstallCommand}`)
37
- await exec(aptInstallCommand)
34
+ );
35
+ logger.info(`${UNICODE.COMMAND} ${aptInstallCommand}`);
36
+ await exec(aptInstallCommand);
38
37
  },
39
- }
40
- }
38
+ };
39
+ };
@@ -1,34 +1,33 @@
1
- import { existsSync } from "node:fs"
2
- import { UNICODE } from "@jsenv/log"
1
+ import { UNICODE } from "@jsenv/humanize";
2
+ import { existsSync } from "node:fs";
3
+ import { memoize } from "../memoize.js";
3
4
 
4
- import { memoize } from "../memoize.js"
5
-
6
- const REASON_CHROME_NOT_DETECTED = `Chrome not detected`
5
+ const REASON_CHROME_NOT_DETECTED = `Chrome not detected`;
7
6
 
8
7
  export const executeTrustQueryOnChrome = ({ logger, macTrustInfo }) => {
9
- const chromeDetected = detectChrome({ logger })
8
+ const chromeDetected = detectChrome({ logger });
10
9
  if (!chromeDetected) {
11
10
  return {
12
11
  status: "other",
13
12
  reason: REASON_CHROME_NOT_DETECTED,
14
- }
13
+ };
15
14
  }
16
15
 
17
16
  return {
18
17
  status: macTrustInfo.status,
19
18
  reason: macTrustInfo.reason,
20
- }
21
- }
19
+ };
20
+ };
22
21
 
23
22
  const detectChrome = memoize(({ logger }) => {
24
- logger.debug(`Detecting Chrome...`)
25
- const chromeDetected = existsSync("/Applications/Google Chrome.app")
23
+ logger.debug(`Detecting Chrome...`);
24
+ const chromeDetected = existsSync("/Applications/Google Chrome.app");
26
25
 
27
26
  if (chromeDetected) {
28
- logger.debug(`${UNICODE.OK} Chrome detected`)
29
- return true
27
+ logger.debug(`${UNICODE.OK} Chrome detected`);
28
+ return true;
30
29
  }
31
30
 
32
- logger.debug(`${UNICODE.INFO} Chrome not detected`)
33
- return false
34
- })
31
+ logger.debug(`${UNICODE.INFO} Chrome not detected`);
32
+ return false;
33
+ });
@@ -1,14 +1,13 @@
1
- import { execSync } from "node:child_process"
2
- import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
3
- import { UNICODE, createTaskLog } from "@jsenv/log"
4
-
5
- import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js"
1
+ import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
2
+ import { UNICODE, createTaskLog } from "@jsenv/humanize";
3
+ import { execSync } from "node:child_process";
4
+ import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js";
6
5
  import {
7
- nssCommandName,
8
6
  detectIfNSSIsInstalled,
9
7
  getCertutilBinPath,
10
8
  getNSSDynamicInstallInfo,
11
- } from "./nss_mac.js"
9
+ nssCommandName,
10
+ } from "./nss_mac.js";
12
11
 
13
12
  export const executeTrustQueryOnFirefox = ({
14
13
  logger,
@@ -48,31 +47,31 @@ export const executeTrustQueryOnFirefox = ({
48
47
  ],
49
48
  getBrowserClosedPromise: async () => {
50
49
  if (!isFirefoxOpen()) {
51
- return
50
+ return;
52
51
  }
53
52
 
54
53
  logger.warn(
55
54
  `${UNICODE.WARNING} firefox is running, it must be stopped before resuming...`,
56
- )
57
- const closeFirefoxTask = createTaskLog("waiting for firefox to close")
55
+ );
56
+ const closeFirefoxTask = createTaskLog("waiting for firefox to close");
58
57
  const next = async () => {
59
- await new Promise((resolve) => setTimeout(resolve, 50))
58
+ await new Promise((resolve) => setTimeout(resolve, 50));
60
59
  if (isFirefoxOpen()) {
61
- await next()
60
+ await next();
62
61
  } else {
63
- closeFirefoxTask.done()
62
+ closeFirefoxTask.done();
64
63
  // wait 50ms more to ensure firefox has time to cleanup
65
64
  // othrwise sometimes there is an SEC_ERROR_REUSED_ISSUER_AND_SERIAL error
66
65
  // because we updated nss database file while firefox is not fully closed
67
- await new Promise((resolve) => setTimeout(resolve, 50))
66
+ await new Promise((resolve) => setTimeout(resolve, 50));
68
67
  }
69
- }
70
- await next()
68
+ };
69
+ await next();
71
70
  },
72
- })
73
- }
71
+ });
72
+ };
74
73
 
75
74
  const isFirefoxOpen = () => {
76
- const psAux = execSync("ps aux")
77
- return psAux.includes("Firefox.app")
78
- }
75
+ const psAux = execSync("ps aux");
76
+ return psAux.includes("Firefox.app");
77
+ };
@@ -4,10 +4,10 @@
4
4
  * - https://www.unix.com/man-page/mojave/1/security/
5
5
  */
6
6
 
7
- import { executeTrustQueryOnMacKeychain } from "./mac_keychain.js"
8
- import { executeTrustQueryOnChrome } from "./chrome_mac.js"
9
- import { executeTrustQueryOnFirefox } from "./firefox_mac.js"
10
- import { executeTrustQueryOnSafari } from "./safari.js"
7
+ import { executeTrustQueryOnChrome } from "./chrome_mac.js";
8
+ import { executeTrustQueryOnFirefox } from "./firefox_mac.js";
9
+ import { executeTrustQueryOnMacKeychain } from "./mac_keychain.js";
10
+ import { executeTrustQueryOnSafari } from "./safari.js";
11
11
 
12
12
  export const executeTrustQuery = async ({
13
13
  logger,
@@ -25,13 +25,13 @@ export const executeTrustQuery = async ({
25
25
  certificateIsNew,
26
26
  certificate,
27
27
  verb,
28
- })
28
+ });
29
29
 
30
30
  const chromeTrustInfo = await executeTrustQueryOnChrome({
31
31
  logger,
32
32
  // chrome needs macTrustInfo because it uses OS trust store
33
33
  macTrustInfo,
34
- })
34
+ });
35
35
 
36
36
  const firefoxTrustInfo = await executeTrustQueryOnFirefox({
37
37
  logger,
@@ -41,18 +41,18 @@ export const executeTrustQuery = async ({
41
41
  certificate,
42
42
  verb,
43
43
  NSSDynamicInstall,
44
- })
44
+ });
45
45
 
46
46
  const safariTrustInfo = await executeTrustQueryOnSafari({
47
47
  logger,
48
48
  // safari needs macTrustInfo because it uses OS trust store
49
49
  macTrustInfo,
50
- })
50
+ });
51
51
 
52
52
  return {
53
53
  mac: macTrustInfo,
54
54
  chrome: chromeTrustInfo,
55
55
  firefox: firefoxTrustInfo,
56
56
  safari: safariTrustInfo,
57
- }
58
- }
57
+ };
58
+ };
@@ -1,31 +1,30 @@
1
1
  // https://ss64.com/osx/security.html
2
2
 
3
- import { fileURLToPath } from "node:url"
4
- import { createDetailedMessage, UNICODE } from "@jsenv/log"
5
-
6
- import { exec } from "../exec.js"
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
+ };