0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloud Run functions × TypeScript 開発をしよう!【セキュリティ:Secret Manager をTerraformで構成する】

Last updated at Posted at 2024-12-16

はじめに

この記事では以下のことについて説明しています。

  • Terraformで Secret Manager を構成する方法

「セキュリティ」なんて大体的なカテゴリにしていますが、Seceret ManagerをCloud Run functionsで使う方法を紹介しているだけです。

Secret Managerとは

以下公式引用です。

Secret Manager は、API キー、ユーザー名、パスワード、証明書などの機密データを保存して管理できるシークレットおよび認証情報管理サービスです。

要するに他所から見られると確実にまずい認証情報を置いておけるサービスです。一度コンソールの方で触ってみてください。

まずはこのSecret Managerに置く秘密情報を、Terraformで作成しましょう。

前準備:Secret Manager APIを有効にする

GCPの検索欄に「Secret Manager」を入力してサービスページにいきます。そして有効化しましょう。
スクリーンショット 2024-12-16 2.20.03.png

Terraformで秘密情報をSecert Managerに置く

今回Secret Managerに配置する秘密情報 my-secret.json です。main.tf と同じ階層に置いておきます。

my-secret.json
{
    "hoge": "hogehoge"
}

シークレットのリソース定義

レプリケーションポリシーを「自動」にした my-secret という名前のシークレットのリソースを作成します。

シークレットのリソース定義
resource "google_secret_manager_secret" "my-secret" {
  secret_id = "my-secret"

  replication {
    automatic = true
  }
}

シークレットのバージョンのリソース定義

シークレットはバージョンという概念で値の管理をしています。まずシークレットの最新バージョンを示すリソース my-secret-version を表現します。値は先ほど作成した my-secret.json にします。

また、新しくバージョンが作られた際に過去のバージョンを全て破棄するようにします。

シークレットのバージョンのリソース定義
resource "google_secret_manager_secret_version" "my-secret-version" {
  secret      = google_secret_manager_secret.my-secret.id
  secret_data = file("${path.module}/my-secret.json") # string形式なのでこれ

  deletion_policy = "DELETE" # 新規バージョン作成時、過去のバージョンを全て破棄
}

注意1

deletion_policy には設定できる項目が DELETE, DISABLE, ABANDON の3つありますが、名前の雰囲気で設定すると「あれ?思ったように動かないぞ?」となります。

  • DELETE : 直前のバージョンの破棄
  • DISABLE : 直前のバージョンの無効化
  • ABANDON : 直前のバージョンを保持

です。ABANDON が破棄じゃないの罠すぎる。

注意2

また、deletion_policy の更新とシークレットの追加を同時に行った場合、更新したdeletion_policy が反映されるのは次にシークレットの追加を行った時です。 注意してください。

事例

■ 状況
ver.1のシークレット: 有効, versionの deletion_policy: ABANDON

■ アクション
deletion_policyDELETEにして ver.2 のシークレットを追加し terraform apply

■ 結果1
ver.1のシークレット: 有効 → 無効にならない
ver.2のシークレット: 有効

■ 行動2
ver.3 のシークレットを追加し terraform apply

■ 結果2
ver.1のシークレット: 有効
ver.2のシークレット: 破棄
ver.3のシークレット: 有効 → これ以降作られるverに新しいdeletion_policyが適応される

解決策

deletion_policy の更新 とシークレットの追加を別々の terraform apply で行うことです。

最新のシークレットバージョンの data ソースを定義する

新規バージョンの作成は上記の "google_secret_manager_secret_version" . "my-secret-version" でできますが、参照は dataソースを使います。リソースで作成済みでないと404エラーになってしまうので、depends_on に対象のバージョンのリソースを記載します。

最新のシークレットのバージョンに関する data ソース
data "google_secret_manager_secret_version" "my-secret-version-latest" {
  secret  = google_secret_manager_secret.my-secret.id
  version = "latest"

  depends_on = [
    google_secret_manager_secret_version.my-secret-version
  ]
}

シークレットにアクセスするIAMを定義

そしてそのシークレットにアクセスするIAMを定義します。シークレットにアクセスするのはCloud Run functionsのランタイムですが、そのランタイムのデフォルトサービスアカウントは <PROJECT_NUMBER>-compute@developer.gserviceaccount.com の形式になっているので、IAMの member に指定してあげます。

Secret ManagerにアクセスできるIAMの設定
resource "google_secret_manager_secret_iam_member" "secretmanager-my-secret" {
  secret_id = google_secret_manager_secret.my-secret.id
  role      = "roles/secretmanager.admin"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com"

  condition {
   title       = "my-secret iam"
   description = "my-secret へのアクセス許可を行うIAM"
   expression  = "resource.name.startsWith(\"${google_secret_manager_secret.my-secret.name}\")"
  }
}

参考

そして terraform plan を入力して、内容に問題がなければ terraform apply をしましょう。

$ terraform apply
# ...省略

  # data.google_secret_manager_secret_version.my-secret-version-latest will be read during apply
  # (config refers to values not yet known)
 <= data "google_secret_manager_secret_version" "my-secret-version-latest" { ... }

  # google_cloud_run_service_iam_member.member will be created
  + resource "google_cloud_run_service_iam_member" "member" { ... }

  # google_cloudfunctions2_function.default will be created
  + resource "google_cloudfunctions2_function" "default" { ... } 

  # google_secret_manager_secret.my-secret will be created
  + resource "google_secret_manager_secret" "my-secret" { ... }

  # google_secret_manager_secret_iam_member.secretmanager-my-secret will be created
  + resource "google_secret_manager_secret_iam_member" "secretmanager-my-secret" { ... }
  
  # google_secret_manager_secret_version.my-secret-version will be created
  + resource "google_secret_manager_secret_version" "my-secret-version" { ... }
  
  # google_storage_bucket.default will be created
  + resource "google_storage_bucket" "default" { ... }
  
  # google_storage_bucket_object.object will be created
  + resource "google_storage_bucket_object" "object" { ... }
  
  # random_id.default will be created
  + resource "random_id" "default" { ... }
Plan: 8 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + function_uri = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
  
# ...省略

Apply complete! Resources: 8 added, 0 changed, 0 destroyed.

Outputs:

function_uri = "https://xxx.a.run.app"

おわりに

Secret Managerを Terraform で構成する方法を紹介しました。次回はこうして作成したシークレットのバージョンにCloud Run functions からアクセスする方法を紹介します。

トラブルシューティング

Error: Error creating function: googleapi: Error 403: Could not create Cloud Run service 関数名. Cannot access API run.googleapis.com in project プロジェクト名...

エラー文

╷
│ Error: Error creating function: googleapi: Error 403: Could not create Cloud Run service sample-crf. Cannot access API run.googleapis.com in project プロジェクト名
│ 
│   with google_cloudfunctions2_function.default,
│   on main.tf line 42, in resource "google_cloudfunctions2_function" "default":
│   42: resource "google_cloudfunctions2_function" "default" {
│ 
╵

解決策

GCPのAPIが一部有効になっていないため発生している可能性があります。以下のコマンドを実行してみましょう。

$ gcloud services enable run.googleapis.com --project プロジェクト名

Operation "operations/acf.p2-735381230523-757f2cf0-10ce-43af-9812-3e93e1993208" finished successfully.
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?