# BigDL PPML Occlum阿里云ECS中文开发文档 ## 概要 本文档介绍了如何用BigDL PPML和Occlum实现基于SGX的端到端、分布式的隐私计算应用。BigDL PPML和Occlum为开发人员提供了一个简单易用的隐私计算环境。开发人员可以将现有应用无缝迁移到该运行环境中,实现端到端安全,并且可验证的分布式隐私计算。该类应用的计算性能接近明文计算,并且可以横向拓展以支持大规模数据集。 文档分为以下几部分: 1. 环境部署。介绍基于阿里云的PPML基本的环境部署和依赖安装。 2. 快速上手。介绍迁移或者开发新的隐私计算应用的基本流程。 3. 应用部署。介绍如何将PPML应用部署到生产环境中。 4. 背景知识。介绍SGX、Occlum和BigDL PPML的基本概念。 使用建议: * 建议1234或者4123的顺序阅读本文档。 * 如果要将应用部署到生成环境中,请和管理员确认3和4中的内容是否符合内部的安全策略。 ![PPML基本架构](../images/spark_sgx_occlum.png) ## 1. 环境部署 以下以阿里云环境为例,如果是基于裸金属机器搭建,请参考附录。 首先,我们需要一个安装了SGX Plugin的K8S集群环境。在本例中,我们在阿里云申请了两台g7t的ECS实例(ecs.g7t.4xlarge),基本配置如下。 | CPU核数 | 内存 | 安全内存(EPC)| 操作系统 | | ------------- | ------------- | ------------- | ------------- | | 32 | 64GB | 32GB | Ubuntu 20.04 LTS 2 | 用户也可以根据自己的需求申请不同配置的ECS安全实例。 VM OS选择Ubuntu20.04 LTS2, 这也是Occlum标准release所基于的操作系统。 另外,系统内核需要升级以支持SGX。 ```bash sudo apt install --install-recommends linux-generic-hwe-20.04 ``` 然后,需要在每台实例上配置安装K8S环境,并配置安装K8S SGX plugin。 细节不再赘述,用户可以参考技术文档《在K8S上部署可扩展的基于Occlum的安全推理实例》或者附录的相关部分。 ## 2. 快速上手 本章会介绍PPML基本概念,以及如何用BigDL PPML occlum image在SGX中执行应用程序。 需要注意的是:为了简化上手流程,我们会在运行环境中编译和运行SGX enclave;这种运行方式会有安全风险,仅能用于开发和测试,实际部署需要参照后面的生产环境部署章节。 ### 2.1 基本概念 SGX应用需要编译(build)成SGX enclave,才能加载到SGX中运行。通常情况下,开发人员需要用SGX SDK重新编写应用,才能编译成合法的enclave,但这样的开发代价较大,维护成本也较高。为了避免上述问题,我们可以用Occlum实现应用的无缝迁移。Occlum是为SGX开发的LibOS应用,它可以将应用的系统调用翻译成SGX可以识别的调用,从而避免修改应用。BigDL PPML在Occlum的基础上,又进行了一次封装和优化,使得大数据应用,如Spark/Flink可以无缝的运行在SGX上。 ![SGX enclave结构](../images/ppml_sgx_enclave.png) 作为硬件级的可信执行环境,SGX的攻击面非常小,攻击者即使攻破操作系统和BIOS也无法获取SGX中的应用和数据。但在端到端的应用中,用户还需要确保其他阶段的安全性。简而言之,用户需要确保数据或者文件在SGX外部是加密的,仅在SGX内部被解密和计算,如下图所示。为了实现这个目的,我们往往需要借助密钥管理服务 (Key Management Service, KMS) 的帮助。用户可以将密钥托管到KMS,等应用在SGX中启动后,再从KMS申请和下载密钥。 ![SGX应用设计原则](../images/ppml_dev_basic.png) PPML项目的核心功能是帮助用户迁移现有的应用,用户可以选择迁移现有的大数据AI应用,也可以选择开发全新的应用。PPML应用的开发和常规应用基本相同。例如PySpark的应用代码和常规应用并没有区别。但在设计、编译和部署时有一定的差异。具体表现为: * 设计时需要考虑加解密流程,确保明文数据只出现在SGX内部 * 编译时,需要通过Occlum将应用编译成SGX enclave * 部署时,需要将SGX enclave部署到有SGX环境的节点 在剩下的章节中,我们以PySpark运行SQL和sklearn求线性回归方程为例,介绍如何 * 通过docker部署单机PySpark应用。 * 通过K8S部署分布式PySpark应用。 前者主要针对小数据量的单机环境,后者主要针对大数据量的分布式环境。 ### 2.2 PySpark执行SQL任务 SparkSQL是Spark生态中的核心功能之一。通过Spark提供的SQL接口,数据分析师和开发人员可以通撰写简单的SQL语句实现对TB/PB级别数据的高效查询。在下面的例子中,我们将介绍如何通过Python格式的SQL文件,查询大规模数据。 #### 2.2.1 部署运行在docker容器中 1. 配置合适的资源,启动运行脚本`start-spark-local.sh`进入docker image中。 ```bash # Clean up old container sudo docker rm -f bigdl-ppml-trusted-big-data-ml-scala-occlum ``` ```bash # Run new command in container sudo docker run -it --rm \ --net=host \ --name=bigdl-ppml-trusted-big-data-ml-scala-occlum \ --cpuset-cpus 10-14 \ --device=/dev/sgx/enclave \ #需提前配置好的sgx环境 --device=/dev/sgx/provision \ -v /var/run/aesmd:/var/run/aesmd \ -v data:/opt/occlum_spark/data \ -e SGX_MEM_SIZE=24GB \ #EPC即使用的SGX内存大小 -e SGX_THREAD=1024 \ -e SGX_HEAP=1GB \ -e SGX_KERNEL_HEAP=1GB \ -e SGX_LOG_LEVEL=off \intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum:2.2.0-SNAPSHOT \ bash ``` 2. 编写python源码,如sql_example.py 并将其放置在image的目录py-examples下 3. 修改/opt/run_spark_on_occlum_glibc.sh文件,设置程序启动入口。 ```bash run_pyspark_sql_example() { init_instance spark #执行occlum init初始化occlum文件结构并设置对应配置 build_spark #拷贝依赖并执行occlum build 构建可执行程序 cd /opt/occlum_spark echo -e "${BLUE}occlum run pyspark SQL example${NC}" occlum run /usr/lib/jvm/java-8-openjdk-amd64/bin/java \ -XX:-UseCompressedOops \ -XX:ActiveProcessorCount=4 \ -Divy.home="/tmp/.ivy" \ -Dos.name="Linux" \ -Djdk.lang.Process.launchMechanism=vfork \ -cp "$SPARK_HOME/conf/:$SPARK_HOME/jars/*" \ -Xmx3g org.apache.spark.deploy.SparkSubmit \ #选择合适的jvm大小 /py-examples/sql_example.py #新添加的文件位置 } # switch case in the last pysql) run_pyspark_sql_example cd ../ ;; ``` 4. 运行PySpark SQL example在container里 ```bash bash /opt/run_spark_on_occlum_glibc.sh pysql ``` 注: 脚本里的build_spark是做”occlum build”来生成Occlum可执行的镜像,这一步骤会耗费不少时间(数分钟左右),请耐心等待。 非即时部署需提前配置源码和程序入口,并将步骤1的最后一行改为 bash /opt/run_spark_on_occlum_glibc.sh $1,即可直接通过运行bash start-spark-local.sh pysql 启动运行SQL example。 #### 2.2.2 将PySpark SQL任务部署运行在k8s集群中 ##### 前提条件: 1. 阿里云实例上k8s集群已经配置好,k8s SGX device plugin已经安装好。 设置环境变量`kubernetes_master_url`。 ```bash export kubernetes_master_url=${master_node_ip} ``` 2. 阿里云实例上安装spark client工具(以3.1.2版本为例),用于提交spark任务。 ```bash wget https://downloads.apache.org/spark/spark-3.1.2/spark-3.1.2-bin-hadoop3.2.tgz sudo mkdir /opt/spark sudo tar -xf spark*.tgz -C /opt/spark --strip-component 1 sudo chmod -R 777 /opt/spark export SPARK_HOME=/opt/spark ``` 3. 下载BigDL的代码,为后续的修改做准备。 ```bash git clone https://github.com/intel-analytics/BigDL.git ``` 接下来的改动位于路径`BigDL/ppml/trusted-big-data-ml/scala/docker-occlum/kubernetes`。 ##### 运行步骤: 1. 配置合适的资源在driver.yml和executor.yaml中 ```yaml #driver.yaml 同executor.yaml env: - name: DRIVER_MEMORY value: "1g" - name: SGX_MEM_SIZE #EPC即使用的SGX内存大小 value: "15GB" - name: SGX_THREAD value: "1024" - name: SGX_HEAP value: "1GB" - name: SGX_KERNEL_HEAP value: "1GB" ``` 2. 运行脚本 run_pyspark_sql_example.sh,需提前配置好Spark和K8s环境。 ```bash ${SPARK_HOME}/bin/spark-submit \ --master k8s://https://${kubernetes_master_url}:6443 \ --deploy-mode cluster \ --name pyspark-sql \ --conf spark.executor.instances=1 \ --conf spark.rpc.netty.dispatcher.numThreads=32 \ --conf spark.kubernetes.container.image=intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum:2.2.0-SNAPSHOT \ --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \ --conf spark.kubernetes.executor.deleteOnTermination=false \ --conf spark.kubernetes.driver.podTemplateFile=./driver.yaml \ #资源配置 --conf spark.kubernetes.executor.podTemplateFile=./executor.yaml \ #资源配置 --conf spark.kubernetes.sgx.log.level=off \ --executor-memory 1g \ --conf spark.kubernetes.driverEnv.SGX_DRIVER_JVM_MEM_SIZE="1g" \ --conf spark.executorEnv.SGX_EXECUTOR_JVM_MEM_SIZE="6g" \ local:/py-examples/sql_example.py # hdfs://ServerIP:Port/path/sql_example.py ``` 注:若用云存储或HDFS或者云存储传入源文件则无需提前在image里传入源文件。 ### 2.3 PySpark运行sklearn LinearRegression #### 2.3.1 部署运行在docker容器中 1. 配置合适的资源,启动运行脚本 start-spark-local.sh 进入docker image中。 ```bash # Clean up old container sudo docker rm -f bigdl-ppml-trusted-big-data-ml-scala-occlum ``` ```bash # Run new command in container sudo docker run -it --rm \ --net=host \ --name=bigdl-ppml-trusted-big-data-ml-scala-occlum \ --cpuset-cpus 10-14 \ --device=/dev/sgx/enclave \ #需提前配置好的sgx环境 --device=/dev/sgx/provision \ -v /var/run/aesmd:/var/run/aesmd \ -v data:/opt/occlum_spark/data \ -e SGX_MEM_SIZE=24GB \ #EPC即使用的SGX内存大小 -e SGX_THREAD=1024 \ -e SGX_HEAP=1GB \ -e SGX_KERNEL_HEAP=1GB \ -e SGX_LOG_LEVEL=off \intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum:2.2.0-SNAPSHOT \ bash ``` 2. 编写python源码,如sklearn_example.py , 并将其放置在image的目录py-examples下。 ```python # sklearn_example.py import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error, median_absolute_error # Generate test data: nSample = 100 x = np.linspace(0, 10, nSample) e = np.random.normal(size=len(x)) y = 2.36 + 1.58 * x + e # y = b0 + b1*x1 x = x.reshape(-1, 1) y = y.reshape(-1, 1) # print(x.shape,y.shape) # OLS modelRegL = LinearRegression() modelRegL.fit(x, y) yFit = modelRegL.predict(x) print('intercept: w0={}'.format(modelRegL.intercept_)) print('coef: w1={}'.format(modelRegL.coef_)) print('R2_score :{:.4f}'.format(modelRegL.score(x, y))) print('mean_squared_error:{:.4f}'.format(mean_squared_error(y, yFit))) print('mean_absolute_error:{:.4f}'.format(mean_absolute_error(y, yFit))) print('median_absolute_error:{:.4f}'.format(median_absolute_error(y, yFit))) ``` 3. 修改/opt/run_spark_on_occlum_glibc.sh文件,设置程序启动入口。 ```bash run_pyspark_sklearn_example() { init_instance spark #执行occlum init初始化occlum文件结构并设置对应配置 build_spark #拷贝依赖并执行occlum build 构建可执行程序 cd /opt/occlum_spark echo -e "${BLUE}occlum run pyspark sklearn example${NC}" occlum run /usr/lib/jvm/java-8-openjdk-amd64/bin/java \ -XX:-UseCompressedOops \ -XX:ActiveProcessorCount=4 \ -Divy.home="/tmp/.ivy" \ -Dos.name="Linux" \ -Djdk.lang.Process.launchMechanism=vfork \ -cp "$SPARK_HOME/conf/:$SPARK_HOME/jars/*" \ -Xmx3g org.apache.spark.deploy.SparkSubmit \ #选择合适的jvm大小 /py-examples/sklearn_example.py #新添加的文件位置 } # switch case in the last pysql) run_pyspark_sklearn_example cd ../ ;; ``` 4. 运行PySpark sklearn example在container里 ```bash bash /opt/run_spark_on_occlum_glibc.sh pysklearn ``` 注: 脚本里的build_spark是做”occlum build”来生成Occlum可执行的镜像,这一步骤会耗费不少时间(数分钟左右),请耐心等待。 非即时部署需提前配置源码和程序入口,并将步骤1的最后一行改为 bash /opt/run_spark_on_occlum_glibc.sh $1,即可直接通过运行bash start-spark-local.sh pysklearn 启动运行 sklearn example。 #### 2.3.2 部署运行在k8s集群中 **前提条件**参考前述章节的配置。 运行步骤: 1. 配置合适的资源在driver.yml和executor.yaml中 ```yaml #driver.yaml 同executor.yaml env: - name: DRIVER_MEMORY value: "1g" - name: SGX_MEM_SIZE #EPC即使用的SGX内存大小 value: "15GB" - name: SGX_THREAD value: "1024" - name: SGX_HEAP value: "1GB" - name: SGX_KERNEL_HEAP value: "1GB" ``` 2. 运行脚本 run_pyspark_sklearn_example.sh,需配置Spark和K8s环境。 ```bash ${SPARK_HOME}/bin/spark-submit \ --master k8s://https://${kubernetes_master_url}:6443 \ --deploy-mode cluster \ --name pyspark-sql \ --conf spark.executor.instances=1 \ --conf spark.rpc.netty.dispatcher.numThreads=32 \ --conf spark.kubernetes.container.image=intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum:2.2.0-SNAPSHOT \ --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \ --conf spark.kubernetes.executor.deleteOnTermination=false \ --conf spark.kubernetes.driver.podTemplateFile=./driver.yaml \ #资源配置 --conf spark.kubernetes.executor.podTemplateFile=./executor.yaml \ #资源配置 --conf spark.kubernetes.sgx.log.level=off \ --executor-memory 1g \ --conf spark.kubernetes.driverEnv.SGX_DRIVER_JVM_MEM_SIZE="1g" \ --conf spark.executorEnv.SGX_EXECUTOR_JVM_MEM_SIZE="6g" \ local:/py-examples/sklearn_example.py # hdfs://ServerIP:Port/path/sklearn_example.py ``` 注:若用云存储或者HDFS传入源文件则无需提前在image里传入源文件。 ## 3. 生产环境部署 与快速上手阶段不同,生产部署需要考虑完整的数据流和密钥安全,并且需要根据现有的服务和设施进行对接。考虑到用户所用的服务有所差异,我们以开源和云服务为案例,介绍部署和配置KMS的基本过程;以及在安全环境中,构建生成环境中所需的image。 安装和配置KMS KMS是SGX应用部署中的核心服务。用户可以直接使用阿里云提供的KMS,并配合云存储实现数据的透明加解密服务,详情请参照《对象存储客户端加密》。通过运行在SGX中的客户端加解密数据,可以保证明文数据只出现在SGX中。其他开源的分布式存储,例如HDFS也提供了类似的方案,请参考Hadoop官方文档配置HDFS透明加密,这里不再赘述。 为了提升安全水位,我们提供了带TEE 保护的开源KMS的部署方式供用户参考。即EHSM(运行在SGX中的KMS)。 ### 3.1 安装和配置EHSM 安装EHSM的教程请参照文档[Deploy BigDL-eHSM-KMS on Kubernetes](https://github.com/intel-analytics/BigDL/tree/main/ppml/services/ehsm/kubernetes)。 **使用PPMLContext和EHSM实现输入输出数据加解密。**基本流程如下: 1. 按照EHSM教程配置好PCCS和EHSM等环境。 注意因为是部署在阿里云上,阿里云有可用的PCCS服务,所以对于教程里的第一步“Deploy BigDL-PCCS on Kubernetes”可以忽略。 2. 注册获取app_id和api_key。 ```bash # Enroll curl -v -k -G "https://:9000/ehsm?Action=Enroll" ...... {"code":200,"message":"successful","result":{"apikey":"E8QKpBBapaknprx44FaaTY20rptg54Sg","appid":"8d5dd3b8-3996-40f5-9785-dcb8265981ba"}} ``` 3. 填入相关参数,启动运行脚本 start-spark-local.sh 进入docker image。 其中,参数PCCS_URL可以根据阿里云安全增强型实例所在区域,设置为相对应的地址,细节请参考阿里云文档。 ```bash # Clean up old container sudo docker rm -f bigdl-ppml-trusted-big-data-ml-scala-occlum ``` ```bash # Run new command in container sudo docker run -it \ --net=host \ --name=bigdl-ppml-trusted-big-data-ml-scala-occlum \ --cpuset-cpus 10-14 \ --device=/dev/sgx/enclave \ --device=/dev/sgx/provision \ -v /var/run/aesmd:/var/run/aesmd \ -v data:/opt/occlum_spark/data \ -e SGX_MEM_SIZE=24GB \ -e SGX_THREAD=512 \ -e SGX_HEAP=512MB \ -e SGX_KERNEL_HEAP=1GB \ -e ATTESTATION=false \ -e PCCS_URL=$PCCS_URL \ #1 -e ATTESTATION_URL=ESHM_IP:EHSM_PORT \ #2 -e APP_ID=your_app_id \ #3 -e API_KEY=your_api_key \ #4 -e CHALLENGE=cHBtbAo= \ -e REPORT_DATA=ppml \ -e SGX_LOG_LEVEL=off \ -e RUNTIME_ENV=native \ intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum:2.2.0-SNAPSHOT \ bash ``` 4. 生成加解密相关的密钥 ```bash bash /opt/ehsm_entry.sh generatekeys $APP_ID $API_KEY ``` 5. 用提供的generate_people_csv.py 生成原始输入数据 ```bash python generate_people_csv.py /opt/occlum_spark/data/people.csv ``` 6. 用密钥加密原始输入数据 ```bash bash /opt/ehsm_entry.sh encrypt $APP_ID $API_KEY /opt/occlum_spark/data/people.csv ``` 7. 修改加密的文件后缀并移动到合适的位置 ```bash mv /opt/occlum_spark/data/people.csv.encrypted /opt/occlum_spark/data/encrypt/people.csv.encrypted.cbc ``` 8. 运行 BigDL SimpleQuery e2e Example(同上开发步骤,已提前写好程序入口,程序源码已打成jar包) ```bash bash /opt/run_spark_on_occlum_glibc.sh sql_e2e ``` 9. 解密计算结果 ```bash bash /opt/ehsm_entry.sh decrypt $APP_ID $API_KEY /opt/occlum_spark/data/model/{result_file_name}. ``` 注:需要把SparkContext换成PPMLContext(源码需改动),才能支持密钥管理,和应用自动加解密服务。其大致流程为: 1. 应用通过PPMLContext读取加密文件 2. PPMLContext自动从指定的密钥管理服务获取解密密钥 3. 应用解密数据并进行计算 4. 应用将计算结果加密后,写入到存储系统 ### 3.2 构建部署生产应用image ![编译和部署PPML应用](../images/ppml_scope.png) 在开发新应用时,SGX程序程序在启动前需要经历occlum init和occlum build两个阶段,才能构建可执行的occlum instance(opt/occlum_spark文件夹,所有依赖和程序都存储在当中)。但是,将build放到部署环境中,会导致build阶段用到的用户密钥(user key)暴露到非安全环境中。为了进一步提高安全性,在实际部署中需要将build阶段和实际运行分开,既在安全环境中build所需的image,然后在部署和运行该image。 在这个过程中,用户也可对BigDL image直接进行修改,加入自己的程序和配置(User image),并提前执行occlum init和build构建实际部署所需的image(Runnable image)。 ```bash # Production and Production-build and Customer image #BigDL image or production image docker pull intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production:2.2.0 #Runable image or production-build image docker pull intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production:2.2.0-build #Small size Runable image or customer image docker pull intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production-customer:2.2.0-build ``` `intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production:2.2.0` image是提供给有定制docker image需求的客户的,下面以 pyspark sql example为例,说明如何定制化runnable image。 1. 获取production image ```bash docker pull intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production:2.2.0 ``` 2. 运行启动脚本进入容器内部 ```bash # Clean up old container export container_name=bigdl-ppml-trusted-big-data-ml-scala-occlum-production sudo docker rm -f $container_name # Run new command in container sudo docker run -it \ --net=host \ --name=$container_name \ --cpuset-cpus 3-5 \ -e SGX_MEM_SIZE=30GB \ -e SGX_THREAD=2048 \ -e SGX_HEAP=1GB \ -e SGX_KERNEL_HEAP=1GB \ -e ENABLE_SGX_DEBUG=true \ -e ATTESTATION=true \ intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production:2.2.0 \ bash ``` 3. 添加相关python源码(/opt/py-examples/)或jar包依赖($BIGDL_HOME/jars/)或python依赖(/opt/python-occlum/)。如添加sql_example.py到/opt/py-examples/目录下。 4. 构建runnable occlum instance。这一步的作用是初始化occlum文件夹,并将源码和相关配置和依赖拷贝进/opt/occlum_spark中,并执行occlum build构建occlum runnable instance即production-build image。 ```bash bash /opt/run_spark_on_occlum_glibc.sh init ``` 5. 退出后提交得到最终的runnable image。 intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production: 2.2.0-build 即不添加任何外部依赖的runnable image,可直接运行任意已有的example。 ```bash docker commit $container_name $container_name-build ``` 得到的未定制的`intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production: 2.2.0-build`大小有14.2GB,其中仅有`/opt/occlum_spark`文件夹和少部分配置文件是运行时所需的,其余大多数是拷贝和编译产生的垃圾文件。可在 production-build image的基础上copy occlum runnable instance 并安装Occlum运行时依赖和其他一些依赖得到最终的customer image,其大小仅不到5GB,且其功能与production-build image基本相同,`intelanalytics/bigdl-ppml-trusted-big-data-ml-scala-occlum-production-customer:2.2.0-build`即不经过任何定制的customer image。(通过修改运行build-customer-image.sh文件构建customer image) Production-build 或 Customer image的attestation流程 1. 配置PCCS和EHSM环境,注册得到app_id和api_key,启动任务时,增加相关环境变量(同上)。 2. 验证ehsm是否可信 ```bash bash start-spark-local.sh verify ``` 3. 离线注册occlum instance,得到 policy_Id ```bash bash start-spark-local.sh register # policy_Id 28da128a-c572-4f5f-993c-6da10d5243f8 ``` 4. 在docker环境或者k8s环境设置policy_Id。 ```yaml #start-spark-local.sh -e ${policy_Id} #driver.yaml and executor.yaml env: - name: policy_Id value: "${policy_Id}" ``` 5. 在docker或k8s启动应用(同上),仅会在SGX中运行EHSM对应用程序进行验证(IV. attest MREnclave)。 ## 4. 背景知识 ### 4.1 Intel SGX 英特尔软件防护扩展(英语:Intel Software Guard Extensions,SGX)是一组安全相关的指令,它被内置于一些现代Intel 中央处理器(CPU)中。它们允许用户态及内核态代码定义将特定内存区域,设置为私有区域,此区域也被称作飞地(Enclaves)。其内容受到保护,不能被本身以外的任何进程存取,包括以更高权限级别运行的进程。 CPU对受SGX保护的内存进行加密处理。受保护区域的代码和数据的加解密操作在CPU内部动态(on the fly)完成。因此,处理器可以保护代码不被其他代码窥视或检查。SGX使用的威胁模型如下:Enclaves是可信的,但Enclaves之外的任何进程都不可信(包括操作系统本身和任何虚拟化管理程序),所有这些不可信的主体都被视为有存在恶意行为的风险。Enclaves之外代码的任何代码读取受保护区域,只能得到加密后的内容。 SGX被设计用于实现安全远程计算、安全网页浏览和数字版权管理(DRM)。其他应用也包括保护专有算法和加密密钥。 ### 4.2 Occlum 2014年正式成立的蚂蚁集团服务于超10亿用户,是全球领先的金融科技企业之一。蚂蚁集团一直积极探索隐私保护机器学习领域,并发起了开源项目 Occlum。Occlum 是用于英特尔® SGX 的内存安全多进程用户态操作系统(LibOS)。 使用 Occlum 后,机器学习工作负载等只需修改极少量(甚至无需修改)源代码即可在英特尔® SGX 上运行,以高度透明的方式保护了用户数据的机密性和完整性。用于英特尔® SGX 的 Occlum 架构如图所示。 ![Occlum架构](https://raw.githubusercontent.com/occlum/occlum/master/docs/images/arch_overview.png) Occlum有以下显著特征: * 高效的多任务处理。 Occlum提供轻量级LibOS流程:它们是轻量级的,因为所有LibOS流程共享同一个SGX enclave。 与重型、per-enclave的LibOS进程相比,Occlum的轻型LibOS进程在启动时最高快1000倍,在IPC上快3倍。 此外,如果需要,Occlum还提供了一个可选的多域软件故障隔离方案来隔离Occlum LibOS进程。 * 支持多个文件系统。 支持多种类型的文件系统,如只读散列文件系统(用于完整性保护)、可写加密文件系统(用于机密保护)、内存文件系统,不受信任的主机文件系统(用于LibOS和主机操作系统之间方便的数据交换)等等,满足应用的各种文件I/O需求。 * 内存安全。 Occlum是第一个用内存安全编程语言(Rust)编写的SGX LibOS。Rust语言是为追求内存安全,且不会带来额外的性能损耗的编程语言。因此,在Occlum中杜绝了低级的内存安全错误,对于托管安全关键的应用程序更值得信任。 * 支持musl-libc和glibc应用,支持超过150个常用系统调用,绝大多数程序无需改动(甚至无需重新编译)或者只需少许改动即可运行在Occlum LibOS之上。 * 支持多种语言开发的应用,包括但不限于c/c++,Java,Python,Go和Rust。 * 易用性。 Occlum提供了类容器的用户友好的构建和命令行工具。 在SGX enclave内的Occlum上运行应用程序可以非常简单。 ### 4.3 BigDL PPML 在Occlum提供的安全内存运行环境上,英特尔和蚂蚁集团基于BigDL构建了一个分布式的隐私保护机器学习(Privacy Preserving Machine Learning, PPML)平台,能够保护端到端(包括数据输入、数据分析、机器学习、深度学习等各个阶段)的分布式人工智能应用。 ![BigDL PPML 软件栈](https://user-images.githubusercontent.com/61072813/177922914-f670111c-e174-40d2-b95a-aafe92485024.png) 与传统的隐私计算框架不同,BigDL PPML提供了一个可以运行标准大数据应用的环境,希望帮助现有的大数据/分布式应用无缝的迁移到端到端安全的环境中,并且强化每个环节的安全性。在此基础上,PPML也提供了安全参数聚集、隐私求交和联邦学习等高阶功能,帮助行业客户打破数据孤岛,进一步实现数据赋能。 以Apache Spark为例,通过BigDL PPML和Occlum提供的Spark in SGX功能,可以让现有的Spark应用,直接运行到SGX环境中,而不用做任何代码修改。受益于第三代至强平台提供的大容量SGX EPC,Spark的内存计算可以完全被SGX保护,并且可以根据数据规模进行横向拓展,从而轻松支持TB级别的数据规模;另一方面,负责完整性的远程证明功能,也被无感的添加到了整个流程中,应用开发者不需要显式的增加远程证明代码,即可通过Occlum和PPML提供的远程证明功能实现实例的远程证明和校验。