@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 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
@@ -204,7 +204,7 @@ const main = async () => {
204
204
  ),
205
205
  );
206
206
  } else {
207
- customUrl = "http://ipfs.ethernity.cloud:5001";
207
+ customUrl = "https://ipfs.ethernity.cloud";
208
208
  }
209
209
 
210
210
  fs.mkdirSync("src/serverless", { recursive: true });
@@ -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
- ENV SCONE_LOG=info
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
- # Enable production mode for mainnet
60
- # RUN scone-signer sign --key=/enclave-key.pem --env --production /usr/bin/node
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
@@ -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
- const 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
- fs.writeFileSync('Dockerfile', dockerfileSecureContent);
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
- fs.writeFileSync('Dockerfile', dockerfileSecureContent.replace('# RUN scone-signer sign', 'RUN scone-signer sign'));
133
- imagesTag = process.env.BLOCKCHAIN_NETWORK.split("_")[0].toLowerCase()
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