不変ストレージ(AzureBlobStorage)に関する手記

### はじめに
保管したシステムログや履歴情報を保管後は一切更新や削除ができないストレージに保管したいってことがあるように思います。そんな、不変ストレージをAzureBlobStorageで実現できるので、その記録を記載していきます。

## 不変ストレージとは
MicrosoftのDocs内に、一言でわかりやすい記載がありました。
『ビジネス クリティカルな BLOB データを書き込み 1 回、読み取り複数回 (WORM) の状態で保存する。』

参考：[MS Lern：BLOBデータの不変ストレージの概要](https://learn.microsoft.com/ja-jp/azure/storage/blobs/immutable-storage-overview)

つまり、一度書き込んだら、更新とか削除できないストレージコンテナってことです。

#### 利用ケース
考えられる利用ケースは以下のような情報(データ)です。　※よく使いそうな順番
+ 法律上、変更されないストレージに保管することが義務づけられている情報（電帳法等）
+ 監査で使用するシステムログやアクティビティログ
+ セキュリティ上のリスクが発生した際に、悪意を持って変更されないようにしたい情報
+ 一度出力されたらもう更新しない前提の情報

#### NGケース
逆に使用してはいけないものは以下です。　※他にあれば教えてください。
+ データベースのストレージ領域
+ 蓄積型で更新されるログの直接の出力先
+ その他、都度更新の発生するファイル

## AzureBlobStorageでの設定の流れ
設定のざっくりとした流れです。
これに沿って細かく説明していきます。
1. Storageアカウントを準備する
1. コンテナ(Blob)を作成する
1. コンテナ内のアクセスポリシーを設定する
1. 動作確認
1. ロックのポリシーを有効化する

#### シナリオ
以下設定の詳細を記載していきますが、構築におけるシナリオです。
+ AzureBlobStorageでコンテナベースの不変ストレージを構成する
+ 監査の記録等、変更されてはいけないかつ公開してはいけない情報を保存する
+ 保存期間は30日とする
+ 内部ネットワークからのアクセスのみを許可する

以下で一つ一つ細かく見ていきます。
## 1. Storageアカウントを準備する
AzurePortalのストレージアカウントのページから以下のような感じで作っていきます。特に注意点は無いです。

### 1-1.「基本」タブ
普通に入力していくだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/76f8a597-0854-f160-e732-4185613bc4c8.png)

### 1-2.「詳細」タブ
デフォルトでOK

### 1-3.「ネットワーク」タブ
内部ネットワークのみアクセス可能とするため、以下の通りの設定としています。
不変ストレージの設定のみしたいのであれば、ここまでする必要はありません。
「すべてのネットワークからのパブリックアクセスを有効にする」でも良いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/75a3d2ca-336e-ffc1-a56c-541c9a3fb1f5.png)

### 1-4.「データ」保護
今回はコンテナレベルで不変ポリシーを当てていくので、「バージョンレベルの不変性のサポートを有効にする」はチェックしません。説明は、[後述](#### 補足：バージョンレベルの不変性のサポートについて)します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/3456ce7e-5c39-6812-4578-a2d90dafb5ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/80d2b718-eb77-799b-55c1-804f0076f7f9.png)

#### 補足：論理削除機能について
論理削除機能とは、有効にしておくことで誤ってコンテナやファイルを削除した場合も復旧できるようにする機能です。Windowsの「ごみ箱」とかがイメージ近いですね。
今回の不変ストレージでは、そもそもポリシーのロックを有効にした不変ストレージはコンテナを削除できなくなるので、不要なようにも思います。
[MS Learn：コンテナーの論理的な削除](https://learn.microsoft.com/ja-jp/azure/storage/blobs/soft-delete-container-overview)

#### 補足：バージョンレベルの不変性のサポートについて
以下、MSの説明を抜粋です。
>このコンテナーのバージョンレベルの不変性を有効にするかどうかを指定します。バージョンレベルの不変性は、コンテナー内の特定の BLOB (いずれか、またはすべて) に適用できます。バージョンレベルの不変性が設定された BLOB の場合、BLOB の上書きは引き続き許可されますが、Azure により各 BLOB の不変バージョンが保持されます。いったん有効にすると、この設定は削除できません。この機能にはバージョン管理が必要であり、バージョンレベルのポリシーが設定されている間は、ストレージ アカウントでバージョン管理を無効にすることはできません。

うーむ、解読が少し難しいですね。私は以下の通り理解しています。
+ 設定をしておくと、ファイルの上書きが許可されるが、バージョン管理をしているのでいつでも前のバージョンの復元できる。
+ 使用するために、Storage Account作成時に「バージョン管理」を有効化しておく必要がある。

使い勝手次第といった感じですね。

<--- 2024/7/11追記 --->
本設定含めて、バージョン管理については以下記事にまとめました。
[記事のリンク](https://qiita.com/pienhalifax/items/c30b4ae2e360cbc633b0)
<--- ここまで ---->

### 1-5.「暗号化」タブ
今回は暗号化しないので、デフォルトでOKです。

### 1-6.「タグ」タブ
:sunny::sunny:　割愛　:sunny::sunny:

## 2. コンテナ(Blob)を作成する
コンテナ名を記載してこんな感じで作成してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/881f2785-13fc-3352-1346-96daa3e892ba.png)

## 3. コンテナ内のアクセスポリシーを設定する
作成したコンテナに対して、設定をしていきます。

### 3-1. ネットワーク設定
前項で内部ネットワークのみ許可しているので、踏み台環境からアクセスするか一時的に以下手順でクライアントからの接続を許可して下さい。（※設定は、自己責任でお願いします）
①セキュリティとネットワーク＞ファイアウォールへ移動
②「クライアントIPアドレスの追加」をチェック
③画面上部の保存をクリック

### 3-2. アクセスポリシーの設定
任意のコンテナへ移動し、アクセスポリシーの設定をしていきます。
下記の画面まで移動してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/55363c09-2569-8554-a2d6-1e945e392e6e.png)

不変BLOBストレージのポリシーの追加をクリックして、設定項目を入力していきます。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/45f39f56-2212-5e1c-db07-71c7c4bb2b7f.png">

今回は以下のような感じで設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/88b54d47-5f86-42b5-8ad6-8c0814918e10.png)

