すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:TEE SDKを使用してIntel SGX 2.0アプリケーションを開発および構築する

最終更新日:Dec 14, 2024

このトピックでは、信頼できる実行環境 (TEE) SDKを使用して、Intel Software Guard Extensions (SGX) 2.0アプリケーションを開発、ビルド、およびデプロイする方法について説明します。 このトピックでは、helloworldという名前のアプリケーションを例として使用します。 このアプリケーションは、エンクレーブで定期的にメッセージを生成し、信頼できないバッファにメッセージを送信します。 その後、メッセージは端末に送信される。

前提条件

インテルSGXのしくみ

image

Intel SGX 2.0アプリケーションは、信頼できないコンポーネントと信頼できるコンポーネントの2つのコンポーネントで構成されています。

  • 信頼できないコンポーネント: 信頼できないコンポーネントは、メモリの暗号化されていない部分です。 この部分にアプリケーションのコードとデータを格納する場合、アプリケーションのmain() 入力関数も信頼できないコンポーネントに配置する必要があります。 上の図では、main() 関数とbar() 関数が信頼できないコンポーネントに配置されています。

  • 信頼できるコンポーネント: 信頼できるコンポーネントまたはエンクレーブは、メモリの暗号化された部分です。 このコンポーネントはCPUによって作成され、このコンポーネントのデータとコードはCPUによってのみアクセスできます。 上の図では、helloworld() 関数とfoo() 関数がエンクレーブに配置されています。

信頼できないコンポーネントからエンクレーブ内の関数を呼び出すには、アプリケーションはエンクレーブ呼び出し (ECALL) を実行する必要があります。 エンクレーブから信頼されていないコンポーネントの関数を呼び出すには、アプリケーションは外部呼び出し (OCALL) を実行する必要があります。 ECALLおよびOCALLは、エンクレーブ定義言語 (EDL) ファイルで宣言される。

サンプルコードとディレクトリツリー

この例では、helloworldという名前のIntel SGX 2.0アプリケーションがデプロイされています。 ソースコードの詳細については、『GitHub』をご参照ください。 ソースコードには、アプリケーションのコンパイル、イメージの構築、およびアプリケーションの展開のためのコードが含まれます。 次のサンプルコードは、ディレクトリツリーを示しています。

App.hsgx-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
                                         └── Makefile

次の表に、srcディレクトリと関連ファイルを示します。

ディレクトリ

説明

ファイル

説明

アプリ

Appディレクトリには、main() 関数 (エントリ関数) やOCALL関数のコードなど、信頼できないコードが含まれています。

App.cpp

信頼できないコンポーネントのコード。The code in the untrusted component.

アプリ. h

ヘッダーファイル。

エンクレーブ

ECALL関数のコードを含む、信頼済みコンポーネント内のコード。

Enclave.edl

EDLファイル。

Enclave.lds

enclaveリンカスクリプト。

Enclave_private.pem

enclave.soファイルに署名するために使用される秘密鍵。

Enclave.config.xml

スタックサイズやデバッグを有効にするかどうかなどのパラメーターを指定するエンクレーブ構成ファイル。

Enclave.hとEnclave.cpp。

信頼できるコンポーネントを実装するコード。

