You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2020/05/20 02:50:39 UTC
[incubator-teaclave] branch master updated: [sdk] Improve the
Python SDK and update examples (#303)
This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/master by this push:
new 8085e06 [sdk] Improve the Python SDK and update examples (#303)
8085e06 is described below
commit 8085e06babca89c33f174465774adb4995945fbb
Author: Mingshen Sun <bo...@mssun.me>
AuthorDate: Tue May 19 19:50:30 2020 -0700
[sdk] Improve the Python SDK and update examples (#303)
---
examples/python/builtin_echo.py | 193 +++++++------------------------------
examples/python/mesapy_echo.py | 207 +++++++++-------------------------------
examples/python/utils.py | 23 +++++
sdk/python/teaclave.py | 180 +++++++++++++++++++++++++++++++++-
4 files changed, 278 insertions(+), 325 deletions(-)
diff --git a/examples/python/builtin_echo.py b/examples/python/builtin_echo.py
index 0a0a76d..fd980ce 100644
--- a/examples/python/builtin_echo.py
+++ b/examples/python/builtin_echo.py
@@ -1,149 +1,21 @@
#!/usr/bin/env python3
-import socket
-import ssl
-import os
-import time
import sys
-from teaclave import read_message, write_message, verify_report
-
-HOSTNAME = 'localhost'
-AUTHENTICATION_SERVICE_ADDRESS = (HOSTNAME, 7776)
-FRONTEND_SERVICE_ADDRESS = (HOSTNAME, 7777)
-CONTEXT = ssl._create_unverified_context()
-
-USER_ID = "example_user"
-USER_PASSWORD = "test_password"
-
-if os.environ.get('DCAP'):
- AS_ROOT_CERT_FILENAME = "dcap_root_ca_cert.pem"
-else:
- AS_ROOT_CERT_FILENAME = "ias_root_ca_cert.pem"
-
-if os.environ.get('TEACLAVE_PROJECT_ROOT'):
- AS_ROOT_CA_CERT_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
- "/keys/" + AS_ROOT_CERT_FILENAME
- ENCLAVE_INFO_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
- "/release/tests/enclave_info.toml"
-else:
- AS_ROOT_CA_CERT_PATH = "../../keys/" + AS_ROOT_CERT_FILENAME
- ENCLAVE_INFO_PATH = "../../release/tests/enclave_info.toml"
-
-
-def user_register(channel, user_id, user_password):
- message = {
- "request": "user_register",
- "id": user_id,
- "password": user_password
- }
- write_message(channel, message)
- read_message(channel)
-
-
-def user_login(channel, user_id, user_password):
- message = {
- "request": "user_login",
- "id": user_id,
- "password": user_password
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
- return response["content"]["token"]
-
-
-def register_function(channel, user_id, token):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "register_function",
- "name": "builtin-echo",
- "description": "Native Echo Function",
- "executor_type": "builtin",
- "public": True,
- "payload": [],
- "arguments": ["message"],
- "inputs": [],
- "outputs": [],
- }
- write_message(channel, message)
-
- response = read_message(channel)
- return response["content"]["function_id"]
-
-
-def create_task(channel, user_id, token, function_id, message):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "create_task",
- "function_id": function_id,
- "function_arguments": {
- "message": message,
- },
- "executor": "builtin",
- "inputs_ownership": [],
- "outputs_ownership": [],
- }
- write_message(channel, message)
-
- response = read_message(channel)
- return response["content"]["task_id"]
-
-
-def approve_task(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "approve_task",
- "task_id": task_id,
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
-
-
-def invoke_task(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "invoke_task",
- "task_id": task_id,
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
-
-
-def get_task_result(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "get_task",
- "task_id": task_id,
- }
- while True:
- write_message(channel, message)
- response = read_message(channel)
- time.sleep(1)
- if response["content"]["status"] == 10:
- break
-
- return response["content"]["result"]["result"]["Ok"]["return_value"]
+from teaclave import (
+ AuthenticationService,
+ FrontendService,
+ AuthenticationClient,
+ FrontendClient
+)
+from utils import (
+ AUTHENTICATION_SERVICE_ADDRESS,
+ FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH,
+ USER_ID,
+ USER_PASSWORD
+)
class BuiltinEchoExample:
@@ -152,33 +24,40 @@ class BuiltinEchoExample:
self.user_password = user_password
def echo(self, message="Hello, Teaclave!"):
- sock = socket.create_connection(AUTHENTICATION_SERVICE_ADDRESS)
- channel = CONTEXT.wrap_socket(sock, server_hostname=HOSTNAME)
- cert = channel.getpeercert(binary_form=True)
- verify_report(AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, cert, "authentication")
+ channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect()
+ client = AuthenticationClient(channel)
print("[+] registering user")
- user_register(channel, self.user_id, self.user_password)
+ client.user_register(self.user_id, self.user_password)
print("[+] login")
- token = user_login(channel, self.user_id, self.user_password)
+ token = client.user_login(self.user_id, self.user_password)
- sock = socket.create_connection(FRONTEND_SERVICE_ADDRESS)
- channel = CONTEXT.wrap_socket(sock, server_hostname=HOSTNAME)
- cert = channel.getpeercert(binary_form=True)
- verify_report(AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, cert, "frontend")
+ channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect()
+ metadata = {"id": self.user_id, "token": token}
+ client = FrontendClient(channel, metadata)
print("[+] registering function")
- function_id = register_function(channel, self.user_id, token)
+ function_id = client.register_function(
+ name="builtin-echo",
+ description="Native Echo Function",
+ executor_type="builtin",
+ arguments=["message"])
print("[+] creating task")
- task_id = create_task(channel, self.user_id,
- token, function_id, message)
+ task_id = client.create_task(function_id=function_id,
+ function_arguments={"message": message},
+ executor="builtin")
+
print("[+] invoking task")
- invoke_task(channel, self.user_id, token, task_id)
+ client.invoke_task(task_id)
print("[+] getting result")
- result = get_task_result(channel, self.user_id, token, task_id)
+ result = client.get_task_result(task_id)
print("[+] done")
return bytes(result)
diff --git a/examples/python/mesapy_echo.py b/examples/python/mesapy_echo.py
index 313af1c..6e6d1d8 100644
--- a/examples/python/mesapy_echo.py
+++ b/examples/python/mesapy_echo.py
@@ -1,155 +1,21 @@
#!/usr/bin/env python3
-import socket
-import ssl
-import os
-import time
import sys
-from teaclave import read_message, write_message, verify_report
-
-HOSTNAME = 'localhost'
-AUTHENTICATION_SERVICE_ADDRESS = (HOSTNAME, 7776)
-FRONTEND_SERVICE_ADDRESS = (HOSTNAME, 7777)
-CONTEXT = ssl._create_unverified_context()
-
-USER_ID = "example_user"
-USER_PASSWORD = "test_password"
-
-if os.environ.get('DCAP'):
- AS_ROOT_CERT_FILENAME = "dcap_root_ca_cert.pem"
-else:
- AS_ROOT_CERT_FILENAME = "ias_root_ca_cert.pem"
-
-if os.environ.get('TEACLAVE_PROJECT_ROOT'):
- AS_ROOT_CA_CERT_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
- "/keys/" + AS_ROOT_CERT_FILENAME
- ENCLAVE_INFO_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
- "/release/tests/enclave_info.toml"
-else:
- AS_ROOT_CA_CERT_PATH = "../../keys/" + AS_ROOT_CERT_FILENAME
- ENCLAVE_INFO_PATH = "../../release/tests/enclave_info.toml"
-
-
-def user_register(channel, user_id, user_password):
- message = {
- "request": "user_register",
- "id": user_id,
- "password": user_password
- }
- write_message(channel, message)
- read_message(channel)
-
-
-def user_login(channel, user_id, user_password):
- message = {
- "request": "user_login",
- "id": user_id,
- "password": user_password
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
- return response["content"]["token"]
-
-
-def register_function(channel, user_id, token):
- payload = b"""
-def entrypoint(argv):
- assert argv[0] == 'message'
- assert argv[1] is not None
- return argv[1]
-"""
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "register_function",
- "name": "mesapy-echo",
- "description": "An echo function implemented in Python",
- "executor_type": "python",
- "public": True,
- "payload": list(payload),
- "arguments": ["message"],
- "inputs": [],
- "outputs": [],
- }
- write_message(channel, message)
-
- response = read_message(channel)
- return response["content"]["function_id"]
-
-
-def create_task(channel, user_id, token, function_id, message):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "create_task",
- "function_id": function_id,
- "function_arguments": {
- "message": message,
- },
- "executor": "mesapy",
- "inputs_ownership": [],
- "outputs_ownership": [],
- }
- write_message(channel, message)
-
- response = read_message(channel)
- return response["content"]["task_id"]
-
-
-def approve_task(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "approve_task",
- "task_id": task_id,
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
-
-
-def invoke_task(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "invoke_task",
- "task_id": task_id,
- }
- write_message(channel, message)
-
- response = read_message(channel)
- assert(response["result"] == "ok")
-
-
-def get_task_result(channel, user_id, token, task_id):
- message = {
- "metadata": {
- "id": user_id,
- "token": token
- },
- "request": "get_task",
- "task_id": task_id,
- }
- while True:
- write_message(channel, message)
- response = read_message(channel)
- time.sleep(1)
- if response["content"]["status"] == 10:
- break
-
- return response["content"]["result"]["result"]["Ok"]["return_value"]
+from teaclave import (
+ AuthenticationService,
+ FrontendService,
+ AuthenticationClient,
+ FrontendClient
+)
+from utils import (
+ AUTHENTICATION_SERVICE_ADDRESS,
+ FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH,
+ USER_ID,
+ USER_PASSWORD
+)
class MesaPyEchoExample:
@@ -158,33 +24,48 @@ class MesaPyEchoExample:
self.user_password = user_password
def echo(self, message="Hello, Teaclave!"):
- sock = socket.create_connection(AUTHENTICATION_SERVICE_ADDRESS)
- channel = CONTEXT.wrap_socket(sock, server_hostname=HOSTNAME)
- cert = channel.getpeercert(binary_form=True)
- verify_report(AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, cert, "authentication")
+ channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect()
+ client = AuthenticationClient(channel)
print("[+] registering user")
- user_register(channel, self.user_id, self.user_password)
+ client.user_register(self.user_id, self.user_password)
print("[+] login")
- token = user_login(channel, self.user_id, self.user_password)
+ token = client.user_login(self.user_id, self.user_password)
- sock = socket.create_connection(FRONTEND_SERVICE_ADDRESS)
- channel = CONTEXT.wrap_socket(sock, server_hostname=HOSTNAME)
- cert = channel.getpeercert(binary_form=True)
- verify_report(AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, cert, "frontend")
+ channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect()
+ metadata = {"id": self.user_id, "token": token}
+ client = FrontendClient(channel, metadata)
print("[+] registering function")
- function_id = register_function(channel, self.user_id, token)
+
+ payload = b"""
+def entrypoint(argv):
+ assert argv[0] == 'message'
+ assert argv[1] is not None
+ return argv[1]
+ """
+ function_id = client.register_function(
+ name="mesapy-echo",
+ description="An echo function implemented in Python",
+ executor_type="python",
+ payload=list(payload),
+ arguments=["message"])
print("[+] creating task")
- task_id = create_task(channel, self.user_id,
- token, function_id, message)
+ task_id = client.create_task(function_id=function_id,
+ function_arguments={"message": message},
+ executor="mesapy")
+
print("[+] invoking task")
- invoke_task(channel, self.user_id, token, task_id)
+ client.invoke_task(task_id)
print("[+] getting result")
- result = get_task_result(channel, self.user_id, token, task_id)
+ result = client.get_task_result(task_id)
print("[+] done")
return bytes(result)
diff --git a/examples/python/utils.py b/examples/python/utils.py
new file mode 100644
index 0000000..2bd4725
--- /dev/null
+++ b/examples/python/utils.py
@@ -0,0 +1,23 @@
+import os
+
+HOSTNAME = 'localhost'
+AUTHENTICATION_SERVICE_ADDRESS = (HOSTNAME, 7776)
+FRONTEND_SERVICE_ADDRESS = (HOSTNAME, 7777)
+
+USER_ID = "example_user"
+USER_PASSWORD = "test_password"
+
+if os.environ.get('DCAP'):
+ AS_ROOT_CERT_FILENAME = "dcap_root_ca_cert.pem"
+else:
+ AS_ROOT_CERT_FILENAME = "ias_root_ca_cert.pem"
+
+if os.environ.get('TEACLAVE_PROJECT_ROOT'):
+ AS_ROOT_CA_CERT_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
+ "/keys/" + AS_ROOT_CERT_FILENAME
+ ENCLAVE_INFO_PATH = os.environ['TEACLAVE_PROJECT_ROOT'] + \
+ "/release/tests/enclave_info.toml"
+else:
+ AS_ROOT_CA_CERT_PATH = "../../keys/" + AS_ROOT_CERT_FILENAME
+ ENCLAVE_INFO_PATH = "../../release/tests/enclave_info.toml"
+
diff --git a/sdk/python/teaclave.py b/sdk/python/teaclave.py
index c7b7421..7e1e4c5 100644
--- a/sdk/python/teaclave.py
+++ b/sdk/python/teaclave.py
@@ -5,6 +5,9 @@ import json
import base64
import toml
import os
+import time
+import ssl
+import socket
from cryptography import x509
from cryptography.hazmat.backends import default_backend
@@ -14,9 +17,175 @@ from OpenSSL.crypto import X509Store, X509StoreContext
from OpenSSL import crypto
+class RequestEncoder(json.JSONEncoder):
+ def default(self, o):
+ return o.__dict__
+
+
+class UserRegisterReqeust:
+ def __init__(self, user_id, user_password):
+ self.request = "user_register"
+ self.id = user_id
+ self.password = user_password
+
+
+class UserLoginRequest:
+ def __init__(self, user_id, user_password):
+ self.request = "user_login"
+ self.id = user_id
+ self.password = user_password
+
+
+class AuthenticationClient:
+ def __init__(self, channel):
+ self.channel = channel
+
+ def user_register(self, user_id, user_password):
+ request = UserRegisterReqeust(user_id, user_password)
+ write_message(self.channel, request)
+ return read_message(self.channel)
+
+ def user_login(self, user_id, user_password):
+ request = UserLoginRequest(user_id, user_password)
+ write_message(self.channel, request)
+ response = read_message(self.channel)
+ return response["content"]["token"]
+
+
+class AuthenticationService:
+ context = ssl._create_unverified_context()
+
+ def __init__(self, address, as_root_ca_cert_path, enclave_info_path):
+ self.address = address
+ self.as_root_ca_cert_path = as_root_ca_cert_path
+ self.enclave_info_path = enclave_info_path
+
+ def connect(self):
+ sock = socket.create_connection(self.address)
+ channel = self.context.wrap_socket(sock,
+ server_hostname=self.address[0])
+ cert = channel.getpeercert(binary_form=True)
+ verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
+ "authentication")
+
+ return channel
+
+
+class FrontendService:
+ context = ssl._create_unverified_context()
+
+ def __init__(self, address, as_root_ca_cert_path, enclave_info_path):
+ self.address = address
+ self.as_root_ca_cert_path = as_root_ca_cert_path
+ self.enclave_info_path = enclave_info_path
+
+ def connect(self):
+ sock = socket.create_connection(self.address)
+ channel = self.context.wrap_socket(sock,
+ server_hostname=self.address[0])
+ cert = channel.getpeercert(binary_form=True)
+ verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
+ "frontend")
+
+ return channel
+
+
+class RegisterFunctionRequest:
+ def __init__(self, metadata, name, description, executor_type, public,
+ payload, arguments, inputs, outputs):
+ self.request = "register_function"
+ self.metadata = metadata
+ self.name = name
+ self.description = description
+ self.executor_type = executor_type
+ self.public = public
+ self.payload = payload
+ self.arguments = arguments
+ self.inputs = inputs
+ self.outputs = outputs
+
+
+class CreateTaskRequest:
+ def __init__(self, metadata, function_id, function_arguments, executor,
+ inputs_ownership, outputs_ownership):
+ self.request = "create_task"
+ self.metadata = metadata
+ self.function_id = function_id
+ self.function_arguments = function_arguments
+ self.executor = executor
+ self.inputs_ownership = inputs_ownership
+ self.outputs_ownership = outputs_ownership
+
+
+class InvokeTaskRequest:
+ def __init__(self, metadata, task_id):
+ self.request = "invoke_task"
+ self.metadata = metadata
+ self.task_id = task_id
+
+
+class GetTaskRequest:
+ def __init__(self, metadata, task_id):
+ self.request = "get_task"
+ self.metadata = metadata
+ self.task_id = task_id
+
+
+class FrontendClient:
+ def __init__(self, channel, metadata):
+ self.channel = channel
+ self.metadata = metadata
+
+ def register_function(self,
+ name,
+ description,
+ executor_type,
+ public=True,
+ payload=[],
+ arguments=[],
+ inputs=[],
+ outputs=[]):
+ request = RegisterFunctionRequest(self.metadata, name, description,
+ executor_type, public, payload,
+ arguments, inputs, outputs)
+ write_message(self.channel, request)
+ response = read_message(self.channel)
+ return response["content"]["function_id"]
+
+ def create_task(self,
+ function_id,
+ function_arguments,
+ executor,
+ inputs_ownership=[],
+ outputs_ownership=[]):
+ request = CreateTaskRequest(self.metadata, function_id,
+ function_arguments, executor,
+ inputs_ownership, outputs_ownership)
+ write_message(self.channel, request)
+ response = read_message(self.channel)
+ return response["content"]["task_id"]
+
+ def invoke_task(self, task_id):
+ request = InvokeTaskRequest(self.metadata, task_id)
+ write_message(self.channel, request)
+ response = read_message(self.channel)
+ assert (response["result"] == "ok")
+
+ def get_task_result(self, task_id):
+ request = GetTaskRequest(self.metadata, task_id)
+
+ while True:
+ write_message(self.channel, request)
+ response = read_message(self.channel)
+ time.sleep(1)
+ if response["content"]["status"] == 10:
+ break
+
+ return response["content"]["result"]["result"]["Ok"]["return_value"]
+
+
def write_message(sock, message):
- message = json.dumps(message)
- message = message.encode()
+ message = json.dumps(message, cls=RequestEncoder).encode()
sock.write(struct.pack(">Q", len(message)))
sock.write(message)
@@ -28,7 +197,8 @@ def read_message(sock):
return response
-def verify_report(as_root_ca_cert_path, enclave_info_path, cert, endpoint_name):
+def verify_report(as_root_ca_cert_path, enclave_info_path, cert,
+ endpoint_name):
if os.environ.get('SGX_MODE') == 'SW':
return
@@ -58,8 +228,8 @@ def verify_report(as_root_ca_cert_path, enclave_info_path, cert, endpoint_name):
quote = base64.b64decode(quote)
# get mr_enclave and mr_signer from the quote
- mr_enclave = quote[112:112+32].hex()
- mr_signer = quote[176:176+32].hex()
+ mr_enclave = quote[112:112 + 32].hex()
+ mr_signer = quote[176:176 + 32].hex()
# get enclave_info
enclave_info = toml.load(enclave_info_path)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org