ONTAPのSecurity機能について12【ONTAP S3のSecurity機能(S3 Snapshot / S3 object lock)】

## はじめに
前回の[記事](https://qiita.com/s_yosh1d/items/fc72dcf99945b8b5c8a9)で、ONTAP S3の構築手順とバージョニング機能について紹介しましたが、実はONTAP S3には他にも便利な機能が他にもあります。
今回はその中でも**特にSecurity機能である「S3 Snapshot」,「S3 object lock」について記載**します。
これらの機能を活用すると、データを効率的で安全に管理する事が可能になります。

なお、ONTAP S3の機能である**S3 multiprotocolについては、弊社の[井上の記事](https://qiita.com/koheiinoue/items/78b885e644601afd5812)と[清水の記事](https://qiita.com/yshimizu22/items/a6fb736dcfb22ac8f7dd)を参照**頂ければと思います。

<img width="650" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/36e74549-5d28-1566-314d-e7848af6cc40.png>



## ONTAP S3における主要な機能について
ONTAPのversionに依存しますが、ONATP S3の主要機能としては以下の通りです。

|ONTAP S3における主要機能|ONTAP Version|説明  |
|---|---|---|
|Cross-Origin Resource Sharing（CORS）との統合|9.16.1|異なるドメインのクライアントWebアプリがONTAP Bucketにアクセス可能 |
|MultipartUpload|9.16.1|大きなObjectを小さなパートとしてアップロード |
|**S3 Snapshot**|9.16.1|Bucketの静的イメージの作成|
|AD/LDAP利用|9.14.1|権限設定の際にAD/LDAPグループをプリンシパルとして使用可能 |
|**S3 object lock**|9.14.1|Objectに対するWORM(Write Once Read Many)機能 |
|Bucket Lifecycle |9.13.1|Bucket内の特定Objectに対し保持ポリシーの作成|
|S3 multiprotocol |9.12.1|S3クライアントによるNASデータへのアクセス |
|Bucket Versioning |9.11.1|Objectの複数のバージョンを保持  |
|S3 Audit|9.10.1|Objectアクセスインベント、管理イベントの記録 |



## 何をしたい？できる？
- **S3 Snapshotを作成し、SnapshotへのアクセスやObjectのリストア**を実施する
- **S3 object lockを有効化し、Objectが削除から保護される事**を確認

## 記事における環境情報
本記事では、以下の環境で実施した内容となります。
- Red Hat Enterprise Linux  : 8.10
- ONTAP  : 9.16.1

環境のイメージとしては以下の通りです。
<img width="400" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/2ce41893-92af-e0f6-dcdb-c87408ee4ffb.png>


## 実施手順

本記事では、**ONTAP S3の機能確認が主要な目的の為、S3アクセスを設定する際はHTTPアクセスを有効化します。**(手順を減らす)



### 1. S3 Snapshotの確認

S3 Snapshotは、**ONTAP9.16.1以降で利用可能**な機能であり、**Bucketの静的イメージを作成**します。

<img width="500" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/fc35f9d2-3242-9e44-6990-ce9a1cb568a2.png>



S3 Snapshotの利用にあたって、以下の制限を確認しておく必要があります。
- S3バケットに対して最大Snapshot世代は1023
- ONTAP9.16.1より前のONTAに戻す場合、全Bucketから全てのS3 Snapshot削除が必要
- S3 Bucket自体の削除時には、対応するSnapshotも削除していることを確認

また、**以下の構成ではS3 Snapshotはサポートされません。**
- SnapMirror関係のBucket
- S3 object lockが有効なBucket
- NetApp BlueXPからの操作
- System Managerからの操作
- ONTAP MetroCluster構成

**本記事では、S3用のSVMを作成後、S3アクセスできるような設定を実施後の状態となってます。**

#### 1-1. 現状構成の確認
S3 object lockが有効なBucketではSnapshot作成はサポートされていないので、object lockが無効である事を確認します。
また、**objectの有無を分かり易くする為に、Snapshotの機能確認ではVersioningは無効化して確認**します。
```bash:
# object-storeの設定確認
> vserver object-store-server show -vserver s3_test

Vserver: s3_test
             Object Store Server Name: s3_test.demo.netapp.com
                 Administrative State: up
                         HTTP Enabled: true
               Listener Port For HTTP: 80
                        HTTPS Enabled: false
       Secure Listener Port For HTTPS: 443
    Certificate for HTTPS Connections: -
                    Default UNIX User: pcuser
                 Default Windows User: -
             is-ldap-fastbind-enabled: true
            Maximum Value for Key TTL: -
 Maximum Object Lock Retention Period: none
 Minimum Object Lock Retention Period: none
                              Comment:

                  
# object lockの無効化確認
> vserver object-store-server bucket show -vserver s3_test -instance

Vserver: s3_test
  Bucket                               :bk001
  Type                                 :s3
  Versioning                           :disabled
  Uuid                                 :5babac6a-bb5c-11ef-8021-005056b7acc1
  Volume                               :fg_oss_1734319067
  Size                                 :10GB
  Logical Used Size                    :0B
  Object Count                         :0
  Incomplete Multipart Uploads count   :0
  Encryption                           :false
  Comment                              :
  Qos Policy Group                     :-
  Role                                 :standalone
  Bucket Protected                     :false
  Bucket Protected On ONTAP            :false
  Bucket Protected On Cloud            :false
  Bucket Protected on External Cloud   :false
  NAS Path                             :-
  Object Lock Retention Mode           :no-lock
  Object Lock Default Retention Period :-

```

#### 1-2. S3へObjectのUpload

Linux側からaws cliを使って、作成したBacketへフォルダを作成しObjectをuploadします。
```bash:
# フォルダ作成
> aws --endpoint-url  http://192.168.0.161/ s3api put-object --bucket bk001 --key "dir01/"
{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\""
}


# ObjectのUpload
>  aws --endpoint-url  http://192.168.0.161/ s3 cp file01.txt s3://bk001/dir01/
upload: ./file01.txt to s3://bk001/dir01/file01.txt

>  aws --endpoint-url  http://192.168.0.161/ s3 cp file02.txt s3://bk001/dir01/
upload: ./file02.txt to s3://bk001/dir01/file02.txt


# Objectの一覧確認
>  aws --endpoint-url  http://192.168.0.161/ s3 ls s3://bk001/dir01/
2024-12-15 22:37:56          0
2024-12-15 22:41:04         29 file01.txt
2024-12-15 22:41:10         29 file02.txt
```

#### 1-3. Snapshotの取得

**ここではスケジュール化してのSnapshotではなく、手動でSnapshotの取得**を実施します。
スケジュール化が必要な場合には、vserver object-store-server bucket  modify -bucket <backet名> -snapshot-policy <Policy名>といった形で設定を実施します。

<font color="Red">**作成したSnapshotは、[元となるbacket名]-s3snap-[Snapshot名] を指定する事で、Backetとしての確認ができます。**</font>
<img width="500" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/bef0eca8-c64d-6319-c3c6-317b70b8677a.png>

```bash:
# Snapshotの作成
> vserver object-store-server bucket snapshot create -bucket bk001 -snapshot snap001
[Job 91] Job succeeded: Successful


# Snapshotの一覧確認
> vserver object-store-server bucket snapshot show -bucket bk001
Vserver  Bucket     Snapshot                          Create Time
-------- ---------- --------------------------------- ------------------------
s3_test  bk001      snap001                           Mon Dec 16 03:46:36 2024


# Snapshot領域の確認
> aws --endpoint-url  http://192.168.0.161/ s3 ls s3://bk001-s3snap-snap001/dir01/
2024-12-15 22:37:56          0
2024-12-15 22:41:04         29 file01.txt
2024-12-15 22:41:10         29 file02.txt
```


#### 1-4. Objectを削除し、SnapShotからのリストアを実施
まず、LinuxからBacketに対してfile01.txtというObjectの削除を実施します。
```bash:
# Objectの削除
> aws --endpoint-url  http://192.168.0.161/ s3 rm s3://bk001/dir01/file01.txt
delete: s3://bk001/dir01/file01.txt


# 一覧の確認
> aws --endpoint-url  http://192.168.0.161/ s3 ls s3://bk001/dir01/
2024-12-15 22:37:56          0
2024-12-15 22:41:10         29 file02.txt
```
次にSnapshot Bucketからのコピーを利用したRestoreを実施します。
(Object単位の指定でも可能です)

<img width="500" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/a4fdc7d2-76cf-5d6a-b75f-089dc38c05d2.png>


```bash:


# リストアの実施
> aws --endpoint-url  http://192.168.0.161/ s3 cp s3://bk001-s3snap-snap001/ s3://bk001/ --recursive
copy: s3://bk001-s3snap-snap001/dir01/file02.txt to s3://bk001/dir01/file02.txt
copy: s3://bk001-s3snap-snap001/dir01/file01.txt to s3://bk001/dir01/file01.txt


# 一覧の確認
> aws --endpoint-url  http://192.168.0.161/ s3 ls s3://bk001/dir01/
2024-12-15 22:37:56          0
2024-12-15 23:10:08         29 file01.txt
2024-12-15 23:10:08         29 file02.txt
```



### 2. S3 Object Lockの実施
ONTAP 9.14.1から、**S3 Object Lockを使用する事でBucket内のObjectを保護/消去不能/書き換え不可とする事が可能**です。

<img width="500" alt="qiita-square" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/857308c9-7208-7bfb-ebe9-47f58530aee3.png>


**利用にあたっての前提条件は以下の通り**です。
- SnapLockライセンスが適用されている
- Clusterのコンプライアンスクロックが初期化されている

Retention Modeとしては、以下のどちらかを利用できますが、[マニュアル](https://docs.netapp.com/us-en/ontap/s3-config/ontap-s3-supported-actions-reference.html#user-management)にLegal hold operations (locks without defined retention times) are not supported.の記載があるように**Legal Holdは未サポート**となります。

**■ Governance**
- SnapLock Enterpriseと同様に、Clientは特定の保持期間にわたってObjectをWORM状態にコミット
- Objectを削除できるのは、s3：BypassGovernanceRetentionの使用を許可されているユーザ

**■ Compliance**
- SnapLock Complianceと同様に、クライアントは特定の保持期間にわたってObjectをWORM状態にコミット
- 保持期限が切れるまでは、s3：BypassGovernanceRetentionの使用を許可されているユーザであってもObjectを削除できない

#### 2-1. License確認とコンプライアンスクロック初期化
Licenseの確認とコンプライアンスクロックの初期化を実施します。

```bash:
# Licenseの確認
> license show -package SnapLock
  (system license show)

Serial Number: 000000000072
Owner: cluster2-01
Installed License: Labs On Demand ONTAP Bundle
Capacity: -
Package           Type     Description           Expiration          CustomerID
----------------- -------- --------------------- ------------------- ----------
SnapLock          enabled  SnapLock License      -                   none

Serial Number: 000000000073
Owner: cluster2-02
Installed License: Labs On Demand ONTAP Bundle
Capacity: -
Package           Type     Description           Expiration          CustomerID
----------------- -------- --------------------- ------------------- ----------
SnapLock          enabled  SnapLock License      -                   none
2 entries were displayed.



# コンプライアンスクロックが初期化
> snaplock compliance-clock initialize -node *

Warning: You are about to initialize the secure ComplianceClock of the node "cluster2-01" to the current value of the node's
         system clock. ComplianceClock re-initialization requires all nodes in the cluster to be healthy, all volumes are in
         online state, no volumes are present in the volume recovery queue and there are no SnapLock volumes or volumes with
         "snapshot-locking-enabled" set to true or S3 buckets with object locking enabled. Ensure that the system time is set
         correctly before proceeding. The current node's system clock is: Mon Dec 16 18:05:19 JST 2024

Do you want to continue? {y|n}: y

Warning: You are about to initialize the secure ComplianceClock of the node "cluster2-02" to the current value of the node's
         system clock. ComplianceClock re-initialization requires all nodes in the cluster to be healthy, all volumes are in
         online state, no volumes are present in the volume recovery queue and there are no SnapLock volumes or volumes with
         "snapshot-locking-enabled" set to true or S3 buckets with object locking enabled. Ensure that the system time is set
         correctly before proceeding. The current node's system clock is: Mon Dec 16 18:05:20 JST 2024

Do you want to continue? {y|n}: y
2 entries were acted on.
```

#### 2-2. WORMが有効化されているBacket作成

本記事では、**ObjectのVersion削除ができない事を確認する為、WORMの有効化/無効化されているBacketをそれぞれ作成し、同じaws cli操作を実施して比較**を行います。

また、**s3：BypassGovernanceRetention権限のあるユーザで削除できない事を確認する為、Complianceモード**を使用します。

WORM機能を有効化したBacket作成を行うと合わせてVersioningも有効化されます。
```bash:
> set advanced

Warning: These advanced commands are potentially dangerous; use them only when directed to do so by NetApp personnel.
Do you want to continue? {y|n}: y

# WORMの無効化されているBacket作成(Versioningは有効化)
*> vserver object-store-server bucket create -vserver s3_test -bucket no-lock100 -aggr-list aggr1_node1,aggr1_node2 -size 10g -versioning-state enabled


# WORMの有効化されているBacket作成(保持期間は1日設定)
*> vserver object-store-server bucket create -vserver s3_test -bucket lock100 -aggr-list aggr1_node1,aggr1_node2 -size 10g -retention-mode compliance -default-retention-period 1days

Warning: Creating an S3-bucket with "-retention-mode" set to "compliance" or "governance" enables versioning.
Do you want to continue? {y|n}: y
```


#### 2-3. Bucketへの権限設定
作成したBucketへの権限を設定します。
Complianceモードの動作を確認する為、WORMの有効化されているBacket向けにはBypassGovernanceRetentionを含めて設定します。

```bash:
# WORMの無効化されているBacket向けの権限設定
*> object-store-server bucket policy statement create  -bucket no-lock100 -effect allow -action GetObject,PutObject,DeleteObject,ListBucket,GetBucketAcl,GetObjectAcl,ListBucketMultipartUploads,ListMultipartUploadParts,GetObjectTagging,PutObjectTagging,DeleteObjectTagging,GetBucketLocation,GetBucketVersioning,PutBucketVersioning,ListBucketVersions,GetBucketPolicy,PutBucketPolicy,DeleteBucketPolicy -vserver s3_test -resource no-lock100,no-lock100/*

# WORMの有効化されているBacket向けの権限設定
*> object-store-server bucket policy statement create  -bucket lock100 -effect allow -action GetObject,PutObject,DeleteObject,ListBucket,GetBucketAcl,GetObjectAcl,ListBucketMultipartUploads,ListMultipartUploadParts,GetObjectTagging,PutObjectTagging,DeleteObjectTagging,GetBucketLocation,GetBucketVersioning,PutBucketVersioning,ListBucketVersions,GetBucketPolicy,PutBucketPolicy,DeleteBucketPolicy,PutLifecycleConfiguration,GetLifecycleConfiguration,GetObjectRetention,PutObjectRetention,BypassGovernanceRetention,PutBucketObjectLockConfiguration,GetBucketObjectLockConfiguration -vserver s3_test -resource lock100,lock100/*
```

#### 2-4. S3クライアントからObjectのUpload

まずはそれぞれのBacketに同じObjectのUploadを実施します。
```bash:
# WORMの無効化されているBacket向けのUpload
> aws --endpoint-url  http://192.168.0.161/ s3 cp file01.txt s3://no-lock100/
upload: ./file01.txt to s3://no-lock100/file01.txt


# WORMの有効化されているBacket向けのUpload
> aws --endpoint-url  http://192.168.0.161/ s3 cp file01.txt s3://lock100/
upload: ./file01.txt to s3://lock100/file01.txt
```
Object削除時に必要となるVersion IDの確認を実施します。

```bash:
# WORMの無効化されているBacketのObject確認
>  aws --endpoint-url  http://192.168.0.161/ s3api head-object --bucket no-lock100 --key file01.txt
{
    "AcceptRanges": "bytes",
    "LastModified": "Mon, 16 Dec 2024 13:59:12 GMT",
    "ContentLength": 29,
    "ETag": "\"fd1998095b101d65fa6bf8ed441c1b86\"",
    "VersionId": "OTY0MTIwMDAwLnYxLjIuMTczNDM1NzU1Mi4u",　　＜＝＝削除操作対象
    "ContentType": "text/plain",
    "Metadata": {}


# WORMの有効化されているBacketのObject確認
>  aws --endpoint-url  http://192.168.0.161/ s3api head-object --bucket lock100 --key file01.txt
{
    "AcceptRanges": "bytes",
    "LastModified": "Mon, 16 Dec 2024 13:59:19 GMT",
    "ContentLength": 29,
    "ETag": "\"fd1998095b101d65fa6bf8ed441c1b86\"",
    "VersionId": "ODM0MDI2MDAwLnYxLjIuMTczNDM1NzU1OS4u",　　＜＝＝削除操作対象
    "ContentType": "text/plain",
    "Metadata": {},
    "ObjectLockMode": "COMPLIANCE",
    "ObjectLockRetainUntilDate": "2024-12-17T13:59:19.000Z"
```

#### 2-5. BacketのObjectのVersionを生成する為、更新ObjectのUpload

```bash:
# Objectを更新
> date >>file01.txt

# WORMの無効化されているBacket向けの再Upload
> aws --endpoint-url  http://192.168.0.161/ s3 cp file01.txt s3://no-lock100/
upload: ./file01.txt to s3://no-lock100/file01.txt


# WORMの有効化されているBacket向けの再Upload
> aws --endpoint-url  http://192.168.0.161/ s3 cp file01.txt s3://lock100/
upload: ./file01.txt to s3://lock100/file01.txt
```

削除対象となる、LatestではないObjectがある事を確認します。
```bash:
# Objectを更新
> date >>file01.txt

# WORMの無効化されているのObject確認
> aws --endpoint-url  http://192.168.0.161/ s3api list-object-versions --bucket no-lock100
{
    "Versions": [
        {
            "ETag": "dad4795d05c3b927e782d50449071747",
            "Size": 58,
            "StorageClass": "STANDARD",
            "Key": "file01.txt",
            "VersionId": "MzM0MzA0MDAwLnYxLjIuMTczNDM1Nzc0Mi4u",
            "IsLatest": true,
            "LastModified": "2024-12-16T14:02:22.334Z"
        },
        {
            "ETag": "fd1998095b101d65fa6bf8ed441c1b86",
            "Size": 29,
            "StorageClass": "STANDARD",
            "Key": "file01.txt",
            "VersionId": "OTY0MTIwMDAwLnYxLjIuMTczNDM1NzU1Mi4u",
            "IsLatest": false,
            "LastModified": "2024-12-16T13:59:12.964Z"
        }
    ]
}


# WORMの有効化されているBacketのObject確認
> aws --endpoint-url  http://192.168.0.161/ s3api list-object-versions --bucket lock100
{
    "Versions": [
        {
            "ETag": "dad4795d05c3b927e782d50449071747",
            "Size": 58,
            "StorageClass": "STANDARD",
            "Key": "file01.txt",
            "VersionId": "NTQ0MjMzMDAwLnYxLjIuMTczNDM1Nzc0Ny4u",
            "IsLatest": true,
            "LastModified": "2024-12-16T14:02:27.544Z"
        },
        {
            "ETag": "fd1998095b101d65fa6bf8ed441c1b86",
            "Size": 29,
            "StorageClass": "STANDARD",
            "Key": "file01.txt",
            "VersionId": "ODM0MDI2MDAwLnYxLjIuMTczNDM1NzU1OS4u",
            "IsLatest": false,
            "LastModified": "2024-12-16T13:59:19.834Z"
        }
    ]
}
```

#### 2-6. Backetの最新では無いObjectを削除
ObjectをVersion指定で削除し、 **WORM無効のBacketでは削除が成功する**事を確認します。


```bash:
# WORMの無効化されているBacketでは削除成功 
> aws --endpoint-url  http://192.168.0.161/ s3api delete-object --bucket no-lock100 --key file01.txt --version-id OTY0MTIwMDAwLnYxLjIuMTczNDM1NzU1Mi4u

{
    "VersionId": "OTY0MTIwMDAwLnYxLjIuMTczNDM1NzU1Mi4u"
}

# 削除されている事を確認
>  aws --endpoint-url  http://192.168.0.161/ s3api list-object-versions --bucket no-lock100                                     {
    "Versions": [
        {
            "ETag": "dad4795d05c3b927e782d50449071747",
            "Size": 58,
            "StorageClass": "STANDARD",
            "Key": "file01.txt",
            "VersionId": "MzM0MzA0MDAwLnYxLjIuMTczNDM1Nzc0Mi4u",
            "IsLatest": true,
            "LastModified": "2024-12-16T14:02:22.334Z"
        }
    ]
}

```

**WORMの有効化されているBacketでは失敗する事(保護されている事)を確認**します。
(本記事では保持期間1日設定なので、翌日には削除できます)
```bash:
> aws --endpoint-url  http://192.168.0.161/ s3api delete-object --bucket lock100 --key file01.txt --version-id ODM0MDI2MDAwLnYxLjIuMTczNDM1NzU1OS4u

An error occurred (AccessDenied) when calling the DeleteObject operation: Access Denied
```

## 参考及びリンク
[ONTAP 9.16.1の新機能](https://docs.netapp.com/ja-jp/ontap/release-notes/whats-new-9161.html#%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF)

[S3 Snapshotの概要](https://docs.netapp.com/ja-jp/ontap/s3-snapshots/index.html)

[Create an ONTAP S3 bucket](https://docs.netapp.com/us-en/ontap/s3-config/create-bucket-task.html#create-s3-buckets-with-the-ontap-cli)

[S3 in ONTAP best practices](https://www.netapp.com/media/17219-tr4814.pdf)

[【今から覚えるONTAPの操作】オブジェクトストレージ 用のSVMを作成する](https://qiita.com/s_yosh1d/items/fc72dcf99945b8b5c8a9)