AWS Nitro enclave

# Getting started: Hello enclave

以下の公式ページだと、いくつか手順が抜けており、コピペだけだと最後までたどり着けません。

- そのため、下記ページをベースに最後までコピペでEnclaveを体験できることを目指します
- 逆にインスタンス作成に関する情報は、この記事においてほとんど省略することとします。

https://docs.aws.amazon.com/enclaves/latest/user/getting-started.html

## Step 1: インスタンスを作成する

### インスタンス情報

- Region: Virginia Region
- Amazon Linux 2: `ami-0b5eea76982371e91`
- Instance Type: m5.xlarge

### 起動時の注意

**EC2 > インスタンス > インスタンスの起動**の画像において、以下の画像のように"高度な詳細"から**Nitro Enlabe**を**有効化**します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73207/a7c0e3a4-5b3b-8f16-9af5-05981d7f7680.png)



## Step 2: enclaveイメージファイルをビルドする

### 事前準備

```bash
yum install docker
sudo  amazon-linux-extras install aws-nitro-enclaves-cli -y
sudo yum install aws-nitro-enclaves-cli-devel -y
```

GID関連の設定

```bash
sudo usermod -aG ne ec2-user
sudo usermod -aG docker ec2-user
```

### アプリケーションのdockerイメージを作成する

アプリケーションからDockerイメージを作成します。今回は予め用意されている`/usr/share/nitro_enclaves/examples/hello`を利用してみましょう。

```bash:command
docker build /usr/share/nitro_enclaves/examples/hello -t hello
```

次のコマンドを実行して、Dockerイメージがビルドされていることを確認します。

```bash:command
docker image ls
```

```terminal
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
hello        latest    7cf4822d36e8   53 minutes ago   4.86MB
busybox      latest    827365c7baf1   2 days ago       4.86MB
```

### Dockerイメージ

`nitro-cli build-enclave`コマンドを使用して、Dockerイメージをenclaveイメージファイルに変換します。この例では`hello.eif`というファイルが作成されたことを確認しましょう。

```bash:command
nitro-cli build-enclave --docker-uri hello:latest --output-file hello.eif
```

出力の例

```json
Start building the Enclave Image...
Using the locally available Docker image...
Enclave Image successfully created.
{
  "Measurements": {
    "HashAlgorithm": "Sha384 { ... }",
    "PCR0": "2bcd96d8e1b533e6a019e75847d0ffce38b11354246045632caf8937ab1144aaacb69828e7639c50630d2737895c931f",
    "PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
    "PCR2": "08d2de83939cc968c823d77ce4afc4da433ad33f7cbdc32215d2d88074a387ccb3b3d69d8e5f837c1e53388607e82720"
  }
}
```

- 出力には一連のハッシュ `PCR0`, `PCR1`, および `PCR2`が含まれます
- これらのハッシュは、enclaveイメージとブートアッププロセスの測定値です
- これらのハッシュは認証プロセスで使用できます。このチュートリアルではこの認証プロセスは使用しません

では、eifファイルが作成されたことを確認してみましょう。

```bash:command
ls -l hello.eif
```

## Step 3: enclaveを実行する

### enclave環境のリソース割当変更

必要に応じて割り当てられるコア数とメモリを調整します。

```bash:command
sudo vim /etc/nitro_enclaves/allocator.yaml
```

```bash
# Enclave configuration file.
#
# How much memory to allocate for enclaves (in MiB).
memory_mib: 512
#
# How many CPUs to reserve for enclaves.
cpu_count: 2
#
# Alternatively, the exact CPUs to be reserved for the enclave can be explicitely
# configured by using `cpu_pool` (like below), instead of `cpu_count`.
# Note: cpu_count and cpu_pool conflict with each other. Only use exactly one of them.
# Example of reserving CPUs 2, 3, and 6 through 9:
# cpu_pool: 2,3,6-9
```

nitro-enclaves-allocatorのデーモンを起動します。また再起動後も自動で立ち上がるようにします。

```bash
sudo systemctl start nitro-enclaves-allocator.service
sudo systemctl status nitro-enclaves-allocator.service
sudo systemctl enable nitro-enclaves-allocator.service
```

次に`hello.eif `使用してenclaveを実行します。

- encdlaveを実行するイメージファイルをenclaveします。このチュートリアルでは, 2つのvCPUと512 MiBのメモリを使って、enclaveファイル `hello.eif` を実行します。
- また、デバッグモードでenclaveそのものも作成します。

`nitro-cli run-enclave`コマンドを使用します。vCPU、メモリ、およびenclaveイメージファイルのパスを指定し、`--debug-mode`オプションをつけて実行します。

```bash
nitro-cli run-enclave \
    --cpu-count 2 \
    --memory 512 \
    --enclave-cid 16 \
    --eif-path hello.eif \
    --debug-mode
```