ステップ1: hello_worldをコンパイルする

  1. 次のコマンドを実行してGitをインストールします。

    sudo yum install git
  2. 次のコマンドを実行して、hello_worldアプリケーションをコンパイルします。

    git clone https://github.com/AliyunContainerService/sgx-device-plugin
    cd sgx-device-plugin/samples/hello_world
    SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make build

    hello_worldというバイナリファイルがプロジェクトのルートディレクトリに生成されます。

    バイナリファイルの内容を表示

    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
    <EnclaveConfiguration>
        <ProdID>0</ProdID>
        <ISVSVN>0</ISVSVN>
        <StackMaxSize>0x40000</StackMaxSize>
        <HeapMaxSize>0x100000</HeapMaxSize>
        <TCSNum>10</TCSNum>
        <TCSPolicy>1</TCSPolicy>
        <!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release -->
        <DisableDebug>0</DisableDebug>
        <MiscSelect>0</MiscSelect>
        <MiscMask>0xFFFFFFFF</MiscMask>
    </EnclaveConfiguration>
    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 mode

  3. を実行します。Run the. /hello_worldSGXをサポートするインスタンスで、hello_worldアプリケーションを実行するコマンドを実行します。

    cd src/
    ./hello_world

    期待される出力:

    Wed May  6 06:53:33 2020
    Hello world From SGX Enclave!
    Wed May  6 06:53:34 2020
    Hello world From SGX Enclave!
    ...

次の内容は、アプリケーションをコンパイルする方法と、コンパイルされたコードのディレクトリツリーを示しています。

コンパイル手順の表示

  1. sgx_edger8rツールとsgx_ecall ecall関数を使用して、信頼できないコード (Enclave_u.cおよびEnclave_u.h) をAppディレクトリに生成します。

  2. Appディレクトリで信頼できないバイナリファイルをコンパイルします。

  3. sgx_edger8rツールを使用して、信頼できるコード (Enclave_t.cおよびEnclave_t.h) をEnclave_tディレクトリに生成します。

  4. enclave.soファイルをコンパイルします。 信頼できるダイナミックリンクライブラリです。

  5. sgx_signツールを使用して、信頼できるダイナミックリンクライブラリに署名します。 信頼できるダイナミックリンクライブラリの名前がenclave.signed.soに変わります。

  6. アプリケーションはコンパイルされます。

コンパイルされたコードのディレクトリツリーの表示

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]
                                         └── Makefile

ファイルパス

説明

サンプルコード

Encalve/Enclave.edl

パブリックECALL関数を宣言するEDLファイル。 SGXアプリケーションのEDLファイルでは、次の関数の少なくとも1つを宣言する必要があります。

  • 型のECALL関数。

  • trusted {...} はECALL関数を宣言します。

  • untrusted {...} はOCALL関数を宣言します。

この例では、アプリケーションはOCALL関数を呼び出す必要はありません。 したがって、ECALL関数 (ecall_hello_from_enclave) は1つだけ宣言されます。 このECALL関数は、エンクレーブにバッファを作成し、helloworldアプリケーションをデプロイするために使用されます。 次に、バッファ内の情報が、信頼できないコンポーネント内の信頼できないバッファにコピーされる。 アプリケーションは、信頼できないコンポーネント内のprintfを呼び出して情報を印刷します。

enclave {
    trusted {
        public void ecall_hello_from_enclave([out, size=len] char* buf, size_t len);
    };
};

Enclave/Enclave.lds

非該当

enclave.so
{
    global:
        g_global_data_sim;
        g_global_data;
        enclave_entry;
        g_peak_heap_used;
    local:
        *;
};

Enclave/Enclave.config.xml

非該当

<EnclaveConfiguration>
  <ProdID>0</ProdID>
  <ISVSVN>0</ISVSVN>
  <StackMaxSize>0x40000</StackMaxSize>
  <HeapMaxSize>0x100000</HeapMaxSize>
  <TCSNum>10</TCSNum>
  <TCSPolicy>1</TCSPolicy>
  <!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release -->
  <DisableDebug>0</DisableDebug>
  <MiscSelect>0</MiscSelect>
  <MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>

Enclave/Enclave.h

ほとんどの場合、このヘッダーファイルは空です。

#ifndef _ENCLAVE_H_
#define _ENCLAVE_H_
#endif

Enclave/Enclave.cpp

非該当

#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <string.h>

void ecall_hello_from_enclave(char *buf, size_t len)
{
    const char *hello = "Hello world";

    size_t size = len;
    if(strlen(hello) < len)
    {
        size = strlen(hello) + 1;
    }

    memcpy(buf, hello, size - 1);
    buf[size-1] = '\0';
}

