mirror of
https://github.com/caprover/caprover
synced 2026-05-05 19:20:38 +00:00
Reorganized directories
This commit is contained in:
@@ -6,7 +6,7 @@ const logger = require("morgan");
|
||||
const cookieParser = require("cookie-parser");
|
||||
const bodyParser = require("body-parser");
|
||||
const httpProxyImport = require("http-proxy");
|
||||
const CaptainManager = require("./user/CaptainManager");
|
||||
const CaptainManager = require("./user/system/CaptainManager");
|
||||
const BaseApi = require("./api/BaseApi");
|
||||
const ApiStatusCodes = require("./api/ApiStatusCodes");
|
||||
const Injector = require("./injection/Injector");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const DataStoreProvider = require("../datastore/DataStoreProvider");
|
||||
const Authenticator = require("../user/Authenticator");
|
||||
const CaptainConstants = require("../utils/CaptainConstants");
|
||||
const CaptainManager = require("../user/CaptainManager");
|
||||
const CaptainManager = require("../user/system/CaptainManager");
|
||||
const ServiceManager = require("../user/ServiceManager");
|
||||
const DockerApiProvider = require("../docker/DockerApi");
|
||||
const BaseApi = require("../api/BaseApi");
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"Injector.js","sourceRoot":"","sources":["../../src/injection/Injector.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"Injector.js","sourceRoot":"","sources":["../../src/injection/Injector.ts"],"names":[],"mappings":"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"}
|
||||
@@ -3,7 +3,7 @@ const express = require("express");
|
||||
const BaseApi = require("../../api/BaseApi");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const CaptainManager = require("../../user/CaptainManager");
|
||||
const CaptainManager = require("../../user/system/CaptainManager");
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
const InjectionExtractor = require("../../injection/InjectionExtractor");
|
||||
const uuid = require("uuid/v4");
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"SystemRouteSelfHostRegistry.js","sourceRoot":"","sources":["../../../src/routes/system/SystemRouteSelfHostRegistry.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"SystemRouteSelfHostRegistry.js","sourceRoot":"","sources":["../../../src/routes/system/SystemRouteSelfHostRegistry.ts"],"names":[],"mappings":"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"}
|
||||
@@ -3,7 +3,7 @@ const express = require("express");
|
||||
const BaseApi = require("../../api/BaseApi");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const CaptainManager = require("../../user/CaptainManager");
|
||||
const CaptainManager = require("../../user/system/CaptainManager");
|
||||
const Validator = require("validator");
|
||||
const SystemRouteSelfHostRegistry = require("./SystemRouteSelfHostRegistry");
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@ const uuid = require("uuid/v4");
|
||||
const bcrypt = require("bcryptjs");
|
||||
const ApiStatusCodes = require("../api/ApiStatusCodes");
|
||||
const EnvVar = require("../utils/EnvVars");
|
||||
const CaptainManager = require("./CaptainManager");
|
||||
const CaptainManager = require("./system/CaptainManager");
|
||||
const CaptainConstants = require("../utils/CaptainConstants");
|
||||
const Logger = require("../utils/Logger");
|
||||
const DataStoreProvider = require("../datastore/DataStoreProvider");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
const Logger = require("../utils/Logger");
|
||||
const CaptainConstants = require("../utils/CaptainConstants");
|
||||
const CaptainManager = require("./CaptainManager");
|
||||
const CaptainManager = require("./system/CaptainManager");
|
||||
const ApiStatusCodes = require("../api/ApiStatusCodes");
|
||||
const Authenticator = require("./Authenticator");
|
||||
const requireFromString = require("require-from-string");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
const fs = require("fs-extra");
|
||||
const ApiStatusCodes = require("../api/ApiStatusCodes");
|
||||
const CaptainConstants = require("../utils/CaptainConstants");
|
||||
const TemplateHelperVersionPrinter = require("./TemplateHelperVersionPrinter");
|
||||
const TemplateHelperVersionPrinter = require("../utils/TemplateHelperVersionPrinter");
|
||||
class TemplateHelper {
|
||||
constructor() {
|
||||
const templates = [
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"TemplateHelper.js","sourceRoot":"","sources":["../../src/user/TemplateHelper.ts"],"names":[],"mappings":";AACA,+BAA+B;AAC/B,wDAAwD;AAExD,8DAA8D;AAE9D,+EAA+E;AAE/E,MAAM,cAAc;IAGhB;QACI,MAAM,SAAS,GAAgB;YAC3B;gBACI,YAAY,EAAE,MAAM;gBACpB,kBAAkB,EAAE,cAAc;gBAClC,SAAS,EAAE,SAAS;aACvB;YACD;gBACI,YAAY,EAAE,KAAK;gBACnB,kBAAkB,EAAE,aAAa;gBACjC,SAAS,EAAE,SAAS;aACvB;YACD;gBACI,YAAY,EAAE,eAAe;gBAC7B,kBAAkB,EAAE,gBAAgB;gBACpC,SAAS,EAAE,YAAY;aAC1B;YACD;gBACI,YAAY,EAAE,WAAW;gBACzB,kBAAkB,EAAE,cAAc;gBAClC,SAAS,EAAE,YAAY;aAC1B;SACJ,CAAA;QAED,MAAM,eAAe,GAAG,SAAS,GAAG,qBAAqB,CAAA;QAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACvC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,EAAE,CAAC,YAAY,CACxC,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,EAC3C,MAAM,CACT,CAAA;SACJ;QAED,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,IAAI,gBAAgB,CAAC,OAAO,EAAE;YAC1B,IAAI,4BAA4B,EAAE,CAAC,gCAAgC,CAC/D,IAAI,CAAC,SAAS,CACjB,CAAA;SACJ;IACL,CAAC;IAED,2BAA2B,CAAC,YAAoB;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,YAAY,EAAE;gBACjD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;aAC3B;SACJ;QACD,MAAM,cAAc,CAAC,WAAW,CAC5B,cAAc,CAAC,oBAAoB,EACnC,2BAA2B,GAAG,YAAY,CAC7C,CAAA;IACL,CAAC;IAED,mCAAmC,CAAC,kBAA0B;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAA;QACjB,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACrD,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACxD,IAAI,CAAC,eAAe,EAAE;YAClB,MAAM,cAAc,CAAC,WAAW,CAC5B,cAAc,CAAC,oBAAoB,EACnC,kCAAkC,CACrC,CAAA;SACJ;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAA;QAElE,MAAM,QAAQ,GACV,WAAW,CAAC,kBAAkB;YAC9B,GAAG;YACH,eAAe;YACf,WAAW,CAAC,SAAS,CAAA;QAEzB,OAAO,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,WAAW,CAAC,aAAa,CAAA;IAChE,CAAC;CACJ;AAED,MAAM,sBAAsB,GAAG,IAAI,cAAc,EAAE,CAAA;AAEnD,iBAAS;IACL,GAAG,EAAE;QACD,OAAO,sBAAsB,CAAA;IACjC,CAAC;CACJ,CAAA"}
|
||||
{"version":3,"file":"TemplateHelper.js","sourceRoot":"","sources":["../../src/user/TemplateHelper.ts"],"names":[],"mappings":";AACA,+BAA+B;AAC/B,wDAAwD;AAExD,8DAA8D;AAE9D,sFAAsF;AAEtF,MAAM,cAAc;IAGhB;QACI,MAAM,SAAS,GAAgB;YAC3B;gBACI,YAAY,EAAE,MAAM;gBACpB,kBAAkB,EAAE,cAAc;gBAClC,SAAS,EAAE,SAAS;aACvB;YACD;gBACI,YAAY,EAAE,KAAK;gBACnB,kBAAkB,EAAE,aAAa;gBACjC,SAAS,EAAE,SAAS;aACvB;YACD;gBACI,YAAY,EAAE,eAAe;gBAC7B,kBAAkB,EAAE,gBAAgB;gBACpC,SAAS,EAAE,YAAY;aAC1B;YACD;gBACI,YAAY,EAAE,WAAW;gBACzB,kBAAkB,EAAE,cAAc;gBAClC,SAAS,EAAE,YAAY;aAC1B;SACJ,CAAA;QAED,MAAM,eAAe,GAAG,SAAS,GAAG,qBAAqB,CAAA;QAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACvC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,EAAE,CAAC,YAAY,CACxC,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,EAC3C,MAAM,CACT,CAAA;SACJ;QAED,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,IAAI,gBAAgB,CAAC,OAAO,EAAE;YAC1B,IAAI,4BAA4B,EAAE,CAAC,gCAAgC,CAC/D,IAAI,CAAC,SAAS,CACjB,CAAA;SACJ;IACL,CAAC;IAED,2BAA2B,CAAC,YAAoB;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,YAAY,EAAE;gBACjD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;aAC3B;SACJ;QACD,MAAM,cAAc,CAAC,WAAW,CAC5B,cAAc,CAAC,oBAAoB,EACnC,2BAA2B,GAAG,YAAY,CAC7C,CAAA;IACL,CAAC;IAED,mCAAmC,CAAC,kBAA0B;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAA;QACjB,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACrD,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACxD,IAAI,CAAC,eAAe,EAAE;YAClB,MAAM,cAAc,CAAC,WAAW,CAC5B,cAAc,CAAC,oBAAoB,EACnC,kCAAkC,CACrC,CAAA;SACJ;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAA;QAElE,MAAM,QAAQ,GACV,WAAW,CAAC,kBAAkB;YAC9B,GAAG;YACH,eAAe;YACf,WAAW,CAAC,SAAS,CAAA;QAEzB,OAAO,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,WAAW,CAAC,aAAa,CAAA;IAChE,CAAC;CACJ;AAED,MAAM,sBAAsB,GAAG,IAAI,cAAc,EAAE,CAAA;AAEnD,iBAAS;IACL,GAAG,EAAE;QACD,OAAO,sBAAsB,CAAA;IACjC,CAAC;CACJ,CAAA"}
|
||||
@@ -0,0 +1,692 @@
|
||||
"use strict";
|
||||
const uuid = require("uuid/v4");
|
||||
const SshClientImport = require("ssh2");
|
||||
const request = require("request");
|
||||
const fs = require("fs-extra");
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const LoadBalancerManager = require("./LoadBalancerManager");
|
||||
const CertbotManager = require("./CertbotManager");
|
||||
const SelfHostedDockerRegistry = require("./SelfHostedDockerRegistry");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const DataStoreProvider = require("../../datastore/DataStoreProvider");
|
||||
const DockerApi = require("../../docker/DockerApi");
|
||||
const DEBUG_SALT = 'THIS IS NOT A REAL CERTIFICATE';
|
||||
const SshClient = SshClientImport.Client;
|
||||
const MAX_FAIL_ALLOWED = 4;
|
||||
const HEALTH_CHECK_INTERVAL = 20000; // ms
|
||||
const TIMEOUT_HEALTH_CHECK = 15000; // ms
|
||||
class CaptainManager {
|
||||
constructor() {
|
||||
const dockerApi = DockerApi.get();
|
||||
this.hasForceSsl = false;
|
||||
this.dataStore = DataStoreProvider.getDataStore(CaptainConstants.rootNameSpace);
|
||||
this.dockerApi = dockerApi;
|
||||
this.certbotManager = new CertbotManager(dockerApi);
|
||||
this.loadBalancerManager = new LoadBalancerManager(dockerApi, this.certbotManager, this.dataStore);
|
||||
this.dockerRegistry = new SelfHostedDockerRegistry(dockerApi, this.dataStore, this.certbotManager, this.loadBalancerManager, this);
|
||||
this.myNodeId = undefined;
|
||||
this.inited = false;
|
||||
this.waitUntilRestarted = false;
|
||||
this.captainSalt = '';
|
||||
this.consecutiveHealthCheckFailCount = 0;
|
||||
this.healthCheckUuid = uuid();
|
||||
}
|
||||
initialize() {
|
||||
// If a linked file / directory is deleted on the host, it loses the connection to
|
||||
// the container and needs an update to be picked up again.
|
||||
const self = this;
|
||||
const dataStore = this.dataStore;
|
||||
const dockerApi = this.dockerApi;
|
||||
const loadBalancerManager = this.loadBalancerManager;
|
||||
const certbotManager = this.certbotManager;
|
||||
let myNodeId;
|
||||
self.refreshForceSslState()
|
||||
.then(function () {
|
||||
return dockerApi.getNodeIdByServiceName(CaptainConstants.captainServiceName, 0);
|
||||
})
|
||||
.then(function (nodeId) {
|
||||
myNodeId = nodeId;
|
||||
self.myNodeId = myNodeId;
|
||||
return dockerApi.isNodeManager(myNodeId);
|
||||
})
|
||||
.then(function (isManager) {
|
||||
if (!isManager) {
|
||||
throw new Error('Captain should only run on a manager node');
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Emptying generated and temp folders.');
|
||||
return fs.emptyDir(CaptainConstants.captainRootDirectoryTemp);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.emptyDir(CaptainConstants.captainRootDirectoryGenerated);
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Ensuring directories are available on host. Started.');
|
||||
return fs.ensureDir(CaptainConstants.letsEncryptEtcPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.letsEncryptLibPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.captainStaticFilesDir);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.perAppNginxConfigPathBase);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureFile(CaptainConstants.baseNginxConfigPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.registryPathOnHost);
|
||||
})
|
||||
.then(function () {
|
||||
return dockerApi.ensureOverlayNetwork(CaptainConstants.captainNetworkName);
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Ensuring directories are available on host. Finished.');
|
||||
return dockerApi.ensureServiceConnectedToNetwork(CaptainConstants.captainServiceName, CaptainConstants.captainNetworkName);
|
||||
})
|
||||
.then(function () {
|
||||
return loadBalancerManager.init(myNodeId, dataStore);
|
||||
})
|
||||
.then(function () {
|
||||
const valueIfNotExist = CaptainConstants.isDebug
|
||||
? DEBUG_SALT
|
||||
: uuid();
|
||||
return dockerApi.ensureSecret(CaptainConstants.captainSaltSecretKey, valueIfNotExist);
|
||||
})
|
||||
.then(function () {
|
||||
return dockerApi.ensureSecretOnService(CaptainConstants.captainServiceName, CaptainConstants.captainSaltSecretKey);
|
||||
})
|
||||
.then(function (secretHadExistedBefore) {
|
||||
if (!secretHadExistedBefore) {
|
||||
return new Promise(function () {
|
||||
Logger.d('I am halting here. I expect to get restarted in a few seconds due to a secret (captain salt) being updated.');
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
const secretFileName = '/run/secrets/' + CaptainConstants.captainSaltSecretKey;
|
||||
if (!fs.existsSync(secretFileName)) {
|
||||
throw new Error('Secret is attached according to Docker. But file cannot be found. ' +
|
||||
secretFileName);
|
||||
}
|
||||
const secretContent = fs.readFileSync(secretFileName).toString();
|
||||
if (!secretContent) {
|
||||
throw new Error('Salt secret content is empty!');
|
||||
}
|
||||
self.captainSalt = secretContent;
|
||||
return true;
|
||||
})
|
||||
.then(function () {
|
||||
return dataStore.setEncryptionSalt(self.getCaptainSalt());
|
||||
})
|
||||
.then(function () {
|
||||
return certbotManager.init(myNodeId);
|
||||
})
|
||||
.then(function () {
|
||||
return dataStore.getRegistriesDataStore().getAllRegistries();
|
||||
})
|
||||
.then(function (registries) {
|
||||
let localRegistry = undefined;
|
||||
for (let idx = 0; idx < registries.length; idx++) {
|
||||
const element = registries[idx];
|
||||
if (element.registryType == IRegistryTypes.LOCAL_REG) {
|
||||
localRegistry = element;
|
||||
}
|
||||
}
|
||||
if (!!localRegistry) {
|
||||
Logger.d('Ensuring Docker Registry is running...');
|
||||
return self.dockerRegistry.ensureDockerRegistryRunningOnThisNode(localRegistry.registryPassword);
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
})
|
||||
.then(function () {
|
||||
self.inited = true;
|
||||
self.performHealthCheck();
|
||||
Logger.d('**** Captain is initialized and ready to serve you! ****');
|
||||
})
|
||||
.catch(function (error) {
|
||||
Logger.e(error);
|
||||
setTimeout(function () {
|
||||
process.exit(0);
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
performHealthCheck() {
|
||||
const self = this;
|
||||
const captainPublicDomain = CaptainConstants.captainSubDomain +
|
||||
'.' +
|
||||
self.dataStore.getRootDomain();
|
||||
function scheduleNextHealthCheck() {
|
||||
self.healthCheckUuid = uuid();
|
||||
setTimeout(function () {
|
||||
self.performHealthCheck();
|
||||
}, HEALTH_CHECK_INTERVAL);
|
||||
}
|
||||
// For debug build, we'll turn off health check
|
||||
if (CaptainConstants.isDebug || !self.dataStore.hasCustomDomain()) {
|
||||
scheduleNextHealthCheck();
|
||||
return;
|
||||
}
|
||||
function checkCaptainHealth(callback) {
|
||||
let callbackCalled = false;
|
||||
setTimeout(function () {
|
||||
if (callbackCalled) {
|
||||
return;
|
||||
}
|
||||
callbackCalled = true;
|
||||
callback(false);
|
||||
}, TIMEOUT_HEALTH_CHECK);
|
||||
const url = 'http://' +
|
||||
captainPublicDomain +
|
||||
CaptainConstants.healthCheckEndPoint;
|
||||
request(url, function (error, response, body) {
|
||||
if (callbackCalled) {
|
||||
return;
|
||||
}
|
||||
callbackCalled = true;
|
||||
if (error || !body || body !== self.getHealthCheckUuid()) {
|
||||
callback(false);
|
||||
}
|
||||
else {
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
function checkNginxHealth(callback) {
|
||||
let callbackCalled = false;
|
||||
setTimeout(function () {
|
||||
if (callbackCalled) {
|
||||
return;
|
||||
}
|
||||
callbackCalled = true;
|
||||
callback(false);
|
||||
}, TIMEOUT_HEALTH_CHECK);
|
||||
self.verifyCaptainOwnsDomainOrThrow(captainPublicDomain, '-healthcheck')
|
||||
.then(function () {
|
||||
if (callbackCalled) {
|
||||
return;
|
||||
}
|
||||
callbackCalled = true;
|
||||
callback(true);
|
||||
})
|
||||
.catch(function () {
|
||||
if (callbackCalled) {
|
||||
return;
|
||||
}
|
||||
callbackCalled = true;
|
||||
callback(false);
|
||||
});
|
||||
}
|
||||
const checksPerformed = {};
|
||||
function scheduleIfNecessary() {
|
||||
if (!checksPerformed.captainHealth ||
|
||||
!checksPerformed.nginxHealth) {
|
||||
return;
|
||||
}
|
||||
let hasFailedCheck = false;
|
||||
if (!checksPerformed.captainHealth.value) {
|
||||
Logger.w('Captain health check failed: #' +
|
||||
self.consecutiveHealthCheckFailCount +
|
||||
' at ' +
|
||||
captainPublicDomain);
|
||||
hasFailedCheck = true;
|
||||
}
|
||||
if (!checksPerformed.nginxHealth.value) {
|
||||
Logger.w('NGINX health check failed: #' +
|
||||
self.consecutiveHealthCheckFailCount);
|
||||
hasFailedCheck = true;
|
||||
}
|
||||
if (hasFailedCheck) {
|
||||
self.consecutiveHealthCheckFailCount =
|
||||
self.consecutiveHealthCheckFailCount + 1;
|
||||
}
|
||||
else {
|
||||
self.consecutiveHealthCheckFailCount = 0;
|
||||
}
|
||||
scheduleNextHealthCheck();
|
||||
if (self.consecutiveHealthCheckFailCount > MAX_FAIL_ALLOWED) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
checkCaptainHealth(function (success) {
|
||||
checksPerformed.captainHealth = {
|
||||
value: success,
|
||||
};
|
||||
scheduleIfNecessary();
|
||||
});
|
||||
checkNginxHealth(function (success) {
|
||||
checksPerformed.nginxHealth = {
|
||||
value: success,
|
||||
};
|
||||
scheduleIfNecessary();
|
||||
});
|
||||
}
|
||||
getHealthCheckUuid() {
|
||||
return this.healthCheckUuid;
|
||||
}
|
||||
isInitialized() {
|
||||
return this.inited && !this.waitUntilRestarted;
|
||||
}
|
||||
getCaptainImageTags() {
|
||||
const url = 'https://hub.docker.com/v2/repositories/' +
|
||||
CaptainConstants.configs.publishedNameOnDockerHub +
|
||||
'/tags';
|
||||
return new Promise(function (resolve, reject) {
|
||||
request(url, function (error, response, body) {
|
||||
if (CaptainConstants.isDebug) {
|
||||
resolve(['v0.0.1']);
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
else if (!body || !JSON.parse(body).results) {
|
||||
reject(new Error('Received empty body or no result for version list on docker hub.'));
|
||||
}
|
||||
else {
|
||||
const results = JSON.parse(body).results;
|
||||
const tags = [];
|
||||
for (let idx = 0; idx < results.length; idx++) {
|
||||
tags.push(results[idx].name);
|
||||
}
|
||||
resolve(tags);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
updateCaptain(versionTag) {
|
||||
const self = this;
|
||||
return Promise.resolve().then(function () {
|
||||
return self.dockerApi.updateService(CaptainConstants.captainServiceName, CaptainConstants.configs.publishedNameOnDockerHub + ':' + versionTag, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
});
|
||||
}
|
||||
getMyNodeId() {
|
||||
if (!this.myNodeId) {
|
||||
const msg = 'myNodeId is not set yet!!';
|
||||
Logger.e(msg);
|
||||
throw new Error(msg);
|
||||
}
|
||||
return this.myNodeId;
|
||||
}
|
||||
getCaptainSalt() {
|
||||
if (!this.captainSalt) {
|
||||
const msg = 'Captain Salt is not set yet!!';
|
||||
Logger.e(msg);
|
||||
throw new Error(msg);
|
||||
}
|
||||
return this.captainSalt;
|
||||
}
|
||||
updateNetDataInfo(netDataInfo) {
|
||||
const self = this;
|
||||
const dockerApi = this.dockerApi;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return dockerApi.ensureContainerStoppedAndRemoved(CaptainConstants.netDataContainerName, CaptainConstants.captainNetworkName);
|
||||
})
|
||||
.then(function () {
|
||||
if (netDataInfo.isEnabled) {
|
||||
const vols = [
|
||||
{
|
||||
hostPath: '/proc',
|
||||
containerPath: '/host/proc',
|
||||
mode: 'ro',
|
||||
},
|
||||
{
|
||||
hostPath: '/sys',
|
||||
containerPath: '/host/sys',
|
||||
mode: 'ro',
|
||||
},
|
||||
{
|
||||
hostPath: '/var/run/docker.sock',
|
||||
containerPath: '/var/run/docker.sock',
|
||||
},
|
||||
];
|
||||
const envVars = [];
|
||||
if (netDataInfo.data.smtp) {
|
||||
envVars.push({
|
||||
key: 'SSMTP_TO',
|
||||
value: netDataInfo.data.smtp.to,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_HOSTNAME',
|
||||
value: netDataInfo.data.smtp.hostname,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_SERVER',
|
||||
value: netDataInfo.data.smtp.server,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_PORT',
|
||||
value: netDataInfo.data.smtp.port,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_TLS',
|
||||
value: netDataInfo.data.smtp.allowNonTls
|
||||
? 'NO'
|
||||
: 'YES',
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_USER',
|
||||
value: netDataInfo.data.smtp.username,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SSMTP_PASS',
|
||||
value: netDataInfo.data.smtp.password,
|
||||
});
|
||||
}
|
||||
if (netDataInfo.data.slack) {
|
||||
envVars.push({
|
||||
key: 'SLACK_WEBHOOK_URL',
|
||||
value: netDataInfo.data.slack.hook,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'SLACK_CHANNEL',
|
||||
value: netDataInfo.data.slack.channel,
|
||||
});
|
||||
}
|
||||
if (netDataInfo.data.telegram) {
|
||||
envVars.push({
|
||||
key: 'TELEGRAM_BOT_TOKEN',
|
||||
value: netDataInfo.data.telegram.botToken,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'TELEGRAM_CHAT_ID',
|
||||
value: netDataInfo.data.telegram.chatId,
|
||||
});
|
||||
}
|
||||
if (netDataInfo.data.pushBullet) {
|
||||
envVars.push({
|
||||
key: 'PUSHBULLET_ACCESS_TOKEN',
|
||||
value: netDataInfo.data.pushBullet.apiToken,
|
||||
});
|
||||
envVars.push({
|
||||
key: 'PUSHBULLET_DEFAULT_EMAIL',
|
||||
value: netDataInfo.data.pushBullet.fallbackEmail,
|
||||
});
|
||||
}
|
||||
return dockerApi.createStickyContainer(CaptainConstants.netDataContainerName, CaptainConstants.netDataImageName, vols, CaptainConstants.captainNetworkName, envVars, ['SYS_PTRACE']);
|
||||
}
|
||||
// Just removing the old container. No need to create a new one.
|
||||
return true;
|
||||
})
|
||||
.then(function () {
|
||||
return self.dataStore.setNetDataInfo(netDataInfo);
|
||||
});
|
||||
}
|
||||
getNodesInfo() {
|
||||
const dockerApi = this.dockerApi;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return dockerApi.getNodesInfo();
|
||||
})
|
||||
.then(function (data) {
|
||||
if (!data || !data.length) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'No cluster node was found!');
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
joinDockerNode(captainIpAddress, isManager, remoteNodeIpAddress, remoteUserName, privateKey) {
|
||||
const dockerApi = this.dockerApi;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return dockerApi.getJoinToken(isManager);
|
||||
})
|
||||
.then(function (token) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const conn = new SshClient();
|
||||
conn.on('error', function (err) {
|
||||
Logger.e(err);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'SSH Connection error!!'));
|
||||
})
|
||||
.on('ready', function () {
|
||||
Logger.d('SSH Client :: ready');
|
||||
conn.exec(dockerApi.createJoinCommand(captainIpAddress, token), function (err, stream) {
|
||||
if (err) {
|
||||
Logger.e(err);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'SSH Running command failed!!'));
|
||||
return;
|
||||
}
|
||||
let hasExisted = false;
|
||||
stream
|
||||
.on('close', function (code, signal) {
|
||||
Logger.d('Stream :: close :: code: ' +
|
||||
code +
|
||||
', signal: ' +
|
||||
signal);
|
||||
conn.end();
|
||||
if (hasExisted) {
|
||||
return;
|
||||
}
|
||||
hasExisted = true;
|
||||
resolve();
|
||||
})
|
||||
.on('data', function (data) {
|
||||
Logger.d('STDOUT: ' + data);
|
||||
})
|
||||
.stderr.on('data', function (data) {
|
||||
Logger.e('STDERR: ' + data);
|
||||
if (hasExisted) {
|
||||
return;
|
||||
}
|
||||
hasExisted = true;
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'Error during setup: ' +
|
||||
data));
|
||||
});
|
||||
});
|
||||
})
|
||||
.connect({
|
||||
host: remoteNodeIpAddress,
|
||||
port: 22,
|
||||
username: remoteUserName,
|
||||
privateKey: privateKey,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
getLoadBalanceManager() {
|
||||
return this.loadBalancerManager;
|
||||
}
|
||||
reloadLoadBalancer(datastore) {
|
||||
const self = this;
|
||||
return self.loadBalancerManager
|
||||
.rePopulateNginxConfigFile(datastore)
|
||||
.then(function () {
|
||||
Logger.d('sendReloadSignal...');
|
||||
return self.loadBalancerManager.sendReloadSignal();
|
||||
});
|
||||
}
|
||||
getDockerRegistry() {
|
||||
return this.dockerRegistry;
|
||||
}
|
||||
enableSsl(emailAddress) {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.certbotManager.ensureRegistered(emailAddress);
|
||||
})
|
||||
.then(function () {
|
||||
return self.certbotManager.enableSsl(CaptainConstants.captainSubDomain +
|
||||
'.' +
|
||||
self.dataStore.getRootDomain());
|
||||
})
|
||||
.then(function () {
|
||||
return self.dataStore.setUserEmailAddress(emailAddress);
|
||||
})
|
||||
.then(function () {
|
||||
return self.dataStore.setHasRootSsl(true);
|
||||
})
|
||||
.then(function () {
|
||||
return self.loadBalancerManager.rePopulateNginxConfigFile(self.dataStore);
|
||||
})
|
||||
.then(function () {
|
||||
return self.loadBalancerManager.sendReloadSignal();
|
||||
});
|
||||
}
|
||||
forceSsl(isEnabled) {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.dataStore.getHasRootSsl();
|
||||
})
|
||||
.then(function (hasRootSsl) {
|
||||
if (!hasRootSsl) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'You first need to enable SSL on the root domain before forcing it.');
|
||||
}
|
||||
return self.dataStore.setForceSsl(isEnabled);
|
||||
})
|
||||
.then(function () {
|
||||
return self.refreshForceSslState();
|
||||
});
|
||||
}
|
||||
refreshForceSslState() {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.dataStore.getForceSsl();
|
||||
})
|
||||
.then(function (hasForceSsl) {
|
||||
self.hasForceSsl = hasForceSsl;
|
||||
});
|
||||
}
|
||||
getForceSslValue() {
|
||||
return !!this.hasForceSsl;
|
||||
}
|
||||
/**
|
||||
* Returns a promise successfully if verification is succeeded. If it fails, it throws an exception.
|
||||
*
|
||||
* @param domainName the domain to verify, app.mycaptainroot.com or www.myawesomeapp.com
|
||||
* @param identifierSuffix an optional suffix to be added to the identifier file name to avoid name conflict
|
||||
*
|
||||
* @returns {Promise.<boolean>}
|
||||
*/
|
||||
verifyCaptainOwnsDomainOrThrow(domainName, identifierSuffix) {
|
||||
const self = this;
|
||||
const randomUuid = uuid();
|
||||
const captainConfirmationPath = CaptainConstants.captainConfirmationPath +
|
||||
(identifierSuffix ? identifierSuffix : '');
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.certbotManager.domainValidOrThrow(domainName);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.outputFile(CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir +
|
||||
'/' +
|
||||
domainName +
|
||||
captainConfirmationPath, randomUuid);
|
||||
})
|
||||
.then(function () {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(function () {
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const url = 'http://' +
|
||||
domainName +
|
||||
':' +
|
||||
CaptainConstants.nginxPortNumber +
|
||||
captainConfirmationPath;
|
||||
request(url, function (error, response, body) {
|
||||
if (error || !body || body !== randomUuid) {
|
||||
Logger.e('Verification Failed for ' + domainName);
|
||||
Logger.e('Error ' + error);
|
||||
Logger.e('body ' + body);
|
||||
Logger.e('randomUuid ' + randomUuid);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.VERIFICATION_FAILED, 'Verification Failed.'));
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
getNginxConfig() {
|
||||
const self = this;
|
||||
return Promise.resolve().then(function () {
|
||||
return self.dataStore.getNginxConfig();
|
||||
});
|
||||
}
|
||||
setNginxConfig(baseConfig, captainConfig) {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.dataStore.setNginxConfig(baseConfig, captainConfig);
|
||||
})
|
||||
.then(function () {
|
||||
self.resetSelf();
|
||||
});
|
||||
}
|
||||
requestCertificateForDomain(domainName) {
|
||||
return this.certbotManager.enableSsl(domainName);
|
||||
}
|
||||
verifyDomainResolvesToDefaultServerOnHost(domainName) {
|
||||
const self = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
const url = 'http://' +
|
||||
domainName +
|
||||
CaptainConstants.captainConfirmationPath;
|
||||
Logger.d('Sending request to ' + url);
|
||||
request(url, function (error, response, body) {
|
||||
if (error ||
|
||||
!body ||
|
||||
body !==
|
||||
self.loadBalancerManager.getCaptainPublicRandomKey()) {
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.VERIFICATION_FAILED, 'Verification Failed.'));
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
changeCaptainRootDomain(requestedCustomDomain) {
|
||||
const self = this;
|
||||
// Some DNS servers do not allow wild cards. Therefore this line may fail.
|
||||
// We still allow users to specify the domains in their DNS settings individually
|
||||
// SubDomains that need to be added are "captain." "registry." "app-name."
|
||||
const url = (CaptainConstants.configs.preCheckForWildCard
|
||||
? uuid()
|
||||
: CaptainConstants.captainSubDomain) +
|
||||
'.' +
|
||||
requestedCustomDomain +
|
||||
':' +
|
||||
CaptainConstants.nginxPortNumber;
|
||||
return self
|
||||
.verifyDomainResolvesToDefaultServerOnHost(url)
|
||||
.then(function () {
|
||||
return self.dataStore.getHasRootSsl();
|
||||
})
|
||||
.then(function (hasRootSsl) {
|
||||
if (hasRootSsl &&
|
||||
self.dataStore.getRootDomain() !== requestedCustomDomain) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'SSL is enabled for root. Too late to change your mind!');
|
||||
}
|
||||
return self.dataStore.setCustomDomain(requestedCustomDomain);
|
||||
})
|
||||
.then(function () {
|
||||
return self.reloadLoadBalancer(self.dataStore);
|
||||
});
|
||||
}
|
||||
resetSelf() {
|
||||
const self = this;
|
||||
Logger.d('Captain is resetting itself!');
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
const promiseToIgnore = self.dockerApi.updateService(CaptainConstants.captainServiceName, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
static get() {
|
||||
return captainManagerInstance;
|
||||
}
|
||||
}
|
||||
const captainManagerInstance = new CaptainManager();
|
||||
module.exports = CaptainManager;
|
||||
//# sourceMappingURL=CaptainManager.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,288 @@
|
||||
"use strict";
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const fs = require("fs-extra");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const CAPTAIN_WEBROOT_PATH_CERTBOT = '/captain-webroot';
|
||||
const shouldUseStaging = false; // CaptainConstants.isDebug;
|
||||
class CertbotManager {
|
||||
constructor(dockerApi) {
|
||||
this.dockerApi = dockerApi;
|
||||
this.dockerApi = dockerApi;
|
||||
}
|
||||
domainValidOrThrow(domainName) {
|
||||
if (!domainName) {
|
||||
throw new Error('Domain Name is empty');
|
||||
}
|
||||
const RegExpression = /^[a-z0-9\.\-]*$/;
|
||||
if (!RegExpression.test(domainName)) {
|
||||
throw new Error('Bad Domain Name!');
|
||||
}
|
||||
}
|
||||
getCertRelativePathForDomain(domainName) {
|
||||
const self = this;
|
||||
self.domainValidOrThrow(domainName);
|
||||
return '/live/' + domainName + '/fullchain.pem';
|
||||
}
|
||||
getKeyRelativePathForDomain(domainName) {
|
||||
const self = this;
|
||||
self.domainValidOrThrow(domainName);
|
||||
return '/live/' + domainName + '/privkey.pem';
|
||||
}
|
||||
enableSsl(domainName) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const self = this;
|
||||
Logger.d('Enabling SSL for ' + domainName);
|
||||
self.domainValidOrThrow(domainName);
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
const webrootInCaptainContainer = CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir +
|
||||
'/' +
|
||||
domainName;
|
||||
return fs.ensureDir(webrootInCaptainContainer);
|
||||
})
|
||||
.then(function () {
|
||||
const cmd = [
|
||||
'certbot',
|
||||
'certonly',
|
||||
'--webroot',
|
||||
'-w',
|
||||
CAPTAIN_WEBROOT_PATH_CERTBOT + '/' + domainName,
|
||||
'-d',
|
||||
domainName,
|
||||
'--non-interactive',
|
||||
];
|
||||
if (shouldUseStaging) {
|
||||
cmd.push('--staging');
|
||||
}
|
||||
return self.runCommand(cmd).then(function (output) {
|
||||
Logger.d(output);
|
||||
if (output.indexOf('Congratulations! Your certificate and chain have been saved') >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (output.indexOf('Certificate not yet due for renewal; no action taken') >= 0) {
|
||||
return true;
|
||||
}
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.VERIFICATION_FAILED, 'Unexpected output when enabling SSL for' +
|
||||
domainName +
|
||||
' with ACME Certbot \n' +
|
||||
output);
|
||||
});
|
||||
});
|
||||
}
|
||||
ensureRegistered(emailAddress) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
const rootPathDir = CaptainConstants.letsEncryptEtcPath +
|
||||
'/accounts/acme-' +
|
||||
(shouldUseStaging ? 'staging' : 'v01') +
|
||||
'.api.letsencrypt.org/directory';
|
||||
if (!fs.existsSync(rootPathDir)) {
|
||||
Logger.d('Fresh install of Certbot. There is no registration directory');
|
||||
return undefined;
|
||||
}
|
||||
const files = fs.readdirSync(rootPathDir);
|
||||
if (files.length === 0) {
|
||||
Logger.d('Fresh install of Certbot. There is nothing in the registration directory');
|
||||
return undefined;
|
||||
}
|
||||
if (files.length !== 1) {
|
||||
throw new Error('I do not know know what to do when there are multiple directories in ' +
|
||||
rootPathDir);
|
||||
}
|
||||
const regFilePath = rootPathDir + '/' + files[0] + '/regr.json';
|
||||
if (!fs.existsSync(regFilePath)) {
|
||||
throw new Error('ACME Reg directory exists, but there is no file! ' +
|
||||
regFilePath);
|
||||
}
|
||||
return fs.readJson(regFilePath);
|
||||
})
|
||||
.then(function (regrContent) {
|
||||
if (!regrContent) {
|
||||
const cmd = [
|
||||
'certbot',
|
||||
'register',
|
||||
'--email',
|
||||
emailAddress,
|
||||
'--agree-tos',
|
||||
'--no-eff-email',
|
||||
'--non-interactive',
|
||||
];
|
||||
if (shouldUseStaging) {
|
||||
cmd.push('--staging');
|
||||
}
|
||||
return self.runCommand(cmd).then(function (registerOutput) {
|
||||
if (registerOutput.indexOf('Your account credentials have been saved in your Certbot') >= 0) {
|
||||
return true;
|
||||
}
|
||||
throw new Error('Unexpected output when registering with ACME Certbot \n' +
|
||||
registerOutput);
|
||||
});
|
||||
}
|
||||
else {
|
||||
/*
|
||||
|
||||
/etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/864339b5816d33d67743 # cat regr.json
|
||||
|
||||
{
|
||||
"body":{
|
||||
"contact":[
|
||||
"mailto:testemail@gmail.com"
|
||||
],
|
||||
"agreement":"https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf",
|
||||
"key":{
|
||||
"e":"AQAB",
|
||||
"kty":"RSA",
|
||||
"n":"1l-5ihAl0BFSiS3Pl3LjQ"
|
||||
}
|
||||
},
|
||||
"uri":"https://acme-v01.api.letsencrypt.org/acme/reg/0421",
|
||||
"new_authzr_uri":"https://acme-v01.api.letsencrypt.org/acme/new-authz",
|
||||
"terms_of_service":"https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
|
||||
}
|
||||
|
||||
*/
|
||||
let contact = undefined;
|
||||
if (regrContent &&
|
||||
regrContent.body &&
|
||||
regrContent.body.contact &&
|
||||
Array.isArray(regrContent.body.contact)) {
|
||||
contact = regrContent.body.contact;
|
||||
for (let idx = 0; idx < contact.length; idx++) {
|
||||
if (contact[idx] === 'mailto:' + emailAddress) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error('Previously registered with a different address: ' +
|
||||
contact
|
||||
? JSON.stringify(contact)
|
||||
: 'NULL');
|
||||
}
|
||||
});
|
||||
}
|
||||
runCommand(cmd) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const self = this;
|
||||
return Promise.resolve().then(function () {
|
||||
return dockerApi.executeCommand(CaptainConstants.certbotServiceName, cmd);
|
||||
});
|
||||
}
|
||||
renewAllCerts() {
|
||||
const self = this;
|
||||
/*
|
||||
From Certbot docs:
|
||||
This command attempts to renew all previously-obtained certificates that expire in less than 30 days.
|
||||
The same plugin and options that were used at the time the certificate was originally issued will be
|
||||
used for the renewal attempt, unless you specify other plugins or options. Unlike certonly, renew
|
||||
acts on multiple certificates and always takes into account whether each one is near expiry. Because
|
||||
of this, renew is suitable (and designed) for automated use, to allow your system to automatically
|
||||
renew each certificate when appropriate. Since renew only renews certificates that are near expiry
|
||||
it can be run as frequently as you want - since it will usually take no action.
|
||||
*/
|
||||
// before doing renewal, let's schedule the next one in 20.3 hours!
|
||||
// this random schedule helps to avoid retrying at the same time of
|
||||
// the day in case if that's our super high traffic time
|
||||
setTimeout(function () {
|
||||
self.renewAllCerts();
|
||||
}, 1000 * 3600 * 20.3);
|
||||
const cmd = ['certbot', 'renew'];
|
||||
if (shouldUseStaging) {
|
||||
cmd.push('--staging');
|
||||
}
|
||||
return self.runCommand(cmd).then(function (output) {
|
||||
// Ignore output :)
|
||||
});
|
||||
}
|
||||
init(myNodeId) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const self = this;
|
||||
const domainSpecificRootDirectoryInHost = CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir;
|
||||
function createCertbotServiceOnNode(nodeId) {
|
||||
return dockerApi
|
||||
.createServiceOnNodeId(CaptainConstants.certbotImageName, CaptainConstants.certbotServiceName, undefined, nodeId, undefined, undefined, undefined)
|
||||
.then(function () {
|
||||
const waitTimeInMillis = 5000;
|
||||
Logger.d('Waiting for ' +
|
||||
waitTimeInMillis / 1000 +
|
||||
' seconds for Certbot to start up');
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
resolve(true);
|
||||
}, waitTimeInMillis);
|
||||
});
|
||||
});
|
||||
}
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.letsEncryptEtcPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.letsEncryptLibPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(domainSpecificRootDirectoryInHost);
|
||||
})
|
||||
.then(function () {
|
||||
return dockerApi.isServiceRunningByName(CaptainConstants.certbotServiceName);
|
||||
})
|
||||
.then(function (isRunning) {
|
||||
if (isRunning) {
|
||||
Logger.d('Captain Certbot is already running.. ');
|
||||
return dockerApi.getNodeIdByServiceName(CaptainConstants.certbotServiceName, 0);
|
||||
}
|
||||
else {
|
||||
Logger.d('No Captain Certbot service is running. Creating one...');
|
||||
return createCertbotServiceOnNode(myNodeId).then(function () {
|
||||
return myNodeId;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function (nodeId) {
|
||||
if (nodeId !== myNodeId) {
|
||||
Logger.d('Captain Certbot is running on a different node. Removing...');
|
||||
return dockerApi
|
||||
.removeServiceByName(CaptainConstants.certbotServiceName)
|
||||
.then(function () {
|
||||
return createCertbotServiceOnNode(myNodeId).then(function () {
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Updating Certbot service...');
|
||||
return dockerApi.updateService(CaptainConstants.certbotServiceName, undefined, [
|
||||
{
|
||||
hostPath: CaptainConstants.letsEncryptEtcPath,
|
||||
containerPath: '/etc/letsencrypt',
|
||||
},
|
||||
{
|
||||
hostPath: CaptainConstants.letsEncryptLibPath,
|
||||
containerPath: '/var/lib/letsencrypt',
|
||||
},
|
||||
{
|
||||
hostPath: domainSpecificRootDirectoryInHost,
|
||||
containerPath: CAPTAIN_WEBROOT_PATH_CERTBOT,
|
||||
},
|
||||
],
|
||||
// No need to certbot to be connected to the network
|
||||
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
})
|
||||
.then(function () {
|
||||
// schedule the first attempt to renew certs in 1 minute
|
||||
setTimeout(function () {
|
||||
self.renewAllCerts();
|
||||
}, 1000 * 60);
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = CertbotManager;
|
||||
//# sourceMappingURL=CertbotManager.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,393 @@
|
||||
"use strict";
|
||||
const ejs = require("ejs");
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const fs = require("fs-extra");
|
||||
const uuid = require("uuid/v4");
|
||||
const request = require("request");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const defaultPageTemplate = fs
|
||||
.readFileSync(__dirname + '/../../template/default-page.ejs')
|
||||
.toString();
|
||||
class LoadBalancerManager {
|
||||
constructor(dockerApi, certbotManager, dataStore) {
|
||||
this.dockerApi = dockerApi;
|
||||
this.certbotManager = certbotManager;
|
||||
this.dataStore = dataStore;
|
||||
this.reloadInProcess = false;
|
||||
this.requestedReloadPromises = [];
|
||||
this.captainPublicRandomKey = uuid();
|
||||
}
|
||||
/**
|
||||
* Reloads the configuation for NGINX.
|
||||
* NOTE that this can return synchronously with UNDEFINED if there is already a process in the background.
|
||||
* @param dataStoreToQueue
|
||||
* @returns {Promise.<>}
|
||||
*/
|
||||
rePopulateNginxConfigFile(dataStoreToQueue) {
|
||||
const self = this;
|
||||
return new Promise(function (res, rej) {
|
||||
self.requestedReloadPromises.push({
|
||||
dataStore: dataStoreToQueue,
|
||||
resolve: res,
|
||||
reject: rej,
|
||||
});
|
||||
self.consumeQueueIfAnyInNginxReloadQueue();
|
||||
});
|
||||
}
|
||||
consumeQueueIfAnyInNginxReloadQueue() {
|
||||
const self = this;
|
||||
const q = self.requestedReloadPromises.pop();
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
if (self.reloadInProcess) {
|
||||
Logger.d('NGINX Reload already in process, Bouncing off...');
|
||||
return;
|
||||
}
|
||||
Logger.d('Locking NGINX configuration reloading...');
|
||||
self.reloadInProcess = true;
|
||||
const dataStore = q.dataStore;
|
||||
// This will resolve to something like: /captain/nginx/conf.d/captain
|
||||
const configFilePathBase = CaptainConstants.perAppNginxConfigPathBase +
|
||||
'/' +
|
||||
dataStore.getNameSpace();
|
||||
const FUTURE = configFilePathBase + '.fut';
|
||||
const BACKUP = configFilePathBase + '.bak';
|
||||
const CONFIG = configFilePathBase + '.conf';
|
||||
let nginxConfigContent = '';
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return fs.remove(FUTURE);
|
||||
})
|
||||
.then(function () {
|
||||
return dataStore.getServerList();
|
||||
})
|
||||
.then(function (servers) {
|
||||
const promises = [];
|
||||
if (servers && !!servers.length) {
|
||||
for (let i = 0; i < servers.length; i++) {
|
||||
const s = servers[i];
|
||||
if (s.hasSsl) {
|
||||
s.crtPath = self.getSslCertPath(s.publicDomain);
|
||||
s.keyPath = self.getSslKeyPath(s.publicDomain);
|
||||
}
|
||||
s.staticWebRoot =
|
||||
CaptainConstants.nginxStaticRootDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir +
|
||||
'/' +
|
||||
s.publicDomain;
|
||||
promises.push(Promise.resolve()
|
||||
.then(function () {
|
||||
return ejs.render(s.nginxConfigTemplate, {
|
||||
s: s,
|
||||
});
|
||||
})
|
||||
.then(function (rendered) {
|
||||
nginxConfigContent += rendered;
|
||||
}));
|
||||
}
|
||||
}
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.outputFile(FUTURE, nginxConfigContent);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.remove(BACKUP);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureFile(CONFIG);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.renameSync(CONFIG, BACKUP); // sync method. It's really fast.
|
||||
})
|
||||
.then(function () {
|
||||
return fs.renameSync(FUTURE, CONFIG); // sync method. It's really fast.
|
||||
})
|
||||
.then(function () {
|
||||
return self.createRootConfFile(dataStore);
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('SUCCESS: UNLocking NGINX configuration reloading...');
|
||||
self.reloadInProcess = false;
|
||||
q.resolve();
|
||||
self.consumeQueueIfAnyInNginxReloadQueue();
|
||||
})
|
||||
.catch(function (error) {
|
||||
Logger.e(error);
|
||||
Logger.d('Error: UNLocking NGINX configuration reloading...');
|
||||
self.reloadInProcess = false;
|
||||
q.reject(error);
|
||||
self.consumeQueueIfAnyInNginxReloadQueue();
|
||||
});
|
||||
}
|
||||
sendReloadSignal() {
|
||||
return this.dockerApi.sendSingleContainerKillHUP(CaptainConstants.nginxServiceName);
|
||||
}
|
||||
getCaptainPublicRandomKey() {
|
||||
return this.captainPublicRandomKey;
|
||||
}
|
||||
getSslCertPath(domainName) {
|
||||
const self = this;
|
||||
return (CaptainConstants.letsEncryptEtcPathOnNginx +
|
||||
self.certbotManager.getCertRelativePathForDomain(domainName));
|
||||
}
|
||||
getSslKeyPath(domainName) {
|
||||
const self = this;
|
||||
return (CaptainConstants.letsEncryptEtcPathOnNginx +
|
||||
self.certbotManager.getKeyRelativePathForDomain(domainName));
|
||||
}
|
||||
getInfo() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const url = 'http://' + CaptainConstants.nginxServiceName + '/nginx_status';
|
||||
request(url, function (error, response, body) {
|
||||
if (error || !body) {
|
||||
Logger.e('Error ' + error);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'Request to nginx Failed.'));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = new LoadBalancerInfo();
|
||||
const lines = body.split('\n');
|
||||
data.activeConnections = Number(lines[0].split(' ')[2].trim());
|
||||
data.accepted = Number(lines[2].split(' ')[1].trim());
|
||||
data.handled = Number(lines[2].split(' ')[2].trim());
|
||||
data.total = Number(lines[2].split(' ')[3].trim());
|
||||
data.reading = Number(lines[3].split(' ')[1].trim());
|
||||
data.writing = Number(lines[3].split(' ')[3].trim());
|
||||
data.waiting = Number(lines[3].split(' ')[5].trim());
|
||||
resolve(data);
|
||||
}
|
||||
catch (error) {
|
||||
Logger.e('Cannot parse ' + body);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'Parser Failed. See internal logs...'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
createRootConfFile(dataStore) {
|
||||
const self = this;
|
||||
const captainDomain = CaptainConstants.captainSubDomain + '.' + dataStore.getRootDomain();
|
||||
const registryDomain = CaptainConstants.registrySubDomain + '.' + dataStore.getRootDomain();
|
||||
let hasRootSsl = false;
|
||||
const FUTURE = CaptainConstants.rootNginxConfigPath + '.fut';
|
||||
const BACKUP = CaptainConstants.rootNginxConfigPath + '.bak';
|
||||
const CONFIG = CaptainConstants.rootNginxConfigPath + '.conf';
|
||||
let rootNginxTemplate = undefined;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return dataStore.getNginxConfig();
|
||||
})
|
||||
.then(function (nginxConfig) {
|
||||
rootNginxTemplate =
|
||||
nginxConfig.captainConfig.customValue ||
|
||||
nginxConfig.captainConfig.byDefault;
|
||||
return dataStore.getHasRootSsl();
|
||||
})
|
||||
.then(function (hasSsl) {
|
||||
hasRootSsl = hasSsl;
|
||||
return dataStore.getHasRegistrySsl();
|
||||
})
|
||||
.then(function (hasRegistrySsl) {
|
||||
return ejs.render(rootNginxTemplate, {
|
||||
captain: {
|
||||
crtPath: self.getSslCertPath(captainDomain),
|
||||
keyPath: self.getSslKeyPath(captainDomain),
|
||||
hasRootSsl: hasRootSsl,
|
||||
serviceName: CaptainConstants.captainServiceName,
|
||||
domain: captainDomain,
|
||||
serviceExposedPort: CaptainConstants.captainServiceExposedPort,
|
||||
defaultHtmlDir: CaptainConstants.nginxStaticRootDir +
|
||||
CaptainConstants.nginxDefaultHtmlDir,
|
||||
staticWebRoot: CaptainConstants.nginxStaticRootDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir +
|
||||
'/' +
|
||||
captainDomain,
|
||||
},
|
||||
registry: {
|
||||
crtPath: self.getSslCertPath(registryDomain),
|
||||
keyPath: self.getSslKeyPath(registryDomain),
|
||||
hasRootSsl: hasRegistrySsl,
|
||||
domain: registryDomain,
|
||||
staticWebRoot: CaptainConstants.nginxStaticRootDir +
|
||||
CaptainConstants.nginxDomainSpecificHtmlDir +
|
||||
'/' +
|
||||
registryDomain,
|
||||
},
|
||||
});
|
||||
})
|
||||
.then(function (rootNginxConfContent) {
|
||||
return fs.outputFile(FUTURE, rootNginxConfContent);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.remove(BACKUP);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureFile(CONFIG);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.renameSync(CONFIG, BACKUP); // sync method. It's really fast.
|
||||
})
|
||||
.then(function () {
|
||||
return fs.renameSync(FUTURE, CONFIG); // sync method. It's really fast.
|
||||
});
|
||||
}
|
||||
ensureBaseNginxConf() {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.dataStore.getNginxConfig();
|
||||
})
|
||||
.then(function (captainConfig) {
|
||||
const baseConfigTemplate = captainConfig.baseConfig.customValue ||
|
||||
captainConfig.baseConfig.byDefault;
|
||||
return ejs.render(baseConfigTemplate, {});
|
||||
})
|
||||
.then(function (baseNginxConfFileContent) {
|
||||
return fs.outputFile(CaptainConstants.baseNginxConfigPath, baseNginxConfFileContent);
|
||||
});
|
||||
}
|
||||
init(myNodeId, dataStore) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const self = this;
|
||||
function createNginxServiceOnNode(nodeId) {
|
||||
Logger.d('No Captain Nginx service is running. Creating one on captain node...');
|
||||
return dockerApi
|
||||
.createServiceOnNodeId(CaptainConstants.nginxImageName, CaptainConstants.nginxServiceName, [
|
||||
{
|
||||
protocol: 'tcp',
|
||||
publishMode: 'host',
|
||||
containerPort: 80,
|
||||
hostPort: CaptainConstants.nginxPortNumber,
|
||||
},
|
||||
{
|
||||
protocol: 'tcp',
|
||||
publishMode: 'host',
|
||||
containerPort: 443,
|
||||
hostPort: 443,
|
||||
},
|
||||
], nodeId, undefined, undefined, {
|
||||
Reservation: {
|
||||
MemoryBytes: 30 * 1024 * 1024,
|
||||
},
|
||||
})
|
||||
.then(function () {
|
||||
const waitTimeInMillis = 5000;
|
||||
Logger.d('Waiting for ' +
|
||||
waitTimeInMillis / 1000 +
|
||||
' seconds for nginx to start up');
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
resolve(true);
|
||||
}, waitTimeInMillis);
|
||||
});
|
||||
});
|
||||
}
|
||||
return fs
|
||||
.outputFile(CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDefaultHtmlDir +
|
||||
CaptainConstants.captainConfirmationPath, self.getCaptainPublicRandomKey())
|
||||
.then(function () {
|
||||
return ejs.render(defaultPageTemplate, {
|
||||
message: 'Nothing here yet :/',
|
||||
});
|
||||
})
|
||||
.then(function (staticPageContent) {
|
||||
return fs.outputFile(CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDefaultHtmlDir +
|
||||
'/index.html', staticPageContent);
|
||||
})
|
||||
.then(function () {
|
||||
return ejs.render(defaultPageTemplate, {
|
||||
message: 'An Error Occurred :/',
|
||||
});
|
||||
})
|
||||
.then(function (errorPageContent) {
|
||||
return fs.outputFile(CaptainConstants.captainStaticFilesDir +
|
||||
CaptainConstants.nginxDefaultHtmlDir +
|
||||
'/error.html', errorPageContent);
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Setting up NGINX conf file...');
|
||||
return self.ensureBaseNginxConf();
|
||||
})
|
||||
.then(function () {
|
||||
return self.rePopulateNginxConfigFile(dataStore);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.letsEncryptEtcPath);
|
||||
})
|
||||
.then(function () {
|
||||
return fs.ensureDir(CaptainConstants.nginxSharedPathOnHost);
|
||||
})
|
||||
.then(function () {
|
||||
return dockerApi.isServiceRunningByName(CaptainConstants.nginxServiceName);
|
||||
})
|
||||
.then(function (isRunning) {
|
||||
if (isRunning) {
|
||||
Logger.d('Captain Nginx is already running.. ');
|
||||
return dockerApi.getNodeIdByServiceName(CaptainConstants.nginxServiceName, 0);
|
||||
}
|
||||
else {
|
||||
return createNginxServiceOnNode(myNodeId).then(function () {
|
||||
return myNodeId;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function (nodeId) {
|
||||
if (nodeId !== myNodeId) {
|
||||
Logger.d('Captain Nginx is running on a different node. Removing...');
|
||||
return dockerApi
|
||||
.removeServiceByName(CaptainConstants.nginxServiceName)
|
||||
.then(function () {
|
||||
return createNginxServiceOnNode(myNodeId).then(function () {
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d('Updating NGINX service...');
|
||||
return dockerApi.updateService(CaptainConstants.nginxServiceName, undefined, [
|
||||
{
|
||||
containerPath: CaptainConstants.nginxStaticRootDir,
|
||||
hostPath: CaptainConstants.captainStaticFilesDir,
|
||||
},
|
||||
{
|
||||
containerPath: '/etc/nginx/nginx.conf',
|
||||
hostPath: CaptainConstants.baseNginxConfigPath,
|
||||
},
|
||||
{
|
||||
containerPath: '/etc/nginx/conf.d',
|
||||
hostPath: CaptainConstants.perAppNginxConfigPathBase,
|
||||
},
|
||||
{
|
||||
containerPath: CaptainConstants.letsEncryptEtcPathOnNginx,
|
||||
hostPath: CaptainConstants.letsEncryptEtcPath,
|
||||
},
|
||||
{
|
||||
containerPath: CaptainConstants.nginxSharedPathOnNginx,
|
||||
hostPath: CaptainConstants.nginxSharedPathOnHost,
|
||||
},
|
||||
], [CaptainConstants.captainNetworkName], undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
})
|
||||
.then(function () {
|
||||
const waitTimeInMillis = 5000;
|
||||
Logger.d('Waiting for ' +
|
||||
waitTimeInMillis / 1000 +
|
||||
' seconds for nginx reload to take into effect');
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
Logger.d('NGINX is fully set up and working...');
|
||||
resolve(true);
|
||||
}, waitTimeInMillis);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = LoadBalancerManager;
|
||||
//# sourceMappingURL=LoadBalancerManager.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,156 @@
|
||||
"use strict";
|
||||
const CaptainConstants = require("../../utils/CaptainConstants");
|
||||
const Logger = require("../../utils/Logger");
|
||||
const fs = require("fs-extra");
|
||||
const ApiStatusCodes = require("../../api/ApiStatusCodes");
|
||||
const bcrypt = require("bcryptjs");
|
||||
class SelfHostedDockerRegistry {
|
||||
constructor(dockerApi, dataStore, certbotManager, loadBalancerManager, captainManager) {
|
||||
this.dockerApi = dockerApi;
|
||||
this.dataStore = dataStore;
|
||||
this.certbotManager = certbotManager;
|
||||
this.loadBalancerManager = loadBalancerManager;
|
||||
this.captainManager = captainManager;
|
||||
//
|
||||
}
|
||||
enableRegistrySsl() {
|
||||
const self = this;
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.dataStore.getHasRootSsl();
|
||||
})
|
||||
.then(function (rootHasSsl) {
|
||||
if (!rootHasSsl) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.ILLEGAL_OPERATION, 'Root must have SSL before enabling ssl for docker registry.');
|
||||
}
|
||||
return self.certbotManager.enableSsl(CaptainConstants.registrySubDomain +
|
||||
'.' +
|
||||
self.dataStore.getRootDomain());
|
||||
})
|
||||
.then(function () {
|
||||
return self.dataStore.setHasRegistrySsl(true);
|
||||
})
|
||||
.then(function () {
|
||||
return self.loadBalancerManager.rePopulateNginxConfigFile(self.dataStore);
|
||||
})
|
||||
.then(function () {
|
||||
return self.loadBalancerManager.sendReloadSignal();
|
||||
});
|
||||
}
|
||||
getLocalRegistryDomainAndPort() {
|
||||
const self = this;
|
||||
return (CaptainConstants.registrySubDomain +
|
||||
'.' +
|
||||
self.dataStore.getRootDomain() +
|
||||
':' +
|
||||
CaptainConstants.configs.registrySubDomainPort);
|
||||
}
|
||||
ensureServiceRemoved() {
|
||||
const dockerApi = this.dockerApi;
|
||||
return Promise.resolve() //
|
||||
.then(function () {
|
||||
return dockerApi.isServiceRunningByName(CaptainConstants.registryServiceName);
|
||||
})
|
||||
.then(function (isRunning) {
|
||||
if (!isRunning)
|
||||
return;
|
||||
return dockerApi.removeServiceByName(CaptainConstants.registryServiceName);
|
||||
});
|
||||
}
|
||||
ensureDockerRegistryRunningOnThisNode(password) {
|
||||
const dockerApi = this.dockerApi;
|
||||
const dataStore = this.dataStore;
|
||||
const myNodeId = this.captainManager.getMyNodeId();
|
||||
function createRegistryServiceOnNode() {
|
||||
return dockerApi.createServiceOnNodeId(CaptainConstants.registryImageName, CaptainConstants.registryServiceName, [
|
||||
{
|
||||
protocol: 'tcp',
|
||||
containerPort: 5000,
|
||||
hostPort: CaptainConstants.configs.registrySubDomainPort,
|
||||
},
|
||||
], myNodeId, [
|
||||
{
|
||||
containerPath: '/cert-files',
|
||||
hostPath: CaptainConstants.letsEncryptEtcPath,
|
||||
},
|
||||
{
|
||||
containerPath: '/var/lib/registry',
|
||||
hostPath: CaptainConstants.registryPathOnHost,
|
||||
},
|
||||
{
|
||||
containerPath: '/etc/auth',
|
||||
hostPath: CaptainConstants.registryAuthPathOnHost,
|
||||
},
|
||||
], [
|
||||
{
|
||||
key: 'REGISTRY_HTTP_TLS_CERTIFICATE',
|
||||
value: '/cert-files/live/' +
|
||||
CaptainConstants.registrySubDomain +
|
||||
'.' +
|
||||
dataStore.getRootDomain() +
|
||||
'/fullchain.pem',
|
||||
},
|
||||
{
|
||||
key: 'REGISTRY_HTTP_TLS_KEY',
|
||||
value: '/cert-files/live/' +
|
||||
CaptainConstants.registrySubDomain +
|
||||
'.' +
|
||||
dataStore.getRootDomain() +
|
||||
'/privkey.pem',
|
||||
},
|
||||
{
|
||||
key: 'REGISTRY_AUTH',
|
||||
value: 'htpasswd',
|
||||
},
|
||||
{
|
||||
key: 'REGISTRY_AUTH_HTPASSWD_REALM',
|
||||
value: 'Registry Realm',
|
||||
},
|
||||
{
|
||||
key: 'REGISTRY_AUTH_HTPASSWD_PATH',
|
||||
value: '/etc/auth',
|
||||
},
|
||||
], undefined);
|
||||
}
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
const authContent = CaptainConstants.captainRegistryUsername +
|
||||
':' +
|
||||
bcrypt.hashSync(password, bcrypt.genSaltSync(5));
|
||||
return fs.outputFile(CaptainConstants.registryAuthPathOnHost, authContent);
|
||||
})
|
||||
.then(function () {
|
||||
return dockerApi.isServiceRunningByName(CaptainConstants.registryServiceName);
|
||||
})
|
||||
.then(function (isRunning) {
|
||||
if (isRunning) {
|
||||
Logger.d('Captain Registry is already running.. ');
|
||||
return dockerApi.getNodeIdByServiceName(CaptainConstants.registryServiceName, 0);
|
||||
}
|
||||
else {
|
||||
Logger.d('No Captain Registry service is running. Creating one...');
|
||||
return createRegistryServiceOnNode().then(function () {
|
||||
return myNodeId;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function (nodeId) {
|
||||
if (nodeId !== myNodeId) {
|
||||
Logger.d('Captain Registry is running on a different node. Removing...');
|
||||
return dockerApi
|
||||
.removeServiceByName(CaptainConstants.registryServiceName)
|
||||
.then(function () {
|
||||
Logger.d('Creating Registry on this node...');
|
||||
return createRegistryServiceOnNode().then(function () {
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = SelfHostedDockerRegistry;
|
||||
//# sourceMappingURL=SelfHostedDockerRegistry.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"SelfHostedDockerRegistry.js","sourceRoot":"","sources":["../../../src/user/system/SelfHostedDockerRegistry.ts"],"names":[],"mappings":"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"}
|
||||
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
const request = require("request");
|
||||
const ApiStatusCodes = require("../api/ApiStatusCodes");
|
||||
const Logger = require("./Logger");
|
||||
function getTagsForImage(imageBaseName, url, allTags) {
|
||||
if (!url) {
|
||||
url =
|
||||
'https://hub.docker.com/v2/repositories/' + imageBaseName + '/tags';
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
request(url, function (error, response, body) {
|
||||
if (error || !body) {
|
||||
Logger.e(error);
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Sometimes Docker server is down and it crashes Captain!
|
||||
body = JSON.parse(body);
|
||||
}
|
||||
catch (e) {
|
||||
Logger.e(e);
|
||||
}
|
||||
let results;
|
||||
if (body) {
|
||||
results = body.results;
|
||||
}
|
||||
if (!results) {
|
||||
Logger.e('NO RESULT');
|
||||
reject(new Error('NO RESULT'));
|
||||
return;
|
||||
}
|
||||
if (!allTags) {
|
||||
allTags = [];
|
||||
}
|
||||
for (let idx = 0; idx < results.length; idx++) {
|
||||
allTags.push(results[idx].name);
|
||||
}
|
||||
if (body.next) {
|
||||
resolve(getTagsForImage(imageBaseName, body.next, allTags));
|
||||
return;
|
||||
}
|
||||
resolve(allTags);
|
||||
});
|
||||
});
|
||||
}
|
||||
function firstEndsWithSecond(str1, str2) {
|
||||
if (!str1 || !str2) {
|
||||
throw new Error('Str1 or Str2 are null ' + !str1 + ' ' + !str2);
|
||||
}
|
||||
const idx = str1.indexOf(str2);
|
||||
return idx >= 0 && idx + str2.length === str1.length;
|
||||
}
|
||||
function isEmpty(obj) {
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
class TemplateHelperVersionPrinter {
|
||||
constructor() {
|
||||
this.cachedImageTags = {};
|
||||
}
|
||||
getDockerVersionsForTemplateName(templateObj) {
|
||||
const self = this;
|
||||
if (isEmpty(this.cachedImageTags)) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'Please wait about 30 seconds, then try again.');
|
||||
}
|
||||
const tags = self.cachedImageTags[templateObj.dockerHubImageName];
|
||||
const dockerVersions = [];
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
const t = tags[i];
|
||||
if (firstEndsWithSecond(t, templateObj.tagSuffix)) {
|
||||
dockerVersions.push(t.substring(0, t.length - templateObj.tagSuffix.length));
|
||||
}
|
||||
}
|
||||
return dockerVersions;
|
||||
}
|
||||
printAvailableImageTagsForReadme(templates) {
|
||||
const self = this;
|
||||
self.cachedImageTags = {};
|
||||
const tempCache = {};
|
||||
for (let i = 0; i < templates.length; i++) {
|
||||
const currentImageName = templates[i].dockerHubImageName;
|
||||
getTagsForImage(currentImageName, undefined, undefined)
|
||||
.then(function (tags) {
|
||||
tempCache[currentImageName] = tags;
|
||||
let isAllDone = true;
|
||||
for (let j = 0; j < templates.length; j++) {
|
||||
const imageName = templates[j].dockerHubImageName;
|
||||
if (!tempCache[imageName]) {
|
||||
isAllDone = false;
|
||||
}
|
||||
}
|
||||
if (isAllDone) {
|
||||
Logger.d('Template Cache Updated!');
|
||||
self.cachedImageTags = tempCache;
|
||||
// Used for README
|
||||
for (let tempIdx = 0; tempIdx < templates.length; tempIdx++) {
|
||||
Logger.d(' ');
|
||||
Logger.d(templates[tempIdx].templateName + '/');
|
||||
Logger.d(self
|
||||
.getDockerVersionsForTemplateName(templates[tempIdx])
|
||||
.join(', '));
|
||||
Logger.d(' ');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
Logger.e(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = TemplateHelperVersionPrinter;
|
||||
//# sourceMappingURL=TemplateHelperVersionPrinter.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"TemplateHelperVersionPrinter.js","sourceRoot":"","sources":["../../src/utils/TemplateHelperVersionPrinter.ts"],"names":[],"mappings":"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"}
|
||||
@@ -6,7 +6,7 @@ import cookieParser = require('cookie-parser')
|
||||
import bodyParser = require('body-parser')
|
||||
import httpProxyImport = require('http-proxy')
|
||||
|
||||
import CaptainManager = require('./user/CaptainManager')
|
||||
import CaptainManager = require('./user/system/CaptainManager')
|
||||
import BaseApi = require('./api/BaseApi')
|
||||
import ApiStatusCodes = require('./api/ApiStatusCodes')
|
||||
import Injector = require('./injection/Injector')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import DataStoreProvider = require('../datastore/DataStoreProvider')
|
||||
import Authenticator = require('../user/Authenticator')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import CaptainManager = require('../user/CaptainManager')
|
||||
import CaptainManager = require('../user/system/CaptainManager')
|
||||
import ServiceManager = require('../user/ServiceManager')
|
||||
import DockerApiProvider = require('../docker/DockerApi')
|
||||
import BaseApi = require('../api/BaseApi')
|
||||
|
||||
@@ -2,7 +2,7 @@ import express = require('express')
|
||||
import BaseApi = require('../../api/BaseApi')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import CaptainManager = require('../../user/CaptainManager')
|
||||
import CaptainManager = require('../../user/system/CaptainManager')
|
||||
import Validator = require('validator')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
import InjectionExtractor = require('../../injection/InjectionExtractor')
|
||||
|
||||
@@ -2,7 +2,7 @@ import express = require('express')
|
||||
import BaseApi = require('../../api/BaseApi')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import CaptainManager = require('../../user/CaptainManager')
|
||||
import CaptainManager = require('../../user/system/CaptainManager')
|
||||
import Validator = require('validator')
|
||||
import SystemRouteSelfHostRegistry = require('./SystemRouteSelfHostRegistry')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
|
||||
@@ -5,7 +5,7 @@ import bcrypt = require('bcryptjs')
|
||||
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import EnvVar = require('../utils/EnvVars')
|
||||
import CaptainManager = require('./CaptainManager')
|
||||
import CaptainManager = require('./system/CaptainManager')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('../utils/Logger')
|
||||
import DataStoreProvider = require('../datastore/DataStoreProvider')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import CaptainManager = require('./CaptainManager')
|
||||
import LoadBalancerManager = require('./LoadBalancerManager')
|
||||
import CaptainManager = require('./system/CaptainManager')
|
||||
import LoadBalancerManager = require('./system/LoadBalancerManager')
|
||||
import DockerApi = require('../docker/DockerApi')
|
||||
import DataStore = require('../datastore/DataStore')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
|
||||
@@ -4,7 +4,7 @@ import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import { ITemplate } from '../models/OtherTypes'
|
||||
import TemplateHelperVersionPrinter = require('./TemplateHelperVersionPrinter')
|
||||
import TemplateHelperVersionPrinter = require('../utils/TemplateHelperVersionPrinter')
|
||||
|
||||
class TemplateHelper {
|
||||
private templates: ITemplate[]
|
||||
|
||||
+11
-11
@@ -2,17 +2,17 @@ import uuid = require('uuid/v4')
|
||||
import SshClientImport = require('ssh2')
|
||||
import request = require('request')
|
||||
import fs = require('fs-extra')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import LoadBalancerManager = require('./LoadBalancerManager')
|
||||
import EnvVars = require('../utils/EnvVars')
|
||||
import Encryptor = require('../utils/Encryptor')
|
||||
import EnvVars = require('../../utils/EnvVars')
|
||||
import Encryptor = require('../../utils/Encryptor')
|
||||
import CertbotManager = require('./CertbotManager')
|
||||
import DockerRegistry = require('./DockerRegistry')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import DataStoreProvider = require('../datastore/DataStoreProvider')
|
||||
import DataStore = require('../datastore/DataStore')
|
||||
import DockerApi = require('../docker/DockerApi')
|
||||
import SelfHostedDockerRegistry = require('./SelfHostedDockerRegistry')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import DataStoreProvider = require('../../datastore/DataStoreProvider')
|
||||
import DataStore = require('../../datastore/DataStore')
|
||||
import DockerApi = require('../../docker/DockerApi')
|
||||
|
||||
const DEBUG_SALT = 'THIS IS NOT A REAL CERTIFICATE'
|
||||
const SshClient = SshClientImport.Client
|
||||
@@ -30,7 +30,7 @@ class CaptainManager {
|
||||
private dockerApi: DockerApi
|
||||
private certbotManager: CertbotManager
|
||||
private loadBalancerManager: LoadBalancerManager
|
||||
private dockerRegistry: DockerRegistry
|
||||
private dockerRegistry: SelfHostedDockerRegistry
|
||||
private myNodeId: string | undefined
|
||||
private inited: boolean
|
||||
private waitUntilRestarted: boolean
|
||||
@@ -52,7 +52,7 @@ class CaptainManager {
|
||||
this.certbotManager,
|
||||
this.dataStore
|
||||
)
|
||||
this.dockerRegistry = new DockerRegistry(
|
||||
this.dockerRegistry = new SelfHostedDockerRegistry(
|
||||
dockerApi,
|
||||
this.dataStore,
|
||||
this.certbotManager,
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import fs = require('fs-extra')
|
||||
import uuid = require('uuid/v4')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import DockerApi = require('../docker/DockerApi')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import DockerApi = require('../../docker/DockerApi')
|
||||
|
||||
const CAPTAIN_WEBROOT_PATH_CERTBOT = '/captain-webroot'
|
||||
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
import ejs = require('ejs')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import fs = require('fs-extra')
|
||||
import uuid = require('uuid/v4')
|
||||
import request = require('request')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import DockerApi = require('../docker/DockerApi')
|
||||
import DataStore = require('../datastore/DataStore')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import DockerApi = require('../../docker/DockerApi')
|
||||
import DataStore = require('../../datastore/DataStore')
|
||||
import CertbotManager = require('./CertbotManager')
|
||||
import { AnyError } from '../models/OtherTypes'
|
||||
import { AnyError } from '../../models/OtherTypes'
|
||||
|
||||
const defaultPageTemplate = fs
|
||||
.readFileSync(__dirname + '/../../template/default-page.ejs')
|
||||
+11
-11
@@ -1,17 +1,17 @@
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('../utils/Logger')
|
||||
import EnvVars = require('../utils/EnvVars')
|
||||
import CaptainConstants = require('../../utils/CaptainConstants')
|
||||
import Logger = require('../../utils/Logger')
|
||||
import EnvVars = require('../../utils/EnvVars')
|
||||
import fs = require('fs-extra')
|
||||
import uuid = require('uuid/v4')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import ApiStatusCodes = require('../../api/ApiStatusCodes')
|
||||
import bcrypt = require('bcryptjs')
|
||||
import DockerApi = require('../docker/DockerApi')
|
||||
import DataStore = require('../datastore/DataStore')
|
||||
import CertbotManager = require('../user/CertbotManager')
|
||||
import LoadBalancerManager = require('../user/LoadBalancerManager')
|
||||
import CaptainManager = require('../user/CaptainManager')
|
||||
import DockerApi = require('../../docker/DockerApi')
|
||||
import DataStore = require('../../datastore/DataStore')
|
||||
import CertbotManager = require('./CertbotManager')
|
||||
import LoadBalancerManager = require('./LoadBalancerManager')
|
||||
import CaptainManager = require('./CaptainManager')
|
||||
|
||||
class DockerRegistry {
|
||||
class SelfHostedDockerRegistry {
|
||||
constructor(
|
||||
private dockerApi: DockerApi,
|
||||
private dataStore: DataStore,
|
||||
@@ -215,4 +215,4 @@ class DockerRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
export = DockerRegistry
|
||||
export = SelfHostedDockerRegistry
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import request = require('request')
|
||||
import fs = require('fs-extra')
|
||||
import ApiStatusCodes = require('../api/ApiStatusCodes')
|
||||
import Logger = require('../utils/Logger')
|
||||
import CaptainConstants = require('../utils/CaptainConstants')
|
||||
import Logger = require('./Logger')
|
||||
import CaptainConstants = require('./CaptainConstants')
|
||||
import { ITemplate } from '../models/OtherTypes'
|
||||
|
||||
function getTagsForImage(
|
||||
Reference in New Issue
Block a user