roster-server 2.2.10 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -2
- package/index.js +28 -38
- package/lib/resolve-site-app.js +42 -0
- package/lib/static-site-handler.js +122 -0
- package/package.json +12 -3
- package/skills/roster-server/SKILL.md +15 -4
- package/test/roster-server.test.js +87 -0
- package/vendor/greenlock/.prettierrc +8 -0
- package/vendor/greenlock/LICENSE +312 -0
- package/vendor/greenlock/MIGRATION_GUIDE.md +403 -0
- package/vendor/greenlock/README.md +667 -0
- package/vendor/greenlock/accounts.js +218 -0
- package/vendor/greenlock/bin/add.js +72 -0
- package/vendor/greenlock/bin/certonly.js +368 -0
- package/vendor/greenlock/bin/config.js +77 -0
- package/vendor/greenlock/bin/defaults.js +58 -0
- package/vendor/greenlock/bin/greenlock.js +26 -0
- package/vendor/greenlock/bin/init.js +159 -0
- package/vendor/greenlock/bin/lib/cli.js +230 -0
- package/vendor/greenlock/bin/lib/flags.js +385 -0
- package/vendor/greenlock/bin/remove.js +46 -0
- package/vendor/greenlock/bin/tmpl/app.tmpl.js +9 -0
- package/vendor/greenlock/bin/tmpl/cluster.tmpl.js +30 -0
- package/vendor/greenlock/bin/tmpl/greenlock.tmpl.js +13 -0
- package/vendor/greenlock/bin/tmpl/server.tmpl.js +20 -0
- package/vendor/greenlock/bin/update.js +62 -0
- package/vendor/greenlock/certificates.js +324 -0
- package/vendor/greenlock/errors.js +58 -0
- package/vendor/greenlock/greenlock.js +621 -0
- package/vendor/greenlock/greenlockrc.js +169 -0
- package/vendor/greenlock/lib/challenges-wrapper.js +88 -0
- package/vendor/greenlock/lib/directory-url.js +44 -0
- package/vendor/greenlock/lib/init.js +191 -0
- package/vendor/greenlock/lib/manager-wrapper.js +625 -0
- package/vendor/greenlock/lib/rc.js +70 -0
- package/vendor/greenlock/logo/beaker-browser-301x112.png +0 -0
- package/vendor/greenlock/logo/from-not-secure-to-secure-url-bar.png +0 -0
- package/vendor/greenlock/logo/greenlock-1063x250.png +0 -0
- package/vendor/greenlock/logo/greenlock-850x200.png +0 -0
- package/vendor/greenlock/logo/ibm-301x112.png +0 -0
- package/vendor/greenlock/logo/telebit-301x112.png +0 -0
- package/vendor/greenlock/order.js +63 -0
- package/vendor/greenlock/package-lock.json +140 -0
- package/vendor/greenlock/package.json +56 -0
- package/vendor/greenlock/plugins.js +270 -0
- package/vendor/greenlock/tests/cli.sh +31 -0
- package/vendor/greenlock/tests/index.js +53 -0
- package/vendor/greenlock/user-events.js +7 -0
- package/vendor/greenlock/utils.js +281 -0
- package/vendor/greenlock-express/greenlock-shim.js +3 -1
- package/vendor/greenlock-express/package.json +0 -1
- package/tasks/lessons.md +0 -4
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var U = module.exports;
|
|
4
|
+
|
|
5
|
+
var promisify = require('util').promisify;
|
|
6
|
+
//var resolveSoa = promisify(require('dns').resolveSoa);
|
|
7
|
+
var resolveMx = promisify(require('dns').resolveMx);
|
|
8
|
+
var punycode = require('punycode');
|
|
9
|
+
var Keypairs = require('@root/keypairs');
|
|
10
|
+
// TODO move to @root
|
|
11
|
+
var certParser = require('cert-info');
|
|
12
|
+
|
|
13
|
+
U._parseDuration = function(str) {
|
|
14
|
+
if ('number' === typeof str) {
|
|
15
|
+
return str;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var pattern = /^(\-?\d+(\.\d+)?)([wdhms]|ms)$/;
|
|
19
|
+
var matches = str.match(pattern);
|
|
20
|
+
if (!matches || !matches[0]) {
|
|
21
|
+
throw new Error('invalid duration string: ' + str);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var n = parseInt(matches[1], 10);
|
|
25
|
+
var unit = matches[3];
|
|
26
|
+
|
|
27
|
+
switch (unit) {
|
|
28
|
+
case 'w':
|
|
29
|
+
n *= 7;
|
|
30
|
+
/*falls through*/
|
|
31
|
+
case 'd':
|
|
32
|
+
n *= 24;
|
|
33
|
+
/*falls through*/
|
|
34
|
+
case 'h':
|
|
35
|
+
n *= 60;
|
|
36
|
+
/*falls through*/
|
|
37
|
+
case 'm':
|
|
38
|
+
n *= 60;
|
|
39
|
+
/*falls through*/
|
|
40
|
+
case 's':
|
|
41
|
+
n *= 1000;
|
|
42
|
+
/*falls through*/
|
|
43
|
+
case 'ms':
|
|
44
|
+
n *= 1; // for completeness
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return n;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
U._encodeName = function(str) {
|
|
51
|
+
return punycode.toASCII(str.toLowerCase(str));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
U._validName = function(str) {
|
|
55
|
+
// A quick check of the 38 and two ½ valid characters
|
|
56
|
+
// 253 char max full domain, including dots
|
|
57
|
+
// 63 char max each label segment
|
|
58
|
+
// Note: * is not allowed, but it's allowable here
|
|
59
|
+
// Note: _ (underscore) is only allowed for "domain names", not "hostnames"
|
|
60
|
+
// Note: - (hyphen) is not allowed as a first character (but a number is)
|
|
61
|
+
return (
|
|
62
|
+
/^(\*\.)?[a-z0-9_\.\-]+\.[a-z0-9_\.\-]+$/.test(str) &&
|
|
63
|
+
str.length < 254 &&
|
|
64
|
+
str.split('.').every(function(label) {
|
|
65
|
+
return label.length > 0 && label.length < 64;
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
U._validMx = function(email) {
|
|
71
|
+
var host = email.split('@').slice(1)[0];
|
|
72
|
+
// try twice, just because DNS hiccups sometimes
|
|
73
|
+
// Note: we don't care if the domain exists, just that it *can* exist
|
|
74
|
+
return resolveMx(host).catch(function() {
|
|
75
|
+
return U._timeout(1000).then(function() {
|
|
76
|
+
return resolveMx(host);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// should be called after _validName
|
|
82
|
+
U._validDomain = function(str) {
|
|
83
|
+
// TODO use @root/dns (currently dns-suite)
|
|
84
|
+
// because node's dns can't read Authority records
|
|
85
|
+
return Promise.resolve(str);
|
|
86
|
+
/*
|
|
87
|
+
// try twice, just because DNS hiccups sometimes
|
|
88
|
+
// Note: we don't care if the domain exists, just that it *can* exist
|
|
89
|
+
return resolveSoa(str).catch(function() {
|
|
90
|
+
return U._timeout(1000).then(function() {
|
|
91
|
+
return resolveSoa(str);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
*/
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// foo.example.com and *.example.com overlap
|
|
98
|
+
// should be called after _validName
|
|
99
|
+
// (which enforces *. or no *)
|
|
100
|
+
U._uniqueNames = function(altnames) {
|
|
101
|
+
var dups = {};
|
|
102
|
+
var wilds = {};
|
|
103
|
+
if (
|
|
104
|
+
altnames.some(function(w) {
|
|
105
|
+
if ('*.' !== w.slice(0, 2)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (wilds[w]) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
wilds[w] = true;
|
|
112
|
+
})
|
|
113
|
+
) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return altnames.every(function(name) {
|
|
118
|
+
var w;
|
|
119
|
+
if ('*.' !== name.slice(0, 2)) {
|
|
120
|
+
w =
|
|
121
|
+
'*.' +
|
|
122
|
+
name
|
|
123
|
+
.split('.')
|
|
124
|
+
.slice(1)
|
|
125
|
+
.join('.');
|
|
126
|
+
} else {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!dups[name] && !dups[w]) {
|
|
131
|
+
dups[name] = true;
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
U._timeout = function(d) {
|
|
138
|
+
return new Promise(function(resolve) {
|
|
139
|
+
setTimeout(resolve, d);
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
U._genKeypair = function(keyType) {
|
|
144
|
+
var keyopts;
|
|
145
|
+
var len = parseInt(keyType.replace(/.*?(\d)/, '$1') || 0, 10);
|
|
146
|
+
if (/RSA/.test(keyType)) {
|
|
147
|
+
keyopts = {
|
|
148
|
+
kty: 'RSA',
|
|
149
|
+
modulusLength: len || 2048
|
|
150
|
+
};
|
|
151
|
+
} else if (/^(EC|P\-?\d)/i.test(keyType)) {
|
|
152
|
+
keyopts = {
|
|
153
|
+
kty: 'EC',
|
|
154
|
+
namedCurve: 'P-' + (len || 256)
|
|
155
|
+
};
|
|
156
|
+
} else {
|
|
157
|
+
// TODO put in ./errors.js
|
|
158
|
+
throw new Error('invalid key type: ' + keyType);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return Keypairs.generate(keyopts).then(function(pair) {
|
|
162
|
+
return U._jwkToSet(pair.private);
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// TODO use ACME._importKeypair ??
|
|
167
|
+
U._importKeypair = function(keypair) {
|
|
168
|
+
// this should import all formats equally well:
|
|
169
|
+
// 'object' (JWK), 'string' (private key pem), kp.privateKeyPem, kp.privateKeyJwk
|
|
170
|
+
if (keypair.private || keypair.d) {
|
|
171
|
+
return U._jwkToSet(keypair.private || keypair);
|
|
172
|
+
}
|
|
173
|
+
if (keypair.privateKeyJwk) {
|
|
174
|
+
return U._jwkToSet(keypair.privateKeyJwk);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if ('string' !== typeof keypair && !keypair.privateKeyPem) {
|
|
178
|
+
// TODO put in errors
|
|
179
|
+
throw new Error('missing private key');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return Keypairs.import({ pem: keypair.privateKeyPem || keypair }).then(
|
|
183
|
+
function(priv) {
|
|
184
|
+
if (!priv.d) {
|
|
185
|
+
throw new Error('missing private key');
|
|
186
|
+
}
|
|
187
|
+
return U._jwkToSet(priv);
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
U._jwkToSet = function(jwk) {
|
|
193
|
+
var keypair = {
|
|
194
|
+
privateKeyJwk: jwk
|
|
195
|
+
};
|
|
196
|
+
return Promise.all([
|
|
197
|
+
Keypairs.export({
|
|
198
|
+
jwk: jwk,
|
|
199
|
+
encoding: 'pem'
|
|
200
|
+
}).then(function(pem) {
|
|
201
|
+
keypair.privateKeyPem = pem;
|
|
202
|
+
}),
|
|
203
|
+
Keypairs.export({
|
|
204
|
+
jwk: jwk,
|
|
205
|
+
encoding: 'pem',
|
|
206
|
+
public: true
|
|
207
|
+
}).then(function(pem) {
|
|
208
|
+
keypair.publicKeyPem = pem;
|
|
209
|
+
}),
|
|
210
|
+
Keypairs.publish({
|
|
211
|
+
jwk: jwk
|
|
212
|
+
}).then(function(pub) {
|
|
213
|
+
keypair.publicKeyJwk = pub;
|
|
214
|
+
})
|
|
215
|
+
]).then(function() {
|
|
216
|
+
return keypair;
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
U._attachCertInfo = function(results) {
|
|
221
|
+
var certInfo = certParser.info(results.cert);
|
|
222
|
+
|
|
223
|
+
// subject, altnames, issuedAt, expiresAt
|
|
224
|
+
Object.keys(certInfo).forEach(function(key) {
|
|
225
|
+
results[key] = certInfo[key];
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
return results;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
U._certHasDomain = function(certInfo, _domain) {
|
|
232
|
+
var names = (certInfo.altnames || []).slice(0);
|
|
233
|
+
return names.some(function(name) {
|
|
234
|
+
var domain = _domain.toLowerCase();
|
|
235
|
+
name = name.toLowerCase();
|
|
236
|
+
if ('*.' === name.substr(0, 2)) {
|
|
237
|
+
name = name.substr(2);
|
|
238
|
+
domain = domain
|
|
239
|
+
.split('.')
|
|
240
|
+
.slice(1)
|
|
241
|
+
.join('.');
|
|
242
|
+
}
|
|
243
|
+
return name === domain;
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// a bit heavy to be labeled 'utils'... perhaps 'common' would be better?
|
|
248
|
+
U._getOrCreateKeypair = function(db, subject, query, keyType, mustExist) {
|
|
249
|
+
var exists = false;
|
|
250
|
+
return db
|
|
251
|
+
.checkKeypair(query)
|
|
252
|
+
.then(function(kp) {
|
|
253
|
+
if (kp) {
|
|
254
|
+
exists = true;
|
|
255
|
+
return U._importKeypair(kp);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (mustExist) {
|
|
259
|
+
// TODO put in errors
|
|
260
|
+
throw new Error(
|
|
261
|
+
'required keypair not found: ' +
|
|
262
|
+
(subject || '') +
|
|
263
|
+
' ' +
|
|
264
|
+
JSON.stringify(query)
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return U._genKeypair(keyType);
|
|
269
|
+
})
|
|
270
|
+
.then(function(keypair) {
|
|
271
|
+
return { exists: exists, keypair: keypair };
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
U._getKeypair = function(db, subject, query) {
|
|
276
|
+
return U._getOrCreateKeypair(db, subject, query, '', true).then(function(
|
|
277
|
+
result
|
|
278
|
+
) {
|
|
279
|
+
return result.keypair;
|
|
280
|
+
});
|
|
281
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var path = require("path");
|
|
4
|
+
|
|
3
5
|
module.exports.create = function(opts) {
|
|
4
|
-
var Greenlock = require("
|
|
6
|
+
var Greenlock = require(path.resolve(__dirname, "..", "greenlock", "greenlock.js"));
|
|
5
7
|
var log = require("lemonlog")("greenlock-shim");
|
|
6
8
|
//var Init = require("@root/greenlock/lib/init.js");
|
|
7
9
|
var greenlock = opts.greenlock;
|
package/tasks/lessons.md
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
# Lessons Learned
|
|
2
|
-
|
|
3
|
-
- When wildcard TLS must run under Bun, do not rely on manual DNS instructions; default to API-driven DNS-01 TXT creation/removal (Linode/Akamai) with propagation polling, then fall back to manual mode only when no provider token is configured.
|
|
4
|
-
- Do not keep speculative resolver/workaround attempts that are not the root cause; if a change does not resolve the issue with evidence, revert/simplify immediately so temporary experiments do not become permanent complexity.
|