Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for multiple domains with single hostname cert #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -102,14 +102,17 @@ crtMgr.generateRootCA(options, (error, keyPath, crtPath) {
- `hostname` `string`
所要获取证书内容的hostname

- `extraHosts`: `string[]`
可选,附带其他的 hostname 列表,用于一个证书支持多个域名场景

- `callback` `function`
获取到内容后的回调函数,主要包含key的内容和crt的内容,如果获取过程中出现异常,则放入error变量中

> 获取子域名的证书,要求已经存在根证书,否则会提示失败。组件会抛出对应的异常。您可以捕获并通过 `generateRootCA()`来生成根证书。**并安装并请信任该根证书**

#### 调用实例
```js
certManager.getCertificate('localhost', (error, keyContent, crtContent) => {
certManager.getCertificate('localhost', ['127.0.0.1'], (error, keyContent, crtContent) => {

// 如果根证书还没有生成,需要先生成根证书
if (error === 'ROOT_CA_NOT_EXISTS') {
Expand Down
25 changes: 10 additions & 15 deletions src/certGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -100,7 +95,7 @@ function generateCertsForHostname(domain, rootCAConfig) {

const extensions = [
{ name: 'basicConstraints', cA: false },
getExtensionSAN(domain)
getExtensionSAN(domain, extraHosts)
];

cert.setSubject(attrs);
Expand Down
8 changes: 6 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down