エンクレーブ /Enclave_private.pem

enclave.soファイルの署名に使用される秘密鍵

openssl genrsa -out Enclave/Enclave_private.pem -3 3072

アプリ /App.h

非該当

#ifndef _APP_H_
#define _APP_H_

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "sgx_error.h"       /* sgx_status_t */
#include "sgx_eid.h"     /* sgx_enclave_id_t */

#ifndef TRUE
# define TRUE 1
#endif

#ifndef FALSE
# define FALSE 0
#endif

# define TOKEN_FILENAME   "enclave.token"
# define ENCLAVE_FILENAME "enclave.signed.so"

extern sgx_enclave_id_t global_eid;    /* global enclave id */

#if defined(__cplusplus)
extern "C" {
#endif


#if defined(__cplusplus)
}
#endif

#endif /* !_APP_H_ */

App/App.cpp

非該当

#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <time.h>
#include <ctime>

# include <unistd.h>
# include <pwd.h>
# define MAX_PATH FILENAME_MAX

#include "sgx_urts.h"
#include "App.h"
#include "Enclave_u.h"

/* Global EID shared by multiple threads */
sgx_enclave_id_t global_eid = 0;

int initialize_enclave(void)
{
    sgx_status_t ret = SGX_ERROR_UNEXPECTED;

    char enclavefile[256];
    getcwd(enclavefile, sizeof(enclavefile));
    strcat(enclavefile, "/enclave.signed.so");

    /* Call sgx_create_enclave to initialize an enclave instance */
    /* Debug Support: set 2nd parameter to 1 */
    ret = sgx_create_enclave(enclavefile, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
    if (ret != SGX_SUCCESS) {
        printf("Failed to create enclave, ret code: %d, enclave file: %s\n", ret, enclavefile);
        return -1;
    }

    return 0;
}

tm* get_time() {
    time_t rawtime;
    struct tm * timeinfo;
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    return timeinfo;
}

/* Application entry */
int SGX_CDECL main(int argc, char *argv[])
{
    (void)(argc);
    (void)(argv);

    const size_t max_buf_len = 100;
    char buffer[max_buf_len] = {0};


    /* Initialize the enclave */
    if(initialize_enclave() < 0){
        printf("Enter a character before exit ...\n");
        getchar();
        return -1;
    }

    /* Enclave calls */
    while(1) {
        ecall_hello_from_enclave(global_eid, buffer, max_buf_len);

        printf("%s%s\n", asctime(get_time()), buffer);
        fflush(stdout);

        sleep(1);
    }

    /* Destroy the enclave */
    sgx_destroy_enclave(global_eid);

    printf("Info: SampleEnclave successfully returned.\n");

    printf("Enter a character before exit ...\n");
    getchar();
    return 0;
}

ステップ2: helloworldアプリケーションのビルドとデプロイ

潜在的なリスクを軽減するために、Alibaba Cloud Linuxイメージを構築し、最新のSGX SDKバージョンをインストールし、SDKを定期的に更新することを推奨します。

サンプルDockerfile

次のサンプルDockerfileはAlibaba Cloud Linux 3を使用しています。

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"]

手順

  1. Dockerをインストールします。

    詳細については、「Dockerのインストール」をご参照ください。

  2. 次のコマンドを実行して、テストイメージをコンパイルしてビルドします。

    ${IMAGE_URL} をテストイメージのアドレスに置き換えます。

    cd sgx-device-plugin/samples/hello_world
    TARGET_IMAGE=${IMAGE_URL} SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make image
    docker push ${IMAGE_URL}
  3. 次のコマンドを実行して、helloworldアプリケーションをデプロイします。

    ${IMAGE_URL} を、前の手順で構築したテストイメージのアドレスに置き換えます。

    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

関連ドキュメント