setup oneuptime package for greenlock

This commit is contained in:
deityhub
2021-11-28 10:31:17 +01:00
parent 46f4443bb6
commit 663fbb67ea
16 changed files with 743 additions and 0 deletions

1
oneuptime-acme-http-01/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/node_modules

View File

@@ -0,0 +1,21 @@
# oneuptime-acme-http-01 Package for Greenlock
This module handles acme-http-01 challenge and also the api call to OneUptime backend to persist keyAuthorization and token data from acme directory in our mongodb. The stored data will be used by OneUptime to validate all our certificate order/renewal.
## Install
npm install oneuptime-acme-http-01
## Usage
// make sure greenlock is already installed
const Greenlock = require('greenlock');
Greenlock.create({
challenges: {
'http-01': {
module: 'oneuptime-acme-http-01',
},
},
// ...
});

View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = require('./lib/index.js');

View File

@@ -0,0 +1,49 @@
'use strict';
const axios = require('axios');
const BASE_URL = `${process.env.BACKEND_PROTOCOL}://${process.env.ONEUPTIME_HOST}`;
module.exports = {
create: function(config) {
return {
// init: function(opts) {
// //request = opts.request;
// return Promise.resolve(null);
// },
set: function(data) {
const ch = data.challenge;
// make api call to backend to store
// keyAuthorization, challengeUrl, and token
const url = `${BASE_URL}/api/ssl/challenge`;
const dataConfig = {
token: ch.token,
keyAuthorization: ch.keyAuthorization,
challengeUrl: ch.challengeUrl,
};
return axios({
url,
method: 'post',
data: dataConfig,
}).finally(() => null); // always return null
},
get: function(data) {
const ch = data.challenge;
const url = `${BASE_URL}/api/ssl/challenge/${ch.token}`;
return axios.get(url).then(result => result);
},
remove: function(data) {
const ch = data.challenge;
const url = `${BASE_URL}/api/ssl/challenge/${ch.token}`;
return axios({ url, method: 'delete' }).finally(() => null); // always return null
},
options: config,
};
},
};

106
oneuptime-acme-http-01/package-lock.json generated Normal file
View File

@@ -0,0 +1,106 @@
{
"name": "oneuptime-acme-http-01",
"version": "3.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1"
},
"devDependencies": {
"acme-challenge-test": "^3.3.2",
"dotenv": "^8.0.0"
}
},
"node_modules/@root/request": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@root/request/-/request-1.7.0.tgz",
"integrity": "sha512-lre7XVeEwszgyrayWWb/kRn5fuJfa+n0Nh+rflM9E+EpC28yIYA+FPm/OL1uhzp3TxhQM0HFN4FE2RDIPGlnmg==",
"dev": true
},
"node_modules/acme-challenge-test": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/acme-challenge-test/-/acme-challenge-test-3.3.2.tgz",
"integrity": "sha512-0AbMcaON20wpI5vzFDAqwcv2VerY4xIlNCqX0w1xEJUIu/EQtQNmkje+rKNuy2TUl2KBMdIaR6YBbJUdaEiC4w==",
"dev": true,
"dependencies": {
"@root/request": "^1.3.11"
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
}
},
"dependencies": {
"@root/request": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@root/request/-/request-1.7.0.tgz",
"integrity": "sha512-lre7XVeEwszgyrayWWb/kRn5fuJfa+n0Nh+rflM9E+EpC28yIYA+FPm/OL1uhzp3TxhQM0HFN4FE2RDIPGlnmg==",
"dev": true
},
"acme-challenge-test": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/acme-challenge-test/-/acme-challenge-test-3.3.2.tgz",
"integrity": "sha512-0AbMcaON20wpI5vzFDAqwcv2VerY4xIlNCqX0w1xEJUIu/EQtQNmkje+rKNuy2TUl2KBMdIaR6YBbJUdaEiC4w==",
"dev": true,
"requires": {
"@root/request": "^1.3.11"
}
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"dev": true
},
"follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
}
}
}

View File

@@ -0,0 +1,35 @@
{
"name": "oneuptime-acme-http-01",
"version": "3.0.0",
"description": "HTTP Authentication (In-Memory) for Let's Encrypt for Node.js - ACME http-01 challenges for OneUptime",
"main": "index.js",
"files": [
"*.js",
"lib",
"test.js"
],
"scripts": {
"test": "node test.js"
},
"keywords": [
"standalone",
"memory",
"http-01",
"letsencrypt",
"acme",
"greenlock",
"oneuptime"
],
"author": "Jude Ojini <judoc96@gmail.com>",
"contributors": [
"Jude Ojini <judoc96@gmail.com>"
],
"license": "MIT",
"devDependencies": {
"acme-challenge-test": "^3.3.2",
"dotenv": "^8.0.0"
},
"dependencies": {
"axios": "^0.21.1"
}
}