出来たら、こんな感じで一覧に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/217afc9f-a232-d443-ecdb-d62bbd24123d.png)

#### 補足：ポリシーの種類について
以下、２種類があります。
+ 訴訟ホールド：無期限で、保存したファイルの削除や更新ができなくなる設定。訴訟ホールドをクリアすれば、削除可能になる。基本的に法律上保管の必要なデータとかはこれでいいかもだが、慎重に考えてね。[ポリシーのクリア方法はこちら](https://learn.microsoft.com/ja-jp/azure/storage/blobs/immutable-policy-configure-version-scope?tabs=azure-portal)
+ 時間ベースの保持：保存してから一定の期間だけ削除や更新ができなくなる設定。基本はこれ使う。ロックをしない限りは、期間の延長や短縮が可能ですが設定の変更は5回まで

#### 補足：次に対する保護された追加書き込みを許可する
時間ベースの保持ポリシーでのみ設定可能な項目です。追加BLOBとブロックBLOBはそれだけで記事が書けてしまうので、ここでは割愛しますが気になる方は[こちらの記事](https://learn.microsoft.com/ja-jp/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs)を参照ください。
また、追加BLOBを議題に記事書いたらこちらにリンク載せておきます。

参考：[MS Learn：コンテナーの不変性ポリシーを構成する](https://learn.microsoft.com/ja-jp/azure/storage/blobs/immutable-policy-configure-container-scope?tabs=azure-portal)

## 4. 動作確認
それでは、設定ができたので動作確認をしていきます。
まずは、ファイル(test.txt)を格納してみます。
ファイルの格納ができました。⇒結果：OK(想定通り)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/9b3f62b4-1c34-f016-fb44-a8b9c002af68.png)

続いて、格納したファイルを削除してみます。
エラーが出ました。⇒結果：OK(想定通り)
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/886bae2e-392c-99eb-8713-1850af046036.png">

格納したファイルを更新してみます。
エラーが出ました。⇒結果：OK(想定通り)
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/919abf48-5355-daf4-9fe7-158bf964d662.png">

30日後・・・削除してみてください。

## 5. ロックのポリシーを有効化する
以上で動作確認ができたら、作成したポリシーを他のユーザーに変更されないようにロックをしていきます。「アクセスポリシー」の画面から、任意のポリシーの右側の「・・・」をクリックして、ロックのポリシーを選択。
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/91691303-e22d-6e17-06df-126b9af5d7e2.png">

出来たら、こんな感じで一覧の状態が変更されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/fa5b65df-6206-8775-fea3-c3c017b9a89d.png)

#### 補足：ロックされたポリシーについて
以下、設定のポイントとなります。設定前に読んでおいて下さい。
+ ロックすることで、ポリシーの削除、変更ができなくなります
+ 時間ベースのポリシーにおいては、期間の延長は出来すが短縮は出来ません
+ 保持間隔の有効期限が切れた後は BLOBストレージを削除できます。



参考：[MS Learn：BLOBデータの不変ストレージの概要](https://learn.microsoft.com/ja-jp/azure/storage/blobs/immutable-storage-overview) > 
ロックされたポリシーとロック解除されたポリシー

## まとめ
以上になります。もし疑問点や、記事の内容で議論したいこと、誤り等あればどんどんコメントを下さい！