Google Cloud上にVault Enterpriseクラスタを構築してみた

記事タイトルとURLをコピーする

当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。


みずほリサーチ&テクノロジーズ株式会社の高瀬です。

Google Cloud(旧GCP)上に HashiCorp 社の Vault Enterprise クラスタを構築したので流れをまとめました。 未経験の状態で構築しましたので、つまずきポイントも併記しています。

当ブログは G-gen × みずほRT によるコラボ記事です

はじめに

Vault (HashiCorp) とは

Vaultとは HashiCorp 社の製品で、プラットフォームフリーで、シークレットを一元管理することができる製品です。 例えばVaultでは一時的なユーザの発行も行え、有効期限を1週間にしたユーザーを作成すると1週間後に自動的にユーザが削除されます。自動でユーザが削除されるのはとても便利ですね。
詳細はこちらをご確認ください。

構築のおおまかな流れ

構築にはTerraform Cloud BusinessとCloud Shellを利用します。
今回構築するのは下図のVault Enterpriseの構成で、複数のアベイラビリティゾーンにクラスタを分割する可用性の高い構成です。

図は公式マニュアルより引用

構築は以下の順に行います。

  1. Terraform CloudとGoogle Cloudを連携
  2. Vault Enterpriseクラスタを構築するためのTerraformモジュールを入手
  3. Cloud ShellでTerraformを実行

後で触れるTerraformモジュールの実行にはVaultのライセンスファイルが必要なため、必要な際はこちらより HashiCorp社へお問い合わせ下さい。

Terraform Cloudの設定

まず Terraform Cloud と Google Cloud を連携させるための認証情報の登録を行います。

Google Cloudの資格情報が必要ですので Google CloudのIAMと管理>サービスアカウントからサービスアカウントを作成し、キーを控えておいてください。

今回は静的にGoogle Cloudの資格情報を設定していますが、Terraform CloudではOpenID Connectを利用し、動的にGoogle Cloudの資格情報を利用する事が可能です。セキュアにTerraformを扱うための必要な機能がビルドインされています。

それではTerraform CloudとGoogle Cloudの連携を実施していきます。 はじめにTerraform Cloudの設定から行います。
Terraform Cloudの Projects & workspaces からワークスペースを作成し、CLI-drivenを選択してください。 次にSettings>Generalに移動し、Execution ModeをAgentに変更します。
※Agentモードが利用できるのはBusinessプランのみとなります。他のモードでも実行できると思いますが、今回はAgentモードを利用していきます。

Terraform VersionはCloud ShellとのTerraformバージョンと同じものに変更します。その後、下までスクロールして保存してください。

TerraformのバージョンはCloud Shellから以下コマンドで確認可能です。

terraform --version

次にTerraform CloudにGoogle Cloudの認証情報を設定します。設定方法については以下URLがわかりやすいのでご参考ください。

最後にCloud Shellからterraform loginコマンドを実行し、Terraform Cloudにログインします。設定方法については以下URLをご参考ください。

Terraformモジュールの準備

Vault Enterpriseクラスタを構築するためのTerraformモジュール、vault-ent-starterがあるためダウンロードしていきます。
このモジュールを利用すると、Vault with Integrated Storage Reference Architectureに沿った構成をGoogle Cloud上にプロビジョニングできます。 今回の構築にはvault-ent-starterを利用していきます。

vault-ent-starterモジュールをダウンロードします。Google CloudからCloud Shellを立ち上げてコマンドを実行してみてください。 ちなみに私はvault-testというフォルダを作成してその中で実行しています。

cd vault-test

git clone https://github.com/hashicorp/terraform-gcp-vault-ent-starter

コマンドを実行するとterraform-gcp-vault-ent-starterがダウンロードされます。中にexamples/prereqs_quickstartmodulesが入っていることを確認してください。

modulesを実行するためには先にVPCとTLS証明書を用意する必要があり、examplesにはVPCとTLS証明書を作成するためのモジュールが入っています。 今回はexampleを使ってVPC、TLS証明書を作成していきます。

