This topic walks you through building an Intel Software Guard Extensions (SGX) 2.0 application using the trusted execution environment (TEE) SDK, then packaging and deploying it to an ACK confidential computing cluster. The example application, helloworld, runs inside an enclave, generates messages periodically, and prints them to the terminal.
Prerequisites
Before you begin, make sure you have:
An ACK managed cluster for confidential computing. See Create an ACK managed cluster for confidential computing
SSH or Cloud Assistant access to an instance that supports confidential computing
Git installed, or the ability to install it with
sudo yum install gitDocker installed. See Install and use Docker on a Linux instance
kubectlconfigured to connect to your ACK cluster
How it works
An Intel SGX 2.0 application has two components:
Untrusted component: Unencrypted memory that contains the
main()entry function and any OCALL (outside call) implementations. In the diagram,main()andbar()run in the untrusted component.Trusted component (enclave): Encrypted memory created and protected by the CPU. Only the CPU can access the code and data inside. In the diagram,
helloworld()andfoo()run in the enclave.
To call enclave functions from untrusted code, the application uses ECALL (enclave call). To call untrusted functions from inside the enclave, it uses OCALL. Both are declared in Enclave Definition Language (EDL) files.
Sample code and directory structure
The helloworld source code is on GitHub. It includes the application source, Makefile, and Dockerfile.
Top-level structure:
sgx-device-plugin/samples/hello_world/
├── Dockerfile
├── Makefile
├── README.md
└── src
├── App
│ ├── App.cpp
│ └── App.h
├── Enclave
│ ├── Enclave.config.xml
│ ├── Enclave.cpp
│ ├── Enclave.edl
│ ├── Enclave.h
│ ├── Enclave.lds
│ └── Enclave_private.pem
└── MakefileThe src directory has two subdirectories:
Directory | Description | Key files |
| Untrusted code: the |
|
| Trusted code that runs inside the enclave |
|
Key source files
`Enclave/Enclave.edl` — declares the ECALL and OCALL interface. Every SGX application must declare at least one trusted {} block (ECALLs) or one untrusted {} block (OCALLs) in the EDL file.
In this example, the application only needs one ECALL: ecall_hello_from_enclave. It creates a buffer inside the enclave, writes "Hello world" into it, then copies the buffer content to an untrusted buffer so the untrusted component can call printf.
enclave {
trusted {
public void ecall_hello_from_enclave([out, size=len] char* buf, size_t len);
};
};`Enclave/Enclave.config.xml` — controls the enclave's runtime resource limits. Three parameter groups determine memory and thread behavior:
TCS parameters (
TCSNum,TCSPolicy):TCSNumsets the number of Thread Control Structures, which determines how many threads can run concurrently inside the enclave.TCSPolicycontrols whether TCS slots are bound to OS threads or can be reused.Stack parameters (
StackMaxSize): the maximum stack size available to each enclave thread. If your enclave uses deep call stacks or large local variables, increase this value.Heap parameters (
HeapMaxSize): the maximum heap size available to the enclave. Set this based on how much dynamic memory your enclave code allocates.
For production builds, change DisableDebug from 0 to 1 to prevent debuggers from attaching to the enclave.
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x40000</StackMaxSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<TCSNum>10</TCSNum>
<TCSPolicy>1</TCSPolicy>
<!-- Change 'DisableDebug' to 1 before release to prevent debugger access -->
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>`Enclave/Enclave_private.pem` — the RSA private key used to sign enclave.so. Generated with:
openssl genrsa -out Enclave/Enclave_private.pem -3 3072Step 1: Compile the hello_world application
Install Git:
sudo yum install gitClone the repository and compile:
git clone https://github.com/AliyunContainerService/sgx-device-plugin cd sgx-device-plugin/samples/hello_world SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make buildThe build runs six steps:
sgx_edger8rand thesgx_ecallECALL function generate untrusted stub code (Enclave_u.c,Enclave_u.h) in theAppdirectory.The untrusted binary files in
Appare compiled.sgx_edger8rgenerates trusted code (Enclave_t.c,Enclave_t.h) in theEnclavedirectory.enclave.sois compiled as a trusted dynamic-link library.sgx_signsignsenclave.so, producingenclave.signed.so.The final
hello_worldbinary is linked.
A successful build ends with output similar to:
GEN => App/Enclave_u.h CC <= App/Enclave_u.c CXX <= App/App.cpp LINK => app GEN => Enclave/Enclave_t.h CC <= Enclave/Enclave_t.c CXX <= Enclave/Enclave.cpp LINK => enclave.so ... tcs_num 10, tcs_max_num 10, tcs_min_pool 1 The required memory is 3960832B. The required memory is 0x3c7000, 3868 KB. Succeed. SIGN => enclave.signed.so The project has been built in debug hardware modeVerify that the last line reads
The project has been built in debug hardware mode. This confirms the build used real SGX hardware (not simulation mode) and that signing completed successfully. The compiled output tree:sgx-device-plugin/samples/hello_world/src/ ├── hello_world #[generated] ├── App │ ├── App.cpp │ ├── App.h │ ├── App.o #[generated] │ ├── Enclave_u.c #[generated] │ ├── Enclave_u.h #[generated] │ └── Enclave_u.o #[generated] ├── Enclave │ ├── Enclave.config.xml │ ├── Enclave.cpp │ ├── Enclave.edl │ ├── Enclave.h │ ├── Enclave.lds │ ├── Enclave.o #[generated] │ ├── Enclave_private.pem │ ├── Enclave_t.c #[generated] │ ├── Enclave_t.h #[generated] │ └── Enclave_t.o #[generated] ├── enclave.signed.so #[generated] ├── enclave.so #[generated] └── MakefileRun the application on an SGX-capable instance to verify it works:
cd src/ ./hello_worldExpected output:
Wed May 6 06:53:33 2020 Hello world From SGX Enclave! Wed May 6 06:53:34 2020 Hello world From SGX Enclave! ...
Step 2: Build and deploy the helloworld application
Use an Alibaba Cloud Linux base image and install the latest SGX SDK. Update the SDK periodically to get security patches.
Sample Dockerfile
FROM registry.cn-hangzhou.aliyuncs.com/alinux/alinux3
ARG REGION_ID=cn-hangzhou
RUN yum install -y curl && \
repo_url=https://enclave-${REGION_ID}.oss-${REGION_ID}.aliyuncs.com/repo/alinux/enclave-expr.repo && \
yum install -y yum-utils && \
yum-config-manager --add-repo ${repo_url} && \
yum install -y libsgx-urts libsgx-uae-service # Add more SGX runtime dependencies on demand.
WORKDIR /src
COPY src/hello_world src/enclave.signed.so /src
ENTRYPOINT ["/src/hello_world"]The Dockerfile installs two required SGX runtime packages:
libsgx-urts: the SGX untrusted runtime system, required to load and run enclaves.libsgx-uae-service: the platform services library for remote attestation and related operations.
Build and push the container image
Build and push the container image. Replace
${IMAGE_URL}with your image registry address:cd sgx-device-plugin/samples/hello_world TARGET_IMAGE=${IMAGE_URL} SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make image docker push ${IMAGE_URL}Deploy the
helloworldapplication to your ACK cluster. Replace${IMAGE_URL}with the image address from the previous step:cat <<EOF | kubectl create -f - apiVersion: apps/v1 kind: Deployment metadata: name: helloworld namespace: default spec: replicas: 2 selector: matchLabels: app: helloworld template: metadata: labels: app: helloworld spec: containers: - image: ${IMAGE_URL} imagePullPolicy: Always name: helloworld resources: limits: cpu: 250m memory: 512Mi alibabacloud.com/sgx_epc_MiB: 2 EOF