@abtnode/core 1.17.4-beta-20251205-104405-28838df1 → 1.17.4-beta-20251206-081442-6f622450
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/lib/index.js +2 -0
- package/lib/router/helper.js +138 -0
- package/package.json +24 -24
package/lib/index.js
CHANGED
|
@@ -325,6 +325,7 @@ function ABTNode(options) {
|
|
|
325
325
|
getSitesFromSnapshot,
|
|
326
326
|
getRoutingCrons,
|
|
327
327
|
ensureWildcardCerts,
|
|
328
|
+
ensureServerlessCerts,
|
|
328
329
|
getRouterProvider,
|
|
329
330
|
addRoutingSite,
|
|
330
331
|
deleteRoutingSite,
|
|
@@ -730,6 +731,7 @@ function ABTNode(options) {
|
|
|
730
731
|
getSitesFromSnapshot,
|
|
731
732
|
ensureDashboardRouting,
|
|
732
733
|
ensureWildcardCerts,
|
|
734
|
+
ensureServerlessCerts,
|
|
733
735
|
|
|
734
736
|
addDomainAlias,
|
|
735
737
|
deleteDomainAlias,
|
package/lib/router/helper.js
CHANGED
|
@@ -25,9 +25,12 @@ const md5 = require('@abtnode/util/lib/md5');
|
|
|
25
25
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
26
26
|
const getTmpDir = require('@abtnode/util/lib/get-tmp-directory');
|
|
27
27
|
const downloadFile = require('@abtnode/util/lib/download-file');
|
|
28
|
+
const axios = require('@abtnode/util/lib/axios');
|
|
28
29
|
const { getIpDnsDomainForBlocklet } = require('@abtnode/util/lib/get-domain-for-blocklet');
|
|
29
30
|
const { forEachBlockletSync } = require('@blocklet/meta/lib/util');
|
|
30
31
|
const { processLogByDate } = require('@abtnode/analytics');
|
|
32
|
+
const pRetry = require('p-retry');
|
|
33
|
+
const { buildLauncherUrl, buildRequestHeaders } = require('@abtnode/auth/lib/launcher');
|
|
31
34
|
const {
|
|
32
35
|
DOMAIN_FOR_DEFAULT_SITE,
|
|
33
36
|
DOMAIN_FOR_IP_SITE_REGEXP,
|
|
@@ -52,6 +55,7 @@ const {
|
|
|
52
55
|
EVENTS,
|
|
53
56
|
DEFAULT_IP_DOMAIN,
|
|
54
57
|
WELLKNOWN_BLACKLIST_PREFIX,
|
|
58
|
+
NODE_MODES,
|
|
55
59
|
} = require('@abtnode/constant');
|
|
56
60
|
const {
|
|
57
61
|
BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
@@ -903,6 +907,133 @@ module.exports = function getRouterHelpers({
|
|
|
903
907
|
]);
|
|
904
908
|
};
|
|
905
909
|
|
|
910
|
+
const ensureServerlessCerts = async () => {
|
|
911
|
+
const info = await nodeState.read();
|
|
912
|
+
|
|
913
|
+
if (info.mode !== NODE_MODES.SERVERLESS) {
|
|
914
|
+
logger.warn('ensureServerlessCerts: not in serverless mode', { mode: info.mode });
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
const launcherUrl = process.env.ABT_NODE_BLOCKLET_LAUNCHER_URL || info.registerUrl;
|
|
919
|
+
const provisionToken = process.env.ABT_NODE_PROVISION_TOKEN;
|
|
920
|
+
|
|
921
|
+
if (!launcherUrl) {
|
|
922
|
+
logger.warn('ensureServerlessCerts: missing launcher URL');
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
let authHeaders = {};
|
|
927
|
+
let authType = 'none';
|
|
928
|
+
|
|
929
|
+
const payload = {
|
|
930
|
+
did: info.did,
|
|
931
|
+
version: info.version,
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
if (provisionToken) {
|
|
935
|
+
authHeaders = { Authorization: `Bearer ${provisionToken}` };
|
|
936
|
+
authType = 'bearer';
|
|
937
|
+
} else if (info.sk) {
|
|
938
|
+
try {
|
|
939
|
+
authHeaders = await buildRequestHeaders(info.sk, payload);
|
|
940
|
+
authType = 'signature';
|
|
941
|
+
} catch (error) {
|
|
942
|
+
logger.error('ensureServerlessCerts: failed to create signature', { error });
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
} else {
|
|
946
|
+
logger.warn('ensureServerlessCerts: no authentication method available');
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
const fn = async () => {
|
|
951
|
+
const provisionUrl = await buildLauncherUrl(launcherUrl, '/api/serverless/provision');
|
|
952
|
+
const destFolder = getTmpDir(path.join(`serverless-cert-${Date.now()}`));
|
|
953
|
+
|
|
954
|
+
logger.info('download serverless certificate start', { provisionUrl, destFolder, authType });
|
|
955
|
+
|
|
956
|
+
try {
|
|
957
|
+
const filename = path.join(destFolder, 'certificate.tar.gz');
|
|
958
|
+
fs.ensureDirSync(destFolder);
|
|
959
|
+
|
|
960
|
+
const { data } = await axios({
|
|
961
|
+
method: 'post',
|
|
962
|
+
url: provisionUrl,
|
|
963
|
+
headers: authHeaders,
|
|
964
|
+
responseType: 'stream',
|
|
965
|
+
data: payload,
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
const fileStream = data.pipe(fs.createWriteStream(filename));
|
|
969
|
+
await new Promise((resolve, reject) => {
|
|
970
|
+
fileStream.on('finish', resolve);
|
|
971
|
+
fileStream.on('error', reject);
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
await decompressCertificates(filename, destFolder);
|
|
975
|
+
|
|
976
|
+
const certificateFilePath = path.join(destFolder, 'cert.pem');
|
|
977
|
+
const privateKeyFilePath = path.join(destFolder, 'privkey.pem');
|
|
978
|
+
|
|
979
|
+
if (!fs.existsSync(certificateFilePath)) {
|
|
980
|
+
throw new Error('serverless certificate invalid: cert.pem does not exist');
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (!fs.existsSync(privateKeyFilePath)) {
|
|
984
|
+
throw new Error('serverless certificate invalid: privkey.pem does not exist');
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
const certificate = fs.readFileSync(certificateFilePath).toString();
|
|
988
|
+
const privateKey = fs.readFileSync(privateKeyFilePath).toString();
|
|
989
|
+
|
|
990
|
+
const certInfo = getHttpsCertInfo(certificate);
|
|
991
|
+
const domain = certInfo.sans?.[0] || certInfo.domain;
|
|
992
|
+
|
|
993
|
+
if (!domain) {
|
|
994
|
+
throw new Error('serverless certificate invalid: no domain found');
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
await certManager.upsertByDomain({
|
|
998
|
+
domain,
|
|
999
|
+
privateKey,
|
|
1000
|
+
certificate,
|
|
1001
|
+
isProtected: false,
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
logger.info('serverless certificate updated', { domain, authType });
|
|
1005
|
+
return domain;
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
logger.error('serverless certificate download failed', { error, authType });
|
|
1008
|
+
throw error;
|
|
1009
|
+
} finally {
|
|
1010
|
+
fs.removeSync(destFolder);
|
|
1011
|
+
logger.info('remove serverless certificate dest folder', { destFolder });
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
const delay = 10 * 1000;
|
|
1016
|
+
try {
|
|
1017
|
+
await pRetry(fn, {
|
|
1018
|
+
retries: 3,
|
|
1019
|
+
minTimeout: delay,
|
|
1020
|
+
maxTimeout: delay,
|
|
1021
|
+
onFailedAttempt: (error) => {
|
|
1022
|
+
logger.error('serverless certificate download retry', {
|
|
1023
|
+
error,
|
|
1024
|
+
attempt: error.attemptNumber,
|
|
1025
|
+
retriesLeft: error.retriesLeft,
|
|
1026
|
+
});
|
|
1027
|
+
if (error.response && error.response.status >= 400 && error.response.status < 500) {
|
|
1028
|
+
throw error;
|
|
1029
|
+
}
|
|
1030
|
+
},
|
|
1031
|
+
});
|
|
1032
|
+
} catch (error) {
|
|
1033
|
+
logger.error('serverless certificate update failed', { error, authType });
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
|
|
906
1037
|
const upsertSiteRule = async ({ site, rule }, context) => {
|
|
907
1038
|
const findExistingRule = (prefix) => site.rules.find((r) => r.from.pathPrefix === normalizePathPrefix(prefix));
|
|
908
1039
|
|
|
@@ -2040,6 +2171,7 @@ module.exports = function getRouterHelpers({
|
|
|
2040
2171
|
getSitesFromSnapshot,
|
|
2041
2172
|
getCertificates,
|
|
2042
2173
|
ensureWildcardCerts,
|
|
2174
|
+
ensureServerlessCerts,
|
|
2043
2175
|
addWellknownSite,
|
|
2044
2176
|
upsertSiteRule,
|
|
2045
2177
|
getRouterProvider: (name) => providers[name],
|
|
@@ -2052,6 +2184,12 @@ module.exports = function getRouterHelpers({
|
|
|
2052
2184
|
fn: () => updateDashboardCertificates(),
|
|
2053
2185
|
options: { runOnInit: true },
|
|
2054
2186
|
},
|
|
2187
|
+
{
|
|
2188
|
+
name: 'update-serverless-certificate',
|
|
2189
|
+
time: '0 10 */6 * * *', // refetch on 0:10, 6:10, etc. (offset from dashboard cert update)
|
|
2190
|
+
fn: () => ensureServerlessCerts(),
|
|
2191
|
+
options: { runOnInit: false },
|
|
2192
|
+
},
|
|
2055
2193
|
{
|
|
2056
2194
|
name: 'rotate-log-files',
|
|
2057
2195
|
time: '1 0 0 * * *', // rotate at 00:00:01 every day
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.17.4-beta-
|
|
6
|
+
"version": "1.17.4-beta-20251206-081442-6f622450",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -17,21 +17,21 @@
|
|
|
17
17
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
18
18
|
"license": "Apache-2.0",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@abtnode/analytics": "1.17.4-beta-
|
|
21
|
-
"@abtnode/auth": "1.17.4-beta-
|
|
22
|
-
"@abtnode/certificate-manager": "1.17.4-beta-
|
|
23
|
-
"@abtnode/constant": "1.17.4-beta-
|
|
24
|
-
"@abtnode/cron": "1.17.4-beta-
|
|
25
|
-
"@abtnode/db-cache": "1.17.4-beta-
|
|
26
|
-
"@abtnode/docker-utils": "1.17.4-beta-
|
|
27
|
-
"@abtnode/logger": "1.17.4-beta-
|
|
28
|
-
"@abtnode/models": "1.17.4-beta-
|
|
29
|
-
"@abtnode/queue": "1.17.4-beta-
|
|
30
|
-
"@abtnode/rbac": "1.17.4-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.17.4-beta-
|
|
32
|
-
"@abtnode/static-server": "1.17.4-beta-
|
|
33
|
-
"@abtnode/timemachine": "1.17.4-beta-
|
|
34
|
-
"@abtnode/util": "1.17.4-beta-
|
|
20
|
+
"@abtnode/analytics": "1.17.4-beta-20251206-081442-6f622450",
|
|
21
|
+
"@abtnode/auth": "1.17.4-beta-20251206-081442-6f622450",
|
|
22
|
+
"@abtnode/certificate-manager": "1.17.4-beta-20251206-081442-6f622450",
|
|
23
|
+
"@abtnode/constant": "1.17.4-beta-20251206-081442-6f622450",
|
|
24
|
+
"@abtnode/cron": "1.17.4-beta-20251206-081442-6f622450",
|
|
25
|
+
"@abtnode/db-cache": "1.17.4-beta-20251206-081442-6f622450",
|
|
26
|
+
"@abtnode/docker-utils": "1.17.4-beta-20251206-081442-6f622450",
|
|
27
|
+
"@abtnode/logger": "1.17.4-beta-20251206-081442-6f622450",
|
|
28
|
+
"@abtnode/models": "1.17.4-beta-20251206-081442-6f622450",
|
|
29
|
+
"@abtnode/queue": "1.17.4-beta-20251206-081442-6f622450",
|
|
30
|
+
"@abtnode/rbac": "1.17.4-beta-20251206-081442-6f622450",
|
|
31
|
+
"@abtnode/router-provider": "1.17.4-beta-20251206-081442-6f622450",
|
|
32
|
+
"@abtnode/static-server": "1.17.4-beta-20251206-081442-6f622450",
|
|
33
|
+
"@abtnode/timemachine": "1.17.4-beta-20251206-081442-6f622450",
|
|
34
|
+
"@abtnode/util": "1.17.4-beta-20251206-081442-6f622450",
|
|
35
35
|
"@aigne/aigne-hub": "^0.10.10",
|
|
36
36
|
"@arcblock/did": "^1.27.12",
|
|
37
37
|
"@arcblock/did-connect-js": "^1.27.12",
|
|
@@ -43,15 +43,15 @@
|
|
|
43
43
|
"@arcblock/pm2-events": "^0.0.5",
|
|
44
44
|
"@arcblock/validator": "^1.27.12",
|
|
45
45
|
"@arcblock/vc": "^1.27.12",
|
|
46
|
-
"@blocklet/constant": "1.17.4-beta-
|
|
46
|
+
"@blocklet/constant": "1.17.4-beta-20251206-081442-6f622450",
|
|
47
47
|
"@blocklet/did-space-js": "^1.2.6",
|
|
48
|
-
"@blocklet/env": "1.17.4-beta-
|
|
48
|
+
"@blocklet/env": "1.17.4-beta-20251206-081442-6f622450",
|
|
49
49
|
"@blocklet/error": "^0.3.3",
|
|
50
|
-
"@blocklet/meta": "1.17.4-beta-
|
|
51
|
-
"@blocklet/resolver": "1.17.4-beta-
|
|
52
|
-
"@blocklet/sdk": "1.17.4-beta-
|
|
53
|
-
"@blocklet/server-js": "1.17.4-beta-
|
|
54
|
-
"@blocklet/store": "1.17.4-beta-
|
|
50
|
+
"@blocklet/meta": "1.17.4-beta-20251206-081442-6f622450",
|
|
51
|
+
"@blocklet/resolver": "1.17.4-beta-20251206-081442-6f622450",
|
|
52
|
+
"@blocklet/sdk": "1.17.4-beta-20251206-081442-6f622450",
|
|
53
|
+
"@blocklet/server-js": "1.17.4-beta-20251206-081442-6f622450",
|
|
54
|
+
"@blocklet/store": "1.17.4-beta-20251206-081442-6f622450",
|
|
55
55
|
"@blocklet/theme": "^3.2.11",
|
|
56
56
|
"@fidm/x509": "^1.2.1",
|
|
57
57
|
"@ocap/mcrypto": "^1.27.12",
|
|
@@ -116,5 +116,5 @@
|
|
|
116
116
|
"express": "^4.18.2",
|
|
117
117
|
"unzipper": "^0.10.11"
|
|
118
118
|
},
|
|
119
|
-
"gitHead": "
|
|
119
|
+
"gitHead": "37b0b1147d40a5cf787cba5d111a63a2b6259790"
|
|
120
120
|
}
|