```json
tart allocating memory...
Started enclave with enclave-cid: 16, memory: 512 MiB, cpu-ids: [1, 3]{
  "EnclaveName": "hello",
  "EnclaveID": "i-06f16fe06a19f5bae-enc18547d25f02f95d",
  "ProcessID": 31735,
  "EnclaveCID": 16,
  "NumberOfCPUs": 2,
  "CPUIDs": [
    1,
    3
  ],
  "MemoryMiB": 512
}
```

このコマンドは、エンクレーブID、vCPU数、メモリ量、状態など、エンクレーブに関する情報を提供します。この場合、エンクレーブはRUNNING状態になっています。

## STEP4 作成したenclaveを確認する

### 起動したenclaveの詳細情報確認

エンクレーブを作成したので、`nitro-cli describe-enclaves` コマンドを使用して、それが実行されていることを確認することができます。このコマンドは、エンクレーブID、vCPU数、メモリ量、状態など、エンクレーブに関する情報を提供します。この場合、エンクレーブはRUNNING状態になっています。

```bash:command
nitro-cli describe-enclaves
```

```json
[
  {
    "EnclaveName": "hello",
    "EnclaveID": "i-06f16fe06a19f5bae-enc18547d25f02f95d",
    "ProcessID": 31735,
    "EnclaveCID": 16,
    "NumberOfCPUs": 2,
    "CPUIDs": [
      1,
      3
    ],
    "MemoryMiB": 512,
    "State": "RUNNING",
    "Flags": "DEBUG_MODE",
    "Measurements": {
      "HashAlgorithm": "Sha384 { ... }",
      "PCR0": "2bcd96d8e1b533e6a019e75847d0ffce38b11354246045632caf8937ab1144aaacb69828e7639c50630d2737895c931f",
      "PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
      "PCR2": "08d2de83939cc968c823d77ce4afc4da433ad33f7cbdc32215d2d88074a387ccb3b3d69d8e5f837c1e53388607e82720"
    }
  }
]
```

### enclave内のコンソール出力内容を確認

さらに、エンクレーブをデバッグモードで作成したため、`nitro-cli console` コマンドを使用して、エンクレーブの読み取り専用のコンソール出力を表示することができます。

最初に先程実行した`nitro-cli describe-enclaves`を用いて、`EnclaveID`を取得しておきます。

```bash
enclave_id=$(nitro-cli describe-enclaves | jq -r .[].EnclaveID) && echo $enclave_id
```
```terminal
i-06f16fe06a19f5bae-enc18547d25f02f95d
```

```bash
nitro-cli console --enclave-id ${enclave_id}
```

成功すると以下のような出力が得られます。

```terminal
onnecting to the console for enclave 16...
Successfully connected to the console.
[ 287] Hello from the enclave side!
[ 288] Hello from the enclave side!
[ 289] Hello from the enclave side!
[ 290] Hello from the enclave side!
[ 291] Hello from the enclave side!
[ 292] Hello from the enclave side!
[ 293] Hello from the enclave side!
[ 294] Hello from the enclave side!
[ 295] Hello from the enclave side!
[ 296] Hello from the enclave side!
[ 297] Hello from the enclave side!
[ 298] Hello from the enclave side!
[ 299] Hello from the enclave side!
[ 300] Hello from the enclave side!
[ 301] Hello from the enclave side!
[ 1500.646745] NSM RNG: returning rand bytes = 64
[ 302] Hello from the enclave side!
[ 303] Hello from the enclave side!
[ 304] Hello from the enclave side!
[ 305] Hello from the enclave side!
```


## STEP5 enclaveを終了する

`EnclaveID`がわからない場合は`nitro-cli describe-enclaves`コマンドを利用して取得します。

```bash:command
enclave_id=$(nitro-cli describe-enclaves | jq -r .[].EnclaveID) && echo ${enclave_id}
```
```terminal
i-06f16fe06a19f5bae-enc18547d25f02f95d
```

enclaveを終了します

```bash:command
nitro-cli terminate-enclave --enclave-id ${enclave_id}
```

```terminal
Successfully terminated enclave i-06f16fe06a19f5bae-enc18547d25f02f95d.
{
  "EnclaveName": "hello",
  "EnclaveID": "i-06f16fe06a19f5bae-enc18547d25f02f95d",
  "Terminated": true
}
```

# Appendix

## nitro-cli

```terminal:help
$ nitro-cli --help
Nitro CLI 1.2.1
CLI for enclave lifetime management

USAGE:
    nitro-cli [SUBCOMMAND]

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    build-enclave        Builds an enclave image and saves it to a file
    console              Connect to the console of an enclave
    describe-eif         Returns information about the EIF found at a given path.
    describe-enclaves    Returns a list of the running enclaves
    explain              Display detailed information about an error returned by a misbehaving
                             Nitro CLI command
    help                 Print this message or the help of the given subcommand(s)
    pcr                  Return the PCR hash value of the given input
    run-enclave          Starts a new enclave
    terminate-enclave    Terminates an enclave
```


## 参考

https://aws.amazon.com/jp/blogs/news/aws-nitro-enclaves-isolated-ec2-environments-to-process-confidential-data/