本番利用の際はそれぞれ非機能要求にあったものをご準備ください。

  • gcp-vpc
    Vault対応のVPCを作成するためのモジュールです。
  • gcp-tls
    Load Balancerに設定するTLS証明書を作成するためのモジュールです。VaultクラスタはLoadBalancerで負荷分散されます。
  • vault-ent-starter
    Enterprise Vaultクラスタを作成するためのモジュールです。実行にはVPCとTLS証明書の作成および、Vaultのライセンスファイルを用意しておく必要があります。

ダウンロードしたterraform-gcp-vault-ent-starterフォルダ。

terraform-gcp-vault-ent-starterの直下からvault-testexamplesを移動してください。検証時、examplesを移動せずに実行するとエラーが発生しました。 modulesはterraform-gcp-vault-ent-starter直下で実行するため移動不要です。

クラスタの作成

prereqs_quickstart を実行

prereqs_quickstartを実行し、VPCとTLSを作成します。

Terraform Cloudで実行するための設定がモジュールには記載されていませんので、main.tfとvariables.tfに設定を追加していきます。
examples/prereqs_quickstart/main.tfにTerraform Cloudの設定を追加してください。

terraform {
  cloud {
    organization = "Terraform Cloudのorganization名"

    workspaces {
      name = "Terraform Cloudのworkspaces名"
    }
  }
}

examples/prereqs_quickstart/variables.tfにデプロイ先であるGoogle CLoudのプロジェクトIDとリージョン名を追加します。

variable "network_name" {
  type        = string
  default     = "consul-test-network"
  description = "The name of the VPC network being created"
}

variable "project_id" {
  type        = string
  description = "The GCP project ID in which to launch resources"
  # 追加
  default     = "Google CloudのプロジェクトID"
}

variable "region" {
  type        = string
  description = "GCP region in which to launch resources"
  # 追加(今回は東京リージョンに構築していきます)
  default     = "asia-northeast1"
}

Google CloudのプロジェクトIDが不明の場合はCloud Shellから以下コマンドで取得可能です。

gcloud projects list --format 'value(projectId)' --filter name=プロジェクト名

Terraformで定義したvariables(変数)はdefault値が指定されていなかったり、コマンドラインで値が指定されていなかったりした場合、applyの際に対話式で設定値の入力を促されます。

Terraform Cloudでのapplyでは対話入力できなかったため、今回はdefault値を設定しました。(下記のエラーが発生しました)

