Cloud Runはコンテナをデプロイするだけでサービスを公開できる手軽さを持つ一方、セキュリティ設定を怠ると、意図しないアクセスや情報漏洩のリスクに直結します。 「簡単に公開できる」からこそ、その裏側にあるセキュリティ上の注意点を理解し、対策を講じることが不可欠です。 本稿は、Cloud Runでサービスを公開する幅広い開発者に向けた内容であり、特にフリーランスや小規模チームにとっても有用なセキュリティ対策の実践セットを、具体的なコマンドやコード断片を交えて解説します。
Cloud Run公開時に直面する主なリスク
サービスを公開する前に、まずどのようなリスクが存在するのかを理解しておくことが重要です。ここでは、Cloud Run利用時に特に注意すべき4つのリスクと、その対策の方向性を紹介します。
誰でも叩けるエンドポイント
失敗例: デプロイしたAPIが認証なしで全世界に公開されており、悪意のあるBotやDDoS攻撃の標的となり、想定外の高額請求が発生する。
対策: Ingress設定でアクセス元を制限し、必要に応じてIAP(Identity-Aware Proxy)やIDトークンによる認証を必須とします。
認証情報(APIキー・SA鍵)の漏洩
失敗例: ソースコードや環境変数にハードコードしたAPIキーがGitHubリポジトリ経由で漏洩し、第三者に不正利用される。
対策: Secret Managerを活用し、認証情報をコードや環境変数から完全に分離します。Cloud Runサービスには、参照権限を持つサービスアカウント経由で安全に注入します。
過剰な権限での実行
失敗例: 手間を惜しんでプロジェクトの「オーナー」権限を持つデフォルトのサービスアカウントでCloud Runを実行した結果、万が一コンテナが乗っ取られた際に、プロジェクト全体に被害が及ぶ。
対策: 「最小権限の原則」に基づき、アプリケーションが必要とする権限のみを持つ専用のサービスアカウントを作成し、利用します。
監査不足(ログ/アラート未整備)
失敗例: サービスでエラーが多発している、あるいは不正アクセスの兆候があるにも関わらず、ログの監視やアラート設定をしていなかったため、問題の発見が大幅に遅れる。
対策: Cloud LoggingとCloud Monitoringを標準で活用し、異常(5xxエラーの急増など)を検知したら即座に通知されるアラートポリシーを設定します。
最低限押さえるべきセキュリティ対策

