@ethernity-cloud/sdk-js 1.6.1 → 1.7.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/README.md +44 -6
- package/cas/config.js +61 -3
- package/info.js +333 -324
- package/init.js +20 -4
- package/nodenithy/build/securelock/Dockerfile.tmpl +34 -32
- package/nodenithy/build/securelock/scripts/binary-fs-build.sh +7 -6
- package/nodenithy/build/securelock/src/securelock.js.tmpl +5 -2
- package/nodenithy/build.mjs +83 -71
- package/nodenithy/run/docker-compose-final.yml.tmpl +36 -31
- package/nodenithy/run/docker-compose.yml.tmpl +34 -45
- package/nodenithy/run/image_registry.js +396 -380
- package/nodenithy/run.js +42 -28
- package/package.json +5 -3
- package/publish.js +4 -2
- package/pynithy/build/securelock/Dockerfile.base.tpl +13 -0
- package/pynithy/build/securelock/Dockerfile.tpl +131 -0
- package/pynithy/build/securelock/scripts/binary-fs-build.sh +25 -34
- package/pynithy/build/securelock/scripts/pyfreeze.sh +32 -0
- package/pynithy/build/securelock/src/{pox.abi → abi/etnyImplementationV2.abi} +1489 -1489
- package/pynithy/build/securelock/src/abi/image_registry.abi +1 -0
- package/pynithy/build/securelock/src/ecld_state.py +906 -0
- package/pynithy/build/securelock/src/esr.abi +1 -0
- package/pynithy/build/securelock/src/esr_local.py +267 -0
- package/pynithy/build/securelock/src/esr_wallet.py +150 -0
- package/pynithy/build/securelock/src/etny_crypto.py +208 -167
- package/pynithy/build/securelock/src/etny_exec.py +385 -79
- package/pynithy/build/securelock/src/etny_exec_flask.py +535 -0
- package/pynithy/build/securelock/src/etny_exec_serv.py +353 -0
- package/pynithy/build/securelock/src/etny_session_exec.py +245 -0
- package/pynithy/build/securelock/src/get_sgx_report.so +0 -0
- package/pynithy/build/securelock/src/image_registry.abi +1 -1
- package/pynithy/build/securelock/src/key_generation.py +17 -17
- package/pynithy/build/securelock/src/local_api.py +189 -0
- package/pynithy/build/securelock/src/models.py +200 -176
- package/pynithy/build/securelock/src/securelock.py.tmpl +1037 -727
- package/pynithy/build/securelock/src/swift_stream_service.py +206 -186
- package/pynithy/build.mjs +142 -92
- package/pynithy/run/docker-compose-final.yml.tmpl +58 -51
- package/pynithy/run/docker-compose.yml.tmpl +62 -48
- package/pynithy/run/etny-securelock-test.yaml.tpl +4 -1
- package/pynithy/run/image_registry.js +396 -380
- package/pynithy/run.js +44 -28
- package/pynithy/src/serverless/Dockerfile.serverless +8 -0
- package/pynithy/src/serverless/requirements.txt +6 -0
- package/run.js +69 -28
- package/nodenithy/build/las/Dockerfile +0 -5
- package/pynithy/build/docker-compose.yml +0 -70
- package/pynithy/build/las/Dockerfile +0 -11
- package/pynithy/build/las/src/etny_entrypoint.sh +0 -6
- package/pynithy/build/las/src/las_entrypoint.sh +0 -26
- package/pynithy/build/scripts/binary-fs-build.sh +0 -28
- package/pynithy/build/securelock/Dockerfile.tmpl +0 -95
|
@@ -1,186 +1,206 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
1
|
+
# PEP 563: make annotations lazy strings so builtin-generic subscripts like
|
|
2
|
+
# list[str] (PEP 585, Python 3.9+) don't get evaluated at class-definition time.
|
|
3
|
+
# The enclave base image is Python 3.7, where `list[str]` raises
|
|
4
|
+
# "TypeError: 'type' object is not subscriptable" and kills securelock at import
|
|
5
|
+
# (the enclave then exits before emitting its public key).
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
from minio import Minio
|
|
11
|
+
from minio.error import S3Error
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SwiftStreamService:
|
|
15
|
+
|
|
16
|
+
def __init__(self, endpoint: str, access_key: str, secret_key: str):
|
|
17
|
+
# Bound the HTTP timeouts. In the public-key extraction environment there
|
|
18
|
+
# is NO etny-swift-stream (MinIO) container, so the first .env fetch would
|
|
19
|
+
# otherwise block on a TCP connect to a non-existent host indefinitely
|
|
20
|
+
# (MinIO's default client has effectively unbounded connect/read timeouts),
|
|
21
|
+
# hanging the enclave after it has already emitted its PUBLIC_CERT. A short
|
|
22
|
+
# timeout makes that call fail fast so securelock can exit cleanly in
|
|
23
|
+
# cert-harvest mode. Real task runs reach SwiftStream in well under this.
|
|
24
|
+
import urllib3
|
|
25
|
+
http_client = urllib3.PoolManager(
|
|
26
|
+
timeout=urllib3.Timeout(connect=10.0, read=30.0),
|
|
27
|
+
retries=urllib3.Retry(total=2, backoff_factor=0.5),
|
|
28
|
+
)
|
|
29
|
+
self.client = Minio(endpoint=endpoint,
|
|
30
|
+
access_key=access_key,
|
|
31
|
+
secret_key=secret_key,
|
|
32
|
+
secure=False,
|
|
33
|
+
http_client=http_client)
|
|
34
|
+
|
|
35
|
+
def create_bucket(self, bucket_name: str) -> (bool, str):
|
|
36
|
+
try:
|
|
37
|
+
if not self.client.bucket_exists(bucket_name):
|
|
38
|
+
self.client.make_bucket(bucket_name)
|
|
39
|
+
else:
|
|
40
|
+
return False, f"Bucket, {bucket_name} already exists!"
|
|
41
|
+
except S3Error as err:
|
|
42
|
+
return False, err
|
|
43
|
+
|
|
44
|
+
return True, f"Bucket, {bucket_name} successfully created!"
|
|
45
|
+
|
|
46
|
+
def delete_bucket(self, bucket_name: str) -> (bool, str):
|
|
47
|
+
try:
|
|
48
|
+
if self.client.bucket_exists(bucket_name):
|
|
49
|
+
file_objects = self.client.list_objects(bucket_name)
|
|
50
|
+
if file_objects.size() == 0:
|
|
51
|
+
self.client.remove_bucket(bucket_name)
|
|
52
|
+
else:
|
|
53
|
+
for file_object in file_objects:
|
|
54
|
+
self.delete_file(bucket_name, file_object)
|
|
55
|
+
self.client.remove_bucket(bucket_name)
|
|
56
|
+
else:
|
|
57
|
+
return False, f"Bucket, {bucket_name} does not exists!"
|
|
58
|
+
except S3Error as err:
|
|
59
|
+
return False, err
|
|
60
|
+
|
|
61
|
+
return True, f"Bucket, {bucket_name} successfully deleted!"
|
|
62
|
+
|
|
63
|
+
def delete_file(self, bucket_name: str, file_name: str) -> (bool, str):
|
|
64
|
+
try:
|
|
65
|
+
self.client.remove_object(bucket_name, file_name)
|
|
66
|
+
except S3Error as err:
|
|
67
|
+
return False, err
|
|
68
|
+
|
|
69
|
+
return True, f"File, {file_name} successfully deleted!"
|
|
70
|
+
|
|
71
|
+
def delete_files(self, bucket_name: str, list_of_files: list[str]) -> (bool, str):
|
|
72
|
+
try:
|
|
73
|
+
errors = self.client.remove_objects(bucket_name, list_of_files)
|
|
74
|
+
for error in errors:
|
|
75
|
+
print(f"[Error] Error occurred when deleting file: {error}!")
|
|
76
|
+
except S3Error as err:
|
|
77
|
+
return False, err
|
|
78
|
+
|
|
79
|
+
return True, f"Files, {list_of_files} successfully deleted!"
|
|
80
|
+
|
|
81
|
+
def upload_file(self, bucket_name: str, file_name: str, file_path: str) -> (bool, str):
|
|
82
|
+
try:
|
|
83
|
+
if self.client.bucket_exists(bucket_name):
|
|
84
|
+
self.client.fput_object(bucket_name, file_name, file_path)
|
|
85
|
+
else:
|
|
86
|
+
self.create_bucket(bucket_name)
|
|
87
|
+
self.client.fput_object(bucket_name, file_name, file_path)
|
|
88
|
+
except S3Error as err:
|
|
89
|
+
return False, err
|
|
90
|
+
|
|
91
|
+
return True, f"{file_path} is successfully uploaded to bucket {bucket_name}."
|
|
92
|
+
|
|
93
|
+
def upload_files(self, bucket_name: str, list_of_files: list[str],
|
|
94
|
+
upload_file_paths: list[str]) -> (bool, str):
|
|
95
|
+
try:
|
|
96
|
+
if self.client.bucket_exists(bucket_name):
|
|
97
|
+
for file_idx in range(len(upload_file_paths)):
|
|
98
|
+
self.client.fput_object(bucket_name,
|
|
99
|
+
list_of_files[file_idx],
|
|
100
|
+
upload_file_paths[file_idx])
|
|
101
|
+
else:
|
|
102
|
+
self.create_bucket(bucket_name)
|
|
103
|
+
for file_idx in range(len(upload_file_paths)):
|
|
104
|
+
self.client.fput_object(bucket_name,
|
|
105
|
+
list_of_files[file_idx],
|
|
106
|
+
upload_file_paths[file_idx])
|
|
107
|
+
except S3Error as err:
|
|
108
|
+
return False, err
|
|
109
|
+
|
|
110
|
+
return True, f"{upload_file_paths} are successfully uploaded to bucket {bucket_name}."
|
|
111
|
+
|
|
112
|
+
def download_file(self, bucket_name: str, file_name: str, file_path: str) -> (bool, str):
|
|
113
|
+
try:
|
|
114
|
+
if self.client.bucket_exists(bucket_name):
|
|
115
|
+
self.client.fget_object(bucket_name, file_name, file_path)
|
|
116
|
+
else:
|
|
117
|
+
return False, f"Bucket, {bucket_name} does not exists!"
|
|
118
|
+
except S3Error as err:
|
|
119
|
+
return False, err
|
|
120
|
+
|
|
121
|
+
return True, f"File, {file_name} from bucket {bucket_name} was downloaded in {file_path}."
|
|
122
|
+
|
|
123
|
+
def download_files(self, bucket_name: str, list_of_files: list[str],
|
|
124
|
+
download_file_paths: list[str]) -> (bool, str):
|
|
125
|
+
try:
|
|
126
|
+
if self.client.bucket_exists(bucket_name):
|
|
127
|
+
for file_idx in range(len(list_of_files)):
|
|
128
|
+
self.client.fget_object(bucket_name,
|
|
129
|
+
list_of_files[file_idx],
|
|
130
|
+
download_file_paths[file_idx])
|
|
131
|
+
else:
|
|
132
|
+
return False, f"Bucket, {bucket_name} does not exists!"
|
|
133
|
+
except S3Error as err:
|
|
134
|
+
return False, err
|
|
135
|
+
|
|
136
|
+
return True, f"{download_file_paths} are successfully uploaded to bucket {bucket_name}."
|
|
137
|
+
|
|
138
|
+
def get_file_content_bytes(self, bucket_name: str, file_name: str) -> (bool, bytes):
|
|
139
|
+
response = None
|
|
140
|
+
try:
|
|
141
|
+
response = self.client.get_object(bucket_name, file_name)
|
|
142
|
+
_d = b''
|
|
143
|
+
for data in response.stream(amt=1024 * 1024):
|
|
144
|
+
_d = _d + data
|
|
145
|
+
|
|
146
|
+
except S3Error as err:
|
|
147
|
+
return False, err
|
|
148
|
+
finally:
|
|
149
|
+
if response is not None:
|
|
150
|
+
response.close()
|
|
151
|
+
response.release_conn()
|
|
152
|
+
return True, _d
|
|
153
|
+
|
|
154
|
+
def get_file_content(self, bucket_name: str, file_name: str) -> (bool, str):
|
|
155
|
+
status, content = self.get_file_content_bytes(bucket_name, file_name)
|
|
156
|
+
if status:
|
|
157
|
+
return True, content.decode('utf-8')
|
|
158
|
+
return status, content
|
|
159
|
+
|
|
160
|
+
def put_file_content(self, bucket_name: str, object_name: str, object_path: str,
|
|
161
|
+
object_data: object = None) -> (bool, str):
|
|
162
|
+
try:
|
|
163
|
+
if object_data is not None:
|
|
164
|
+
self.client.put_object(bucket_name,
|
|
165
|
+
object_name,
|
|
166
|
+
object_data,
|
|
167
|
+
len(object_data.getbuffer()))
|
|
168
|
+
else:
|
|
169
|
+
object_stat = os.stat(object_path)
|
|
170
|
+
with open(object_path, 'rb') as file_data:
|
|
171
|
+
self.client.put_object(bucket_name,
|
|
172
|
+
object_name,
|
|
173
|
+
file_data,
|
|
174
|
+
object_stat.st_size)
|
|
175
|
+
file_data.close()
|
|
176
|
+
except S3Error as err:
|
|
177
|
+
return False, err
|
|
178
|
+
|
|
179
|
+
return True, f"{object_name} is successfully uploaded to bucket {bucket_name}."
|
|
180
|
+
|
|
181
|
+
def is_object_in_bucket(self, bucket_name: str, object_name: str) -> (bool, str):
|
|
182
|
+
found = False
|
|
183
|
+
try:
|
|
184
|
+
result = self.client.stat_object(bucket_name, object_name)
|
|
185
|
+
if result:
|
|
186
|
+
found = True
|
|
187
|
+
except S3Error as err:
|
|
188
|
+
return False, err
|
|
189
|
+
|
|
190
|
+
if found:
|
|
191
|
+
return found, f"{object_name} exists inside {bucket_name}."
|
|
192
|
+
else:
|
|
193
|
+
return found, f"{object_name} doesn't exists inside {bucket_name}."
|
|
194
|
+
|
|
195
|
+
def _list_buckets(self) -> None:
|
|
196
|
+
buckets = self.client.list_buckets()
|
|
197
|
+
for bucket in buckets:
|
|
198
|
+
print(bucket.name, bucket.creation_date)
|
|
199
|
+
|
|
200
|
+
def _list_objects(self, bucket_name: str) -> None:
|
|
201
|
+
objects = self.client.list_objects(bucket_name)
|
|
202
|
+
for obj in objects:
|
|
203
|
+
print("-> ", obj.object_name, obj.owner_name)
|
|
204
|
+
|
|
205
|
+
def _is_bucket(self, bucket_name: str) -> bool:
|
|
206
|
+
return self.client.bucket_exists(bucket_name)
|