│ Error: No value for required variable
│
│   on variables.tf line 7:
│    7: variable "project_id" {
│
│ The root module input variable "project_id" is not set, and has no default
│ value. Use a -var or -var-file command line argument to provide a value for
│ this variable.

ここまででTerraform Cloudで実行するための準備が完了しました。

Terraformでは実際にリソースを作成する前に、terraform planコマンドでどのようなリソースが作成されるか確認することができます。tfファイルの構造が正しいか確認するためにも使用できます。

まずはteraform planでエラーが発生しないことを確認します。planでエラーがなかった場合、terraform applyを実行しリソースを作成してください。

実行後、Outputsに作成されたVPCやTLS証明書の情報が出力されます。のちの手順で利用しますので控えておいてください。

cd examples/prereqs_quickstart/

terraform init

terraform plan

terraform apply
Outputs:

leader_tls_servername = "vault.server.com"
ssl_certificate_name = "vault-xxxxxxx"
subnetwork = "https://xxxxxxxx"
tls_secret_id = "terraform_example_module_vault_tls_secret"

terraform-gcp-vault-ent-starterを実行

prereqs_quickstartが無事に実行できたら、次はterraform-gcp-vault-ent-starterを実行し、Enterprise Vaultクラスタを作成します。

実行の前提条件としてVaultのライセンスファイルが必要です。 ライセンスファイルをterraform-gcp-vault-ent-starterの直下に配置してください。

入手したままではTerraform Cloudで実行するための設定が記載されていません。examples/prereqs_quickstart実行時と同じように、Terraform Cloudで実行するための設定をmain.tfとvariables.tfに追記していきます。

terraform-gcp-vault-ent-starter/main.tfに以下を追加してください。

terraform {
  cloud {
    organization = "Terraform Cloudのorganization名"

    workspaces {
      name = "Terraform Cloudのworkspaces名"
    }
  }
}

terraform-gcp-vault-ent-starter/variables.tfにdefaultを追加していきます。defaultにはexamples実行時のOutputsで出力された値を入力してください。

variable "leader_tls_servername" {
  type        = string
  description = "One of the shared DNS SAN used to create the certs used for mTLS"
  # 追加
  default = "vault.server.com"
}

variable "project_id" {
  type        = string
  description = "GCP project in which to launch resources"
  # 追加
  default = "Google CloudのプロジェクトID"
}

variable "resource_name_prefix" {
  type        = string
  description = "Prefix for naming resources"
  # 追加(お好きなprefixを付けてください)
  default = "demo"
}

variable "ssl_certificate_name" {
  type        = string
  description = "Name of the created managed SSL certificate. Required when create_load_balancer is true"
  # 追加
  default = "vault-xxxxxxx"
}

variable "subnetwork" {
  type        = string
  description = "The self link of the subnetwork in which to deploy resources"
  # 追加
  default = "https://xxxxxxxx"
}

variable "tls_secret_id" {
  type        = string
  description = "Secret id/name given to the Google Secret Manager secret"
  # 追加
  default = "terraform_example_module_vault_tls_secret"
}

variable "vault_license_filepath" {
  type        = string
  description = "Filepath to location of Vault license file"
  # 追加(ライセンスファイルをterraform-gcp-vault-ent-starter直下に配置した場合)
  default = "vault.hclic"
}

修正が終わったらterraform-gcp-vault-ent-starterを実行し、Enterprise Vaultクラスタを作成します。planでエラーがないことを確認後、applyを実行して下さい。

cd ../../terraform-gcp-vault-ent-starter/

terraform init

terraform plan

terraform apply

もしrequired field is not setエラーが発生した場合は、エラーが発生したmain.tfにパラメータを追加します。

│ Error: project: required field is not set
│
│   with module.iam.google_service_account.main,
│   on modules/iam/main.tf line 5, in resource "google_service_account" "main":
│    5: resource "google_service_account" "main" {

下記エラーですとmodules/iam/main.tfの5行目、google_service_accountprojectを追加します。検証時は設定がうまくいっていなかったのかprojectとregionのエラーが頻発したため都度追加していきました。

resource "google_service_account" "main" {
  account_id   = "${var.resource_name_prefix}-vault-${random_id.vault.hex}"
  display_name = "Vault KMS and auto-join for auto-unseal"
  # 追加
  project = プロジェクトID
}

以下のように既存リソースが削除されるメッセージが出力された場合は、prereqs_quickstartterraform-gcp-vault-ent-starterで同じTerraform Cloudのワークスペースを参照している可能性があります。 新規でワークスペースを作成し、terraform-gcp-vault-ent-starter/main.tfworkspacesnameを作成したワークスペース名に修正してください。

  # module.secrets.google_compute_region_ssl_certificate.main will be destroyed
  # (because google_compute_region_ssl_certificate.main is not in configuration)
  - resource "google_compute_region_ssl_certificate" "main" {
      - certificate        = (sensitive value)
      - certificate_id     = xxxxxxxxxxxxxx -> null
      ....
    }

Applyが表示され、VMインスタンスが立ち上がれば成功です!

立ち上げたインスタンスにSSHでログイン可能か確認してください。

まとめ

はじめての構築のため不格好ではありますが、無事に実行することができました。Vaultを使うにあたってテンプレートがあるのは非常に便利だなと思います。 もし本記事がこれからVaultを使おうとしている方の助けになれましたら幸いです。

高瀬 優紀

みずほリサーチ&テクノロジーズ株式会社

先端技術研究部に所属。Google Cloudは触り始めて数か月。社内のAWS人材育成を主に担当している。