diff --git a/readme.md b/readme.md index 68f2eae..9edc907 100644 --- a/readme.md +++ b/readme.md @@ -90,7 +90,7 @@ crtMgr.generateRootCA(options, (error, keyPath, crtPath) { }); ``` -### getCertificate(hostname, callback([error, keyContent, crtContent])) +### getCertificate(hostname, [extraHosts,] callback([error, keyContent, crtContent])) 获取指定域名下的证书的key和crt内容,如果证书还不存在,则会先创建该证书。 > 证书的生成基于生成的rootCA根证书来签名,如果rootCA根证书还未创建,则会终止并抛出错误:`ROOT_CA_NOT_EXISTS` @@ -102,6 +102,9 @@ crtMgr.generateRootCA(options, (error, keyPath, crtPath) { - `hostname` `string` 所要获取证书内容的hostname +- `extraHosts`: `string[]` +可选,附带其他的 hostname 列表,用于一个证书支持多个域名场景 + - `callback` `function` 获取到内容后的回调函数,主要包含key的内容和crt的内容,如果获取过程中出现异常,则放入error变量中 @@ -109,7 +112,7 @@ crtMgr.generateRootCA(options, (error, keyPath, crtPath) { #### 调用实例 ```js -certManager.getCertificate('localhost', (error, keyContent, crtContent) => { +certManager.getCertificate('localhost', ['127.0.0.1'], (error, keyContent, crtContent) => { // 如果根证书还没有生成,需要先生成根证书 if (error === 'ROOT_CA_NOT_EXISTS') { diff --git a/src/certGenerator.js b/src/certGenerator.js index 8068ae2..fe0690c 100644 --- a/src/certGenerator.js +++ b/src/certGenerator.js @@ -14,19 +14,14 @@ let defaultAttrs = [ * different domain format needs different SAN * */ -function getExtensionSAN(domain = '') { - const isIpDomain = Util.isIpDomain(domain); - if (isIpDomain) { - return { - name: 'subjectAltName', - altNames: [{ type: 7, ip: domain }] - }; - } else { - return { - name: 'subjectAltName', - altNames: [{ type: 2, value: domain }] - }; - } +function getExtensionSAN(domain = '', extraHosts = []) { + return { + name: 'subjectAltName', + altNames: (extraHosts || []).concat([domain]).map(d => { + const isIpDomain = Util.isIpDomain(d); + return isIpDomain ? { type: 7, ip: d } : { type: 2, value: d }; + }) + }; } function getKeysAndCert(serialNumber) { @@ -76,7 +71,7 @@ function generateRootCA(commonName) { }; } -function generateCertsForHostname(domain, rootCAConfig) { +function generateCertsForHostname(domain, rootCAConfig, extraHosts) { // generate a serialNumber for domain const md = forge.md.md5.create(); md.update(domain); @@ -100,7 +95,7 @@ function generateCertsForHostname(domain, rootCAConfig) { const extensions = [ { name: 'basicConstraints', cA: false }, - getExtensionSAN(domain) + getExtensionSAN(domain, extraHosts) ]; cert.setSubject(attrs); diff --git a/src/index.js b/src/index.js index 19fe213..3024ff2 100644 --- a/src/index.js +++ b/src/index.js @@ -56,7 +56,11 @@ function CertManager(options) { } } - function getCertificate(hostname, certCallback) { + function getCertificate(hostname, extraHosts, certCallback) { + if (typeof extraHosts === 'function' && !certCallback) { + certCallback = extraHosts; + extraHosts = undefined; + } if (!_checkRootCA()) { console.log(color.yellow('please generate root CA before getting certificate for sub-domains')); certCallback && certCallback(Errors.ROOT_CA_NOT_EXISTS); @@ -76,7 +80,7 @@ function CertManager(options) { const result = certGenerator.generateCertsForHostname(hostname, { cert: cacheRootCACrtFileContent, key: cacheRootCAKeyFileContent - }); + }, extraHosts); fs.writeFileSync(keyFile, result.privateKey); fs.writeFileSync(crtFile, result.certificate); callback(null, result.privateKey, result.certificate);