TECH PLAY

ワークショップ

イベント

マガジン

技術ブログ

Azureを使ったハンズオンやワークショップを開催する際、参加者のユーザーや参加者毎の専用リソースグループを用意し、それぞれに適切な権限を設定したいことがあると思います。 本記事では、Terraformのfor eachを使用してこれらの準備を効率的に行う方法について解説します。 for eachとは Terraformのfor eachは、リソースを複数回繰り返し作成するための機能です。 通常、複数のリソースを作成する際はそれぞれ個別にresourceブロックを記述必要がありますが、この機能を使用すると複数のリソースを1つのresourceブロックで定義することができます。 メリット 1. 効率性の向上 for eachを使用しない場合、コンソールで作成またはresourceブロックを記述する作業をリソースの数だけ繰り返すことになります。 for eachを使用すれば、リストとresourceブロックをそれぞれ1つ記述するだけで作成できます。 2. パラメーターの設定ミスの低減 「同じパラメーターでリソース名だけが違う」というように、一部のパラメーターだけが異なるリソースを複数作成するケースがあると思います。 for eachを使用せずに個別に作成すると、作業ミスで一部のリソースだけ異なる設定にしてしまうことがあるかもしれません。 しかし、for eachを使用すれば、変えたいパラメーター(リソース名等)だけをリストに記述し、他のパラメーターは全く同じリソースを安全に作成することができます。 使い方 まずは、リストを記述します。 locals { names = ["group_a", "group_b", "group_c"] } for eachにこのリストを指定し、{パラメーター名} = each.key と記述すると、そのパラメーターの値がリストの各要素の値となったリソースが作成されます。 下記のコードの場合、リソース名がgroup_a、group_b、group_cのリソースグループ3つが作成されます。 resource "azurerm_resource_group" "example_groups" { for_each = toset(local.names) name = each.key ・・・ } また、for eachを使用して作成されたリソースはマップ型になっているため、それらのパラメーターはeach.value.{パラメーター名}で参照できます。 下記のコードの場合、リソース名がexample_vmの仮想マシンがgroup_a、group_b、group_cに作成されます。 resource "azurerm_windows_virtual_machine" "example_VMs" { for_each = azurerm_resource_group.example_groups name = "example_vm" resource_group_name = each.value.name ・・・ } 想定ユースケース ここからはfor eachを活用した実践的な例として、Azureのワークショップやハンズオンの環境準備を想定したTerraformコードについて解説します。 想定するユースケースは以下の通りです。 参加者にはそれぞれユーザーを発行する 参加者毎に専用のリソースグループを作成し、自分のリソースグループでのみリソースの作成/閲覧/更新/削除ができるようにする 参加者全員が参照する共通のリソースは閲覧のみ可能にする 構成イメージ Terraformコード 最終的なコードは以下の通りです。以降の章で各部の解説を行います。 # ユーザー名のリスト variable "user_names" { default = ["user1", "user2", "user3"] } # ユーザーIDと専用リソースグループの名前のリスト locals { user_ids = [for user_name in var.user_names: "${user_name}_workshop@xxxxx.onmicrosoft.com"] resource_groups = [for user_name in var.user_names: "${user_name}_workshop_group"] } # ユーザーを作成 resource "azuread_user" "workshop_users" { for_each = toset(local.user_ids) user_principal_name = each.key display_name = each.key password = "xxxxx" } # グループを作成 resource "azuread_group" "workshop_group" { display_name = "workshop" security_enabled = true } # ユーザーをグループに追加 resource "azuread_group_member" "workshop_members" { for_each = azuread_user.workshop_users group_object_id = azuread_group.workshop_group.object_id member_object_id = each.value.object_id } # 共通リソースグループを作成 resource "azurerm_resource_group" "shared_rg" { name = "shared_workshop_group" location = "japaneast" } # 専用リソースグループを作成 resource "azurerm_resource_group" "user_rg" { for_each = toset(local.resource_groups) name = each.key location = "japaneast" } # 共通リソースグループに対する権限を定義 resource "azurerm_role_definition" "shared_rg_read" { name = "SharedRGRead" scope = azurerm_resource_group.shared_rg.id description = "全員共通RGの閲覧権限" permissions { actions = [ "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/subscriptions/resourceGroups/resources/read" ] not_actions = [] } assignable_scopes = [azurerm_resource_group.shared_rg.id] } # 共通リソースグループに権限を付与 resource "azurerm_role_assignment" "group_shared_rg_read_assign" { scope = azurerm_resource_group.shared_rg.id role_definition_id = azurerm_role_definition.shared_rg_read.role_definition_resource_id principal_id = azuread_group.workshop_group.object_id } # 専用リソースグループへの権限を定義 resource "azurerm_role_definition" "user_rg_crud" { for_each = azurerm_resource_group.user_rg name = "UserRGCRUD_${each.key}" scope = each.value.id description = "${each.key}専用RG用のCRUD権限" permissions { actions = [ "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/subscriptions/resourceGroups/write", "Microsoft.Resources/subscriptions/resourceGroups/delete", "Microsoft.Resources/*/read", "Microsoft.Resources/*/write", "Microsoft.Resources/*/delete", "Microsoft.Resources/deployments/*" ] not_actions = [] } assignable_scopes = [each.value.id] } # 専用リソースグループに権限を付与 resource "azurerm_role_assignment" "user_rg_crud_assign" { for_each = { for idx, rg_name in local.resource_groups : rg_name => local.user_ids[idx] } scope = azurerm_resource_group.user_rg[each.key].id role_definition_id = azurerm_role_definition.user_rg_crud[each.key].role_definition_resource_id principal_id = azuread_user.workshop_users[each.value].object_id } 1. ユーザー名のリストを作成 ユーザー名のリストを作成しています。 # ユーザー名のリスト variable "user_names" { default = ["user1", "user2", "user3"] } 2. ユーザーIDと専用リソースグループの名前のリストを作成 1のリストを使用して、ユーザーIDと専用リソースグループの名前のリストを作成します。 # ユーザーIDと専用リソースグループの名前のリスト locals { user_ids = [for user_name in var.user_names: "${user_name}_workshop@xxxxx.onmicrosoft.com"] resource_groups = [for user_name in var.user_names: "${user_name}_workshop_group"] } 3. ユーザーを作成 2のユーザーIDのリストを使用して、ユーザーを作成します。 ※ 手順の簡略化のため、ユーザーの表示名はユーザーIDと同じ値にしています。 # ユーザーを作成 resource "azuread_user" "workshop_users" { for_each = toset(local.user_ids) user_principal_name = each.key display_name = each.key password = "xxxxx" } 4. グループを作成 & ユーザーを追加 グループを作成し、3のユーザーをグループに追加します。 # グループを作成 resource "azuread_group" "workshop_group" { display_name = "workshop" security_enabled = true } # ユーザーをグループに追加 resource "azuread_group_member" "workshop_members" { for_each = azuread_user.workshop_users group_object_id = azuread_group.workshop_group.object_id member_object_id = each.value.object_id } 5. 共通リソースグループを作成 共通リソースグループを作成します。 # 共通リソースグループを作成 resource "azurerm_resource_group" "shared_rg" { name = "shared_workshop_group" location = "japaneast" } 6. 各ユーザーの専用リソースグループを作成 2の専用リソースグループの名前のリストを使用して、専用リソースグループを作成します。 # 専用リソースグループを作成 resource "azurerm_resource_group" "user_rg" { for_each = toset(local.resource_groups) name = each.key location = "japaneast" } 7. 共通リソースグループへのRead権限を定義 & グループに権限を付与 5の共通リソースグループへのRead権限を定義し、4のグループに付与します。 # 共通リソースグループに対する権限を定義 resource "azurerm_role_definition" "shared_rg_read" { name = "SharedRGRead" scope = azurerm_resource_group.shared_rg.id description = "全員共通RGの閲覧権限" permissions { actions = [ "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/subscriptions/resourceGroups/resources/read" ] not_actions = [] } assignable_scopes = [azurerm_resource_group.shared_rg.id] } # 共通リソースグループに権限を付与 resource "azurerm_role_assignment" "group_shared_rg_read_assign" { scope = azurerm_resource_group.shared_rg.id role_definition_id = azurerm_role_definition.shared_rg_read.role_definition_resource_id principal_id = azuread_group.workshop_group.object_id } 8. 専用リソースグループへのCRUD権限を定義 & 各ユーザーに権限を付与 6の専用リソースグループへのCRUD権限を定義し、各ユーザーに付与します。 Microsoft.Resources/*/read, write, delete の、「*」の部分にサービス名を記述することで、特定のサービスに限定した権限を付与することもできます。 # 専用リソースグループへの権限を定義 resource "azurerm_role_definition" "user_rg_crud" { for_each = azurerm_resource_group.user_rg name = "UserRGCRUD_${each.key}" scope = each.value.id description = "${each.key}専用RG用のCRUD権限" permissions { actions = [ "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/subscriptions/resourceGroups/write", "Microsoft.Resources/subscriptions/resourceGroups/delete", "Microsoft.Resources/*/read", "Microsoft.Resources/*/write", "Microsoft.Resources/*/delete", "Microsoft.Resources/deployments/*" ] not_actions = [] } assignable_scopes = [each.value.id] } # 専用リソースグループに権限を付与 resource "azurerm_role_assignment" "user_rg_crud_assign" { for_each = { for idx, rg_name in local.resource_groups : rg_name => local.user_ids[idx] } scope = azurerm_resource_group.user_rg[each.key].id role_definition_id = azurerm_role_definition.user_rg_crud[each.key].role_definition_resource_id principal_id = azuread_user.workshop_users[each.value].object_id } 確認 terraform applyを実行してAzure環境にコードで記述した内容を反映した後、管理者権限を持つユーザーでログインすると、以下のようにグループにユーザーが3つ追加されていることがわかります。 また、リソースグループも共通1つと専用3つの計4つが作成されていることが確認できます。 続いて、参加者用ユーザーでログインします。(下の画像はuser1_workshop@xxxxx.onmicrosoft.comでログイン) リソースグループを見に行くと、共通リソースグループと自分の専用リソースグループしか表示されないことが確認できます。 まとめ 以上の手順で効率的にユーザー/グループ/リソースグループの作成と権限の付与ができます。 TerraformをはじめとするIaCツールを使用せずに手作業で上記の環境準備を実施する場合、特に各自の専用リソースグループに対する権限付与の部分で多くの手間がかかってしまいます。 本記事で紹介したケースに限らず、for_eachを使用することで効率的にインフラ構築ができますの皆様もぜひお試しください!
LINEヤフーでは、開発業務に関わる全てのエンジニアを対象に、AI活用スキルを実践的に高めるワークショップ「Orchestration Development Workshop」を開始しました。この取...
1. はじめに(自己紹介) こんにちは。Insight Edgeでデザインストラテジストをしている望月です。 Insight Edgeは住友商事グループの内製支援組織として、エンジニアやデザイナー、コンサルタントなどのスペシャリストが所属し、グループ内のデジタル活用を支援しています。 僕自身はデザインストラテジストという肩書きで、UIなどの狭い意味でのデザインに閉じず、戦略策定や文化醸成施策の検討、新規事業の構想などに関わっています。主にはデザインの考え方や手法を活かして、ビジネス課題を解くことがミッションです。 この記事では「総合商社DXでのデザイナーの役割と魅力」というテーマで、総合商社の現場でデザイナーがどんな形で効くのか/面白さがどこにあるのかを、自分の実践も交えながらまとめます。 2. なぜデザイナーが必要なのか? 総合商社のDXは、いわゆるプロダクト開発の文脈と比べると、前に進める難しさの質が少し違うと感じています。大きく言うと、次の3つが重なりやすいです。 ステークホルダーが多い/役割が重層 本社機能、事業部門、現場、グループ会社、外部パートナーなど、関わる人が多いです。しかも「同じプロジェクトに関わっているのに、見ている景色が違う」ことがよく起きます。 こういった状況で合意形成や意思決定を円滑に進めるために必要とされることが多いです。 事業×業務×デジタル(手法)が絡む 業務プロセスを変えるだけでは成果が出ないし、デジタルを入れるだけでも成果が出ない。 事業(どんな価値を出すか)・業務(どう回すか)・手法(どう実現するか)が絡み合っているため、そういった状況を整理する場面も多いです。 正解が一つじゃない 「これが唯一の正解」という問題よりも、「複数の選択肢の中で、どれを採るか」を決め続ける問題が多いです。 さらに、途中で前提が変わることもあるので、決め方や学び方が重要になります。 こういう環境で前に進めるために単に作ること以上に、次のような動きを求められることが多いです。 状況を整理して共通理解を作る 合意形成の場を設計する 失敗を小さくしながら学びを回す 導入して終わりではなく、運用・定着まで見据える こういった点で、デザイナーの強みがハマることが多いです。 3. デザイナーの役割 ここからは、総合商社DXの現場でデザイナーが担う役割を、僕の感覚で整理してみます。 (1) 複雑さの翻訳:業務・用語・前提を共通言語にする 多くの人が携わるプロジェクトでは「同じ言葉を使っているのに意味が違う」ことが起きがちです。 このズレが残ったままだと、会議は増えるのに決まらない/決めても動かない、が発生します。 そこで、コンセプト策定、業務フロー、概念図、情報設計などを使って、全員が同じ認識で話せる状態を作ります。 (2) 合意形成の設計:意思決定の場を前に進める 同様に、多くの、さまざまな価値観を持った人が携わるプロジェクトでは、合意形成のプロセス自体も重要になります。 ワークショップの設計やファシリテーション、必要なアウトプットの作成を行うことで、前に進む形を作ります。 (3) 価値検証の設計:作る前に失敗を小さくする DXやAI活用は特に新しい領域のため、「作ってみないとわからない」「前例のない取り組み」が多いです。とはいえ、作り込んでからズレるとコストも心理的負担も大きくなります。 仮説を置いて、軽い検証を回して、学びを意思決定に戻す。 プロトタイプ、業務シナリオ、ユーザー/現場ヒアリングなどを使いながら、「作る前に失敗を小さくする」ための設計をします。 (4)「やってみなければわからない」領域に飛び込むための指針/ビジョンを作る AIやデジタルを用いた新規事業の構想に取り組む際、特に最初期は「やってみないとわからない」ことが多いため、最初からビジョンやロードマップを作るというよりも、スモールスタートで課題やニーズを検証し、一歩ずつ進めるやり方を取ることが多いです。 しかし、ある程度進めていくと、取り組みを加速させるために巻き込む関係者を増やし、共通のゴールに向かって進めることが必要になってきます。そのときに必要になるのが「何のためにやるのか」「どこに向かうのか」という指針です。 こういった取り組みの中で、「自分たちがどのような将来像を作っていきたいのか?」というビジョンやコンセプト、それを実現するためのロードマップを作成することで、成功に向けた筋道を作っていきます。 (5) 運用の設計:導入後も回る仕組みを作る ツールを導入して終わりにせず、その後も使われ続ける状態を作る。もっと言うと、今後新しい技術や社会の変化が起こったときに、現場で自律的にそういった変化に対応できる状態を作っていくことが、DXの難しいところだと思っています。 特にAIは、たとえば次のような理由で定着しないことがあります。 使っていいのか不安 失敗したときの責任が曖昧 日々の業務の中で使うタイミングがない 便利でも評価されない なので、ガバナンス、教育、コミュニティ、成功体験の作り方、評価や称賛の仕組みまで含めて、導入後も回る形を設計します。単に使い方を丁寧にインストールするのではなく、仕組みを作って自律的に回っていく状態を作っていきます。 4. 関わった取り組みの例 ここからは、実際に自分が関わった取り組みの中で、上の役割がどう出てくるかを例として紹介します(守秘の都合で抽象化しています)。 実践例1:AI活用事業のビジョンの策定 AI活用のプロジェクトは、立ち上げ段階で議論が「夢が大きい話」と「目先の課題解決」の間を行ったり来たりしがちです。 このままだと、合意形成が進まない/進んでも伸びしろがない/現場の細かい要望に左右されて、当初目指したかったものからぶれた、局所的な解決に陥ってしまうことが多いです。 そこで、自分たちがどのように取り組んでいきたいのかを、言語・ビジュアルで表してビジョンを作り、推進するための軸を作ることにも取り組んでいます。 取り組みのプロセス 社会の潮流や他社の事例、AIの受け取られ方や活用方法についてのリサーチ 実際にプロジェクトを推進しているメンバーや携わっている人たちの想いを知るためのインタビュー リサーチを踏まえ、強みや差別点、大事にしていきたいポイントを整理するための分析 ワークショップでの「自分たちが実現したいイメージ」のアイデア出し アイデアを統合し、ビジョンについて合意形成 ビジョンをキャッチコピーとビジュアルに落とし込み 実現に向けた筋道を整理し、ビジョンブックとして制作 実践例2:事業構想ワークショップの企画・実施 基本的に総合商社の人たちは事業を検討したり育てていくことに非常に慣れ親しんでいるのですが、デザイン的な観点での事業構想や、技術活用とのつなぎ込みの観点から、事業構想の支援としてワークショップなどを企画・開催することもあります。 取り組みのプロセス 事業アイデアを生み出すためのワークショップを企画・設計 ワークショップをファシリテーションし、ビジネスアイデアについて議論 良さそうなビジネスアイデアについてはエンジニアメンバ等も巻き込み、実行に向けた支援を行う 実践例3:AI活用の文化を醸成するための施策立案 AI活用は、環境を用意しても使われないことがあります。理由は単純なスキル不足だけではなく、心理的な不安や運用の摩擦が大きいです。 そういった場面で、技術的な観点ではなく、人間の感情や行動の観点から、どうしたら現場の人たちが抵抗なくAIを業務に取り込み、業務を変化させていけるかの文化醸成戦略の立案を行ったりもします。 取り組みのプロセス リサーチや施策の実行を通じて、現場の人たちの声を収集 収集した内容を分析し、AI活用に対してどのような点で課題を感じているのか/どのような点に魅力を感じているのかを構造的に整理 課題を解決するための施策案を、技術的なサポートからイベントやセミナーの実施、制度の作成やコミュニケーションチャネル作りなど、さまざまな観点で立案 施策をロードマップ化し、担い手と運用の形まで落とす 5. 使っているスキル 向き合っている課題や領域が幅広いので、仕事の中で使っているスキルも一つに固定されません。常に勉強しながら、状況に応じて必要なものを組み合わせています。 最近よく使っているものを、僕の中ではだいたい次のように整理しています。 (1) 複雑さを扱う「構造化・可視化」 ステークホルダーが多い環境では、議論が言葉だけで進むと前提がズレたまま進んでしまうことがあります。 そこで、論点・前提・関係性を“見える形”にして、同じものを見て話せる状態を作ります。 複雑な要因を構造的に整理するためにシステム思考などの考え方で構造化を行うことも多いです。 業務フロー/概念図/関係者マップ 論点整理(決めること・決めないこと) 価値の分解(狙う価値、判断軸の整理) (2) 意思決定を進める「場の設計・ファシリテーション」 ワークショップの設計やファシリテーションを行う機会も多いです。問いの順番、アウトプット、参加者の役割を設計して、合意形成を前に進めます。 ワークショップ設計 ファシリテーション (3) 「仮説→検証→学習」を回す検証設計 AI活用や新規事業の構想は、最初から正解を当てにいくより、早く学ぶことが重要になる場面が多いです。 仮説を分解して、何から検証するかを設計し、結果を次の意思決定につなげます。このあたりはデザイン思考的な考え方で回すことが多いです。 デザインリサーチ(インタビュー設計・実施、分析) 価値仮説の分解と検証計画の作成 業務シナリオ/簡易プロトタイプでの検証 学びの整理(継続・ピボット・停止につなぐ) (4) 伝わる形にする「ストーリーテリング/表現設計」 ビジョンやコンセプトは、言葉として正しいだけでは広がりません。 関係者が同じ未来を想像できるように、ストーリーや表現に落とします。 コピーライティング(キャッチコピー、メッセージ設計) クリエイティブディレクション、ビジュアル制作 ビジョンブックなど、共有のための成果物制作 上に挙げたものは「全部できないといけない」という話ではありません。同じチームの中にも得意領域が違う人がいて、役割分担しながら進めることが多いです。 デザイン的な課題解決が好きで、より社会的なインパクトの大きいテーマに向き合ってみたい人であれば、活躍できる余地は大きい仕事だと思っています。 6. 仕事の魅力 最後に、僕がこの仕事で魅力的だと感じている点を紹介します。 インパクトが大きい(業務・組織・投資が動く) 世界規模で動いている事業に関わる機会があり、意思決定の結果が業務や組織、投資に波及します。 難しい一方で、うまく前に進んだときの手触りは大きいです。 エコシステム全般に向き合える ステークホルダーが多い=やりとりが大変、でもあるんですが、総合商社の扱っているバリューチェーンの「エコシステム全体」を対象に、デザイン的な観点で課題分析に取り組むことができます。 事業・業務・IT・ガバナンス・人や文化まで含めて扱うので、デザインの射程が自然と広がります。 AIという今いちばん熱い道具を使って、事業、ひいては社会をどう変えるかを描ける 基本的には社会は技術の進歩によって大きく変わってきましたが、今私たちが向き合っている「AI」の登場は、今後の産業構造を大きく変えていきうる変革のポイントだと考えています。 そういった中で、総合商社の幅広いフィールドを対象に取り組むことは、「今後の社会をどう変えていくのか?」を描くのに近い仕事でもあると思っています。 まとめ ここまでお読みいただき、ありがとうございました。 Insight Edgeのデザインストラテジストの仕事に、少しでも興味を持っていただけたら嬉しいです。Insight Edgeでは、住友商事グループのデジタル活用支援として、DX推進や生成AIなど最先端のテーマに関わる機会があります。 また、プロジェクトによっては新規事業の構想や支援に関わり、関係者と一緒に筋道を作りながら進めていくこともあります。その中で幅広いスキルを身につけつつ、社会に届ける価値をデザインで形にできる環境があると感じています。 現在、Insight Edgeではデザインストラテジストを募集しています。これまで培ってきた経験を活かし、デザインを武器に未来の姿を一緒につくりませんか?

動画

書籍