体験 Confidential Computing -3 － Hyper Protect Virtual Server for VPC へのサンプル・アプリケーションのデプロイ

Confidential Computing については、これまで下記の投稿をしてきました。

* [体験 Confidential Computing -1 － ビットコイン・ウォレット を乗っ取って Confidential Computing の必要性を体験する](https://qiita.com/6onoda/items/1d51c930f166d348711d)
* [体験 Confidential Computing -2 － Secure Build Server で安全・安心なビットコイン・ウォレットを構築する](https://qiita.com/6onoda/items/74889e3779224550a0b8)

「[体験 Confidential Computing -2 － Secure Build Server で安全・安心なビットコイン・ウォレットを構築する](https://qiita.com/6onoda/items/74889e3779224550a0b8)」は、IBM の第一世代(Gen1)の Hyper Protect Virtual Server(HPVS) 用のアプリケーション構築の手順を述べました。
この環境では Secure Build Server とい専用サーバーを立てて HPVS 用のイメージを作成します。

この Gen1 の HPVS は専用のネットワーク上に構築されましたが、その後、Gen2 として VPC 内にデプロイできるようになりました。
これについては、下記の記事が投稿されています。

* [Confidential Computingを実現するHyper Protect Virtual Server for VPCを試してみた](https://qiita.com/testnin2/items/daf89d990581667ba857)

Gen2 の HPVS では IBM s390x プロセッサー・アーキテクチャー の LinuxONE の「IBM Secure Execution for Linux」を利用して Confidential Computing を実現します。

コンテナイメージで LPAR を独占し root ログインができない点は Gen1 と同じですが、Gen2 の Secure Execution では Secure Build Server ではなく s390x 用のコンテナイメージを通常の dcoker コマンドでビルドしレジストリーに push しておき、そのレジストリー情報に加えてログの出力先の IBM Cloud Log Analysis with LogDNA の情報を含んた契約(コントラクト)と言われる暗号化されたテキストファイルをユーザーデータに指定して HPVS をデプロイします。

詳しくは、下記をご覧ください。

* [LinuxONE を使用した機密コンピューティング](https://cloud.ibm.com/docs/vpc?topic=vpc-about-se)

Docs には下記のチュートリアルが用意されています。今回は、こちらを実行していきましょう。

* [Hyper Protect Virtual Server for VPC へのサンプル・アプリケーションのデプロイ](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc)

しかし、このチュートリアルは詳細な手順が述べられておらず、そのままでは実行困難だと思われます。
そこで、今回、実際にチュートリアルを実行した体験を投稿します。

チュートリアルは大きく 4 つのパートに分かれます

* 準備 - クライアント環境や VPC 環境の用意
* コンテナイメージのビルドとレジストリーへの push
* 契約(コントラクト)の作成
* HPVS のデプロイ

今回は 有料となった Dcoker Desktop 利用したくないために コンテナイメージの作成には Winodws Hyper-V 上に ubuntu 22.04 server を立てて作業を行っています。
Windows Subsystem for Linux (WSL) でも構わないはずなのですが、導入している VPN S/W ために私の WSL 環境では Docker が正常に動作しないので、今回は Hyper-V を利用しました。
こちらの環境に導入が必要なのは、下記の3つです。

* Git
    サンプルアプリケーションを git clone するのに使います。
* Docker
    サンプルアプリケーションのコンテナイメージをビルドするのに使います。
* IBM Cloud CLI と コンテナー・レジストリー CLI プラグイン
    コンテナイメージをイメージレジストリーに push するのに使います。

契約(コントラクト)の作成以降の作業は Windows で実施しています。
こちらの環境に導入が必要なのは、下記の3つです。

* Git
    契約(コントラクト)を作成するための環境・コードを git clone するのに使います。
* terraform CLI
    コントラクトを作成するためのコードは terraform で記述されています。
    コントラクトの作成に利用します。
* openssh
    コントラクトの作成時に terraform から呼び出されます。

なお、この記述は Docs を補完するもので、置き換えるものではありません。見出しは Docs での記述に一致させていますので、Docs を確認しながら読んでください。
大見出しは Docs の該当部分へのリンクにもなっています。

# [開始前に](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc#hpvs-ftcc-before-you-begin)

このチュートリアルを実行するには、以下の前提条件を満たしていなければなりません。

## ① IBM Cloud アカウントを作成します。

ポータルにログインします。

 * [https://cloud.ibm.com/login](https://cloud.ibm.com/login)

## ② ユーザー ID の API キーを作成します。

* [https://cloud.ibm.com/iam/apikeys](https://cloud.ibm.com/iam/apikeys)

作成した API キーは、コピーするがダウンロードしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/668ac47b-d2e5-dbbe-3834-1d55ea89d437.png)

## ③ IBM Cloud CLI および コンテナー・レジストリー CLI プラグインをインストールします。

IBM Cloud CLI の インストーラーは下記からダウンロードできます。
Mac および Windows™ の場合、インストーラーを実行します。
Linux™ の場合、パッケージを解凍し、install スクリプトを実行します。

* [IBM-Cloud/ibm-cloud-cli-release](https://github.com/IBM-Cloud/ibm-cloud-cli-release/releases/)

IBM Cloudにログインします

```
ibmcloud login
```

コンテナー・レジストリー CLI プラグインをインストールします。

```
ibmcloud plugin install cr
```

## ④ パブリック・ゲートウェイ と セキュリティー・グループ を持つ VPC とサブネット を作成し、ポート 8443 とすべてのアウトバウンド IP 接続で少なくともインバウンド IP 接続を許可する規則を適用します。

下記からVPC を作成します。

* [https://cloud.ibm.com/vpc-ext/provision/vpc](https://cloud.ibm.com/vpc-ext/provision/vpc)

ロケーションを選び、名前を入力します。
現在は大阪にはHPVSが用意されていませんので、日本のリージョンを選ぶ場合は東京を選んでください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/bfbc9c52-4911-470c-841b-5ae76c87acf3.png)

HPVS を設置するサブネットの鉛筆マークをクリックし、パブリック・ゲートウェイをオンにし「保存」した後に「仮想プライベートクラウドの作成」を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/6b6fa118-a7ed-199d-0259-2dc6b1781cf2.png)

下記で作成された VPC が確認できます。

* [https://cloud.ibm.com/vpc-ext/network/vpcs](https://cloud.ibm.com/vpc-ext/network/vpcs)

リストに VPC が見つからない場合はリージョンが正しいか確認してください。

ポート 8443 は、今回の Web アプリケーションが利用するポート番号です。
回部から接続ができるようにインバウンド・ルールを作成します。

VPC の「デフォルト・セキュリティ・グループ」をクリックします(名前は環境によって異なります)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/c8ca15db-13a3-3d68-289a-f5f8d83c6d0a.png)

「ルール」タブの作成で「作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/fa439dcd-d714-156a-2b19-26d686202fdf.png)

ポート 8443 への接続を許すインバウンド・ルールを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/e0c61da3-8aa9-d194-1dda-295cdeb0674e.png)

追加されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/3202846f-5010-aca5-ad16-589865c126e5.png)

VPC の構成に不明な点がある場合「[IBM Cloud Virtual Private Cloud (VPC) 構築実践チュートリアル](https://qiita.com/6onoda/items/06f9a4b1090d05ea0813)」を一度、やっていただくといいかもしれません。

## ⑤ IBM Cloudで Log Analysis インスタンス を作成します。 取り込みホストと取り込み鍵をメモしておきます。

HPVS では root 接続はなく、インスタンスにログインしてログを確認することはできません。
そのため、Log Analysis インスタンスにログを書き出します。
Log Analysis のインスタンスは複数の HPVS で共有できます。

作成は下記から行います。

* [https://cloud.ibm.com/catalog/services/logdna?callback=%2Fobserve%2Flogging%2Fcreate](https://cloud.ibm.com/catalog/services/logdna?callback=%2Fobserve%2Flogging%2Fcreate)

ロケーションとプランを選び、名前必要に応じて作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/da538753-0a9c-7802-3aed-0da6af5ebe46.png)

取り込みホストと取り込み鍵を確認します。

取り込みホストは、リージョン事に共通です。「 [Syslog エンドポイント](https://cloud.ibm.com/docs/log-analysis?topic=log-analysis-endpoints&locale=ja#endpoints_syslog)」で確認できます。
東京の場合は「syslog-a.jp-tok.logging.cloud.ibm.com」です。

取り込み鍵は「アクション」の「鍵の管理」で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/9a407dd0-72ce-cf72-d5b7-18280c3392a2.png)

## ⑥ Gitをインストールします。

下記より環境にあった Git クライアントを導入します。

* [Install Git](https://github.com/git-guides/install-git)


# [ステップ 1。 PayNow アプリケーション・コンテナー・イメージのビルド](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc#hpvs-ftcc-step1)

このチュートリアルでは、自分でコンテナー・イメージをビルドし、プライベート・レジストリーに登録します。

このパートは Winodws Hyper-V 上に ubuntu 22.04 を立てて作業を行っています。
作業は root で行います。

## ① Git を使用して、 [リポジトリー](https://github.com/ibm-hyper-protect/paynow-website)を複製します。

この「paynow-website」が今回実行するDockerコンテナのコードです。

```
sudo -s
git clone https://github.com/ibm-hyper-protect/paynow-website
cd paynow-website
```

「 [Dockerfile](https://github.com/ibm-hyper-protect/hps-paynow-website/blob/main/Dockerfile)」を確認すると「node:19」がベースイメージの node.js アプリケーションであることが分かります。

## ② 以下のコマンドを使用して、linux/s390x プラットフォーム用の PayNow コンテナー・イメージをビルドし、コンテナー・イメージにタグを付けます。

Docs には下記のコマンドが記述されているだけですが、いくつか注意が必要です。

```
docker buildx build --platform linux/s390x -t us.icr.io/hpvs-sample/paynow-website .
```

### 「docker buildx」対応

一つ目は実行コマンドが「docker buildx」であることです。
「[Docker Buildx](https://matsuand.github.io/docs.docker.jp.onthefly/buildx/working-with-buildx/)」によると下記の説明があります。

> Docker Buildx は Docker コマンドを拡張する CLI プラグインであり、Moby BuildKit ビルダーツールキットにより提供される機能に完全対応するものです。

> Windows と macOS
Docker Buildx は Windows と macOS に対しては Docker Desktop に含まれます。
>
> Linux パッケージ
DEB や RPM パッケージ を利用する場合も、Linux パッケージとして Docker Buildx が含まれます。

Docker Desktop は、従業員数250人以上かつ年間売上高1000万ドル以上の組織など向けは有料です。今回の私の Windows 環境では Docker Desktop が利用できません。
そこで、このステップは Hyper-V 上に ubuntu 22.04 を立ててその中の Docker 環境を使うことにしました。

### マルチプラットフォーム対応

二つ目は「--platform linux/s390x」と linux/s390x 用のイメージを作成する必要があることです。

今回の作業環境は x86-64 です。マルチプラットフォーム対応を行わないで、ビルドしようとすると、x86-64 環境で s390x の「/bin/sh」の実行はできないので「RUN」の実行でエラーが起こります。

```
 => ERROR [4/5] RUN npm install                                                                                    0.5s
------
 > [4/5] RUN npm install:
#0 0.442 exec /bin/sh: exec format error
------
ERROR: failed to solve: executor failed running [/bin/sh -c npm install]: exit code: 1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/54c00b19-d2b3-86e4-7861-72eb9630c877.png)


マルチプラットフォームに対応するため下記を参考にして QEMU エミュレーター環境を用意します。

* [Multi-platform images](https://docs.docker.com/build/building/multi-platform/)

```
docker run --privileged --rm tonistiigi/binfmt --install all
```
再度、実行します。

```
docker buildx build --platform linux/s390x -t us.icr.io/hpvs-sample/paynow-website .
```

今度は成功しました。

```
root@u2204:/home/user01/paynow-website# docker buildx build --platform linux/s390x -t us.icr.io/hpvs-sample/paynow-website .
[+] Building 22.4s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 32B                                                                                0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/node:19                                                         1.8s
 => [1/5] FROM docker.io/library/node:19@sha256:92f06fc13bcc09f1ddc51f6ebf1aa3d21a6532b74f076f224f188bc6b9317570   0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 936B                                                                                  0.0s
 => CACHED [2/5] WORKDIR /app                                                                                      0.0s
 => CACHED [3/5] COPY app/package*.json ./                                                                         0.0s
 => [4/5] RUN npm install                                                                                         20.3s
 => [5/5] COPY app/ .                                                                                              0.1s
 => exporting to image                                                                                             0.2s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:0773ff260d574b2041090ff987965d171c8e22624e80cfbc6928a6293703f6f1                       0.0s
 => => naming to us.icr.io/hpvs-sample/paynow-website
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/5ce6dcd8-b9e9-625b-6f9c-42ae39533055.png)

作成したイメージを確認をしましょう。

```
docker image ls
```

作成されているのがわかります。

```
root@u2204:/home/user01/paynow-website# docker image ls
REPOSITORY                             TAG       IMAGE ID       CREATED         SIZE
us.icr.io/hpvs-sample/paynow-website   latest    0773ff260d57   8 minutes ago   934MB
tonistiigi/binfmt                      latest    354472a37893   13 months ago   60.2MB
```

## ③ 以下のコマンドを使用して、 IBM Cloud Container Registry にログインします。 

上記で述べたように IBM Cloud CLI と Container Rregistry(cr) プラグインを事前に導入しておきます。

```
ibmcloud login
```

```
ibmcloud target -r us-south
```

```
ibmcloud cr login --client docker
```

## ④ 以下のコマンドを実行して、名前空間を作成し、コンテナー・イメージをプッシュします。

```
ibmcloud cr namespace-add [hpvs-xxxx]
```

[hpvs-xxxx]の部分をチュートリアル通りに「hpvs-sample」とすると、namespace は既にあるとエラーになると思います。

```
root@u2204:/home/user01/paynow-website# ibmcloud cr namespace-add hpvs-sample
No resource group is targeted. Therefore, the default resource group for the account ('Default') is targeted.

Adding namespace 'hpvs-sample' in resource group 'Default' for account 6onoda in registry us.icr.io...

FAILED
The requested namespace is already in use in registry 'us.icr.io'.
Choose a different namespace.
```

下記の理由です。

* [名前空間を追加できないのはなぜですか?](https://cloud.ibm.com/docs/Registry?topic=Registry-troubleshoot-add-namespace)

> 名前空間は、同じリージョンのすべての IBM Cloud アカウントで固有である必要があります。

リージョン内でユニークな名前を付けましょう。
今回は「hpvs-6onoda」としました。

```
root@u2204:/home/user01/paynow-website# ibmcloud cr namespace-add hpvs-6onoda
No resource group is targeted. Therefore, the default resource group for the account ('Default') is targeted.

Adding namespace 'hpvs-6onoda' in resource group 'Default' for account 6onoda in registry us.icr.io...

Successfully added namespace 'hpvs-6onoda'

OK
```

作成した名前空間内にイメージを push します。

```
docker push us.icr.io/[hpvs-xxxx]/paynow-website
```

しかし、ビルドしたイメージのタグ名は「us.icr.io/hpvs-sample/paynow-website」と名前空間が「hpvs-sample」であることを前提にしています。

```
root@u2204:/home/user01/paynow-website# docker images
REPOSITORY                             TAG       IMAGE ID       CREATED         SIZE
us.icr.io/hpvs-sample/paynow-website   latest    0773ff260d57   2 hours ago     934MB
tonistiigi/binfmt                      latest    354472a37893   13 months ago   60.2MB
```

push する前にタグを付け替えましょう。

```
docker tag us.icr.io/hpvs-sample/paynow-website us.icr.io/[hpvs-xxxx]/paynow-website
```

今回は「us.icr.io/**hpvs-6onoda**/paynow-web」です。

```
root@u2204:/home/user01/paynow-website# docker tag us.icr.io/hpvs-sample/paynow-website us.icr.io/hpvs-6onoda/paynow-web
site
```

「docker image ls」で期待するタグが付いていることが確認できます。

```
root@u2204:/home/user01/paynow-website# docker image ls
REPOSITORY                             TAG       IMAGE ID       CREATED         SIZE
us.icr.io/hpvs-6onoda/paynow-website   latest    0773ff260d57   2 hours ago     934MB
us.icr.io/hpvs-sample/paynow-website   latest    0773ff260d57   2 hours ago     934MB
tonistiigi/binfmt                      latest    354472a37893   13 months ago   60.2MB
```

では push しましょう。

```
docker push us.icr.io/[hpvs-xxxx]/paynow-website
```

push が完了しました。

```
root@u2204:/home/user01/paynow-website# docker push us.icr.io/hpvs-6onoda/paynow-website
Using default tag: latest
The push refers to repository [us.icr.io/hpvs-6onoda/paynow-website]
0446aecf2080: Pushed
541c5d2542e6: Pushed
6344efdf17d8: Pushed
537fc69e514b: Pushed
ef13dc0a223f: Pushed
dbb9dc07e484: Pushed
c5f97d296ded: Pushed
aa65986e06f7: Pushed
dc1321bea2d8: Pushed
b83c6b8b1c33: Pushed
4a89c79f1902: Pushed
fda0660b571f: Pushed
latest: digest: sha256:9baeee279daf893692eb12983a0c98bece7011c553c518d27a9457a1e261adb1 size: 2839
```

## ⑤ コンテナー・イメージ・ダイジェストを表示します。 コンテナー・レジストリー内のコンテナー・イメージ・ダイジェストを表示してメモすることも、以下のコマンドを使用することもできます。

コンテナー・イメージ・ダイジェストは HPVS をデプロイする時に指定し、コンテナー・イメージが改変されていないかの確認に使われます。

```
docker inspect us.icr.io/[hpvs-xxxx]/paynow-website | grep -A 1 RepoDigests
```

今回はコマンドで確認しています。

```
root@u2204:/home/user01/paynow-website# docker inspect us.icr.io/hpvs-6onoda/paynow-website | grep -A 1 RepoDigests
        "RepoDigests": [
            "us.icr.io/hpvs-6onoda/paynow-website@sha256:9baeee279daf893692eb12983a0c98bece7011c553c518d27a9457a1e261adb1"
```

# [ステップ 2。 Terraform を使用した PayNow アプリケーションの契約の作成](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc#hpvs-ftcc-step2)

今回は、このステップから Windows のコマンドプロンプトで作業しました。もちろん、ubuntu 環境で継続しても構いません。

このステップでは「契約(コントラクト)」というファイルを作成します。
「契約(コントラクト)」は、どこからコンテナイメージを入手するか、ハッシュは期待通りでイメージは改ざんされていないか、ログの出力先はどこかを HPVS のデプロイ時にユーザーデータとして指定するファイルです。

契約(コントラクト)ついての詳細やマニュアルでの作成方法は下記に説明があります。

* [契約について](https://cloud.ibm.com/docs/vpc?topic=vpc-about-contract_se)

ただし、手順が煩雑なので IBM は terraform を使った作成の自動化ツールを github で提供しています。
チュートリアルでは、この自動化ツールで契約(コントラクト)を生成します。

## ① 契約作成の準備:

### a. OpenSSL バイナリーがインストールされていることを確認します。 詳しくは、 [OpenSSL](https://github.com/ibm-hyper-protect/linuxone-vsi-automation-samples)を参照してください。

今回は下記サイトから「Win64 OpenSSL v1.1.1v」を導入しました。

* [Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions](https://slproweb.com/products/Win32OpenSSL.html)

インストーラーの実行では PATH に追加されませんでしたので、自分で追加しました

```
PATH=%PATH%;C:\Program Files\OpenSSL-Win64\bin
```

### b. [Terraform 資料](https://developer.hashicorp.com/terraform)を使用して、ご使用の環境用の Terraform CLI をインストールします。

今回は下記サイトから「terraform_1.5.7_windows_amd64.zip 」を導入しました。

* [Install Terraform | Terraform | HashiCorp Developer](https://developer.hashicorp.com/terraform/downloads)

zip を展開すると「terraform.exe」があるので PATH に追加されているフォルダーに移動しました。

### 環境の確認

Git、openssl、terraform の導入を確認しておきます。

```
C:\Temp>git -v
git version 2.42.0.windows.2

C:\Temp>openssl version
OpenSSL 1.1.1v  1 Aug 2023

C:\Temp>terraform -version
Terraform v1.5.6
on windows_amd64
```

## ② 契約を作成します。

契約(コントラクト)は、HPVS をデプロイする時に、どのコンテナイメージを使うか、そのハッシュはいくつか、ログの出力先をどこにするかを指定するファイルです。
この契約(コントラクト)に従って、アプリケーションが自動導入されるわけです。

### a. Git を使用して、[リポジトリー](https://github.com/ibm-hyper-protect/linuxone-vsi-automation-samples)を複製します。

契約(コントラクト)を作成するコートを入手します。

```
git clone https://github.com/ibm-hyper-protect/linuxone-vsi-automation-samples
```

### b.次のコマンドを使用して、以下のディレクトリーに移動します。

```
cd linuxone-vsi-automation-samples\terraform-hpvs\create-contract-dynamic-registry
```

## ③ compose フォルダー内の docker-compose.yml ファイルを更新します。 コンテナー・イメージ・ダイジェストと公開ポートを指定する必要があります。 以下の docker-compose.yml ファイルの例を参照してください。

「create-contract-dynamic-registry」フォルダーの直下に「compose」フォルダー
があり、その内に「docker-compose.yml」というファイルがあります。

これを下記内容で、置き換えます。

```docker-compose.yml
version: "3"
services:
  paynow:
    image: ${REGISTRY}/hpvs-sample/paynow-website@sha256:<sha256>
    ports:
      - "8080:8080"
      - "8443:8443"
```

「image: ${REGISTRY}/hpvs-sample/paynow-website@sha256:\<sha256>」の行を環境に合うように書き換えます。

「${REGISTRY}/hpvs-sample/paynow-website」は自分のイメージのURLです。
今回の私の場合は「us.icr.io/hpvs-6onoda/paynow-website」です。

「\<sha256>」は、先に確認したコンテナー・イメージ・ダイジェストです。

つまり「image:」に先ほど「docker inspect」で確認した RepoDigests の値を設定すればいいわけです。

```text:「docker inspect」再掲
root@u2204:/home/user01/paynow-website# docker inspect us.icr.io/hpvs-6onoda/paynow-website | grep -A 1 RepoDigests
        "RepoDigests": [
            "us.icr.io/hpvs-6onoda/paynow-website@sha256:9baeee279daf893692eb12983a0c98bece7011c553c518d27a9457a1e261adb1"
```

「us.icr.io/hpvs-6onoda/paynow-website@sha256:9baeee279daf893692eb12983a0c98bece7011c553c518d27a9457a1e261adb1」の部分ですね。

今回のように設定しました。

```docker-compose.yml
version: "3"
services:
  paynow:
    image: us.icr.io/hpvs-6onoda/paynow-website@sha256:9baeee279daf893692eb12983a0c98bece7011c553c518d27a9457a1e261adb1
    ports:
      - "8080:8080"
      - "8443:8443"
```

## ④ 必要な Terraform 変数を設定します。 これを行うには、ファイル my-settings.auto.tfvars-template を my-settings.auto.tfvarsにコピーし、コピーしたファイルを編集して、変数値を調整する必要があります。 以下の例を参照してください。

「my-settings.auto.tfvars-template」は現在の「create-contract-dynamic-registry」フォルダーにあります。
「my-settings.auto.tfvars」にコピーします。

```
copy my-settings.auto.tfvars-template my-settings.auto.tfvars
```

「my-settings.auto.tfvars」を環境に合わせて変更します。

```
registry="us.icr.io"           # 使っているコンテナ・レジストリーに変更
pull_username="iamapikey"      # 変更しない
pull_password="<your API key>" # 作成した API Key の値をセット
logdna_ingestion_key="<the ingestion key of your log instance>"   # Log Analysis の 取り込み鍵
logdna_ingestion_hostname="syslog-a.jp-tok.logging.cloud.ibm.com" # Log Analysis の 取り込みホスト
```

## ⑤ Terraform を初期化するには、以下のコマンドを実行します。

```
terraform init
```

```
C:\Temp\linuxone-vsi-automation-samples\terraform-hpvs\create-contract-dynamic-registry>terraform init

Initializing the backend...

Initializing provider plugins...
- Finding ibm-hyper-protect/hpcr versions matching ">= 0.1.1"...
- Finding latest version of hashicorp/local...
- Installing ibm-hyper-protect/hpcr v0.2.7...
- Installed ibm-hyper-protect/hpcr v0.2.7 (self-signed, key ID 17BF3C873BC107DB)
- Installing hashicorp/local v2.4.0...
- Installed hashicorp/local v2.4.0 (signed by HashiCorp)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

## ⑥ Terraform を使用して契約を作成します。

```
terraform apply
```

`Enter a value:` で停止するので`yes`で答えます。

```
C:\Temp\linuxone-vsi-automation-samples\terraform-hpvs\create-contract-dynamic-registry>terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # hpcr_contract_encrypted.contract will be created
  + resource "hpcr_contract_encrypted" "contract" {
      + cert     = <<-EOT
            -----BEGIN CERTIFICATE-----
            MIIHVjCCBT6gAwIBAgIQFrfH+bYVSFBvTmO6b9QARTANBgkqhkiG9w0BAQ0FADCB
            0TELMAkGA1UEBhMCREUxGzAZBgNVBAgMEkJhZGVuLVfDvHJ0dGVtYmVyZzETMBEG
            A1UEBwwKQsO2YmxpbmdlbjE0MDIGA1UECgwrSUJNIERldXRzY2hsYW5kIFJlc2Vh
            cmNoICYgRGV2ZWxvcG1lbnQgR21iSDEkMCIGA1UECxMbSUJNIFogSHlicmlkIENs
            b3VkIFBsYXRmb3JtMTQwMgYDVQQDDCtJQk0gRGV1dHNjaGxhbmQgUmVzZWFyY2gg
            JiBEZXZlbG9wbWVudCBHbWJIMB4XDTIyMTIwODE1MjQwNloXDTIzMTIwODE1MjQx
            NlowgbYxCzAJBgNVBAYTAkRFMQswCQYDVQQIEwJCVzETMBEGA1UEBxMKQm9lYmxp
            bmdlbjEhMB8GA1UECgwYSUJNIERldXRzY2hsYW5kIFImRCBHbWJIMSQwIgYDVQQL
            ExtJQk0gWiBIeWJyaWQgQ2xvdWQgUGxhdGZvcm0xPDA6BgNVBAMTM0h5cGVyIFBy
            b3RlY3QgQ29udGFpbmVyIFJ1bnRpbWUgQ29udHJhY3QgRW5jcnlwdGlvbjCCAiIw
            DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANDNG31a9Z5X+4Qbo8YmImgaQsMK
            pojFK8YeeRzGnAWWat/ml25o5chRX0/tg1LdSxX4CWPj7F0BsLB+WRbfFmnzuHiR
            J7rYIpAnR4myfUJrnZx/yDinpRWlJORudsDX/FlCUV2PCyyTqmvu+SpCNFeSr0F8
            oWmauFbw+9wMAAkZ4ys7NRwSenIfsEtIo5tQI8rnzOA43QuJQs2vqMxFjlivrveD
            kEiqyPOLINTI0k5yhyZgOs/YpRpzWNfNIy6Ga9rrG6E983RrAf+c4WDLYisSadBt
            V5apqYCBqBLMCkE7jR+BPaoVxsgRMs//D4BTHxkQQeYeM5dcGf91gHC3GDEGgJ0g
            Yh42EtuXGH/Cwj3CG3sU0PT3BbCxK6TUy4UvZQG/0cb5VQio8WhcSeyDWF0aAm50
            R6ZZtUPcL2BsYZENpGz31RorFVwIkXBRL703HxJ+LUhehUzsOok3emSR/iwIbaUN
            u13g50O3T190gK4q3jzP5PiRj/ptThJgmJ+tnOz5KCZKwgnAfD0rAWqvXv/uzSJ3
            1xMazIKzJpfs6TpXVJXoR08YHpyKxgthSIpBpLYIxkYRnigebzA0uBd4M+qXmYGD
            VQ/9udAw+UHhTunCh8+x5Z/rnMM8U61w67PjBg+vVvfDDkgHuMn7Z6yZ/77QtEzf
            xyyy9WjDOpzos85ZAgMBAAGjggFBMIIBPTCBkwYDVR0fBIGLMIGIMEKgQKA+hjxo
            dHRwczovL2libS5iaXovaHlwZXItcHJvdGVjdC1jb250YWluZXItcnVudGltZS0w
            MjNCQzktY3JsLTEwQqBAoD6GPGh0dHBzOi8vaWJtLmJpei9oeXBlci1wcm90ZWN0
            LWNvbnRhaW5lci1ydW50aW1lLTAyM0JDOS1jcmwtMjCBpAYIKwYBBQUHAQEEgZcw
            gZQwSAYIKwYBBQUHMAKGPGh0dHBzOi8vaWJtLmJpei9oeXBlci1wcm90ZWN0LWNv
            bnRhaW5lci1ydW50aW1lLTAyM0JDOS1jcnQtMTBIBggrBgEFBQcwAoY8aHR0cHM6
            Ly9pYm0uYml6L2h5cGVyLXByb3RlY3QtY29udGFpbmVyLXJ1bnRpbWUtMDIzQkM5
            LWNydC0yMA0GCSqGSIb3DQEBDQUAA4ICAQDKpAUiQlz6kDWMyvDRv7EDBxdiwmU3
            J8YpETRE4p3Sy07oh3BwiuDZ+8JxOWbgqRSwiBtSFuuOIOlULa6K+x/ZLHJTa+p4
            KVyiIJmih7mufttO2WgvpNpb3djr8fU2KifOL+8ouY94xvhQ2PL20zKDvYEB+XRo
            KZ9TWXNBCuEP8nqJS/ZzuKciJ7A0Ya5OOQ2IhPY5OoQH3CLErKZ42rCgR6yzBjik
            VjobsFC/e3GqC3YHyrQwt58tKd2cJQFzfQ72aiMj/0XAxJ63iSEgKCrjC+kTYMRX
            CN33iVAv6GUFxjdgOaM47nvUZtttpbQFRd7/ijQ/oCL/pDePjUeRLy40J70k0Uvq
            wIg0pv2qaGbFZeFMGiYNGsTOQKu3ckfl8g7+yJu6jFp/+83HruSuVnKtrEChCvlp
            kDq3sFQdCQNP0dx5W5Q3JaE+UPVhcxLIbqQ/XI0KkF2Whr2lfz0BK0WLDr7yqY3t
            D5Hqaz2oeYYNkR+n6qE1KtYtWm1Wo4i/5IJRh/ar+7ZcraXs5PMMF5DzKlnZyQS+
            RHuYydBnrva0JfcMRocsVGGse9qQW2Ks8ggrBBTg7kf3U2YVYahSvB26DqzrdmV5
            H/+m5vb5QNzw70UNqcSeIJned+RwMq3bSSQGtY9omByfa2ZsgOd0vHYp6JMPH1zw
            P89WiSFqzHnCdQ==
            -----END CERTIFICATE-----
        EOT
      + checksum = (known after apply)
      + contract = (sensitive value)
      + id       = (known after apply)
      + rendered = (known after apply)
      + sha256   = (known after apply)
    }

  # hpcr_tgz.contract will be created
  + resource "hpcr_tgz" "contract" {
      + checksum = (known after apply)
      + folder   = "compose"
      + id       = (known after apply)
      + rendered = (known after apply)
      + sha256   = (known after apply)
    }

  # local_file.contract will be created
  + resource "local_file" "contract" {
      + content              = (known after apply)
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./build/contract.yml"
      + id                   = (known after apply)
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

hpcr_tgz.contract: Creating...
hpcr_tgz.contract: Creation complete after 0s [id=aae43b44-d500-97a6-4255-bcc2b0537021]
hpcr_contract_encrypted.contract: Creating...
hpcr_contract_encrypted.contract: Creation complete after 2s [id=858695cb-0c15-b119-7c01-f61ebe8e941a]
local_file.contract: Creating...
local_file.contract: Creation complete after 0s [id=354b717fcf7b09b649a5fe1c8fc81f4408cac802]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
```

## ⑦ 以下のコマンドを実行して、Terraform スクリプトで作成された契約を表示します。

```
cat build/contract.yml
```

Windows の場合、下記ですね。

```
type build\contract.yml
```

作成されていました。

```
C:\Temp\linuxone-vsi-automation-samples\terraform-hpvs\create-contract-dynamic-registry>type build\contract.yml
env: hyper-protect-basic.Eo3wmpH/M5hv9gUGhaxrQwim5HZMGjKu05hTAOChm9deo5q0tMpM ...
(以下略)
```

契約(コントラクト)ファイルは、いくつかのセクションに分かれ内容は暗号化されています。

# [ステップ 3。 Hyper Protect Virtual Server for VPC を使用した IBM Cloud による機密コンピューティングの有効化](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc#hpvs-ftcc-step3)

## ① IBM Cloudにログインします。

* [https://cloud.ibm.com/login](https://cloud.ibm.com/login)

## ② IBM Cloud カタログの Hyper Protect Virtual Server for VPC の 「プロビジョン」ページ に移動します。

下記の URLで HPVS インスタンスをオーダーします。

* [https://cloud.ibm.com/vpc-ext/provision/vs?architecture=s390x&secureExecution=true](https://cloud.ibm.com/vpc-ext/provision/vs?architecture=s390x&secureExecution=true)

複数のアカントが利用可能な場合、期待通りのアカウントが選択されているか、右上のアカント表示を確認します。

ロケーションとゾーンを確認します。ゾーンには、パブリック・ゲートウェイを設定したサブネットがあるゾーンを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/b8d9e4e0-6fe8-a5be-b5d2-2027cfd2f994.png)

## ③ 仮想サーバー・インスタンスに名前を付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/a079e7fb-455f-826a-6898-f7d3e6708abb.png)

HPVS ではsshでのログインは許可されません。ssh鍵は指定しません。

## ④ 作成した契約情報を **「ユーザー・データ」**に貼り付けます。

「ユーザーデータ」の「ユーザーデータのインポート」に作成した契約(コントラクト)ファイルをインポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/be182f59-f822-7590-f870-9f9eeebb14bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/e55e45c8-2e03-3e92-e370-fa5d5ad81bbe.png)

もちろん、ファイルの内容をコピー & ペーストしても構いません。

## ⑤ **「ネットワーキング」**の下で、VPC とサブネットを選択します。

サブネットはバプリック・ゲートウェイを設定したものを選びます。
HPVS のデプロイ時にレジストリーからイメージを pull する必要があります。
レジストリーへのアクセスのためにバプリック・ゲートウェイを使った外部アクセスが必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/a6d105a3-7109-b38c-cafe-e162172dc6ac.png)

## ⑥ **「仮想サーバーの作成」**をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/aef5728f-24c8-e484-2187-58c0a93deca8.png)

作成後、シリアル・コンソールを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/aa3e2f2f-ab81-4e47-35e9-73fa03f3b5a3.png)

「Logging has been configured」が表示されれば、HPVS は それ以降のログを Log Analysis に転送します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/b05ff223-192f-c352-203a-764ae669e6a7.png)

## ⑦ Log Analysis インスタンス・ダッシュボードでログを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/ab471764-72be-a828-bdd3-ba503197e840.png)

コンテナが正常に起動しアプリケーションが開始されると、このように出力されます。

```
hyper-protect-pay-now@1.0.0 start
node app.js
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/177e2e99-8e3d-6609-0ef9-9220ac78de26.png)

## ⑧ VPC インスタンスの Hyper Protect Virtual Server に浮動 IP アドレスを割り当て、「保存」をクリックします。

こんままでは VPC の外側からはアクセスできませんので、インスタンスに浮動 IP アドレスを割り当てます。

HPVS インスタンスを開き「ネットワーク・インターフェース」の鉛筆マークをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/45a3c67a-2dc0-657f-aea2-64aedc017e07.png)

「浮動 IP アドレス」で既存・未アサインのものから選択するか、新規アサインを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/4e22295f-6ac1-ad90-7323-b845fd3b451a.png)

割り振られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/33c27ff9-155a-0759-7c36-6d4b23616291.png)

## ⑨ PayNow Web サイトを開くには、浮動 IP アドレスをコピーして貼り付け、ブラウザーを使用して PayNow Web サイトを URL https://<floatingip>:8443/index.htmlの下で開きます。

「https://<floatingip>:8443/」にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/2ed6e26d-b370-8487-e576-d4147b36a99c.png)

警告を受け入れると、アプリケーションにアクセスすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/417de2f4-6999-22d0-ba6f-ff48f6ce14eb.png)

Docker コンテナのアプリケーションを HPVS にデプロイできました。

# [次のステップ](https://cloud.ibm.com/docs/vpc?topic=vpc-financial-transaction-confidential-computing-on-hyper-protect-virtual-server-for-vpc#hpvs-ftcc-next-steps)

どのように安全か [デモ・ビデオ](https://mediacenter.ibm.com/media/IBM+Cloud+Show+Me-+Hyper+Protect+Services+for+Confidential+Computing+Demo/1_f7e970ig) をご覧ください。

Docs には下記が記載されています。

> 2 つのサーバー間の比較によって Confidential Computing によって提供されるデータ保護について説明している [デモ・ビデオ](https://mediacenter.ibm.com/media/IBM+Cloud+Show+Me-+Hyper+Protect+Services+for+Confidential+Computing+Demo/1_f7e970ig) をご覧ください。
> 
> * 1 つの なし Confidential Computing。悪意のある root ユーザーが、PII およびクレジット・カード・データを盗むために保護されていないサーバー・メモリーの内容をダンプできます。
> * 1 つの 置き換え Confidential Computing は、Hyper Protect プラットフォームによって保護されているため、root ユーザーであってもサーバー・メモリーにアクセスすることができません。

# 補足

## 「create-contract-dynamic-registry」と「create-contract」の使い分け

今回は「create-contract-dynamic-registry」内のツールを使い、レジストリーのURLやAPI キーを指定しました。
これは、プライベート・レジストリーを想定しているためです。
パブリック・レジストリーにイメージが存在する場合は、となりの「create-contract」が利用できます。
この場合、「logdna_ingestion_key」と「logdna_ingestion_hostname」だけを指定すればよく、レジストリーのURLやAPI キーを指定する必要はありません。

## IBM Log Analysis with LogDNA の Private エンドポイントの利用
今回は IBM Log Analysis with LogDNA は Public エンドポイントを「syslog-a.jp-tok.logging.cloud.ibm.com」を使いましたが「[Confidential Computingを実現するHyper Protect Virtual Server for VPCを試してみた](https://qiita.com/testnin2/items/daf89d990581667ba857)」にあるように Private エンドポイントの「syslog-a.private.jp-tok.logging.cloud.ibm.com」を使うべきでしょう。

## Container Registry のセキュリティ強化
Container Registry にもセキュリティを高める方法が存在するので利用を検討してもいいでしょう。

* [Container Registry 資料](https://cloud.ibm.com/docs/Registry)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/6a0f092c-0361-8293-9602-6f3429b7dbc9.png)