Created
January 31, 2019 17:13
-
-
Save kroneman/47d379db60011ffb5b2a29ce9920cfc1 to your computer and use it in GitHub Desktop.
mkcert-localhost-certificate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const util = require('util'); | |
const path = require('path'); | |
const exec = util.promisify(require('child_process').exec); | |
/** | |
* Script for obtaining a certificate for local development using | |
* Inspiration https://github.com/Shopify/slate/issues/726#issuecomment-425462689 | |
* @dependencies | |
* - OSx, this script won't work on windows | |
* - Brew, in order to install mkcert (manual process) | |
* https://www.howtogeek.com/211541/homebrew-for-os-x-easily-installs-desktop-apps-and-terminal-utilities/ | |
* - $ brew install mkcert | |
* https://github.com/FiloSottile/mkcert | |
* - $ mkcert -install [installs local certificate authority] | |
* - then run this script | |
*/ | |
/** | |
* Config to run any of the functions in the file directly | |
* @typedef executionConfig | |
* @param {RegularExpression} ipAddressTest | |
* @param {String} outputDirectory | |
* @param {String} [localIpAddress] - by default this is null and will need to be filled to run createCertificate | |
*/ | |
const relativeOutputDir = './.certificates'; | |
const config = { | |
// Test String for contents of ip address | |
// source: https://www.regular-expressions.info/ip.html | |
domain: 'localhost', | |
ipAddressTest: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, | |
outputFileMatch: /"\.\/(\S+?)"/gm, | |
outputDirectory: path.resolve(relativeOutputDir), | |
localIpAddress: null, | |
}; | |
const bashCommands = { | |
getLocalIP: 'ipconfig getifaddr $(route get default | grep interface | awk \'{print $2}\')', | |
makeCertificate: ({dir, ipAddress}) => `cd ${dir} && mkcert localhost ${ipAddress} ::1`, | |
changeDirectory: (dir) => `cd ${dir}`, | |
createDirectory: (dir) => `mkdir ${dir}`, | |
removeDirectory: (dir) => `rm -r ${dir}`, | |
}; | |
// eslint-disable-next-line no-undef | |
module.exports = main; | |
/** | |
* Main execution | |
*/ | |
function main(executionConfig) { | |
return changeToOutputDirectory(executionConfig) | |
.then(getLocalIpAddress) | |
.then(createCertificate) | |
.then(matchOutputFiles) | |
.catch((err) => { | |
// eslint-disable-next-line no-console,no-undef | |
console.error(err); | |
}); | |
} | |
/** | |
* mkcert places certificate into directory the process is run from, | |
* so pogramatically changing directories | |
* @param {executionConfig} executionConfig - see typedef | |
* @returns {Promise<Object>} | |
*/ | |
async function changeToOutputDirectory(executionConfig) { | |
try { | |
// normal flow, try to remove directory, if fails it probably doesn't exist | |
// eslint-disable-next-line no-console,no-undef | |
console.log(`${executionConfig.outputDirectory}: removing directory...`); | |
await exec(bashCommands.removeDirectory(executionConfig.outputDirectory)); | |
// eslint-disable-next-line no-console,no-undef | |
console.log(`${executionConfig.outputDirectory}: creating directory...`); | |
await exec(bashCommands.createDirectory(executionConfig.outputDirectory)); | |
// eslint-disable-next-line no-console,no-undef | |
console.log(`${executionConfig.outputDirectory}: changing into directory...`); | |
await exec(bashCommands.changeDirectory(executionConfig.outputDirectory)); | |
} catch (error) { | |
// eslint-disable-next-line no-console,no-undef | |
console.log(`${executionConfig.outputDirectory}: doesn't exist... creating it`); | |
await exec(bashCommands.createDirectory(executionConfig.outputDirectory)); | |
} | |
return executionConfig; | |
} | |
/** | |
* @param {executionConfig} executionConfig - see typedef | |
* @returns {Promise<string>} empty string if error | |
*/ | |
async function getLocalIpAddress(executionConfig) { | |
const localIpAddress = await exec(bashCommands.getLocalIP); | |
const {stdout, stderr} = localIpAddress; | |
if (stderr && stderr.length > 0) { | |
throw new Error(stderr, ' : is not a valid ip address'); | |
} | |
if (!config.ipAddressTest.test(stdout)) { | |
throw new Error(stdout, ' : is not a valid ip address'); | |
} | |
// remove newlines from stdout | |
return { | |
...executionConfig, | |
localIpAddress: stdout.replace('\n', ''), | |
}; | |
} | |
/** | |
* @param {executionConfig} executionConfig - see typedef | |
* @returns {Promise<string>} empty string if error | |
*/ | |
async function createCertificate(executionConfig) { | |
const makeCertConfig = { | |
dir: executionConfig.outputDirectory, | |
ipAddress: executionConfig.localIpAddress, | |
}; | |
const createCertificateProcess = await exec(bashCommands.makeCertificate(makeCertConfig)); | |
const {stderr} = createCertificateProcess; | |
// For some reason mkcert outputs success using stderr, if that changes re-enable these lines | |
// if (stderr && stderr.length > 0) { | |
// throw new Error(stderr); | |
// } | |
return { | |
...executionConfig, | |
result: stderr, | |
}; | |
} | |
/** | |
* Updates the output with the exact location of the files | |
* @returns { key: String, cert: String} relative locations of the key and certificate to the project | |
*/ | |
function matchOutputFiles(executionConfig) { | |
const filenames = executionConfig.result.match(executionConfig.outputFileMatch); | |
let newResult = executionConfig.result; | |
const returnValue = {}; | |
let lenFileNames = filenames.length; | |
while (lenFileNames--) { | |
const currentFileName = filenames[lenFileNames]; | |
let updatedFilePath = currentFileName.replace('./', ''); | |
updatedFilePath = updatedFilePath.replace(/(")/g, ''); | |
newResult = newResult.replace(currentFileName, `${executionConfig.outputDirectory}/${updatedFilePath} \n`); | |
// eslint-disable-next-line no-negated-condition | |
const isCertKey = updatedFilePath.indexOf('key') !== -1 ? 'key' : 'cert'; | |
returnValue[isCertKey ? 'key' : 'cert'] = updatedFilePath; | |
} | |
// eslint-disable-next-line no-console,no-undef | |
console.log(newResult); | |
return returnValue; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment