@ethernity-cloud/sdk-js 1.1.0 → 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.
@@ -1,3 +1,10 @@
1
+ # Publish-time compose: used by ecld-publish to compute the MRENCLAVE
2
+ # (SCONE_HASH=1) and extract the enclave certificate LOCALLY. It intentionally
3
+ # does NOT mount /dev/sgx_enclave so it runs on a developer machine WITHOUT SGX
4
+ # (SCONE_HASH is a build measurement; enclaves reach SGX via LAS over TCP). When
5
+ # no local SGX is present, cert extraction falls back to the remote
6
+ # publickey.ethernity.cloud service. The on-node runtime uses
7
+ # docker-compose-final.yml, which targets real SGX hardware.
1
8
  version: '3.2'
2
9
  services:
3
10
  las:
@@ -5,8 +12,6 @@ services:
5
12
  privileged: true
6
13
  image: localhost:5000/etny-las
7
14
  command: "bash -c '/las_entrypoint.sh && /usr/local/bin/las | tee /var/log/las.log'"
8
- devices:
9
- - "/dev/sgx_enclave:/dev/sgx_enclave"
10
15
  restart: unless-stopped
11
16
  ports:
12
17
  - target: 18766
@@ -25,12 +30,13 @@ services:
25
30
  - SCONE_LAS_ADDR=las
26
31
  - SCONE_CONFIG_ID=__ENCLAVE_NAME_SECURELOCK__/application
27
32
  - SCONE_HEAP=1024M
33
+ # Must match the --stack the securelock binary was signed with (build.mjs),
34
+ # otherwise SCONE recomputes MRENCLAVE at load and re-signs as debug.
35
+ - SCONE_STACK=4M
28
36
  - SCONE_LOG=INFO
29
37
  - SCONE_ALLOW_DLOPEN=1
30
38
  - SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
31
39
  restart: on-failure:5
32
- devices:
33
- - "/dev/sgx_enclave:/dev/sgx_enclave"
34
40
  depends_on:
35
41
  - las
36
42
 
@@ -49,7 +55,5 @@ services:
49
55
  - SCONE_ALLOW_DLOPEN=1
50
56
  - SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
51
57
  restart: on-failure:5
52
- devices:
53
- - "/dev/sgx_enclave:/dev/sgx_enclave"
54
58
  depends_on:
55
59
  - las
package/pynithy/run.js CHANGED
@@ -73,6 +73,29 @@ const runDockerCommand = (service) => {
73
73
  return output.split('\n').filter(line => !/Creating|Pulling|latest|Digest/.test(line)).join('');
74
74
  };
75
75
 
76
+ // Extract the runtime enclave measurement (SCONE_HASH) as a bare 64-hex string.
77
+ // Mirrors Python extract_scone_hash: pick the first 64-hex token in the output.
78
+ const extractSconeHash = (service) => {
79
+ const output = runDockerCommand(service);
80
+ const m = output.match(/\b[a-fA-F0-9]{64}\b/);
81
+ if (!m) throw new Error(`No SHA256 MRENCLAVE found in ${service} SCONE_HASH output.`);
82
+ return m[0];
83
+ };
84
+
85
+ // Read the MRENCLAVE signed at build time (baked into the image as
86
+ // /signed_mrenclave.txt on mainnet). Mirrors Python extract_signed_mrenclave.
87
+ // Returns '' if the file is absent (testnet builds).
88
+ const extractSignedMrenclave = (service) => {
89
+ try {
90
+ const command = `docker-compose -f docker-compose.yml run --no-deps --entrypoint cat ${service} /signed_mrenclave.txt`;
91
+ const output = execSync(command, { stdio: ['pipe', 'pipe', 'pipe'] }).toString().trim();
92
+ const m = output.match(/\b[a-fA-F0-9]{64}\b/);
93
+ return m ? m[0] : '';
94
+ } catch (e) {
95
+ return '';
96
+ }
97
+ };
98
+
76
99
  const main = async () => {
77
100
  process.env.NODE_NO_WARNINGS = 1
78
101
  const backupFiles = ['docker-compose.yml.tmpl', 'docker-compose-final.yml.tmpl'];
@@ -86,13 +109,29 @@ const main = async () => {
86
109
  });
87
110
 
88
111
 
89
- process.env.MRENCLAVE_SECURELOCK = runDockerCommand('etny-securelock');
112
+ process.env.MRENCLAVE_SECURELOCK = extractSconeHash('etny-securelock');
90
113
  console.log(`MRENCLAVE_SECURELOCK: ${process.env.MRENCLAVE_SECURELOCK}`);
91
114
  // process.env.MRENCLAVE_TRUSTEDZONE = runDockerCommand('etny-trustedzone');
92
115
  // console.log(`MRENCLAVE_TRUSTEDZONE: ${process.env.MRENCLAVE_TRUSTEDZONE}`);
93
116
  // process.env.MRENCLAVE_VALIDATOR = runDockerCommand('etny-validator');
94
117
  // console.log(`MRENCLAVE_VALIDATOR: ${process.env.MRENCLAVE_VALIDATOR}`);
95
118
 
119
+ // ----- MRENCLAVE match-gate (mainnet) -----
120
+ // The runtime enclave measured just above (SCONE_HASH) MUST match the
121
+ // MRENCLAVE signed --production at build time (/signed_mrenclave.txt). A
122
+ // mismatch means SCONE recomputed the measurement at load (params drift) and
123
+ // re-signed as DEBUG, which CAS rejects on mainnet. Refuse to publish.
124
+ if (isMainnet) {
125
+ const signedMrenclave = extractSignedMrenclave('etny-securelock');
126
+ if (!signedMrenclave || signedMrenclave !== process.env.MRENCLAVE_SECURELOCK) {
127
+ console.error(`Error: securelock runtime MRENCLAVE (${process.env.MRENCLAVE_SECURELOCK}) != signed MRENCLAVE (${signedMrenclave}).`);
128
+ console.error(' The runtime enclave differs from the --production-signed binary (SCONE recomputed -> debug).');
129
+ console.error(' Refusing to publish. Rebuild with the current SDK (ecld-build) and retry.');
130
+ process.exit(1);
131
+ }
132
+ console.log('\t✔ MRENCLAVE match-gate passed: runtime enclave matches the --production-signed MRENCLAVE');
133
+ }
134
+
96
135
  writeEnv('MRENCLAVE_SECURELOCK', process.env.MRENCLAVE_SECURELOCK);
97
136
  // writeEnv('MRENCLAVE_TRUSTEDZONE', process.env.MRENCLAVE_TRUSTEDZONE);
98
137
  // writeEnv('MRENCLAVE_VALIDATOR', process.env.MRENCLAVE_VALIDATOR);