gcsのip filterを使って特定IPからのアクセスのみ許可する


| 6 min read | engineering gcp gcs terraform
最終更新日:

GCSバケットへのアクセスに対してip制限を設定する機能ができたので試してみる。dbt docsのhtmlをホスティングして、アクセスしてみた。現状はpre-GAの機能

手順としては公開バケットを作成、ip制限の設定をし、dbt docs generateしてhtmlファイルの閲覧ができるか確認した

環境

  • dbt: 1.9.0
  • gcloud SDK: 532.0.0
  • gcloud alpha 2025.03.29

実装

terraform定義

実際のipアドレスにはPCのグローバルipアドレスを設定している。記事中の値は適当に設定している

  • 7/27追記

terraformのgcs resourceで設定がされたため。そちらの形式で設定

allow_all_service_agent_accessをtrueにしておくと、ip filterの設定を無視してサービスエージェント経由でアクセスできるようになる

resource "google_storage_bucket" "dbt_docs_bucket" {
  name          = "dbt-docs"
  location      = "us-central1"
  storage_class = "STANDARD"
  force_destroy = true
 
  labels = {
    managed_by = "terraform"
  }
 
  website {
    main_page_suffix = "static_index.html"
  }
 
  ip_filter {
    mode                           = "Enabled"
    allow_all_service_agent_access = true
    public_network_source {
      allowed_ip_cidr_ranges = [
        "210.0.0.0/24"
      ]
    }
  }
}
 
resource "google_storage_bucket_iam_member" "member" {
  provider = google
  bucket   = google_storage_bucket.dbt_docs_bucket.name
  role     = "roles/storage.objectViewer"
  member   = "allUsers"
}
 
旧:terraformでの定義

null_resource、知らなかったけどclaudeが教えてくれた

resource "google_storage_bucket" "dbt_docs_bucket" {
  name          = "dbt-docs"
  location      = "us-central1" // ap-northeast-1は対象外 // var.region
  storage_class = "STANDARD"
  force_destroy = true
 
  labels = {
    managed_by  = "terraform"
  }
 
  website {
    main_page_suffix = "static_index.html"
  }
}
 
resource "google_storage_bucket_iam_member" "member" {
  provider = google
  bucket   = google_storage_bucket.dbt_docs_bucket.name
  role     = "roles/storage.objectViewer"
  member   = "allUsers"
}
 
resource "null_resource" "gcs_ip_filter" {
  provisioner "local-exec" {
    command = <<EOT
      set -e
      echo '{
        "mode": "Enabled",
        "publicNetworkSource": {
          "allowedIpCidrRanges": [
            "210.0.0.0/24"
          ]
        }
      }' > ip_filter.json
      gcloud alpha storage buckets update gs://${google_storage_bucket.dbt_docs_bucket.name} --ip-filter-file=ip_filter.json
      rm ip_filter.json
    EOT
  }
  depends_on = [google_storage_bucket.dbt_docs_bucket]
}

terraform apply したあと、ipフィルターが設定されていることを確認する

gcloud alpha storage buckets describe gs://dbt-docs --format="default(ip_filter_config)"
ip_filter_config:
  mode: Enabled
  publicNetworkSource:
    allowedIpCidrRanges:
    - "210.0.0.0/24"

一応providerのファイルも

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 6.0"
    }
  }
}
 
provider "google" {
  project = var.project_id
  region  = var.region
}
 
variable "project_id" {
  type = string
  default = "project_id"
}
 
variable "region" {
  type    = string
  default = "asia-northeast1"
}

terraform apply したあと、ipフィルターが設定されていることを確認する

gcloud alpha storage buckets describe gs://dbt-docs --format="default(ip_filter_config)"
 
ip_filter_config:
  allowAllServiceAgentAccess: true
  mode: Enabled
  publicNetworkSource:
    allowedIpCidrRanges:
    - 210.155.75.179/32

dbt docs upload

dbtプロジェクトはすでにあるものを使う。コマンドを実行すると単一の静的ファイルstatic_index.htmlがtargetディレクトリ以下に生成される

生成、uploadのコマンドは以下

dbt docs generate --static
 
gloud storage cp ./target/static_index.html gs://dbt-docs/

エンドポイントは、コンソールからGCSオブジェクトのオーバーフローメニュー(︙)より公開URLをコピーした値

https://storage.googleapis.com/dbt-docs/static_index.html

アクセス可能な場合は表示される

dbt-docs.png

設定範囲に含まれないipアドレスからアクセスを試すために cloud shellからコマンド実行してみると、アクセス拒否された。エラーメッセージがちゃんとしている

There is an IP filtering condition that is preventing access to the resource

  #   Welcome to Cloud Shell! Type "help" to get started.
  # Use `gcloud config set project [PROJECT_ID]` to change to a different project.
  # y@cloudshell:~ (free)$ curl -XGET https://storage.googleapis.com/dbt-docs/static_index.html
  # <?xml version='1.0' encoding='UTF-8'?><Error><Code>AccessDenied</Code><Message>Access denied.</Message><Details>There is an IP filtering condition that is preventing access to the resource.</Deta
  

注意点として、ipフィルターを設定するとIPアドレス以外での実行はコンソールやcloud経由でも受け付けなくなる。IAM権限よりも強い?らしい。つまりバケットの編集や更新ができなくなる

また、allUsersなのでコンソール画面でも以下warningが表示される

公開アクセス インターネットに公開

ip制限がIAM roleよりも先に及ぶこと、コンソールからip制限の設定が確認できないなど、現時点で少し使いづらい部分はあるが、社内外に公開したい場合などには便利そう

サービスエージェントを使ってcloudbuildからアクセス

ip制限すると、CI上からgcsにアクセスさせるのが難しい gcpであれば、サービスエージェント経由でアクセス可能になるのでcodebuild経由で実現できる サービスアカウントもできるようにしてほしかったが、そいうわけにもいかないよう あと、サービスエージェントになりすまして実行などもできなかった

  • 実装、結果

適当にcatさせる

# cloudbuild.yml
steps:
- name: 'gcr.io/google.com/cloudsdktool/google-cloud-cli'
  entrypoint: 'gcloud'
  args:
  - 'storage'
  - 'cat'
  - 'gs://dbt-docs/static_index.html'
gcloud builds submit --config cloudbuild.yml .

logは以下のようになる

...
Digest: sha256:942d69f18e4656df2108c792b34f5e6308e1d30bef1deadc8fd9a1ee1b01b641
Status: Downloaded newer image for gcr.io/google.com/cloudsdktool/google-cloud-cli:latest
gcr.io/google.com/cloudsdktool/google-cloud-cli:latest
<!doctype html>
<html dir="ltr" lang="en-US" ng-app="dbt"
    class="no-flash video supports no-touchevents formvalidation webgl no-cssgridlegacy cssgrid cssfilters objectfit object-fit click landscape videoautoplay loaded">
 
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1" />
    <title>dbt Docs</title>

参考