2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでTROCCOのユーザーをいい感じに管理する

Last updated at Posted at 2025-01-30

はじめに

前回は、TerraformでTROCCOのユーザーを作ったり消したりして利用イメージをご紹介しました。

今回は、実際にTerraformを使ってどのようにTROCCOのユーザーを管理していくと良さそうか、というところを考えていきたいと思います。

やりたいこと

TerraformでTROCCOのユーザーを作成するには下記情報を .tfファイルに書き込む必要があります。

.tf
resource "trocco_user" "example" {
  email                           = "trocco@example.com"
  password                        = "Jb1p4f1uuC"
  role                            = "member"
  can_use_audit_log               = false
  is_restricted_connection_modify = false
}

社内のユーザ管理や弊社Dさんが公開しているサンプルリポジトリを見てどのようにユーザ管理ができれば便利か考えてみました。

以下サンプルリポジトリから抜粋

.tf
admins = [
    "${local.your_email_before_at}+admin1@${local.your_email_domain}",
  ]
  developers = [
    "${local.your_email_before_at}+dev1@${local.your_email_domain}",
    "${local.your_email_before_at}+dev2@${local.your_email_domain}",
  ]
  operators = [
    "${local.your_email_before_at}+user1@${local.your_email_domain}",
    "${local.your_email_before_at}+user2@${local.your_email_domain}",
  ]

こんな感じでグループごとに所属するメンバー(アドレス)を管理する方法が良さそう。
加えて、もっとこうなったら便利だな~と思ったものは下記です。

  • emailのドメインは最初に定義しておいて毎回書かなくて良い状態にしたい
  • 権限関連(role、can_use_audit_log、is_restricted_connection_modify)は所属グループで判別して自動で設定してほしい

これらができるように設定を進めていきます。

以下はすべて .tfファイル内の設定になります。
前回の記事で作成した .tfファイルに追記する、もしくは新しく .tfファイルを作成して同ディレクトリに配置しても問題ありません。

emailのドメインを定義する

Terraformでは、variableを使うことで変数を定義できるようです。

ドメイン(primenumber.co.jp)を下記のように定義しました。

variable "domain".tf
variable "domain" {
  default = "example.com"
}

ユーザーリストをつくる

今回は例として sales、tech、management の3部署分のユーザーリストを作りました

variable "departments".tf
variable "departments" {
  type = map(list(string))
  default = {
    "sales" = ["user1", "user2"]
    "tech"   = ["user3", "user4"]
    "management" = ["user5"]
  }
}

type = map(list(string)) を利用すると文字列のリストが作成できます。
https://qiita.com/hikaru_motomiya/items/d773355d3ffa854c7ad3#list

権限周りは所属グループに合わせて自動で設定する

続いて、権限を自動で設定できるようにします。
部署ごとに、どのように権限をつけるか指定します。
salesチーム、techチームはroleをmember、その他は無効にします。
managementチームはroleをadmin、can_use_audit_logを有効にします。

variable "role".tf
variable "role" {
  type = map(object({
    role                            = string
    can_use_audit_log               = bool
    is_restricted_connection_modify = bool
  }))
  default = {
    management = {
      role                            = "admin"
      can_use_audit_log               = true
      is_restricted_connection_modify = false
    }
    sales = {
      role                            = "member"
      can_use_audit_log               = false
      is_restricted_connection_modify = false
    }
    tech = {
      role                            = "member"
      can_use_audit_log               = false
      is_restricted_connection_modify = false
    }
  }
}

type = map(object ~) でリストの要素1つずつに型を指定できます。

ユーザーを作成してみる

ChatGPTと話し合いをした結果、下記のようになりました。

.tf
resource "trocco_user" "example" {
  for_each = tomap({
    for idx, user in flatten([
      for department, members in var.departments : [
        for member in members : {
          email                           = "${member}@${var.domain}"
          role                            = var.role[lower(department)].role
          can_use_audit_log               = var.role[lower(department)].can_use_audit_log
          is_restricted_connection_modify = var.role[lower(department)].is_restricted_connection_modify
        }
      ]
    ]) : idx => user
  })
  
  email                           = each.value.email
  password                        = "Jb1p4f1uuC"
  role                            = each.value.role
  can_use_audit_log               = each.value.can_use_audit_log
  is_restricted_connection_modify = each.value.is_restricted_connection_modify
}

処理の内容をご紹介していきます。

処理の内容についてはChatGPTを質問責めにして返ってきた内容でふわっと理解しています。

variable "departments"(var.departments)内に含まれるdepartment(部署)に対してループ実行します。キー(部署名)とその値(メンバー)取得し、部署ごとのメンバーリストを作ります。

