@ethernity-cloud/sdk-js 1.1.1 → 1.2.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/build.js +29 -0
- package/init.js +1 -1
- package/nodenithy/build/securelock/Dockerfile.tmpl +21 -5
- package/nodenithy/build.mjs +42 -5
- package/nodenithy/ipfs.mjs +340 -426
- package/nodenithy/run/docker-compose-final.yml.tmpl +3 -0
- package/nodenithy/run/docker-compose.yml.tmpl +10 -8
- package/nodenithy/run.js +44 -1
- package/package.json +46 -46
- package/pynithy/build/securelock/Dockerfile.tmpl +18 -2
- package/pynithy/build.mjs +31 -5
- package/pynithy/ipfs.mjs +376 -155
- package/pynithy/run/docker-compose-final.yml.tmpl +9 -0
- package/pynithy/run/docker-compose.yml.tmpl +10 -6
- package/pynithy/run.js +40 -1
package/build.js
CHANGED
|
@@ -1,7 +1,36 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
require('dotenv').config();
|
|
4
5
|
|
|
6
|
+
// Increment VERSION on every build, mirroring the Python SDK's build.py
|
|
7
|
+
// (config VERSION += 1). VERSION is the immutable per-build registry channel and
|
|
8
|
+
// the enclave-name suffix, so each build must advance it. Existing projects seed
|
|
9
|
+
// VERSION as "v1"; parse whatever trailing integer is present (v1 -> 1, 22 -> 22,
|
|
10
|
+
// empty -> 0), increment, and persist as a plain integer. It must never equal
|
|
11
|
+
// "v3" (the protocol channel that acts as the moving "latest" pointer); plain
|
|
12
|
+
// integers can't collide with the "v3" string, so this is safe.
|
|
13
|
+
const writeEnv = (key, value) => {
|
|
14
|
+
const envFile = '.env';
|
|
15
|
+
let content = fs.existsSync(envFile) ? fs.readFileSync(envFile, 'utf8') : '';
|
|
16
|
+
const regex = new RegExp(`^${key}=.*`, 'm');
|
|
17
|
+
if (regex.test(content)) content = content.replace(regex, `${key}=${value}`);
|
|
18
|
+
else content += (content && !content.endsWith('\n') ? '\n' : '') + `${key}=${value}`;
|
|
19
|
+
fs.writeFileSync(envFile, content, 'utf8');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const bumpVersion = () => {
|
|
23
|
+
const raw = (process.env.VERSION || '0').toString();
|
|
24
|
+
const digits = raw.match(/\d+/);
|
|
25
|
+
const next = (digits ? parseInt(digits[0], 10) : 0) + 1;
|
|
26
|
+
process.env.VERSION = String(next);
|
|
27
|
+
writeEnv('VERSION', String(next));
|
|
28
|
+
console.log(`Version incremented to ${next}`);
|
|
29
|
+
return next;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
bumpVersion();
|
|
33
|
+
|
|
5
34
|
const serviceType = process.env.SERVICE_TYPE;
|
|
6
35
|
|
|
7
36
|
if (serviceType === "Nodenithy") {
|
package/init.js
CHANGED
|
@@ -6,7 +6,6 @@ RUN cd /
|
|
|
6
6
|
|
|
7
7
|
RUN apk add bash
|
|
8
8
|
|
|
9
|
-
ENV SCONE_MODE=SIM
|
|
10
9
|
ENV SCONE_HEAP=256M
|
|
11
10
|
ENV SCONE_LOG=DEBUG
|
|
12
11
|
ENV ENCLAVE_NAME_SECURELOCK=__ENCLAVE_NAME_SECURELOCK__
|
|
@@ -50,14 +49,31 @@ RUN apk add openssl
|
|
|
50
49
|
|
|
51
50
|
RUN openssl genrsa -3 -out /enclave-key.pem 3072
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
# SCONE runtime env. These MUST match the enclave-creation params passed to
|
|
53
|
+
# scone-signer below (SCONE embeds defaults for anything not signed explicitly;
|
|
54
|
+
# any drift makes SCONE recompute + debug re-sign the enclave at load, which CAS
|
|
55
|
+
# rejects on mainnet). Values mirror the publish/run docker-compose securelock
|
|
56
|
+
# service (SCONE_HEAP=1024M, SCONE_STACK=4M, dlopen=1, extensions=libbinary-fs).
|
|
55
57
|
ENV SCONE_HEAP=1024M
|
|
58
|
+
ENV SCONE_STACK=4M
|
|
56
59
|
ENV SCONE_ALLOW_DLOPEN=1
|
|
57
60
|
ENV SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
|
|
58
61
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
62
|
+
# Rendered by build.mjs. Signs the EXECUTED binary (/usr/local/bin/node -- the
|
|
63
|
+
# ENTRYPOINT and the run/publish compose command both run /usr/local/bin/node).
|
|
64
|
+
# Mainnet adds --production (CAS/DCAP attestation); testnet omits it (non-CAS
|
|
65
|
+
# self-sign). On testnet builds this line is a no-op comment.
|
|
66
|
+
__SCONE_SIGN__
|
|
67
|
+
|
|
68
|
+
# Record the SIGNED MRENCLAVE so publish (run.js) can assert the runtime enclave
|
|
69
|
+
# measurement matches what was signed BEFORE registering the CAS session /
|
|
70
|
+
# publishing. A mismatch means SCONE recomputed the enclave at load (params
|
|
71
|
+
# drift) => debug re-sign => CAS rejects the DCAP quote on mainnet. Only produced
|
|
72
|
+
# for --production (mainnet) signs; on testnet the file is absent and the check
|
|
73
|
+
# is skipped. Capture to a file first: piping scone-signer into `head` kills it
|
|
74
|
+
# with SIGPIPE (exit 141) under buildkit's pipefail shell.
|
|
75
|
+
__SIGNED_MRENCLAVE__
|
|
76
|
+
|
|
61
77
|
RUN rm -rf /enclave-key.pem
|
|
62
78
|
|
|
63
79
|
#RUN scone cas attest scone-cas.cf 3061b9feb7fa67f3815336a085f629a13f04b0a1667c93b14ff35581dc8271e4 -GCS --only_for_testing-debug --only_for_testing-ignore-signer
|
package/nodenithy/build.mjs
CHANGED
|
@@ -122,17 +122,54 @@ console.log('Building etny-securelock');
|
|
|
122
122
|
process.chdir('securelock');
|
|
123
123
|
// runCommand(`cat Dockerfile.tmpl | sed s/"__ENCLAVE_NAME_SECURELOCK__"/"${ENCLAVE_NAME_SECURELOCK}"/g > Dockerfile`);
|
|
124
124
|
const dockerfileSecureTemplate = fs.readFileSync('Dockerfile.tmpl', 'utf8');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
let dockerfileSecureContent = dockerfileSecureTemplate.replace(/__ENCLAVE_NAME_SECURELOCK__/g, ENCLAVE_NAME_SECURELOCK).replace(/__BUCKET_NAME__/g, templateName + "-v3").replace(/__SMART_CONTRACT_ADDRESS__/g, ECRunner[templateName][0]).replace(/__IMAGE_REGISTRY_ADDRESS__/g, ECRunner[templateName][1]).replace(/__RPC_URL__/g, ECRunner[templateName][2]).replace(/__CHAIN_ID__/g, ECRunner[templateName][3]).replace(/__TRUSTED_ZONE_IMAGE__/g, templateName);
|
|
126
|
+
|
|
127
|
+
// Amount of enclave heap to allocate (SCONE_HEAP). Kept in sync with the
|
|
128
|
+
// run/docker-compose securelock service; overridable via ECLD_MEMORY_TO_ALLOCATE.
|
|
129
|
+
const MEMORY_TO_ALLOCATE = (process.env.ECLD_MEMORY_TO_ALLOCATE || '1024M').trim();
|
|
130
|
+
|
|
131
|
+
// CRITICAL (mainnet DCAP): sign /usr/local/bin/node -- the binary the enclave
|
|
132
|
+
// actually EXECUTES (ENTRYPOINT + the run/publish compose command both run
|
|
133
|
+
// /usr/local/bin/node). Signing anything else leaves the executed binary as the
|
|
134
|
+
// base image's DEBUG-signed one, so at load SCONE recomputes MRENCLAVE and
|
|
135
|
+
// re-signs it as debug -> CAS rejects the DCAP quote ("Debug mode enabled").
|
|
136
|
+
//
|
|
137
|
+
// The enclave-creation params (--heap/--stack/--dlopen/--extensions) MUST be
|
|
138
|
+
// passed explicitly and match the runtime env exactly (scone-signer embeds SCONE
|
|
139
|
+
// defaults for anything not passed as a flag) -- any drift triggers the same
|
|
140
|
+
// debug re-sign. Values mirror the run/docker-compose securelock service.
|
|
141
|
+
const signFlags =
|
|
142
|
+
`--key=/enclave-key.pem --env --heap=${MEMORY_TO_ALLOCATE} ` +
|
|
143
|
+
`--stack=4M --dlopen=1 --extensions=/lib/libbinary-fs.so`;
|
|
144
|
+
|
|
145
|
+
// scone-signer prints two tab-indented "MRENCLAVE:" lines (non-EDMM first;
|
|
146
|
+
// runtime has EDMM disabled, so the first is what SCONE_HASH produces). Capture
|
|
147
|
+
// to a file first -- piping into head/grep kills scone-signer with SIGPIPE
|
|
148
|
+
// (exit 141) under buildkit's pipefail shell.
|
|
149
|
+
const signedMrenclaveStep =
|
|
150
|
+
'RUN scone-signer info /usr/local/bin/node > /tmp/siginfo.txt 2>&1; \\\n' +
|
|
151
|
+
' grep -iE "MRENCLAVE:" /tmp/siginfo.txt | sed -n \'1p\' \\\n' +
|
|
152
|
+
' | sed -E \'s/.*MRENCLAVE:[[:space:]]*//I\' | tr -d \'[:space:]\' > /signed_mrenclave.txt && \\\n' +
|
|
153
|
+
' echo "SIGNED_MRENCLAVE=$(cat /signed_mrenclave.txt)"';
|
|
128
154
|
|
|
129
155
|
let imagesTag = process.env.BLOCKCHAIN_NETWORK.toLowerCase();
|
|
130
156
|
|
|
131
157
|
if (isMainnet) {
|
|
132
|
-
|
|
133
|
-
|
|
158
|
+
// Mainnet: production sign the executed node binary + bake the signed MRENCLAVE.
|
|
159
|
+
dockerfileSecureContent = dockerfileSecureContent
|
|
160
|
+
.replace('__SCONE_SIGN__', `RUN scone-signer sign ${signFlags} --production /usr/local/bin/node`)
|
|
161
|
+
.replace('__SIGNED_MRENCLAVE__', signedMrenclaveStep);
|
|
162
|
+
imagesTag = process.env.BLOCKCHAIN_NETWORK.split("_")[0].toLowerCase();
|
|
163
|
+
} else {
|
|
164
|
+
// Testnet: non-CAS self-sign path -- no --production sign and no signed
|
|
165
|
+
// MRENCLAVE baking (the enclave self-signs from MR_ENCLAVE at runtime).
|
|
166
|
+
dockerfileSecureContent = dockerfileSecureContent
|
|
167
|
+
.replace('__SCONE_SIGN__', '# testnet: non-CAS self-sign (no --production sign at build time)')
|
|
168
|
+
.replace('__SIGNED_MRENCLAVE__', '# testnet: no signed MRENCLAVE (self-signed from MR_ENCLAVE at runtime)');
|
|
134
169
|
}
|
|
135
170
|
|
|
171
|
+
fs.writeFileSync('Dockerfile', dockerfileSecureContent);
|
|
172
|
+
|
|
136
173
|
|
|
137
174
|
|
|
138
175
|
|