モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

目次目次を開く/閉じる

Terraform の GCP 環境向けの基本的な使い方

モーダルを閉じる

ステッカーを選択してください

お支払い手続きへ
モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2021/03/20
最終更新最終更新
2024/01/30
記事区分記事区分
一般公開

目次

    インフラ構築と自動化が得意。TerraformとAnsibleでインフラを自動構築するお仕事が多め

    GCP 環境をプロビジョニングするための Terraform の基本的な設定を記載します。

    本ページで利用する terraform のバージョンは以下のとおりです。

    [vagrant@localhost myrepo]$ terraform --version
    Terraform v0.14.8
    

    簡単な例 (VPC の作成)

    以下のような main.tf ファイルを作成します。GCP のサービスアカウントの key ファイルのパスを指定します。サービスアカウントには必要なロールを割り当てておく必要があります。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = "3.60.0"
        }
      }
    }
    
    provider "google" {
      credentials = file("./my-service-account-key.json")
      project = "my-project-id"
    }
    
    resource "google_compute_network" "vpc_network" {
      name = "terraform-network"
    }
    

    Terraform では対象とする環境に応じて provider を指定します。GCP の場合は hashicorp/google という provider を利用します。

    以下のコマンドで provider のバイナリのダウンロード等の初期化処理を行います。

    terraform init
    

    変更される内容を dry-run で確認します。

    terraform plan
    

    変更を適用します。

    terraform apply
    

    terraform が認識している状態を確認します。

    terraform show
    

    出力例

    # google_compute_network.vpc_network:
    resource "google_compute_network" "vpc_network" {
        auto_create_subnetworks         = true
        delete_default_routes_on_create = false
        id                              = "projects/my-project-id/global/networks/terraform-network"
        mtu                             = 0
        name                            = "terraform-network"
        project                         = "my-project-id"
        routing_mode                    = "REGIONAL"
        self_link                       = "https://www.googleapis.com/compute/v1/projects/my-project-id/global/networks/terraform-network"
    }
    

    local でビルドした google provider を利用する設定

    terraform の設定が期待通りに動かない場合に、local でビルドした google provider を利用できると検証時に便利です。

    local ビルド

    git clone https://github.com/hashicorp/terraform-provider-google.git
    

    Go 言語でビルドします。

    cd ./terraform-provider-google
    go build
    

    ビルド成果物

    du -h ~/terraform-provider-google/terraform-provider-google
    75M     /home/vagrant/terraform-provider-google/terraform-provider-google
    

    ~/.terraformrc

    以下のようなディレクトリとシンボリックリンクを作成します。

    mkdir -p ~/.terraform.d/plugin/registry.terraform.io/hashicorp/google/99.99.99/linux_amd64
    mkdir -p ~/.terraform.d/plugin-cache
    
    ln -s ~/terraform-provider-google/terraform-provider-google ~/.terraform.d/plugin/registry.terraform.io/hashicorp/google/99.99.99/linux_amd64/terraform-provider-google_v99.99.99
    

    ~/.terraformrc を作成します。

    provider_installation {
      filesystem_mirror {
        path = "/home/vagrant/.terraform.d/plugin"
      }
      direct {
        exclude = []
      }
    }
    
    plugin_cache_dir = "/home/vagrant/.terraform.d/plugin-cache"
    

    terraform init

    main.tf の version を更新します。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
    #      version = "3.60.0"
          version = "99.99.99"
        }
      }
    }
    

    ロックファイルを削除して init しなおします。

    rm .terraform.lock.hcl
    terraform init
    

    以下のように .terraform/* にインストールされました。

    find .terraform/providers/ -name terraform-provider-google* -follow
    
    .terraform/providers/registry.terraform.io/hashicorp/google/3.60.0/linux_amd64/terraform-provider-google_v3.60.0_x5
    .terraform/providers/registry.terraform.io/hashicorp/google/99.99.99/linux_amd64/terraform-provider-google_v99.99.99
    

    応用的な設定例 (Cloud Console および API へのアクセス制限の設定)

    注意: BeyondCorp Enterprise の機能を使うため、以下の手順を試すためには GCP における「組織」の登録が必要となります。

    サービスアカウントを作成

    サービスアカウントは、ある一つのプロジェクトに属します。「組織」にサービスアカウントを作成することはできないため、適当なプロジェクトでサービスアカウントを作成します。

    mylab-308012 というプロジェクトで my-service-account-2 を作成すると、以下のようなメールアドレスになります。

    my-service-account-2@mylab-308012.iam.gserviceaccount.com
    

    JSON 形式の鍵ファイルをダウンロードしておきます。

    「組織」の階層構造を参照する権限の付与

    「組織」の「IAM」において、「roles/browser(参照者)」ロールをサービスアカウントに付与します。

    組織の階層構造を参照できるようになります。

    gcloud auth activate-service-account --key-file ./my-service-account-2.json
    gcloud organizations list
    
    DISPLAY_NAME            ID  DIRECTORY_CUSTOMER_ID
    qoosky.io     111111111111              XXXXXXXXX
    

    「組織」のリソースを編集する権限の付与

    作成したサービスアカウントを用いて Terraform でリソースを作成する必要があるため、更に「roles/editor(編集者)」ロールも付与します。

    editor ロールがあると、組織のリソースを閲覧できるようになります。例えば以下のコマンドがエラーなく実行できます。

    gcloud access-context-manager policies list --organization 111111111111
    
    NAME          ORGANIZATION  TITLE           ETAG
    486212067009  111111111111  default policy  045d9af982e4e4fa
    

    デフォルトのポリシーが既に作成されている「組織」の場合は上記のように表示されます。「組織」は一つのポリシーしか持てないため、デフォルトのポリシーが存在する場合は terraform でポリシーを作成しようとするとエラーになります。

    「アクセスレベル」の作成

    「デフォルトのポリシー」が存在しない場合は、以下のように「組織」のポリシーも terraform で管理します。既にデフォルトのポリシーが存在する場合で terraform 管理しない場合は、以下の main.tf の ${google_access_context_manager_access_policy.my-access-policy.name} をデフォルトポリシーのものでハードコーディングします。

    main.tf

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = "3.60.0"
        }
      }
    }
    
    provider "google" {
      credentials = file("./my-service-account-2.json")
    }
    
    resource "google_access_context_manager_access_policy" "my-access-policy" {
      parent = "organizations/111111111111"
      title  = "my-access-policy"
    }
    
    resource "google_access_context_manager_access_level" "access-level" {
      parent = "accessPolicies/${google_access_context_manager_access_policy.my-access-policy.name}"
      name   = "accessPolicies/${google_access_context_manager_access_policy.my-access-policy.name}/accessLevels/my_ip_restriction"
      title  = "my_ip_restriction"
      basic {
        conditions {
          ip_subnetworks = [
            "123.123.123.123/32"
          ]
        }
      }
    }
    

    google_access_context_manager_access_level リソースのドキュメントはこちらですが、terraform の google プロバイダは、内部的には GCP REST API を実行しているため、ドキュメントでは把握しづらい情報は、REST API のドキュメントを参照して設定します。

    グループの作成

    グループを作成します。これにユーザを所属させることで、アクセス制限を行います。サービスアカウントでグループを作成するためには、必要な権限を付与する必要があります。CloudIdentity の場合は「グループ管理者」を付与します。

    Cloud Identity 管理コンソールで「管理者ロール」をクリックします。

    「グループ管理者」をクリックします。

    「サービスアカウントへの割り当て」をクリックします。

    サービスアカウントのメールアドレスを入力して追加します。

    また、CloudIdentity の顧客ID を確認しておきます。

    gcloud organizations list
    
    DISPLAY_NAME            ID  DIRECTORY_CUSTOMER_ID
    qoosky.io     111111111111              CXXXXXXXX
    

    main.tf に以下のリソース定義を追記します。

    resource "google_cloud_identity_group" "my-group" {
      display_name = "my-ip-restriction-group"
      parent = "customers/CXXXXXXXX"
      group_key {
        id = "my-ip-restriction-group@qoosky.io"
      }
      labels = {
        "cloudidentity.googleapis.com/groups.discussion_forum" = ""
      }
    }
    

    補足

    アカウントタイプ ドメイン Organization Administrator (GCP IAM による cloudidentity.googleapis.com 利用の許可) Groups Admin (Cloud Identity qoosky.io) mygroup@qoosky.io 作成
    ユーザアカウント qoosky.io X X X
    ユーザアカウント qoosky.io O X O
    ユーザアカウント qoosky.io X O O
    ユーザアカウント qoosky.io O O O
    ユーザアカウント abc.com O/X X (権限付与はできません) X
    サービスアカウント xxx.iam.gserviceaccount.com X X X
    サービスアカウント xxx.iam.gserviceaccount.com O X X
    サービスアカウント xxx.iam.gserviceaccount.com X O X
    サービスアカウント xxx.iam.gserviceaccount.com O O O

    アクセスバインディングの作成

    作成した「アクセスレベル」と「グループ」の紐付けを設定します。

    resource "google_access_context_manager_gcp_user_access_binding" "my-access-binding" {
      organization_id = "111111111111"
      group_key       =  trimprefix(google_cloud_identity_group.my-group.id, "groups/")
      access_levels   = [
        google_access_context_manager_access_level.access-level.name,
      ]
    }
    

    補足

    最終的に以下のような main.tf となります。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = "3.60.0"
        }
      }
    }
    
    provider "google" {
      credentials = file("./my-service-account-2.json")
    }
    
    resource "google_access_context_manager_access_policy" "my-access-policy" {
      parent = "organizations/111111111111"
      title  = "my-access-policy"
    }
    
    resource "google_access_context_manager_access_level" "access-level" {
      parent = "accessPolicies/${google_access_context_manager_access_policy.my-access-policy.name}"
      name   = "accessPolicies/${google_access_context_manager_access_policy.my-access-policy.name}/accessLevels/my_ip_restriction"
      title  = "my_ip_restriction"
      basic {
        conditions {
          ip_subnetworks = [
            "123.123.123.123/32"
          ]
        }
      }
    }
    
    resource "google_cloud_identity_group" "my-group" {
      display_name = "my-ip-restriction-group"
      parent = "customers/CXXXXXXXX"
      group_key {
        id = "my-ip-restriction-group@qoosky.io"
      }
      labels = {
        "cloudidentity.googleapis.com/groups.discussion_forum" = ""
      }
    }
    
    resource "google_access_context_manager_gcp_user_access_binding" "my-access-binding" {
      organization_id = "111111111111"
      group_key       =  trimprefix(google_cloud_identity_group.my-group.id, "groups/")
      access_levels   = [
        google_access_context_manager_access_level.access-level.name,
      ]
    }
    

    また、アクセス制限できるのは、同じドメイン qoosky.io におけるユーザアカウントのみです。

    アクセス制限が有効になると cloud console が使えなくなります。

    API も同様です。

    うまくいかない場合の動作検証

    期待通りに動作しない場合は、Cloud Logging のログを「組織」について確認します。

    上記例では、callerIp が IPv6 となっており、IPv4 で設定した許可IP としてアクセスできておらず、Access Denied となっています。自宅や職場のネットワーク設定で IPv6 を利用している場合は注意します。

    IPv4 の 0.0.0.0/0 に相当する ::/0 を許可 IP として設定して Access Denied とならなくなる場合は、これが原因です。

    関連する gcloud コマンド

    グループの情報を調査

    gcloud identity groups describe my-ip-restriction-group@qoosky.io
    

    グループ一覧の確認

    gcloud identity groups search --organization 111111111111 --labels 'cloudidentity.googleapis.com/groups.discussion_forum'
    

    gcloud は内部的に REST API を実行しています。上記と同様の処理を curl で行うためには以下のようにします。parent を URL エンコーディングする必要があることに注意します。

    curl -sS -H "Authorization: Bearer $(gcloud auth print-access-token)" "https://cloudidentity.googleapis.com/v1/groups?parent=customers%2FCXXXXXXXX"
    

    グループを作成できるアカウントであることを gcloud で確認

    gcloud identity groups create my-group@qoosky.io --organization 111111111111 --labels 'cloudidentity.googleapis.com/groups.discussion_forum' --with-initial-owner empty
    

    アクセスバインディングを gcloud で作成、削除 (group-key の指定方法に注意)

    gcloud access-context-manager cloud-bindings create \
        --group-key "04k668n33mb28sl" \
        --level accessPolicies/486212067009/accessLevels/my_ip_restriction \
        --organization 111111111111
    
    gcloud access-context-manager cloud-bindings delete --binding organizations/111111111111/gcpUserAccessBindings/aAQS-YRTcHRZ1IHJsBBe9kx0Tv1WHPqDpiA7yVtVZI55qrJpu
    
    Likeボタン(off)0
    詳細設定を開く/閉じる
    アカウント プロフィール画像

    インフラ構築と自動化が得意。TerraformとAnsibleでインフラを自動構築するお仕事が多め

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    >>さらに詳しくステッカーを贈る
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      ログインする

      関連記事