mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-26 19:36:29 +03:00
FEAT: Allow client side TLS for Docker hosts (#2852)
* FEAT: Allow client side TLS for Docker hosts Inlcude TLS certificate in HTTPS requests when certificate files are locally available to Kuma for a host. * fix: refactor to satisfy linter requirements * fix: linter
This commit is contained in:
parent
a032e11a2e
commit
bce4835362
2 changed files with 59 additions and 4 deletions
|
@ -2,8 +2,15 @@ const axios = require("axios");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const version = require("../package.json").version;
|
const version = require("../package.json").version;
|
||||||
const https = require("https");
|
const https = require("https");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
class DockerHost {
|
class DockerHost {
|
||||||
|
|
||||||
|
static CertificateBasePath = process.env.DOCKER_TLS_DIR_PATH || "data/docker-tls/";
|
||||||
|
static CertificateFileNameCA = process.env.DOCKER_TLS_FILE_NAME_CA || "ca.pem";
|
||||||
|
static CertificateFileNameCert = process.env.DOCKER_TLS_FILE_NAME_CA || "cert.pem";
|
||||||
|
static CertificateFileNameKey = process.env.DOCKER_TLS_FILE_NAME_CA || "key.pem";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a docker host
|
* Save a docker host
|
||||||
* @param {Object} dockerHost Docker host to save
|
* @param {Object} dockerHost Docker host to save
|
||||||
|
@ -60,16 +67,13 @@ class DockerHost {
|
||||||
* @returns {number} Total amount of containers on the host
|
* @returns {number} Total amount of containers on the host
|
||||||
*/
|
*/
|
||||||
static async testDockerHost(dockerHost) {
|
static async testDockerHost(dockerHost) {
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
url: "/containers/json?all=true",
|
url: "/containers/json?all=true",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "*/*",
|
"Accept": "*/*",
|
||||||
"User-Agent": "Uptime-Kuma/" + version
|
"User-Agent": "Uptime-Kuma/" + version
|
||||||
},
|
},
|
||||||
httpsAgent: new https.Agent({
|
|
||||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dockerHost.dockerType === "socket") {
|
if (dockerHost.dockerType === "socket") {
|
||||||
|
@ -77,6 +81,7 @@ class DockerHost {
|
||||||
} else if (dockerHost.dockerType === "tcp") {
|
} else if (dockerHost.dockerType === "tcp") {
|
||||||
options.baseURL = DockerHost.patchDockerURL(dockerHost.dockerDaemon);
|
options.baseURL = DockerHost.patchDockerURL(dockerHost.dockerDaemon);
|
||||||
}
|
}
|
||||||
|
options.httpsAgent = new https.Agent(DockerHost.getHttpsAgentOptions(dockerHost.dockerType, options.baseURL));
|
||||||
|
|
||||||
let res = await axios.request(options);
|
let res = await axios.request(options);
|
||||||
|
|
||||||
|
@ -111,6 +116,53 @@ class DockerHost {
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns HTTPS agent options with client side TLS parameters if certificate files
|
||||||
|
* for the given host are available under a predefined directory path.
|
||||||
|
*
|
||||||
|
* The base path where certificates are looked for can be set with the
|
||||||
|
* 'DOCKER_TLS_DIR_PATH' environmental variable or defaults to 'data/docker-tls/'.
|
||||||
|
*
|
||||||
|
* If a directory in this path exists with a name matching the FQDN of the docker host
|
||||||
|
* (e.g. the FQDN of 'https://example.com:2376' is 'example.com' so the directory
|
||||||
|
* 'data/docker-tls/example.com/' would be searched for certificate files),
|
||||||
|
* then 'ca.pem', 'key.pem' and 'cert.pem' files are included in the agent options.
|
||||||
|
* File names can also be overridden via 'DOCKER_TLS_FILE_NAME_(CA|KEY|CERT)'.
|
||||||
|
*
|
||||||
|
* @param {String} dockerType i.e. "tcp" or "socket"
|
||||||
|
* @param {String} url The docker host URL rewritten to https://
|
||||||
|
* @return {Object}
|
||||||
|
* */
|
||||||
|
static getHttpsAgentOptions(dockerType, url) {
|
||||||
|
let baseOptions = {
|
||||||
|
maxCachedSessions: 0,
|
||||||
|
rejectUnauthorized: true
|
||||||
|
};
|
||||||
|
let certOptions = {};
|
||||||
|
|
||||||
|
let dirName = url.replace(/^https:\/\/([^/:]+)(\/|:).*$/, "$1");
|
||||||
|
let dirPath = DockerHost.CertificateBasePath + dirName + "/";
|
||||||
|
let caPath = dirPath + DockerHost.CertificateFileNameCA;
|
||||||
|
let certPath = dirPath + DockerHost.CertificateFileNameCert;
|
||||||
|
let keyPath = dirPath + DockerHost.CertificateFileNameKey;
|
||||||
|
|
||||||
|
if (dockerType === "tcp" && fs.existsSync(caPath) && fs.existsSync(certPath) && fs.existsSync(keyPath)) {
|
||||||
|
let ca = fs.readFileSync(caPath);
|
||||||
|
let key = fs.readFileSync(keyPath);
|
||||||
|
let cert = fs.readFileSync(certPath);
|
||||||
|
certOptions = {
|
||||||
|
ca,
|
||||||
|
key,
|
||||||
|
cert
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...baseOptions,
|
||||||
|
...certOptions
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -720,6 +720,9 @@ class Monitor extends BeanModel {
|
||||||
options.socketPath = dockerHost._dockerDaemon;
|
options.socketPath = dockerHost._dockerDaemon;
|
||||||
} else if (dockerHost._dockerType === "tcp") {
|
} else if (dockerHost._dockerType === "tcp") {
|
||||||
options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
|
options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
|
||||||
|
options.httpsAgent = CacheableDnsHttpAgent.getHttpsAgent(
|
||||||
|
DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("monitor", `[${this.name}] Axios Request`);
|
log.debug("monitor", `[${this.name}] Axios Request`);
|
||||||
|
|
Loading…
Reference in a new issue