Verified Commit 9a683efd authored by Aral Balkan's avatar Aral Balkan
Browse files

Post install now creates/executes shell script to initialise mkcert

parent ef4b6a51
......@@ -99,20 +99,22 @@ process.stdout.write('done.\n')
//
// Create the root certificate authority and certificates.
//
const caCertFilePath = path.join(settingsPath, 'rootCA.pem')
const caKeyFilePath = path.join(settingsPath, 'rootCA-key.pem')
const keyFilePath = path.join(settingsPath, 'localhost-key.pem')
const certFilePath = path.join(settingsPath, 'localhost.pem')
const allOK = () => {
return fs.existsSync(path.join(settingsPath, 'rootCA.pem')) && fs.existsSync(path.join(settingsPath, 'rootCA-key.pem')) && fs.existsSync(path.join(settingsPath, 'localhost.pem')) && fs.existsSync(path.join(settingsPath, 'localhost-key.pem'))
return fs.existsSync(caCertFilePath)
&& fs.existsSync(caKeyFilePath)
&& fs.existsSync(certFilePath)
&& fs.existsSync(keyFilePath)
}
// On Linux and on macOS, mkcert uses the Mozilla nss library.
// Try to install this automatically and warn the person if we can’t so
// that they can do it manually themselves.
process.stdout.write(` ╰─ Installing certutil if necessary… `)
installCertutil()
process.stdout.write('done.\n')
// mkcert uses the CAROOT environment variable to know where to create/find the certificate authority.
// We also pass the rest of the system environment to the spawned processes.
......@@ -122,8 +124,26 @@ const mkcertProcessOptions = {
}
mkcertProcessOptions.env.CAROOT = settingsPath
// Support all local interfaces so that the machine can be reached over the local network via IPv4.
// This is very useful for testing with multiple devices over the local area network without needing to expose
// the machine over the wide area network/Internet using a service like ngrok.
const localIPv4Addresses =
Object.entries(os.networkInterfaces())
.map(iface =>
iface[1].filter(addresses =>
addresses.family === 'IPv4')
.map(addresses => addresses.address)).flat()
const certificateDetails = [
`-key-file=${keyFilePath}`,
`-cert-file=${certFilePath}`,
'localhost'
].concat(localIPv4Addresses).join(' ')
const account = os.userInfo().username
// Create the local certificate authority.
process.stdout.write(` ╰─ Creating local certificate authority (local CA) using mkcert… `)
process.stdout.write(` ╰─ Initialising mkcert… `)
// We are using the sudo-prompt package here, instead of childProcess.execFileSync() because
// this script is meant to run as an npm script and it appears that npm scripts fail to show
......@@ -133,10 +153,34 @@ process.stdout.write(` ╰─ Creating local certificate authority (local CA)
//
// To workaround this issue, we use sudo-prompt here to display a graphical sudo prompt
// that works well with npm scripts.
//
// Since on macOS the certificate files are created with root permissions, we need to set
// files back to regular account permissions afterwards (this is not an issue on Linux
// where the files are created with regular account permissions even when the mkcert command
// is launched using sudo). In any case, because of this, and because we want the person
// to only enter their password once instead of multiple times, once for each command
// (due to how sudo-prompt works), we first create a shell script and then we execute that.
//
// TODO: Figure out what to do for Windows.
const shellScriptTemplate = `#!/bin/bash
set -e
# Install mkcert and create the certificate authority
${mkcertBinary} -install
# Create the certificates
${mkcertBinary} ${certificateDetails}
# Reset file permissions to regular account
chown -R ${account} ${settingsPath}
`
fs.writeFileSync('/tmp/install-mkcert.sh', shellScriptTemplate, {mode: 0o755})
await (() => {
return new Promise((resolve, reject) => {
sudoPrompt.exec(`${mkcertBinary} -install`, {name: 'Auto Encrypt Localhost'}, function(error, stdout, stderr) {
sudoPrompt.exec(`/tmp/install-mkcert.sh`, {name: 'Auto Encrypt Localhost'}, function(error, stdout, stderr) {
if (error) reject(error)
resolve()
})
......@@ -145,30 +189,6 @@ await (() => {
process.stdout.write('done.\n')
// Create the local certificate.
process.stdout.write(' ╰─ Creating local TLS certificates using mkcert… ')
// Support all local interfaces so that the machine can be reached over the local network via IPv4.
// This is very useful for testing with multiple devices over the local area network without needing to expose
// the machine over the wide area network/Internet using a service like ngrok.
const localIPv4Addresses =
Object.entries(os.networkInterfaces())
.map(iface =>
iface[1].filter(addresses =>
addresses.family === 'IPv4')
.map(addresses => addresses.address)).flat()
const certificateDetails = [
`-key-file=${keyFilePath}`,
`-cert-file=${certFilePath}`,
'localhost'
].concat(localIPv4Addresses)
// We can use a regular execFileSync call here as the sudo permissions will not have timed out yet.
childProcess.execFileSync(mkcertBinary, certificateDetails, mkcertProcessOptions)
process.stdout.write('done.\n')
// This should never happen as an error in the above, if there is one,
// should exit the process, but just in case.
if (!allOK()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment