ICOS Firewallを使ったアクセス制御

#1. ICOS Firewallとは
ICOS(IBM Cloud Object Storage)にFirewallがGAされました。ドキュメントは[こちら](https://cloud.ibm.com/docs/services/cloud-object-storage?topic=cloud-object-storage-setting-a-firewall#setting-a-firewall)。以下の特徴があります。

- 旧SoftLayerポータル(https://control.softlayer.com) から購入したICOSでは利用不可。https://cloud.ibm.com から購入したICOSでのみ利用可能。
- whitelist方式（指定したIP subnetからのアクセスのみを許し、それ以外からのアクセスは禁じる）。ICOS Firewallの設定がない場合は、全てのsubnetからのアクセスを許可します。
- IPv4/IPv6に対応
- bucketごとのルール指定
- 無償
- 設定にはIAMの`Manager`権限が必要
- Customer Portalから容易に設定可能

既知の制約として、もしIBM CloudのAsperaやSQL Queryなどのサービスまでも、（このwhitelistに列挙していない限りは）ブロックしてしまうことです。一般的にIBM Cloudのサービスの発信元IPアドレスは公開しておらず確認する方法がないため、「自社からのIPアドレス＋SQL Queryのみをアクセス許可する」といった使い方は難しいでしょう。サービス連携機能を高めるためには、引き続きの改善が待たれるところです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/fc960739-9a6a-54a5-4d45-e7fea715d064.png)


#2. 検証準備

ICOSのオブジェクトへのcurlでのアクセス方法は[ここ](https://cloud.ibm.com/docs/services/cloud-object-storage?topic=cloud-object-storage-using-curl-#using-curl-)を参照してください。

- Public Access
`curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/<bucket>/<object-key> -H "Authorization: bearer $ACCESS_TOKEN"`
- Private Access `curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/<bucket>/<object-key> -H "Authorization: bearer $ACCESS_TOKEN"`

IAM Tokenの取得方法は[ここ](https://qiita.com/testnin2/items/3a4ca8a1a2b79b713c48)を参照してください。 

#3. 検証

##3-1. Private NWからしかアクセスさせない

ICOS Firewallに10.0.0.0/8のみを登録し、IBM CloudにあるVSIからアクセスしてみます。(IBM CloudのVSIはPublic IPとしてGlobal IPを持ち、Private IPとして10.0.0.0/8上のIPを持っています）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/aa7d84ce-da85-ce36-5422-a4328f419b62.png)



```txt:PublicEndpoint経由でのアクセス（PublicIPを使ってアクセスするので失敗）
# curl https://s3.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><Resource>/mybucketxxx/index.html</Resource><RequestId>2deef42e-372b-46ef-abbb-6eaac9ab5cc1</RequestId><httpStatusCode>403</httpStatusCode></Error>
```

```txt:PrivateEndpoint経由でのアクセス（10.x.x.xのPrivateIPを使ってアクセスに成功）
# curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
Hello World
```

##3-2. 特定のPrivate IPからしかアクセスさせない

ICOS FirewallにIBM CloudにあるVSIのPrivate IPのみを指定し、それ以外のアドレスからのアクセスを禁じてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/0d9d4b41-773b-7167-0ad8-7dc234fa2820.png)


```txt:VSIからPublicEndpoint経由でのアクセス（PublicIPを使ってアクセスするので失敗）
# curl https://s3.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: beaCCESS_TOKEN"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><Resource>/mybucketxxx/index.html</Resource><RequestId>af382318-f8f6-440d-a6d3-c5ece5c9a8dc</RequestId><httpStatusCode>403</httpStatusCode></Error>
```

```txt:VSIからPrivateEndpoint経由でのアクセス（ICOSFirewallで指定したPrivateIPを使ってアクセスするので成功）
# curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
Hello World!
```

```txt:別のVSIからPrivateEndpoint経由でのアクセス（ICOSFirewallで指定していないPrivateを使ってアクセスするので失敗）
# curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><Resource>/mybucketxxx/index.html</Resource><RequestId>a17f2ce6-5a8f-4008-8a38-605c22fb83f0</RequestId><httpStatusCode>403</httpStatusCode></Error>
```

##3-3. 特定のGlobal IP(Public IP)からしかアクセスさせない

今回のテストに利用したIBM Cloud上のVSIのIPアドレスはAA.AA.AA.AAであったため、これをwhitelistに追加します。その他のIPアドレスからのアクセスは禁じます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/7a5f5155-f0c8-4fd8-2ef1-aa4078428735.png)

```txt:VSIからPublicEndpoint経由でのアクセス（ICOSFirewallで指定したPublicIPを使ってアクセスするので成功）
# curl https://s3.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
Hello World
```

```txt:VSIからPrivateEndpoint経由でのアクセス（ICOSFirewallにPrivateIPを登録していないので失敗）
# curl https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><Resource>/mybucketxxx/index.html</Resource><RequestId>1e347877-a4a8-42b1-9768-3432dc0718eb</RequestId><httpStatusCode>403</httpStatusCode></Error>
```

```txt:VSI以外のサーバーからPublicEndpoint経由でのアクセス（ICOSFirewallに登録したPublicIPを利用していないので失敗）
# # curl https://s3.jp-tok.cloud-object-storage.appdomain.cloud/mybucketxxx/index.html -H "Authorization: bearer $ACCESS_TOKEN"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><Resource>/mybucketxxx/index.html</Resource><RequestId>c90d9189-6010-4ab2-87f1-17d0e78af988</RequestId><httpStatusCode>403</httpStatusCode></Error>
```