Verified Commit 31611b2c authored by Aral Balkan's avatar Aral Balkan
Browse files

Upgdate log format to match Site.js and remove debug output

parent 5c834f85
......@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased (work is currently in progress on 1.0.0)
## Unreleased
Nothing yet.
## [1.0.1] - 2020-06-15
### Changed
- Update log format to match Site.js output.
### Fixed
- Remove debug output.
## [1.0.0] - 2020-04-15
Initial release.
......@@ -39,8 +39,6 @@ const server = AutoEncrypt.https.createServer(options, (request, response) => {
response.end('Hello, world!')
})
console.log(AutoEncrypt)
server.listen(443, () => {
console.log(`\n ✨ “Hello, world!” server is running…\n`)
console.log(server.address())
......
......@@ -152,7 +152,7 @@ class AutoEncrypt {
function sniError (symbolName, callback, emoji, ...args) {
const error = Symbol.for(symbolName)
log(` ${emoji} [@small-tech/auto-connect] ${throws.errors[error](...args)}`)
log(` ${emoji} ❨auto-encrypt❩ ${throws.errors[error](...args)}`)
callback(throws.createError(error, ...args))
}
......
......@@ -15,7 +15,6 @@
////////////////////////////////////////////////////////////////////////////////
const fs = require('fs-extra')
const log = require('./util/log')
const Throws = require('./util/Throws')
const NewAccountRequest = require('./acme-requests/NewAccountRequest')
......@@ -60,7 +59,6 @@ class Account {
this.data = await (new NewAccountRequest()).execute()
fs.writeFileSync(accountPath, JSON.stringify(this.data), 'utf-8')
}
log('Account', this.data)
}
// TODO: throw error if Account has not been initialised instead of crashing in getter below.
......
......@@ -125,7 +125,7 @@ class AcmeRequest {
// According to RFC 8555 § 6.5, a bad nonce error should result in retry attempt.
if (error.status === 400 && error.type === 'urn:ietf:params:acme:error:badNonce') {
log(' 🔄 [Auto Encrypt] Server returned a bad nonce error. Retrying with provided nonce. (RFC 8555 § 6.5)')
log(' 🔄 ❨auto-encrypt Server returned a bad nonce error. Retrying with provided nonce. (RFC 8555 § 6.5)')
const serverProvidedNonce = errorHeaders['replay-nonce']
// Take the original request details (arguments array passed to the prepare() method) and
......
......@@ -56,7 +56,6 @@ class Authorisation extends EventEmitter {
async init () {
try {
this.data = await (new AuthorisationRequest()).execute(this.authorisationUrl)
log('Authorisation', this.data)
this.authorisation = this.data.body
} catch (error) {
// TODO: Handle the error.
......@@ -73,7 +72,7 @@ class Authorisation extends EventEmitter {
// then decided to provision a certificate for ar.al and www.ar.al. The authorisation for ar.al will still be
// valid until the expiry period.
if (this.authorisation.status === 'valid') {
log(` 💗 Authorisation was previously validated and is still valid.`)
log(` 💗 ❨auto-encrypt❩ Authorisation was previously validated and is still valid.`)
return true
}
......@@ -93,7 +92,7 @@ class Authorisation extends EventEmitter {
if (request.url === `/.well-known/acme-challenge/${this.challenge.token}`) {
// OK, this is the authorisation we’re being pinged for by the Let’s Encrypt servers.
// Respond with the response it expects according to RFC 8555 § 8.1 (Key Authorizations)
log(` 👍 Responding to ACME authorisation request for ${this.domain}`)
log(` 👍 ❨auto-encrypt❩ Responding to ACME authorisation request for ${this.domain}`)
// TODO: We should validate (as much as possible) that this is actually coming from Let’s
// ===== Encrypt’s servers.
......@@ -143,7 +142,7 @@ class Authorisation extends EventEmitter {
this.alreadyPollingForValidationState = true
log(` 🧐 Starting to poll for authorisation state for domain ${this.domain}…`)
log(` 🧐 ❨auto-encrypt❩ Starting to poll for authorisation state for domain ${this.domain}…`)
// Note: while this is an async function, we are not awaiting the result
// ===== here. Our goal is to simply trigger the start of polling. We do
......@@ -153,12 +152,12 @@ class Authorisation extends EventEmitter {
async pollForValidationState () {
log(` 👋 Polling for authorisation state for domain ${this.domain}…`)
log(` 👋 ❨auto-encrypt❩ Polling for authorisation state for domain ${this.domain}…`)
const result = await (new AuthorisationRequest()).execute(this.authorisationUrl)
if (result.body.status === 'valid') {
log(` 🎉 Authorisation validated for domain ${this.domain}`)
log(` 🎉 ❨auto-encrypt❩ Authorisation validated for domain ${this.domain}`)
this.emit(Authorisation.VALIDATED)
return
} else {
......@@ -171,7 +170,7 @@ class Authorisation extends EventEmitter {
retryAfterHeader = parseInt(retryAfterHeader)
}
log(` Authorisation not valid yet for domain ${this.domain}. Waiting to check again in ${pollingDuration/1000} second${pollingDuration === 1000 ? '' : 's'}…`)
log(` ⌚ ❨auto-encrypt❩ Authorisation not valid yet for domain ${this.domain}. Waiting to check again in ${pollingDuration/1000} second${pollingDuration === 1000 ? '' : 's'}…`)
await waitFor(pollingDuration)
await this.pollForValidationState()
......
......@@ -63,10 +63,10 @@ class Certificate {
this.pem = fs.readFileSync(this.#configuration.certificatePath, 'utf-8')
this.identity = new CertificateIdentity(this.#configuration)
log(' 📃 Certificate exists, loaded it (and the corresponding private key) from disk.')
log(' 📃 ❨auto-encrypt❩ Certificate exists, loaded it (and the corresponding private key) from disk.')
this.startCheckingForRenewal(/* alsoCheckNow = */ true)
} else {
log(' 📃 Certificate does not exist; will be provisioned on first hit of the server.')
log(' 📃 ❨auto-encrypt❩ Certificate does not exist; will be provisioned on first hit of the server.')
}
}
......@@ -118,7 +118,7 @@ class Certificate {
this.#_issueDate = moment(details.issuedAt)
this.#_expiryDate = moment(details.expiresAt)
log(` 📆 Certificate set. Serial #: ${details.serialNumber} Issuer: ${details.issuer} Subject: ${details.subject}. Alternative names: ${details.alternativeNames}. Issued ${this.issueDate.calendar().toLowerCase()} (${this.issueDate.fromNow()}) and expires ${this.expiryDate.calendar().toLowerCase()} (${this.expiryDate.fromNow()}).`)
log(` 📆 ❨auto-encrypt❩ Certificate set. Serial #: ${details.serialNumber} Issuer: ${details.issuer} Subject: ${details.subject}. Alternative names: ${details.alternativeNames}. Issued ${this.issueDate.calendar().toLowerCase()} (${this.issueDate.fromNow()}) and expires ${this.expiryDate.calendar().toLowerCase()} (${this.expiryDate.fromNow()}).`)
}
set identity (certificateIdentity) {
......@@ -149,22 +149,22 @@ class Certificate {
const certificatePath = this.#configuration.certificatePath
if (fs.existsSync(oldCertificateIdentityPath) && fs.existsSync(oldCertificatePath)) {
log(' 🚑 [Auto Correct] Warning: Failed renewal attempt detected. Old certificate files found. Attempting to recover…')
log(' 🚑 ❨auto-encrypt❩ Warning: Failed renewal attempt detected. Old certificate files found. Attempting to recover…')
// Edge case: check if the process succeeded (perhaps the power went out right after the certificate was
// written but before we had a chance to clean up the old files.)
if (fs.existsSync(certificateIdentityPath) && fs.existsSync(certificatePath)) {
log(' 🚑 [Auto Correct] A new certificate was also found. Going to delete the old one and use that.')
log(' 🚑 ❨auto-encrypt❩ A new certificate was also found. Going to delete the old one and use that.')
fs.removeSync(oldCertificateIdentityPath)
fs.removeSync(oldCertificatePath)
} else {
// The renewal process must have failed. Delete any previous state and restore the old certificate.
log(' 🚑 [Auto Correct] Cleaning up previous state and restoring old certificate…')
log(' 🚑 ❨auto-encrypt❩ Cleaning up previous state and restoring old certificate…')
fs.removeSync(certificateIdentityPath)
fs.removeSync(certificatePath)
fs.renameSync(oldCertificateIdentityPath, certificateIdentityPath)
fs.renameSync(oldCertificatePath, certificatePath)
}
log(' 🚑 [Auto Correct] Recovery attempt complete.')
log(' 🚑 ❨auto-encrypt❩ Recovery attempt complete.')
}
}
......@@ -222,7 +222,7 @@ class Certificate {
* @returns {Promise} Fulfils once a certificate has been provisioned.
*/
async provisionCertificate () {
log(` 🤖 [Auto Encrypt] Provisioning Let’s Encrypt certificates for ${this.#domains}.`)
log(` 🤖 ❨auto-encrypt Provisioning Let’s Encrypt certificates for ${this.#domains}.`)
// Create a new order.
const order = await Order.getInstanceAsync(this.#configuration, this.#accountIdentity)
......@@ -234,7 +234,7 @@ class Certificate {
// Start checking for renewal updates, every day, starting tomorrow.
this.startCheckingForRenewal(/* alsoCheckNow = */ false)
log(` 🤖🎉 Auto Encrypt: successfully provisioned Let’s Encrypt certificate for ${this.#domains}.`)
log(` 🎉 ❨auto-encrypt successfully provisioned Let’s Encrypt certificate for ${this.#domains}.`)
}
/**
......@@ -252,7 +252,7 @@ class Certificate {
// cache the secureContext so that the server will start using the new certificate right away.
// If it’s not successful, restore the old files.
//
log(` 🤖 [Auto Encrypt] Renewing Let’s Encrypt certificate for ${this.#domains}.`)
log(` 🤖 ❨auto-encrypt Renewing Let’s Encrypt certificate for ${this.#domains}.`)
this.stopCheckingForRenewal()
......@@ -292,19 +292,19 @@ class Certificate {
* has been renewed.
*/
async checkForRenewal () {
log( ' 🧐 [Auto Encrypt] Checking if we need to renew the certificate… ')
log( ' 🧐 ❨auto-encrypt Checking if we need to renew the certificate… ')
const currentDate = moment()
if (currentDate.isSameOrAfter(this.#renewalDate)) {
//
// Certificate needs renewal.
//
log(` 🌱 [Auto Encrypt] Certificate expires in 30 days or less. Renewing certificate…`)
log(` 🌱 ❨auto-encrypt Certificate expires in 30 days or less. Renewing certificate…`)
// Note: this is not a blocking process. We transparently start using the new certificate
// when it is ready.
await this.renewCertificate()
log(` 🌱 [Auto Encrypt] Successfully renewed Let’s Encrypt certificate.`)
log(` 🌱 ❨auto-encrypt Successfully renewed Let’s Encrypt certificate.`)
} else {
log(' 👍 [Auto Encrypt] Certificate has more than 30 days before it expires. Will check again tomorrow.')
log(' 👍 ❨auto-encrypt Certificate has more than 30 days before it expires. Will check again tomorrow.')
}
}
......@@ -333,7 +333,7 @@ class Certificate {
const onceADay = 24 /* hours */ * 60 /* minutes */ * 60 /* seconds */ * 1000 /* ms */
this.#checkForRenewalIntervalId = setInterval(this.checkForRenewal, onceADay)
log(' ⏰ [Auto Encrypt] Set up timer to check for certificate renewal once a day.')
log(' ⏰ ❨auto-encrypt Set up timer to check for certificate renewal once a day.')
}
/**
......@@ -370,7 +370,7 @@ class Certificate {
}
__changeRenewalDate (momentDate) {
log(' Warning: changing renewal date on the certificate instance. I hope you know what you’re doing.')
log(' ⚠ ❨auto-encrypt❩ Warning: changing renewal date on the certificate instance. I hope you know what you’re doing.')
this.#renewalDate = momentDate
}
......@@ -398,5 +398,4 @@ class Certificate {
}
}
module.exports = Certificate
......@@ -38,13 +38,13 @@ class ChallengeServer {
static async destroySharedInstance () {
if (ChallengeServer.instance === null) {
log(' 🚮 [Auto Correct] Challenge Server was never setup. Nothing to destroy.')
log(' 🚮 ❨auto-encrypt❩ Challenge Server was never setup. Nothing to destroy.')
return
}
log(' 🚮 [Auto Correct] Destroying Challenge Server…')
log(' 🚮 ❨auto-encrypt❩ Destroying Challenge Server…')
await ChallengeServer.instance.destroy()
ChallengeServer.instance = null
log(' 🚮 [Auto Correct] Challenge Server is destroyed.')
log(' 🚮 ❨auto-encrypt❩ Challenge Server is destroyed.')
}
addResponder (responder) {
......@@ -79,7 +79,7 @@ class ChallengeServer {
// If this is not an ACME authorisation request, as nothing else should be using insecure HTTP,
// forward the request to HTTPS.
if (!responded) {
log(` Received non-ACME HTTP request for ${request.url}, not responding.`)
log(` ⚠ ❨auto-encrypt❩ Received non-ACME HTTP request for ${request.url}, not responding.`)
response.statusCode = 403
response.end('403: forbidden')
}
......@@ -100,7 +100,7 @@ class ChallengeServer {
await new Promise((resolve, reject) => {
try {
this.server.listen(80, () => {
log(` 🔒 [Auto Encrypt] HTTP server is listening for challenges`)
log(` 🔒 ❨auto-encrypt HTTP server is listening for challenges`)
resolve()
})
} catch (error) {
......
......@@ -111,7 +111,7 @@ class Configuration {
this.#certificatePath = path.join(this.#certificateDirectoryPath, 'certificate.pem')
this.#certificateIdentityPath = path.join(this.#certificateDirectoryPath, 'certificate-identity.pem')
log(' ⚙️ [Auto Encrypt] Configuration initialised.')
log(' ⚙️ ❨auto-encrypt Configuration initialised.')
}
//
......
......@@ -62,7 +62,7 @@ class Directory {
this.#letsEncryptServer = configuration.server
this.#directoryRequest = prepareRequest('GET', 'json', this.#letsEncryptServer.endpoint)
log(` 📕 [Auto Encrypt] Directory is using endpoint ${this.#letsEncryptServer.endpoint}`)
log(` 📕 ❨auto-encrypt Directory is using endpoint ${this.#letsEncryptServer.endpoint}`)
}
// (Async) Fetches the latest Urls from the Let’s Encrypt ACME endpoint being used.
......
......@@ -33,7 +33,7 @@ class Identity {
throws.error(Symbol.for('UnsupportedIdentityType'))
}
log(` 👤 Creating identity (${identityFilePath})`)
log(` 👤 ❨auto-encrypt❩ Creating identity (${identityFilePath})`)
this.#identityFilePath = identityFilePath
......
......@@ -33,12 +33,12 @@ class Nonce {
set (freshNonce) {
if (freshNonce === undefined || freshNonce === null) {
log(' ⚠ [Auto Encrypt] nonce.set called with undefined/null. Not saving nonce. No effect on functionality. ')
log(' ⚠ ❨auto-encrypt nonce.set called with undefined/null. Not saving nonce. No effect on functionality. ')
return
}
if (freshNonce.match(/^[A-Za-z0-9_-]+$/) === null) {
log (' ⚠ [Auto Encrypt] nonce.set with non-Base64-encoded nonce. Not saving nonce. No effect on functionality.')
log (' ⚠ ❨auto-encrypt nonce.set with non-Base64-encoded nonce. Not saving nonce. No effect on functionality.')
return
}
......
......@@ -116,7 +116,7 @@ class Order {
let numberOfAuthorisationsValidated = 0
let numberOfAuthorisationsToValidate = this.domains.length
log(` 📈 Number of authorisations to validate: ${numberOfAuthorisationsToValidate}`)
log(` 📈 ❨auto-encrypt❩ Number of authorisations to validate: ${numberOfAuthorisationsToValidate}`)
// We’ve got the order back. Download all the authorisations and
// create Authorisation instances from them. The Authorisation
......@@ -130,7 +130,7 @@ class Order {
numberOfAuthorisationsValidated++
log(` 📝 An authorisation was validated for the order! (${numberOfAuthorisationsValidated}/${numberOfAuthorisationsToValidate})`)
log(` 📝 ❨auto-encrypt❩ An authorisation was validated for the order! (${numberOfAuthorisationsValidated}/${numberOfAuthorisationsToValidate})`)
this.#authorisations.push(authorisation)
}
......@@ -141,12 +141,12 @@ class Order {
// it should send a POST request to the order resource's finalize URL.
// The POST body MUST include a CSR.” – RFC 8555 § 7.4 (Applying for Certificate Issuance).
log(` 🎊 All authorisations validated.`)
log(` 🎊 ❨auto-encrypt❩ All authorisations validated.`)
// We no longer need the Challenge Server that was set up by the authorisations, destroy it.
await ChallengeServer.destroySharedInstance()
log(` 💃 Finalising order…`)
log(` 💃 ❨auto-encrypt❩ Finalising order…`)
// Generate and save certificate’s identity (private key).
this.#certificateIdentity = new CertificateIdentity(this.configuration)
......@@ -159,7 +159,7 @@ class Order {
numAttempts++
if (numAttempts > 5) {
log(` Timed out waiting for order validity. `)
log(` ❌ ❨auto-encrypt❩ Timed out waiting for order validity. `)
break;
}
......@@ -177,7 +177,7 @@ class Order {
}
if (this.status === 'valid') {
log(' 🎁 Order is valid.')
log(' 🎁 ❨auto-encrypt❩ Order is valid.')
// Download and cache the certificate.
try {
......@@ -187,7 +187,7 @@ class Order {
throw new Error(error)
}
log(' 💅 Got the certificate.')
log(' 💅 ❨auto-encrypt❩ Got the certificate.')
// Save the certificate.
try {
......@@ -196,16 +196,16 @@ class Order {
throw new Error(error)
}
log(' 💾 Saved the certificate.')
log(' 💾 ❨auto-encrypt❩ Saved the certificate.')
} else {
log(` ℹ️ Order is not valid. Current status: (${this.status})`)
if (this.status === 'invalid')
{
// To let renewal attempts naturally retry every day, we let this pass.
log(` Order is invalid. `)
log(` ❌ ❨auto-encrypt❩ Order is invalid. `)
} else {
log(` Waiting a second before checking again…`)
log(` ⏳ ❨auto-encrypt❩ Waiting a second before checking again…`)
await waitFor(1000)
}
}
......
......@@ -50,7 +50,7 @@ class MockServer {
await new Promise((resolve, reject) => {
try {
server.listen(9829, () => {
log(' 🎭 [Auto Encrypt] Mock server started.')
log(' 🎭 ❨auto-encrypt Mock server started.')
resolve()
})
} catch (error) {
......
{
"name": "@small-tech/auto-encrypt",
"version": "1.0.0",
"version": "1.0.1",
"description": "Adds automatic provisioning and renewal of Let’s Encrypt TLS certificates with OCSP Stapling to Node.js https servers (including Express.js, etc.)",
"keywords": [
"let's encrypt",
......
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