clay-server 2.42.0 → 2.43.0-beta.1
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/bin/cli.js +23 -1
- package/lib/certs/fullchain.pem +76 -42
- package/lib/certs/privkey.pem +3 -3
- package/lib/clay-studio-cert.js +112 -0
- package/lib/daemon.js +10 -1
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -37,6 +37,7 @@ var { loadConfig, saveConfig, configPath, socketPath, logPath, ensureConfigDir,
|
|
|
37
37
|
var { sendIPCCommand } = require("../lib/ipc");
|
|
38
38
|
var { generateAuthToken } = require("../lib/server");
|
|
39
39
|
var { enableMultiUser, disableMultiUser, hasAdmin, isMultiUser, getSetupCode } = require("../lib/users");
|
|
40
|
+
var clayStudioCert = require("../lib/clay-studio-cert");
|
|
40
41
|
|
|
41
42
|
function openUrl(url) {
|
|
42
43
|
try {
|
|
@@ -567,6 +568,12 @@ function getAllIPs() {
|
|
|
567
568
|
|
|
568
569
|
function getBuiltinCert() {
|
|
569
570
|
try {
|
|
571
|
+
// Prefer the cert fetched at runtime from the clay.studio endpoint (always
|
|
572
|
+
// current) over the copy baked into the package (expires ~90 days after
|
|
573
|
+
// publish). forkDaemon refreshes this cache before we get here.
|
|
574
|
+
var fetched = clayStudioCert.cachedCertFiles();
|
|
575
|
+
if (fetched) return { key: fetched.key, cert: fetched.cert, caRoot: null, builtin: true };
|
|
576
|
+
|
|
570
577
|
var certDir = path.join(__dirname, "..", "lib", "certs");
|
|
571
578
|
var keyPath = path.join(certDir, "privkey.pem");
|
|
572
579
|
var certPath = path.join(certDir, "fullchain.pem");
|
|
@@ -1458,13 +1465,19 @@ async function forkDaemon(mode, keepAwake, extraProjects, addCwd, wantOsUsers) {
|
|
|
1458
1465
|
var mkcertDetected = false;
|
|
1459
1466
|
|
|
1460
1467
|
if (useHttps) {
|
|
1468
|
+
// Refresh the runtime cert cache from the clay.studio endpoint (best effort,
|
|
1469
|
+
// short timeout) so getBuiltinCert picks up the current auto-renewed cert
|
|
1470
|
+
// instead of the stale baked copy. Skipped when the user forces mkcert.
|
|
1471
|
+
if (!forceMkcert) {
|
|
1472
|
+
try { await clayStudioCert.refreshCache(5000); } catch (e) {}
|
|
1473
|
+
}
|
|
1461
1474
|
var certPaths = ensureCerts(ip);
|
|
1462
1475
|
if (certPaths) {
|
|
1463
1476
|
hasTls = true;
|
|
1464
1477
|
if (certPaths.builtin) hasBuiltinCert = true;
|
|
1465
1478
|
if (certPaths.mkcertDetected) mkcertDetected = true;
|
|
1466
1479
|
} else {
|
|
1467
|
-
log(sym.warn + " " + a.yellow + "HTTPS unavailable" + a.reset + a.dim + " ·
|
|
1480
|
+
log(sym.warn + " " + a.yellow + "HTTPS unavailable" + a.reset + a.dim + " · could not obtain a certificate" + a.reset);
|
|
1468
1481
|
}
|
|
1469
1482
|
}
|
|
1470
1483
|
|
|
@@ -1640,6 +1653,12 @@ async function devMode(mode, keepAwake, existingPinHash, wantOsUsers) {
|
|
|
1640
1653
|
var mkcertDetected = false;
|
|
1641
1654
|
|
|
1642
1655
|
if (useHttps) {
|
|
1656
|
+
// Refresh the runtime cert cache from the clay.studio endpoint (best effort,
|
|
1657
|
+
// short timeout) so getBuiltinCert picks up the current auto-renewed cert
|
|
1658
|
+
// instead of the stale baked copy. Skipped when the user forces mkcert.
|
|
1659
|
+
if (!forceMkcert) {
|
|
1660
|
+
try { await clayStudioCert.refreshCache(5000); } catch (e) {}
|
|
1661
|
+
}
|
|
1643
1662
|
var certPaths = ensureCerts(ip);
|
|
1644
1663
|
if (certPaths) {
|
|
1645
1664
|
hasTls = true;
|
|
@@ -1851,6 +1870,9 @@ async function devMode(mode, keepAwake, existingPinHash, wantOsUsers) {
|
|
|
1851
1870
|
// ==============================
|
|
1852
1871
|
async function restartDaemonWithTLS(config, callback) {
|
|
1853
1872
|
var ip = getLocalIP();
|
|
1873
|
+
if (!forceMkcert) {
|
|
1874
|
+
try { await clayStudioCert.refreshCache(5000); } catch (e) {}
|
|
1875
|
+
}
|
|
1854
1876
|
var certPaths = ensureCerts(ip);
|
|
1855
1877
|
if (!certPaths) {
|
|
1856
1878
|
callback(config);
|
package/lib/certs/fullchain.pem
CHANGED
|
@@ -1,47 +1,81 @@
|
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
MIIDjTCCAxOgAwIBAgISBrR9JEWSYT2n404PsSP43IdoMAoGCCqGSM49BAMDMDMx
|
|
3
|
+
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZ
|
|
4
|
+
RTEwHhcNMjYwNjE4MDgwNTE5WhcNMjYwOTE2MDgwNTE4WjAaMRgwFgYDVQQDDA8q
|
|
5
|
+
LmQuY2xheS5zdHVkaW8wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASrxxs5PE+8
|
|
6
|
+
vMltWI5D+dynbZexsgegG4LmDP2+ZRt4OIWJA4e8qR39LP0W8IRtvhpjM0ifyImZ
|
|
7
|
+
OFfgxX/NgtCBo4ICHjCCAhowDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsG
|
|
8
|
+
AQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFLBOYatEoih78WWUdl2JCeb5
|
|
9
|
+
BuwyMB8GA1UdIwQYMBaAFLsgykcL/tflnPmPCSqjjDdFsbzYMDMGCCsGAQUFBwEB
|
|
10
|
+
BCcwJTAjBggrBgEFBQcwAoYXaHR0cDovL3llMS5pLmxlbmNyLm9yZy8wGgYDVR0R
|
|
11
|
+
BBMwEYIPKi5kLmNsYXkuc3R1ZGlvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMC8GA1Ud
|
|
12
|
+
HwQoMCYwJKAioCCGHmh0dHA6Ly95ZTEuYy5sZW5jci5vcmcvMTA1LmNybDCCAQwG
|
|
13
|
+
CisGAQQB1nkCBAIEgf0EgfoA+AB1ANdtfRDRp/V3wsfpX9cAv/mCyTNaZeHQswFz
|
|
14
|
+
F8DIxWl3AAABntn46hAAAAQDAEYwRAIgNEAWd2PrGbahnsSv/o3N8P64j+Um64f5
|
|
15
|
+
9TflSDn/1q0CIFzPC7kF0N+CxxA4OHQ14SCqqON6B5l2GbqUMzecmeg6AH8ARq+G
|
|
16
|
+
PTs+5Z+ld96oJF02sNntIqIj9GF3QSKUUu6VUF8AAAGe2fjqtAAIAAAFAAoXXMgE
|
|
17
|
+
AwBIMEYCIQCQC8jNSHFzs8MHr7cs27Evzny0FlI/54qUnRHBXRzqfQIhANIGcX1I
|
|
18
|
+
lWB71hzGllUGdH//wS5I1h3zytf4c4Lrh/wOMAoGCCqGSM49BAMDA2gAMGUCMQCV
|
|
19
|
+
xIhF5thRy53+4Z0Vrtd57Tj2nCHitHw/duSx+Buqcvr0zXJZlHHpRuJ/vst6H2EC
|
|
20
|
+
MG6sYJmeACHB9E/ZHPgjsZo+EZ3EWpCg29tyruOUIcH2wzt+dKoCumkau6H3rwPY
|
|
21
|
+
AQ==
|
|
21
22
|
-----END CERTIFICATE-----
|
|
22
23
|
-----BEGIN CERTIFICATE-----
|
|
23
|
-
|
|
24
|
+
MIICizCCAhGgAwIBAgIQXd1w3TH4AchcGGp6BLgK/jAKBggqhkjOPQQDAzAuMQsw
|
|
25
|
+
CQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZRTAeFw0y
|
|
26
|
+
NTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYD
|
|
27
|
+
VQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZRTEwdjAQBgcqhkjOPQIBBgUr
|
|
28
|
+
gQQAIgNiAAQHZVB1/mimla2hfSurylScjPMZaOJXLz/NnAc2sylm8WDyhU9Ccp+z
|
|
29
|
+
ASQi5vSwGGJjSGklkD9fdPR8GpyDIOIjCEfrnbt/v+ZSEPLLEGbaM6EccDbN7p9x
|
|
30
|
+
teIm2Avf+ryjge4wgeswDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF
|
|
31
|
+
BwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLsgykcL/tflnPmPCSqj
|
|
32
|
+
jDdFsbzYMB8GA1UdIwQYMBaAFKPIJlqOoUzQNWP8myPIOq5W809WMDIGCCsGAQUF
|
|
33
|
+
BwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3llLmkubGVuY3Iub3JnLzATBgNV
|
|
34
|
+
HSAEDDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veWUuYy5s
|
|
35
|
+
ZW5jci5vcmcvMAoGCCqGSM49BAMDA2gAMGUCMQDgjUEahFT/h3DRakqiPZpLvPgf
|
|
36
|
+
Zwkt6K2EOMmh1nvEzl83eMLYcod4GCl3b0J1Nn0CMBNYmEQJb4CEG5WoOe7aRn/L
|
|
37
|
+
VKu6saHmHEynI7ysIPd8zQsK1HdmhlHKlw9Z5GpGvA==
|
|
38
|
+
-----END CERTIFICATE-----
|
|
39
|
+
-----BEGIN CERTIFICATE-----
|
|
40
|
+
MIICpjCCAiugAwIBAgIRAIchZfw0tuX7qK3Vs3BftTowCgYIKoZIzj0EAwMwTzEL
|
|
41
|
+
MAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNo
|
|
42
|
+
IEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDIwHhcNMjYwNTEzMDAwMDAwWhcN
|
|
43
|
+
MzIwOTAyMjM1OTU5WjAuMQswCQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4G
|
|
44
|
+
A1UEAxMHUm9vdCBZRTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDwS/6vhrcVqcbBo
|
|
45
|
+
+wgdI3fwn9x7DNJJOY/lTOti0vkwuRN87RhEhTH17E7XyFjWsPYhIPt/wzOqxTd2
|
|
46
|
+
b+4ZJNy9ID04YywF9U5zasDVyGSNErVNtz8uSGh5izW87j77GaOB6zCB6DAOBgNV
|
|
47
|
+
HQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB
|
|
48
|
+
/zAdBgNVHQ4EFgQUo8gmWo6hTNA1Y/ybI8g6rlbzT1YwHwYDVR0jBBgwFoAUfEKW
|
|
49
|
+
rt5LSDv6kviejM9ti6lyN5UwMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZo
|
|
50
|
+
dHRwOi8veDIuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcGA1Ud
|
|
51
|
+
HwQgMB4wHKAaoBiGFmh0dHA6Ly94Mi5jLmxlbmNyLm9yZy8wCgYIKoZIzj0EAwMD
|
|
52
|
+
aQAwZgIxAMU19WCtmxVND8UHBZRoma49Z7jPs64Dma0eTu1OChVbB/2J7GV3nvYK
|
|
53
|
+
Ax54uk1G9QIxAO0miLVJu8PLNiXXXkiE/gsK3CTRTF/aeo4bMX42Zw40csRU6AC2
|
|
54
|
+
6hSW1/IWaas6dg==
|
|
55
|
+
-----END CERTIFICATE-----
|
|
56
|
+
-----BEGIN CERTIFICATE-----
|
|
57
|
+
MIIEcDCCAligAwIBAgIQbI8dxyfHEX97r4U6yYD5zTANBgkqhkiG9w0BAQsFADBP
|
|
24
58
|
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNjA1MTMwMDAwMDBa
|
|
60
|
+
Fw0zMjA5MDIyMzU5NTlaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5l
|
|
61
|
+
dCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgy
|
|
62
|
+
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
|
|
63
|
+
ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7
|
|
64
|
+
AlF9ItgKbppbd9/w+kHsOdx1ymgHDB/qo4H1MIHyMA4GA1UdDwEB/wQEAwIBBjAd
|
|
65
|
+
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAd
|
|
66
|
+
BgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwHwYDVR0jBBgwFoAUebRZ5nu2
|
|
67
|
+
5eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZodHRw
|
|
68
|
+
Oi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcGA1UdHwQg
|
|
69
|
+
MB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcNAQELBQAD
|
|
70
|
+
ggIBAD2/e9frmMxNpCV03qUHegg+MV2wz9644YoXdqtH8RyWYcBO7xfjjGEXdU1e
|
|
71
|
+
/o0OkEFiynUCOSIk/vLLo7ttz6CPAeNlWfC0XNkoGeWgK6jjXvozBaGuGH5n0Ufo
|
|
72
|
+
shMeWTuURqNN5G00sSXDTBrpp2+mgvdZQjb8K11TYMA25QA+YHNfbIEL0BniAhKS
|
|
73
|
+
2gsnJjSzrdZLI+EZ7SEyqdR2rkjd1KutLDU+n3TFyxjniZVGur4YlhMP3mY/dV95
|
|
74
|
+
IruAkkjOZier6hGBdEgZXXvaCz9u9iVEadsIE75pAGL8oHV5vxdARDiotRpul1IN
|
|
75
|
+
/UZwzAbrfUFcw1HkAcYD/mlZfnQ2ieCF2MS7j3Vhv7JPDKp45fmykmzYNSrumRW0
|
|
76
|
+
upFFKDBOoF7hsOb7oLyHS+Uft6jOUfOrogj8YUx38hKb2K20r42OgsSdDdxdeYWc
|
|
77
|
+
MS3Sb6mwJeSZEYxJ2gaXnDSPaKhhrNkYwljyVQyr4Nq+MEJytXNTnHqaAcrNwZlV
|
|
78
|
+
pcJL1KBnMrMjP7eanvUwL3FYj3cF17jtboLt7gLoi4+2rWZFvn+w54jmd/FIuhhZ
|
|
79
|
+
cEaU/wvU6BUNMtcVquVGHp7itQeDth5j+XL3j4WJ2SABwzUl6OeYdgpIt/ITZa+p
|
|
80
|
+
TT0mQ/r5XyA4MEAiabn7XJjvCERlF2dcn2wqJw+CreTkkQ2R
|
|
47
81
|
-----END CERTIFICATE-----
|
package/lib/certs/privkey.pem
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgeObHdfttml/RvJo1
|
|
3
|
+
pfW5sNawWozxsJYt7wLg6CpXM8KhRANCAASrxxs5PE+8vMltWI5D+dynbZexsgeg
|
|
4
|
+
G4LmDP2+ZRt4OIWJA4e8qR39LP0W8IRtvhpjM0ifyImZOFfgxX/NgtCB
|
|
5
5
|
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Runtime fetch of the *.d.clay.studio wildcard certificate.
|
|
2
|
+
//
|
|
3
|
+
// Clay serves browser-trusted HTTPS for local instances via a Let's Encrypt
|
|
4
|
+
// wildcard cert for *.d.clay.studio. Historically that cert was baked into the
|
|
5
|
+
// npm package (lib/certs/), so every ~90 days the shipped copy expired and all
|
|
6
|
+
// installed clients silently dropped to HTTP until a new release. This module
|
|
7
|
+
// fetches the CURRENT cert from a small endpoint (served off the same VM that
|
|
8
|
+
// auto-renews it) and caches it under ~/.clay/certs, decoupling cert freshness
|
|
9
|
+
// from npm releases. The baked cert remains a fallback for offline starts.
|
|
10
|
+
//
|
|
11
|
+
// The wildcard private key is public by design: every client needs it to
|
|
12
|
+
// terminate TLS for its own <dashed-ip>.d.clay.studio hostname. This is the
|
|
13
|
+
// same trade-off sslip.io-style zero-config HTTPS already accepts, so fetching
|
|
14
|
+
// it at runtime exposes nothing that the npm tarball did not already.
|
|
15
|
+
|
|
16
|
+
var fs = require("fs");
|
|
17
|
+
var path = require("path");
|
|
18
|
+
var https = require("https");
|
|
19
|
+
var { execFileSync } = require("child_process");
|
|
20
|
+
var { REAL_HOME } = require("./config");
|
|
21
|
+
|
|
22
|
+
var DEFAULT_URL = "https://cert.d.clay.studio/clay-cert.json";
|
|
23
|
+
var EXPIRY_SKEW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
24
|
+
|
|
25
|
+
function certUrl() {
|
|
26
|
+
return process.env.CLAY_CERT_URL || DEFAULT_URL;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function cacheDir() {
|
|
30
|
+
var home = process.env.CLAY_HOME || process.env.CLAUDE_RELAY_HOME || path.join(REAL_HOME, ".clay");
|
|
31
|
+
return path.join(home, "certs");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function fullchainPath() { return path.join(cacheDir(), "clay-studio-fullchain.pem"); }
|
|
35
|
+
function privkeyPath() { return path.join(cacheDir(), "clay-studio-privkey.pem"); }
|
|
36
|
+
|
|
37
|
+
// notAfter (ms) of a PEM file, or 0 if it can't be read.
|
|
38
|
+
function certExpiryMs(certPath) {
|
|
39
|
+
try {
|
|
40
|
+
var out = execFileSync("openssl", ["x509", "-in", certPath, "-noout", "-enddate"], { encoding: "utf8" });
|
|
41
|
+
var m = out.match(/notAfter=(.+)/);
|
|
42
|
+
if (m) return new Date(m[1]).getTime();
|
|
43
|
+
} catch (e) {}
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Returns { key, cert } cached file paths if a previously-fetched cert exists
|
|
48
|
+
// and is not expiring within 7 days; otherwise null. Synchronous.
|
|
49
|
+
function cachedCertFiles() {
|
|
50
|
+
var cert = fullchainPath();
|
|
51
|
+
var key = privkeyPath();
|
|
52
|
+
if (!fs.existsSync(cert) || !fs.existsSync(key)) return null;
|
|
53
|
+
var expiry = certExpiryMs(cert);
|
|
54
|
+
if (expiry && expiry - Date.now() < EXPIRY_SKEW_MS) return null;
|
|
55
|
+
return { key: key, cert: cert };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isPem(s) {
|
|
59
|
+
return typeof s === "string" && s.indexOf("-----BEGIN") !== -1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Best-effort fetch of the current cert from the endpoint, written atomically
|
|
63
|
+
// to the cache. Resolves true on success, false on any failure. Never rejects,
|
|
64
|
+
// so callers can `await` it unconditionally on startup.
|
|
65
|
+
function refreshCache(timeoutMs) {
|
|
66
|
+
return new Promise(function (resolve) {
|
|
67
|
+
var done = false;
|
|
68
|
+
function finish(ok) { if (!done) { done = true; resolve(ok); } }
|
|
69
|
+
var req;
|
|
70
|
+
try {
|
|
71
|
+
req = https.get(certUrl(), { timeout: timeoutMs || 5000 }, function (res) {
|
|
72
|
+
if (res.statusCode !== 200) { res.resume(); return finish(false); }
|
|
73
|
+
var body = "";
|
|
74
|
+
res.setEncoding("utf8");
|
|
75
|
+
res.on("data", function (c) {
|
|
76
|
+
body += c;
|
|
77
|
+
if (body.length > 1024 * 1024) { req.destroy(); finish(false); }
|
|
78
|
+
});
|
|
79
|
+
res.on("end", function () {
|
|
80
|
+
try {
|
|
81
|
+
var obj = JSON.parse(body);
|
|
82
|
+
if (!isPem(obj.fullchain) || !isPem(obj.privkey)) return finish(false);
|
|
83
|
+
var dir = cacheDir();
|
|
84
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
85
|
+
var ctmp = fullchainPath() + ".tmp";
|
|
86
|
+
var ktmp = privkeyPath() + ".tmp";
|
|
87
|
+
fs.writeFileSync(ctmp, obj.fullchain);
|
|
88
|
+
fs.writeFileSync(ktmp, obj.privkey);
|
|
89
|
+
try { fs.chmodSync(ktmp, 0o600); } catch (e) {}
|
|
90
|
+
// Don't overwrite a good cache with a near-expired cert.
|
|
91
|
+
var expiry = certExpiryMs(ctmp);
|
|
92
|
+
if (expiry && expiry - Date.now() < EXPIRY_SKEW_MS) {
|
|
93
|
+
try { fs.unlinkSync(ctmp); fs.unlinkSync(ktmp); } catch (e) {}
|
|
94
|
+
return finish(false);
|
|
95
|
+
}
|
|
96
|
+
fs.renameSync(ctmp, fullchainPath());
|
|
97
|
+
fs.renameSync(ktmp, privkeyPath());
|
|
98
|
+
finish(true);
|
|
99
|
+
} catch (e) { finish(false); }
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
req.on("timeout", function () { req.destroy(); finish(false); });
|
|
103
|
+
req.on("error", function () { finish(false); });
|
|
104
|
+
} catch (e) { finish(false); }
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
certUrl: certUrl,
|
|
110
|
+
cachedCertFiles: cachedCertFiles,
|
|
111
|
+
refreshCache: refreshCache,
|
|
112
|
+
};
|
package/lib/daemon.js
CHANGED
|
@@ -78,8 +78,17 @@ if (config.tls) {
|
|
|
78
78
|
var userKeyPath = path.join(certDir, "key.pem");
|
|
79
79
|
var userCertPath = path.join(certDir, "cert.pem");
|
|
80
80
|
|
|
81
|
+
// Cert fetched at runtime from the clay.studio endpoint (always current),
|
|
82
|
+
// cached by the CLI before forking us. Prefer it over the baked copy.
|
|
83
|
+
var fetched = null;
|
|
84
|
+
try { fetched = require("./clay-studio-cert").cachedCertFiles(); } catch (e) {}
|
|
85
|
+
|
|
81
86
|
var keyPath, certPath;
|
|
82
|
-
if (config.builtinCert !== false &&
|
|
87
|
+
if (config.builtinCert !== false && fetched) {
|
|
88
|
+
keyPath = fetched.key;
|
|
89
|
+
certPath = fetched.cert;
|
|
90
|
+
config.builtinCert = true;
|
|
91
|
+
} else if (config.builtinCert !== false && fs.existsSync(builtinKeyPath) && fs.existsSync(builtinCertPath)) {
|
|
83
92
|
keyPath = builtinKeyPath;
|
|
84
93
|
certPath = builtinCertPath;
|
|
85
94
|
config.builtinCert = true;
|
package/package.json
CHANGED