💂

Cloud Storage BucketにIPアドレス制限をかける + LB経由でアクセスしてみる

2024/12/18に公開

概要

2024年11月14日Bucket IP filtering がPreview機能として利用可能になりました。

簡単に説明すると、バケットにIPアドレス制限をかけられるという機能です。

今回はこの機能とLBを組み合わせた時の動作を試した時の記録になります。
まだPreview機能なので将来動作が変わる可能性があることにご注意ください。

制限

2024年12月18日時点でまだPreview機能であり、リリースから日が浅いこともあり実践投入するには課題となりそうな点がいくつか見られました。

  1. 使えるロケーションが限定的: 東京リージョン( asia-northeast1 )ではまだ使うことができません
  2. terraformで管理ができない: 当面はgcloudコマンドを使うことになると思います
  3. コンソールで管理ができない: 当面はgcloudコマンドを(ry
  4. オブジェクトへのアクセスだけでなく、管理操作全般にまでIPアドレス制限がかかる( バイパス方法あり )

これらの課題は徐々に解決していくと思われます。( 4については変わらない気もします )

また、課題というほどではないですが気になった点として以下があります。

  • IPアドレス制限をバイパスする方法はあるが、そのためにはカスタムロールを作成する必要がある

バイパスに関してはまだ検証を行っていないため、これ以上の言及はできません。( 今後検証します )

構築

IP制限の設定以外はterraformでガッと作ります。
リソース名は適当です。
なお、以下のコードは検証に使ったコードとは異なります。間違っているかもしれないのでイメージ程度に捉えてください。

resource "google_storage_bucket" "default" {
  name     = var.bucket_name
  location = "asia-east1" # 台湾リージョンでは利用可能
}

# storage objectのread権限が必要
resource "google_storage_bucket_iam_member" "default" {
  bucket = google_storage_bucket.default.name
  role   = "roles/storage.legacyObjectReader"
  member = "allUsers"
}

resource "google_compute_global_address" "default" {
  name = "test"
}

# --- Certificate Map ---
resource "google_certificate_manager_dns_authorization" "default" {
  name   = "test"
  domain = var.domain
}

resource "google_certificate_manager_certificate" "default" {
  name = "test"

  managed {
    domains            = [var.domain]
    dns_authorizations = [google_certificate_manager_dns_authorization.default.id]
  }
}

resource "google_certificate_manager_certificate_map" "default" {
  name = "test"
}

resource "google_certificate_manager_certificate_map_entry" "default" {
  name         = "test"
  map          = google_certificate_manager_certificate_map.default.name
  hostname     = var.domain
  certificates = [google_certificate_manager_certificate.default.id]
}
# ---

# --- LB ---
resource "google_compute_backend_bucket" "default" {
  name        = "test"
  bucket_name = google_storage_bucket.default.name
}

resource "google_compute_url_map" "default" {
  name            = "test"
  default_service = google_compute_backend_bucket.default.id
}

resource "google_compute_target_https_proxy" "default" {
  name            = "test"
  url_map         = google_compute_url_map.default.id
  certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.default.id}"
}

resource "google_compute_global_forwarding_rule" "default" {
  name                  = "test"
  ip_address            = google_compute_global_address.default.id
  ip_protocol           = "TCP"
  load_balancing_scheme = "EXTERNAL_MANAGED"
  port_range            = "443"
  target                = google_compute_target_https_proxy.default.id
}
# ---

IPフィルタリングの設定をします。

ip-filter.json

{
  "mode": "Enabled",
  "publicNetworkSource": {
    "allowedIpCidrRanges": ["{許可するIPアドレス範囲}"]
  }
}
$ gcloud alpha storage buckets update gs://${bucket_name} --ip-filter-file=ip-filter.json

動作確認

許可していないIPアドレスからオブジェクトに直接アクセス

許可していないIPアドレスから、公開URL( https://storage.googleapis.com/~~~ )でアクセスすると以下のエラーになりました。

<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
<Details>
There is an IP filtering condition that is preventing access to the resource.
</Details>
</Error>

許可しているIPアドレスからオブジェクトに直接アクセス

許可しているIPアドレスから、公開URLでアクセスした時はオブジェクトにアクセス可能でした。

許可していないIPアドレスからLB経由でアクセス

許可していないIPアドレスから、設定したドメインを指定してLB経由でオブジェクトにアクセスすると以下のエラーになりました。
直接アクセスした時と微妙に違うエラーですね。

<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
</Error>

許可しているIPアドレスからLB経由でアクセス

許可しているIPアドレスからLB経由でアクセスした時はオブジェクトにアクセス可能でした。
最初、明示的にLBのIPアドレスを許可しないといけないのかと思ったのですがどうやらクライアントのIPアドレスを尊重してくれるようです。

まとめ

新しくリリースされたBucket IP filteringによって、バケットにIPアドレス制限をかけることができました。
LBを経由するパターンでも問題なく動作していそうです。

バケットにIPアドレス制限をかけたいというリクエスト は7年以上前から挙がっていましたが、遂に実現しましたね。

Discussion