26
oneuptime-acme-http-01/test.js Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env node
'use strict';
// See https://git.coolaj86.com/coolaj86/acme-challenge-test.js
const tester = require('acme-challenge-test');
require('dotenv').config();
// Usage: node ./test.js example.com username xxxxxxxxx
const record = process.argv[2] || process.env.RECORD;
const challenger = require('./index.js').create({});
// The dry-run tests can pass on, literally, 'example.com'
// but the integration tests require that you have control over the domain
tester
.testRecord('http-01', record, challenger)
.then(function() {
// eslint-disable-next-line no-console
console.info('PASS', record);
})
.catch(function(e) {
// eslint-disable-next-line no-console
console.error(e.message);
// eslint-disable-next-line no-console
console.error(e.stack);
});

View File

@@ -0,0 +1,73 @@
# oneuptime-gl-manager
Manages SSL Certificate issuance and renewal for [Greenlock](https://git.rootprojects.org/root/greenlock-manager.js) on [OneUptime](https://oneuptime.com) platform.
Saves global and per-site config to a local File Sytem (current).
## Install
```bash
npm install --save oneuptime-gl-manager
```
# Usage
## Initialize the Manager
```js
Greenlock.create({
...
manager: "oneuptime-gl-manager",
configDir: "./greenlock.d",
packageRoot: __dirname
...
});
```
# Site Management
By "site" we mean a primary domain and, optionally, secondary domains, to be listed on an ssl certificate,
along with any configuration that is necessary for getting and renewing those certificates.
## Add a sites - domains and SSL certificates
```js
greenlock.add({
subject: 'example.com',
altnames: ['example.com', 'www.example.com'],
});
```
## View site config
```js
greenlock.get({
servername: 'www.example.com',
wildname: '*.example.com',
});
```
## Update site config
```js
greenlock.update({
subject: 'www.example.com',
challenges: {
'dns-01': {
module: 'acme-dns-01-ovh',
token: 'xxxx',
},
},
});
```
## Remove a site
To stop automatic renewal of SSL certificates for a particular site.
You to restart renewal you must use `add()`.
```js
greenlock.remove({
subject: 'example.com',
});
```

View File

@@ -0,0 +1,127 @@
'use strict';
const axios = require('axios');
const BASE_URL = `${process.env.BACKEND_PROTOCOL}://${process.env.ONEUPTIME_HOST}`;
const Manager = module.exports;
// eslint-disable-next-line no-unused-vars
Manager.create = function(opts) {
const manager = {};
//
// REQUIRED (basic issuance)
//
manager.get = async function({ servername }) {
const url = `${BASE_URL}/api/manager/site?servername=${servername}`;
const response = await axios({
url,
method: 'get',
});
return response.data;
};
//
// REQUIRED (basic issuance)
//
manager.set = async function(opts) {
const url = `${BASE_URL}/api/manager/site?subject=${opts.subject}`;
const response = await axios({
url,
method: 'put',
data: opts,
});
return response.data;
};
//
// Optional (Fully Automatic Renewal)
//
manager.find = async function(opts) {
// { subject, servernames, altnames, renewBefore }
if (opts.subject) {
const url = `${BASE_URL}/api/manager/site?subject=${opts.subject}`;
const response = await axios({
url,
method: 'get',
});
if (!response.data || response.data.length === 0) {
return [];
}
return [response.data];
}
if (Array.isArray(opts.servernames) && opts.servernames.length > 0) {
const url = `${BASE_URL}/api/manager/site/servernames`;
const response = await axios({
url,
method: 'post',
data: opts.servernames,
});
return response.data;
}
// i.e. find certs more than 30 days old as default
opts.issuedBefore =
opts.issuedBefore || Date.now() - 30 * 24 * 60 * 60 * 1000;
// i.e. find certs that will expire in less than 45 days as default
opts.expiresBefore =
opts.expiresBefore || Date.now() + 45 * 24 * 60 * 60 * 1000;
// i.e. find certs that should be renewed within 21 days as default
opts.renewBefore =
opts.renewBefore || Date.now() + 21 * 24 * 60 * 60 * 1000;
const url = `${BASE_URL}/api/manager/site/opts`;
const response = await axios({
url,
method: 'post',
data: opts,
});
return response.data;
};
//
// Optional (Special Remove Functionality)
// The default behavior is to set `deletedAt`
//
manager.remove = async function(opts) {
const url = `${BASE_URL}/api/manager/site?subject=${opts.subject}`;
const response = await axios({
url,
method: 'delete',
});
return response.data;
};
//
// Optional (special settings save)
// Implemented here because this module IS the fallback
// This is a setter/getter function
//
manager.defaults = async function(opts) {
if (!opts) {
const url = `${BASE_URL}/api/manager/default`;
const response = await axios({
url,
method: 'get',
});
return response.data ? response.data : {};
}
const url = `${BASE_URL}/api/manager/default`;
const response = await axios({
url,
method: 'put',
data: opts,
});
return response.data || {};
};
return manager;
};

57
oneuptime-gl-manager/package-lock.json generated Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "oneuptime-gl-manager",
"version": "3.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1"
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
}
},
"dependencies": {
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
}
}
}

