概要
Google Cloud Storage はデフォルトではアクセスログは記録していません
バケットのロギング機能を有効にすると CSV 形式でアクセスログを特定のバケットに残すことができます
今回はロギングを有効にし生成されたログファイルをパースしてバケットへのアクセス IP を集計してみました
環境
- macOS 10.14.3
- Ruby 2.5.1p57
- google-cloud-storage 1.17.0
- Google Cloud Storage (2019/02/27 時点)
バケットのロギングを ON にする
コンソールからだとできないようなので gsutil
コマンドを使います
ログを格納するバケットを作成し、ロギングするバケットのフラグを ON にするだけです
まずログを格納するバケットを作成しましょう
バケットへのログの書き込みは GCP の内部で管理されている cloud-storage-analytics
というメンバになります
バケットに cloud-storage-analytics
が書き込み可能な権限を付与しましょう
gsutil mb -c regional -l us-central1 gs://log-bucket/
gsutil acl ch -g cloud-storage-analytics@google.com:W gs://log-bucket/
あとはロギングしたいバケットのフラグをオンにします
その際に先程作成したログを格納するためのバケットを指定します
gsutil logging set on -b gs://log-bucket gs://bucket
設定できているかは get
で行います
gsutil logging get gs://log-bucket
これでログがバケット内に格納されはじめます
サービスアカウント作成
今回は Ruby スクリプトを使うのでそれ用のサービスアカウントを作成しましょう
すでにサービスアカウントがある場合はそれを流量しても OK です
また今回の場合バケットに対象のサービスアカウントがアクセスできる必要があるので ACL を設定しましょう
gsutil acl get gs://log-bucket/
gsutil acl ch -u ruby-script-sa@project-123456.iam.gserviceaccount.com:R gs://log-bucket
gsutil acl ch -u ruby-script-sa@project-123456.iam.gserviceaccount.com:R gs://log-bucket/*
もしくはバケットポリシーオンリーを使うとバケットの権限を変更するだけでそのバケット配下のオブジェクトも同じ権限にすることができます
Cloud Storage で該当のバケットを選択し権限の設定メニューを開きます
そして「バケットポリシーのみでアクセス制御を簡素化する」を有効にします
追加したサービスアカウントを「ストレージのレガシー バケット読み取り」で追加すれば配下のオブジェクトも読み取ることができるようになります
また IAM 側でも「環境ユーザと Storage Object の閲覧者」の役割を追加してください
なおバケットポリシーオンリーを有効にすると gsutil acl get
などは使えなくなるのでご注意ください
Ruby のスクリプトでログを取得する
ログは CSV 形式なので手動でダウンロードして適当に集計しても OK です
ただ、ログファイルが複数に分割されているのでスクリプトで一括ダウンロードして集計します
require 'google/cloud/storage'
require 'csv'
storage = Google::Cloud::Storage.new(
project_id: "project-123456",
credentials: "./project-123456.json"
)
b = storage.bucket 'log-bucket'
byte = 0
ret = b.files.each_with_object(Hash.new(0)) { |f, acc|
f.download "./#{f.name}"
csv = CSV.read("./#{f.name}", headers: true)
if f.name.include?('_storage_')
byte = csv['storage_byte_hours']
else
csv.each { |r|
acc[r['c_ip']] += 1
}
end
}
puts byte
pp ret.sort { |(k1, v1), (k2, v2)| v2 <=> v1 }
ちょっと解説
ログファイルは一度ダウンロードしなければ使えません
ファイルは CSV 形式になっていてバケットの使用量をロギングしているファイルが 1 つと複数の分割されたアクセスログがあります
今回ほしい IP アドレスの情報は「c_ip」というカラムで管理されているので CSV から読み込んで取得します
今回は一応使用量をロギングしているファイルからも storage_byte_hours
を読み込んでいますが不要であれば削除してください
バケットおよびオブジェクトへの権限がうまく付与されていない場合は Invalid request (Google::Cloud::PermissionDeniedError)
になるのでその場合は ACL かバケットポリシーオンリーのどちらかを使ってログファイルにアクセスできるようにしましょう
最後に
バケットへのアクセスログを解析して IP の数をカウントしてみました
ポイントはログファイルが CSV なのと複数のファイルに分割されて保存させる点かなと思います
あとは Cloud Storage を使う上で避けては通れない ACL 周りかなと思います
最近だとバケットポリシーオンリーを使って IAM の機能で管理するのが主流になっているぽいです
ACL はオブジェクト単位で管理する必要があるので確かに面倒なイメージはあります
バケット配下のオブジェクトでそれぞれで権限を設定するケースって確かに少ない気がするのでバケットポリシーオンリーが主流になっているだと思います