💂

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

に公開

概要

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

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

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

制限

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

  1. 使えるロケーションが限定的: 東京リージョン( asia-northeast1 )ではまだ使うことができません
  2. terraformで管理ができない: 当面はgcloudコマンドを使うことになると思います
  3. コンソールで管理ができない: 当面はgcloudコマンドを(ry

これらの課題は徐々に解決していくと思われます。

追記: 2025年3月25日現在、東京リージョンでも当該機能が利用できることを確認しました。ドキュメント からも "Supported locations" の項目が無くなっています。リリースノートに記載がなく、正確にいつから使えるようになったのかは分かりませんが、少なくとも 2025-01-26 以降と思われます。

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

  • オブジェクトへのアクセスだけでなく、管理操作全般にまでIPアドレス制限がかかる( バイパス方法あり )
  • 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アドレス範囲}"]
  }
}

許可するIPアドレス範囲にはLBの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経由でアクセスした時はオブジェクトにアクセス可能でした。

まとめ

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

最初、LBのIPアドレスを許可する必要があり、LBを経由すると全てのアクセスが素通りしてしまうのかとも思ったのですが、ちゃんとクライアントのIPアドレスを尊重してくれるようで安心しました。

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

Discussion