for department, members in var.departments : [

取得例:

department = "sales", members = ["user1", "user2"]

部署の各メンバーに対してループ処理し、各メンバー毎のリストを作成します。

for member in members : {

このとき、下記内容も一緒に参照します。

role                            = var.role[lower(department)].role
can_use_audit_log               = var.role[lower(department)].can_use_audit_log
is_restricted_connection_modify = var.role[lower(department)].is_restricted_connection_modify

取得例:

member = "user1"
email = "user1@example.com"
var.role_settings["sales"].role → "member"
var.role[lower(department)].can_use_audit_log → false
var.role[lower(department)].is_restricted_connection_modify → false

取得したリストをフラット化(flatten)します。
また、現時点ではキーが部署名のため一意のキーがありません。フラット化した各要素をループ処理してインデックス(idx)を割り当てます。

for idx, user in flatten ~~ : idx => user

Terraformのfor_eachに渡す値は、すべてユニークなキー(マップのキーやセットの要素)が必要です。下記のようにリソースの名前に使用されるため重複が許されないためです。重複しない値をさくっと生成してくれるのがインデックス(idx)です。

Terraform will perform the following actions:

  # trocco_user.example["0"] will be created
  ~~~
  # trocco_user.example["1"] will be created
  ~~~

for_each に渡す値を明示的にマップ型に変換します。リストや他のデータ構造をそのままfor_eachにわたすことができないためです。

for_each = tomap({

今実行しているループで取得した値を各要素に挿入します

email                           = each.value.email
password                        = "Jb1p4f1uuC"
role                            = each.value.role
can_use_audit_log               = each.value.can_use_audit_log
is_restricted_connection_modify = each.value.is_restricted_connection_modify

実行してみる

処理の内容を認識したところでterraform planを実行してどのような結果になるか見てみます。

>terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # trocco_user.example["0"] will be created
  + resource "trocco_user" "example" {
      + can_use_audit_log               = true
      + email                           = "user5@example.com"
      + id                              = (known after apply)
      + is_restricted_connection_modify = false
      + password                        = (sensitive value)
      + role                            = "admin"
    }

  # trocco_user.example["1"] will be created
  + resource "trocco_user" "example" {
      + can_use_audit_log               = false
      + email                           = "user1@example.com""
      + id                              = (known after apply)
      + is_restricted_connection_modify = false
      + password                        = (sensitive value)
      + role                            = "member"
    }

  # trocco_user.example["2"] will be created
  + resource "trocco_user" "example" {
      + can_use_audit_log               = false
      + email                           = "user2@example.com""
      + id                              = (known after apply)
      + is_restricted_connection_modify = false
      + password                        = (sensitive value)
      + role                            = "member"
    }

  # trocco_user.example["3"] will be created
  + resource "trocco_user" "example" {
      + can_use_audit_log               = false
      + email                           = "user3@example.com""
      + id                              = (known after apply)
      + is_restricted_connection_modify = false
      + password                        = (sensitive value)
      + role                            = "member"
    }

  # trocco_user.example["4"] will be created
  + resource "trocco_user" "example" {
      + can_use_audit_log               = false
      + email                           = "user4@example.com""
      + id                              = (known after apply)
      + is_restricted_connection_modify = false
      + password                        = (sensitive value)
      + role                            = "member"
    }

Plan: 5 to add, 0 to change, 0 to destroy.

想定している設定になっていそうです!

反映させる

terraform applyで反映してみます。(ドメインは環境に合わせて変更しています)

image.png

思った通りに動作して、無事権限の違いがあるアカウントを一括で作ることができました!
メンバーに変更が発生した場合はvariable "departments"の各部署のメンバーを増減させるだけでよいので管理が単純化できそうですね。

おわりに

Terraformでは、処理を指示している文の中で下記のmemberのように要素の名前を定義し始めるので それどこから出てきた??? となることが多かったです・・・

for department, members in var.departments : [
        for member in members : {

また、ループ処理をコードで指定するのは初めてだったのでどのように動作するのかなど全然わからず理解に時間がかかりました。
設定方法を理解するまでは コード管理むずい!!!GUIで設定で良くないか?? と思ったりもしました...。

ただ、設定が終わって実行してみると下記のようなメリットがあると実感でき、コード管理したいというご要望が多い理由もわかったような気がしました。

  • 登録するユーザーの権限について考慮しなくて良い(部署だけ把握していればOK)
  • 一括で複数ユーザーが操作できる(GUIでポチポチするより圧倒的に早い)(手軽さがすごい)

今回、部署毎でユーザ管理したので、TROCCOのチームもTerraformで管理するようにするとより便利になりそうです。
次はチーム管理もTerraformで行ってみたいと思います!

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?