それでは、具体的な対策を見ていきましょう。 以下の設定を実践することで、前述のリスクを大幅に低減できます。
3-1. IAMの最小権限付与
Cloud Runで実行されるアプリケーションには、専用のサービスアカウント(SA)を割り当て、そのSAには必要最小限のIAMロールのみを付与するのが鉄則です。
# サービスアカウント作成
gcloud iam service-accounts create app-runner --display-name="Cloud Run app"
# 最小権限付与(例: BigQuery 読み取り)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:app-runner@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/bigquery.dataViewer"
これにより、万が一このサービスが侵害されても、攻撃者はBigQueryのデータを閲覧することしかできず、データの変更や削除、他のGCPサービスへのアクセスは行えません。
3-2. Secret Managerの活用
APIキーやデータベースパスワードなどの認証情報を、コードや環境変数に直接書き込むのは絶対に避けるべきです。 代わりに、GCPのSecret Managerを使って一元管理し、実行時にCloud Runサービスへ安全にマウントします。
package main
import (
"context"
"fmt"
secretmanager "cloud.google.com/go/secretmanager/apiv1"
smpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)
// readSecret はSecret Managerから最新版のシークレットを読み込む
func readSecret(projectID, name string) (string, error) {
ctx := context.Background()
c, err := secretmanager.NewClient(ctx)
if err != nil {
// クライアント初期化失敗時のエラーハンドリング
return "", fmt.Errorf("failed to create secretmanager client: %w", err)
}
defer c.Close()
req := &smpb.AccessSecretVersionRequest{
Name: fmt.Sprintf("projects/%s/secrets/%s/versions/latest", projectID, name),
}
res, err := c.AccessSecretVersion(ctx, req)
if err != nil {
// シークレットアクセス失敗時のエラーハンドリング
return "", fmt.Errorf("failed to access secret version: %w", err)
}
return string(res.Payload.Data), nil
}
デプロイ時には、--set-secrets
フラグを使ってシークレットを環境変数としてコンテナに渡します。
gcloud run deploy app \
--image=$IMAGE \
--region=asia-northeast1 \
--service-account=app-runner@${PROJECT_ID}.iam.gserviceaccount.com \
--set-secrets=YOUTUBE_API_KEY=projects/${PROJECT_ID}/secrets/YOUTUBE_API_KEY:latest
3-3. Ingress設定と認可(IAP/IDトークン)
Cloud RunのIngress設定は、誰がサービスにアクセスできるかを制御する重要な門です。
--ingress internal-and-cloud-load-balancing
は、インターネットからの直接リクエストを遮断し、VPC内部やロードバランサ経由のトラフィックのみを許可する設定です。
# 認証必須に(未認証アクセス拒否)
gcloud run services update app \
--region=asia-northeast1 \
--ingress internal-and-cloud-load-balancing \
--no-allow-unauthenticated
さらに、IAP(Identity-Aware Proxy)を有効にすれば、SaaSとしての簡易的なVPN代替としても機能し、特に小規模チームの社内ツールに最適です。
ただし、IAPの利用にはGoogleアカウントが必須という制約がある点に注意してください。(有効化はGCPコンソールの Security > Identity-Aware Proxy
から、または gcloud iap web enable
コマンドで行えます)
認証付きサービスは、以下のコマンドでIDトークンを取得し、curlで動作確認できます。 他のGCPサービス(例: GKE上のPod)からアクセスする場合は、Workload Identity連携などを利用してサービスアカウントにIDトークン発行権限を付与します。
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://your-cloud-run-url
3-4. VPC Connectorによる内部通信化
Cloud SQLなどVPC内のリソースと通信する際は、VPCサーバーレスコネクタを利用します。 利用する際は、Cloud Runサービスと同一リージョンに作成することが必須です(一部利用できないリージョンもあるため、公式ドキュメントの確認を推奨します)。
# VPC Connector 作成例
gcloud compute networks vpc-access connectors create run-conn \
--region=asia-northeast1 --network=default --range=10.8.0.0/28
# Cloud Run サービスと接続
gcloud run services update app \
--region=asia-northeast1 \
--vpc-connector=run-conn
コネクタはインスタンスの稼働時間とデータ転送料で課金されます。
min-instances
を設定すると、トラフィックがゼロでもインスタンスが待機するため、常時課金が発生する点に注意が必要です。
また、作成に数分かかるため、CI/CDでの都度作成は非推奨であり、Terraform等で管理する場合もリソースの再作成を避ける設計が推奨されます。
3-5. Cloud Armor/WAF とレート制御(必要に応じて)
より高度な保護が必要な場合は、Cloud Load Balancerを前面に配置し、Cloud Armor(Google CloudのWAFサービス)を組み合わせることが、特にサーバーレスアーキテクチャでサービスを安全に公開する上では必須の組み合わせと言えます。 SQLiやXSSから保護するOWASP Top 10対応の事前定義ルールセットに加え、カスタムルール、Bot対策、レート制御も柔軟に組み合わせることが可能です。
3-6. ログ/監視/アラートで「気づける」体制
セキュリティは「設定して終わり」ではありません。 本番リリース前に負荷試験などを行い、平常時のベースラインを把握した上で、異常を検知するアラートを設定することが重要です。その際、Cloud TraceやCloud Profilerを併用することで、より精緻なボトルネック特定と監視が可能になります。
5xxエラー率の急増: 例: 5分間に10回以上の5xxエラーが発生した場合。
リクエストレイテンシの急増: 例: 99パーセンタイルのレイテンシが平常時の2倍を超えた場合。
認証拒否率の上昇: 不正アクセスの試行が増えている兆候かもしれません。
Cloud Runの同時実行数(Concurrency): 平常時の数倍(例: 3〜5倍)を閾値に設定し、急激な負荷増大を検知します。
これらのアラートポリシーを設定し、Slack、メール、Google Chatのほか、PagerDutyやOpsgenieといった外部ツールも活用して複数のチャネルに通知することで、重要なアラートの見逃しリスクを低減できます。
4. 実案件シナリオ(YouTubeトレンド解析アプリ)
本記事で解説した対策を、具体的なアプリケーションシナリオに当てはめてみましょう。
アプリケーション概要: YouTube APIからトレンド動画の情報を取得し、分析してBigQueryに保存するGo製アプリケーション。
セキュリティ要件:
YouTube APIキーは絶対に漏洩させない。
BigQueryへの書き込み権限は厳密に管理する。
エンドポイントは、許可された利用者(社内メンバー)のみがアクセスできるようにする。
サービスの稼働状況を監視し、異常があれば即座に知りたい。
対策プラン:
Secret Manager:
YOUTUBE_API_KEY
をSecret Managerに保管し、--set-secrets
で注入。IAM: Cloud Run用とバッチ用のSAを分離し、それぞれに最小権限(
bigquery.dataViewer
,bigquery.dataEditor
)を付与。Ingress制御: Ingressを内部に限定し、IAPを有効化してGoogleアカウントで認証。
監視アラート: 5xxエラーとレイテンシ、Concurrencyを監視し、複数チャネルに通知。
5. まとめ

Cloud Runは手軽さと強力さを両立した素晴らしいサービスですが、その手軽さゆえにセキュリティの初期設定が非常に重要になります。 「とりあえず動いたから公開」ではなく、デプロイする前に一度立ち止まり、安全な状態になっているかを確認する習慣をつけましょう。
本番公開する前の最終チェックリストとして、以下の最低限セットを遵守するようにしてください。
IAMの最小権限: 専用のサービスアカウントに、必要な権限だけを付与する。
Secret Manager: APIキーなどの機密情報は、コードや環境変数から分離する。
Ingress制御: 公開範囲を適切に絞り、不要なアクセスをブロックする。
ログ&アラート: サービスの異常を即座に検知できる仕組みを整える。
この4項目が、セキュアなアプリケーション運用の土台となります。これらの基本を押さえたうえで、必要に応じてCloud ArmorやVPC分離、さらにはCloud DLPやSecurity Command CenterといったGCPの高度なセキュリティサービスを検討・拡張していくことで、中長期的な安全運用につながります。 この最低限セットを押さえておけば、安心してCloud Runを本番公開できます。