【AWS】S3バケットにHTTPSではなくHTTPでアクセスする方法

**タイトルは間違いではありません。**
本記事では、S3バケットに **HTTPSではなくHTTPで** アクセスする方法を解説します。

# なぜ、HTTPでアクセスする必要があるのか

想定するケースは以下の2つです。

**1. バケットポリシーの設定を誤ってHTTPSによるアクセスができない状態になってしまった**
　→誤設定によるトラブルシューティングを想定しています。

**2. HTTPではアクセスできないことを確認したい**
　→主にテストで必要になることを想定しています。

詳細は後述しますが、まずは結論から。


# 結論（解決方法）

S3バケットにHTTPでアクセスするには **AWS CLIの--endpoint-urlオプションを用いてHTTPエンドポイントを指定します。**


## 1. バケットポリシーの設定を誤ってHTTPSによるアクセスができない状態になってしまった

以下のコマンドを実行し、誤って設定したバケットポリシーを削除します。
ポイントは **--endpoint-urlオプションでHTTPエンドポイントを指定** している点です。

```
aws s3api delete-bucket-policy --bucket "バケット名" --endpoint-url "http://s3.ap-northeast-1.amazonaws.com"
```

## 2. HTTPではアクセスできないことを確認したい

以下のコマンドを実行し、アクセスできないこと（AccessDeniedになること）を確認します。
やはり、ポイントは **--endpoint-urlオプションでHTTPエンドポイントを指定** している点です。

```
$ aws s3api get-bucket-policy --bucket "バケット名" --endpoint-url "http://s3.ap-northeast-1.amazonaws.com"

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


# 詳細解説

ここからは詳細を解説していきます。

まず、HTTPによるアクセスが必要なケースとして想定したのは以下の2つです。

**1. バケットポリシーの設定を誤ってHTTPSによるアクセスができない状態になってしまった**
**2. HTTPではアクセスできないことを確認したい**

これらのケースは、いずれも **S3バケットへのアクセスをHTTPSに限定したい** という背景があります。


## なぜ、S3バケットへのアクセスをHTTPSに限定するのか

HTTPよりもHTTPSの方がセキュリティ的に優れていることは説明不要でしょう。

[**S3のセキュリティのベストプラクティス**](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/security-best-practices.html) にも以下の記載があり、S3バケットへのアクセスはHTTPSに限定することが推奨されています。

> **送信時のデータの暗号化を強制する**
HTTPS (TLS) を使用すると、潜在的な攻撃者が中間者攻撃または同様の攻撃を使用してネットワークトラフィックを盗聴または操作することを防止できます。Amazon S3 バケットポリシーで aws:SecureTransport 条件を使用して、HTTPS (TLS) を介した暗号化接続のみを許可してください。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/security-best-practices.html


## S3バケットへのアクセスをHTTPSに限定する方法

S3バケットへのアクセスをHTTPSに限定するには、以下のバケットポリシーを設定します。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RestrictToTLSRequestsOnly",
            "Action": "s3:*",
            "Effect": "Deny",
            "Resource": [
                "arn:aws:s3:::バケット名",
                "arn:aws:s3:::バケット名/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            },
            "Principal": "*"
        }
    ]
}
```

**aws:SecureTransport** は、HTTPSによるリクエストの場合は **true** を返し、HTTPによるリクエストの場合は **false** を返します。
この条件を利用して、HTTPによるS3バケットおよびオブジェクトへのアクセスを拒否する設定としたものが上記のバケットポリシーです。

なお、この設定は [**S3のユーザーガイド**](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-HTTP-HTTPS) にも記載されています。

> **HTTPS リクエストのみにアクセスを制限**
潜在的な攻撃者がネットワークトラフィックを操作するのを防ぎたい場合は、HTTPS (TLS) を使用して暗号化された接続のみを許可し、HTTP リクエストによるバケットへのアクセスを制限できます。リクエストが HTTP か HTTPS かを判断するには、S3 バケットポリシーの aws:SecureTransport グローバル条件キーを使用します。aws:SecureTransport 条件キーは、リクエストが HTTP を使用して送信されたかどうかをチェックします。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-HTTP-HTTPS