View File

@@ -0,0 +1,28 @@
{
"name": "oneuptime-gl-manager",
"version": "3.0.0",
"description": "FileSytem-based Manager with optional encrypted Cloud backup for Greenlock SSL",
"main": "manager.js",
"files": [
"*.js"
],
"scripts": {
"test": "node tests"
},
"keywords": [
"greenlock",
"manager",
"cloud",
"fs",
"ssl",
"oneuptime"
],
"author": "Jude Ojini <judoc96@gmail.com>",
"contributors": [
"Jude Ojini <judoc96@gmail.com>"
],
"license": "MIT",
"dependencies": {
"axios": "^0.21.1"
}
}

1
oneuptime-le-store/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/node_modules

View File

@@ -0,0 +1,19 @@
# oneuptime-le-store Package for Greenlock
This module implements a dead-simple, api call to OneUptime backend to store account or certificate details. This allows us to persist our [Let's Encrypt](https://letsencrypt.org/) data in mongo for automated TLS certificate issuance and use.
## Install
npm install oneuptime-le-store
## Usage
// make sure greenlock is already installed
const Greenlock = require('greenlock');
Greenlock.create({
store: {
module: 'oneuptime-le-store',
},
// ...
});

118
oneuptime-le-store/index.js Normal file
View File

@@ -0,0 +1,118 @@
'use strict';
const axios = require('axios');
const BASE_URL = `${process.env.BACKEND_PROTOCOL}://${process.env.ONEUPTIME_HOST}`;
// make api call to designated endpoints
// to make the necessary updates to the db
module.exports.create = function(config) {
const store = {};
store.options = config;
store.accounts = {
setKeypair: function(opts) {
const id =
(opts.account && opts.account.id) || opts.email || 'default';
const url = `${BASE_URL}/api/account/store/${id}`;
const data = {
id: id,
privateKeyPem: opts.keypair.privateKeyPem,
privateKeyJwk: opts.keypair.privateKeyJwk,
publickKeyPem: opts.keypair.publickeyPem,
publicKeyJwk: opts.keypair.publicKeyJwk,
key: opts.keypair.key,
};
return axios({
url,
method: 'put',
data,
})
.then(res => res.data)
.finally(() => null);
},
checkKeypair: function(opts) {
const id =
(opts.account && opts.account.id) || opts.email || 'default';
const url = `${BASE_URL}/api/account/store/${id}`;
return axios({
url,
method: 'get',
})
.then(res => res.data)
.finally(() => null);
},
options: config,
};
store.certificates = {
setKeypair: function(opts) {
const id =
(opts.certificate &&
(opts.certificate.kid || opts.certificate.id)) ||
opts.subject;
const url = `${BASE_URL}/api/certificate/store/${id}`;
const data = {
id: id,
deleted: false,
...opts.keypair,
};
return axios({
url,
method: 'put',
data,
})
.then(res => res.data)
.finally(() => null);
},
checkKeypair: function(opts) {
const id =
(opts.certificate &&
(opts.certificate.kid || opts.certificate.id)) ||
opts.subject;
const url = `${BASE_URL}/api/certificate/store/${id}`;
return axios({
url,
method: 'get',
})
.then(res => res.data)
.finally(() => null);
},
set: function(opts) {
const id =
(opts.certificate && opts.certificate.id) || opts.subject;
const url = `${BASE_URL}/api/certificate/store/${id}`;
const data = {
id: id,
deleted: false,
...opts.pems,
};
return axios({
url,
method: 'put',
data,
})
.then(res => res.data)
.finally(() => null);
},
check: function(opts) {
const id =
(opts.certificate && opts.certificate.id) || opts.subject;
const url = `${BASE_URL}/api/certificate/store/${id}`;
return axios({
url,
method: 'get',
})
.then(res => res.data)
.finally(() => null);
},
options: config,
};
return store;
};

57
oneuptime-le-store/package-lock.json generated Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "oneuptime-le-store",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1"
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
}
},
"dependencies": {
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
}
}
}

View File

@@ -0,0 +1,22 @@
{
"name": "oneuptime-le-store",
"version": "3.0.0",
"description": "Greenlock store module ported for OneUptime",
"main": "index.js",
"keywords": [
"le-store",
"greenlock",
"letsencrypt",
"mongodb",
"mongo",
"oneuptime"
],
"author": "Jude Ojini <judoc96@gmail.com>",
"contributors": [
"Jude Ojini <judoc96@gmail.com>"
],
"license": "MIT",
"dependencies": {
"axios": "^0.21.1"
}
}