Verified Commit ae2620b2 authored by Aral Balkan's avatar Aral Balkan
Browse files

Refactor to inline two small modules

parent 70570a68
This diff is collapsed.
......@@ -56,6 +56,14 @@ hit of an HTTPS route via use of the Server Name Indication (SNI) callback.</p>
<dd></dd>
</dl>
## Functions
<dl>
<dt><a href="#csrAsPem">csrAsPem(domains, key)</a><code>String</code></dt>
<dd><p>Create a CSR given a list of domains and a Jose JWK.rsaKey.</p>
</dd>
</dl>
## Typedefs
<dl>
......@@ -442,6 +450,19 @@ Creates an instance of Order.
| --- | --- | --- |
| configuration | <code>Configuration</code> | (Required) Configuration instance. |
<a name="csrAsPem"></a>
## csrAsPem(domains, key) ⇒ <code>String</code>
Create a CSR given a list of domains and a Jose JWK.rsaKey.
**Kind**: global function
**Returns**: <code>String</code> - A CSR in PEM format.
| Param | Type |
| --- | --- |
| domains | <code>Array.&lt;String&gt;</code> |
| key | <code>JWK.rsaKey</code> |
<a name="PreparedRequest"></a>
## PreparedRequest : <code>Object</code>
......
......@@ -10,7 +10,7 @@ const fs = require('fs-extra')
const tls = require('tls')
const log = require('./util/log')
const moment = require('moment')
const certificateDetails = require('./x.509/certificateDetails')
const x509 = require('./x.509/rfc5280')
const Account = require('./Account')
const AccountIdentity = require('./AccountIdentity')
const Directory = require('./Directory')
......@@ -89,7 +89,6 @@ class Certificate {
#_pem = null
#_identity = null
#_key = null
#_details = null
#_issueDate = null
#_expiryDate = null
......@@ -102,9 +101,7 @@ class Certificate {
set pem (certificatePem) {
this.#_pem = certificatePem
// Also extract certificate details for the first certificate (in case there are intermediaries).
// const firstCertificatePem = certificatePem.slice(0, certificatePem.indexOf('-----END CERTIFICATE-----'))
const details = certificateDetails(certificatePem)
const details = this.parseDetails(certificatePem)
this.#_issueDate = moment(details.issuedAt)
this.#_expiryDate = moment(details.expiresAt)
......@@ -329,6 +326,27 @@ class Certificate {
stopCheckingForRenewal () {
clearInterval(this.#checkForRenewalIntervalId)
}
parseDetails (certificatePem) {
const certificate = (x509.Certificate.decode(certificatePem, 'pem', {label: 'CERTIFICATE'})).tbsCertificate
const issuer = certificate.issuer.value[0][0].value.toString('utf-8').trim()
const issuedAt = new Date(certificate.validity.notBefore.value)
const expiresAt = new Date(certificate.validity.notAfter.value)
const subject = certificate.subject.value[0][0].value.toString('utf-8').slice(2).trim()
const alternativeNames = ((certificate.extensions.filter(extension => {
return extension.extnID === 'subjectAlternativeName'
}))[0].extnValue).map(name => name.value)
return {
issuer,
subject,
alternativeNames,
issuedAt,
expiresAt
}
}
}
module.exports = Certificate
......@@ -12,9 +12,57 @@
// License: AGPLv3 or later.
//
////////////////////////////////////////////////////////////////////////////////
const rsaCsrAsPem = require('./x.509/csr')
const forge = require('node-forge')
const DNS = 2 // The ANS.1 type for DNS name.
function pemToAcmeCSR (csr) {
// Returns a valid ACME-formatted (RFC 8555) CSR.
/**
* Return an ACME-formatted (RFC 8555) CSR given a list of domains and a Jose JWK.rsaKey.
*
* @param {String[]} domains
* @param {JWK.rsaKey} key
* @returns {String} An ACME-formatted CSR in PEM format.
*/
module.exports = function (domains, key) { return pemToAcmeCsr(csrAsPem(domains, key)) }
/**
* Create a CSR given a list of domains and a Jose JWK.rsaKey.
*
* @param {String[]} domains
* @param {JWK.rsaKey} key
* @returns {String} A CSR in PEM format.
*/
function csrAsPem (domains, key) {
var csr = forge.pki.createCertificationRequest()
const keys = {
public: forge.pki.publicKeyFromPem(key.toPEM(/* private = */ false)),
private: forge.pki.privateKeyFromPem(key.toPEM(/* private = */ true))
}
csr.publicKey = keys.public
const altNames = domains.map(domain => {
return {type: DNS, value: domain}
})
// According to RFC 8555, we *either* need to specify the subject or the subjectAltName so skip the subject.
csr.setAttributes([{
name: 'extensionRequest',
extensions: [{
name: 'subjectAltName',
altNames
}]
}])
csr.sign(keys.private)
const pem = forge.pki.certificationRequestToPem(csr)
return pem
}
function pemToAcmeCsr (csr) {
csr = pemToHeaderlessSingleLinePem(csr)
csr = base64ToBase64Url(csr)
return csr
......@@ -36,12 +84,3 @@ function base64ToBase64Url (str) {
.replace(/\//g, '_')
.replace(/=/g, '')
}
// Returns a valid ACME-formatted (RFC 8555) CSR.
async function acmeCsr (domains, key) {
let csrAsPem = await rsaCsrAsPem(domains, key)
acmeCsr = pemToAcmeCSR(csrAsPem)
return acmeCsr
}
module.exports = acmeCsr
const x509 = require('./rfc5280')
module.exports = function (certificatePEM) {
const certificate = (x509.Certificate.decode(certificatePEM, 'pem', {label: 'CERTIFICATE'})).tbsCertificate
const issuer = certificate.issuer.value[0][0].value.toString('utf-8').trim()
const issuedAt = new Date(certificate.validity.notBefore.value)
const expiresAt = new Date(certificate.validity.notAfter.value)
console.log(`Issuer : `, issuer)
console.log('Issued at : ', new Date(issuedAt))
console.log('Expires at : ', new Date(expiresAt))
const subject = certificate.subject.value[0][0].value.toString('utf-8').slice(2).trim()
console.log('Subject : ', subject)
const alternativeNames = ((certificate.extensions.filter(extension => {
return extension.extnID === 'subjectAlternativeName'
}))[0].extnValue).map(name => name.value)
console.log('Alternative names: ', alternativeNames)
return {
issuer,
subject,
alternativeNames,
issuedAt,
expiresAt
}
}
const forge = require('node-forge')
const DNS = 2 // The ANS.1 type for DNS name.
/**
* Create a CSR given a list of domains and a Jose JWK.rsaKey.
*
* @param {String[]} domains
* @param {JWK.rsaKey} key
* @returns String a CSR in PEM format.
*/
module.exports = function (domains, key) {
var csr = forge.pki.createCertificationRequest()
const keys = {
public: forge.pki.publicKeyFromPem(key.toPEM(/* private = */ false)),
private: forge.pki.privateKeyFromPem(key.toPEM(/* private = */ true))
}
csr.publicKey = keys.public
const altNames = domains.map(domain => {
return {type: DNS, value: domain}
})
// According to RFC 8555, we *either* need to specify the subject or the subjectAltName so skip the subject.
csr.setAttributes([{
name: 'extensionRequest',
extensions: [{
name: 'subjectAltName',
altNames
}]
}])
csr.sign(keys.private)
const csrAsPem = forge.pki.certificationRequestToPem(csr)
return csrAsPem
}
......@@ -7,7 +7,7 @@
"test": "QUIET=true tape 'test/**/*.js' | tap-spec",
"test-debug": "tape 'test/**/*.js' | tap-spec",
"coverage": "QUIET=true nyc tape 'test/**/*.js' | tap-nyc",
"generate-dependency-diagram": "node_modules/.bin/depcruise --exclude \"^node_modules|lib/util|typedefs|^crypto$|^fs$|^os$|^tls$|^path$|^events$|^http$|^util$\" --output-type dot index.js | dot -T svg > artefacts/dependency-graph.svg",
"generate-dependency-diagram": "node_modules/.bin/depcruise --exclude \"^node_modules|lib/util|typedefs|^crypto$|^fs$|^os$|^tls$|^path$|^events$|^http$|^util\" --output-type dot index.js | dot -T svg > artefacts/dependency-graph.svg",
"generate-developer-documentation": "npm run generate-dependency-diagram && node_modules/.bin/jsdoc2md --private --template developer-documentation.hbs --files typedefs/**/*.js --files index.js --files lib/*.js > developer-documentation.md"
},
"author": "Aral Balkan",
......
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