## AWS CLIの--endpoint-urlオプションについて

AWS CLIのエンドポイントURLは、選択したサービスとリージョンに基づいて自動的に決定されるため、通常は指定する必要がありません。

エンドポイントURLは以下の形式です。

```text:エンドポイントURL形式
protocol://service-code.region-code.amazonaws.com
```

例えば、東京リージョンのS3のエンドポイントURLは以下になります。

```text:HTTPSの場合
https://s3.ap-northeast-1.amazonaws.com
```

```text:HTTPの場合
http://s3.ap-northeast-1.amazonaws.com
```

AWS CLIの **--endpoint-urlオプション** は、今回のように明示的にエンドポイントURLを指定する必要がある場合に使用します。

> **--endpoint-url \<string\>**
リクエストを送信する URL を指定します。ほとんどのコマンドでは、AWS CLI により、選択したサービスと AWS リージョンに基づいて URL が自動的に決定されます。ただし、一部のコマンドでは、アカウント固有の URL を指定する必要があります。一部の AWS サービスでは、プライベート VPC 内で直接エンドポイントをホストすることもできますが、URL を指定する必要がある場合があります。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-options.html


## ケーススタディ

ここからは想定した2つのケースを解説していきます。

### 1. バケットポリシーの設定を誤ってHTTPSによるアクセスができない状態になってしまった

このケースは、S3バケットへのアクセスをHTTPSに限定しようとして、前述のバケットポリシーを設定する際に、**aws:SecureTransport の値を誤って（もしくは好奇心から） true に設定してしまった** という状況を想定しています。

```
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "true"
                }
            },
```

このポリシーを設定すると、S3バケットへのHTTPSによるアクセスができない状態になります。

慌ててバケットポリシーを修正または削除しようとしても、**マネジメントコンソールやCLIはデフォルトでHTTPSを使用するため、そのリクエスト自体が拒否され**、以下の状態になります。

* **マネジメントコンソール**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2443303/b08d78c7-98a9-da61-2dbc-072912e0874d.png)

* **CLI**
```
$ aws s3api delete-bucket-policy --bucket "バケット名"

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

:::note info
余談
この状況は、解決方法を知らないと、バケットに対するすべての操作が拒否される状態なので焦ります。実際にこの状況になってしまった人から相談を受けたこともありますが、かなり焦っていました。
そのような人を見かけたら、優しく解決方法（本記事）を教えてあげてください。笑
:::

解決方法は、前述のとおり、**AWS CLIの--endpoint-urlオプションを用いてHTTPエンドポイントを指定し**、バケットポリシーを修正または削除します。

### 2. HTTPではアクセスできないことを確認したい

このケースは、[**S3のセキュリティのベストプラクティス**](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/security-best-practices.html) に従い、S3バケットへのアクセスをHTTPSに限定していることの確認が必要な状況を想定しています。
例えば、サービスやプロダクトのテストにおいて、HTTPによるアクセスが拒否されることの確認が求められている場合等です。

この場合、前述のとおり、**AWS CLIの--endpoint-urlオプションを用いてHTTPエンドポイントを指定し**、そのリクエストが拒否されること（AccessDeniedになること）で確認できます。

```
$ aws s3api get-bucket-policy --bucket "バケット名" --endpoint-url "http://s3.ap-northeast-1.amazonaws.com"

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


# 応用：TLSバージョンの指定

応用として、**s3:TlsVersion 条件キー** を使用することにより、TLSバージョンによる制御も可能です。
詳細は以下の [**S3のユーザーガイド**](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/amazon-s3-policy-keys.html#example-object-tls-version) を参照してください。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/amazon-s3-policy-keys.html#example-object-tls-version


# まとめ

:::note info
**AWS CLIの--endpoint-urlオプションを用いてHTTPエンドポイントを指定することにより、S3バケットにHTTPでアクセスすることができます。**
:::

最後まで読んでいただき、ありがとうございます。
この記事が少しでも役に立てば幸いです。

いいねやストックしていただけると励みになります。