🅱

TROCCO で Backlog のユーザー棚卸をする

に公開

はじめに

本記事の内容は #p_UG 東京:新コネクタLT大会で、デモ形式で発表した内容です。

https://pug.connpass.com/event/355776/

スライドは公開していますが、スライドでは伝わらない(何ならデモでもすっ飛ばした可能性がある)内容をこの記事で解説します。

今回のテーマ

(1) 棚卸

クラウドサービスの棚卸、してますか?してますよね??(念押し)
誰かがクラウドサービスを使っているならば、それは誰が管理者で、誰が使っているのか、正確に把握しておく必要があるでしょう。把握できていない状況はセキュリティリスクにつながります。
棚卸は必要。でも時間はかけたくない。そんなせめぎあいを誰しも体験しているかと思うところです。

(2) TROCCO Backlog コネクタ

primeNumber 社のETL製品 TROCCO で立ち上がったコネクタ大幅拡充プロジェクト「CONNECT 100+」。

https://primenumber.com/blog/connector_release_25_04

この中で、4月に追加されていたのが転送元 Backlog でした。
プロジェクト管理ツールとして利用している方は多数おられるのではないでしょうか。もちろん私もユーザーの一人です。

プロジェクト管理ツールという性質上、Backlog のユーザーはかなり大規模になり、参加するプロジェクトの制御のためのチームも増えていくと思います。
ユーザーが多いとつらくなるのが、ユーザーの棚卸です。

今回の記事では、できるだけサッサとユーザー棚卸を終わらせるために、正統派な方法を使ったり、TROCCO を使ったりしてみます。

前提

フォーマット

こんな感じのフォーマットでユーザー管理していると想定します。

ユーザーID 氏名 メールアドレス 所属チーム ロール 最終ログイン アクティブ 備考
user001 山田 太郎 yamada@example.com 営業チーム ADMIN 2025-06-20
user002 佐藤 花子 sato@example.com 開発チーム MEMBER 2025-06-21 退職予定
user003 鈴木 次郎 suzuki@example.com 管理チーム GUEST 2025-06-22 アカウント停止中

というわけで、何らかの手段で、できるだけ速く、できるだけ楽をしてこのフォーマットでユーザー一覧を作成することを考えます。

環境

棚卸の方法を試す Backlog 環境を用意します。
CSV で一括作成しましょう。

https://support-ja.backlog.com/hc/ja/articles/360035643534-ユーザーの追加-編集-削除#add_plural_users

ユーザー追加csvのテンプレ
"Email","Name","Role","Teams"
"user1@apps.nulab.com","User 1","Admin",""
"user2@apps.nulab.com","User 2","Member",""
"user3@apps.nulab.com","User 3","Guest","Cacoo Team;Typetalk Team"

一気に100人まで追加できるみたいなので、お言葉に甘えて100人追加しようとしています。が、フリープランのユーザー数上限は10ユーザーです。。。

ヌーラボさん、変な動きをするアカウントですみません。。。。

招待し、追加してからユーザー数が圧倒的に超過していることに気づいたので、30ほどユーザーを削除。
こうして、10人のユーザー、2つのチームを用意しました。この環境で棚卸を行っていきます。

方法(1) Backlog 自身のユーザー一覧 CSV を利用する

ユーザー一覧csv

当然ながら、Backlog 自身にもユーザー一覧を出力する機能は存在します。

https://support-ja.backlog.com/hc/ja/articles/360035645694-ユーザー一覧をダウンロードすることはできますか

フォーマットはこんな感じです。

<!--

"Email","Name","Unique ID","Role","Inviting","Managed Account","Teams","Teams where you're admin","External Organizations","Active"
"■■■■■■+user10@gmail.com","User 10","■■■■■■user10","GUEST","false","false","""TEST""","","","true"
"■■■■■■+user13@gmail.com","","","MEMBER","true","false","""TEST""","","","true"
"■■■■■■+user14@gmail.com","","","GUEST","true","false","""TEST""","","","true"
"■■■■■■+user16@gmail.com","User 16","■■■■■■user16","MEMBER","false","false","""TEST""","","","true"
"■■■■■■+user18@gmail.com","","","GUEST","true","false","""TEST""","","","true"
"■■■■■■+user1@gmail.com","User 1","■■■■■■user1","MEMBER","false","false","""TEST""","","","true"
"■■■■■■+user20@gmail.com","","","MEMBER","true","false","""TEST""","","","true"
"■■■■■■+user23@gmail.com","","","MEMBER","true","false","""TEST""","","","true"
:中略
"■■■■■■@gmail.com","梶谷美帆","■■■■■■","ADMIN (Plan admin)","false","false","""MIHOKAJIYA全体"";""TEST"";""TEST2""","""MIHOKAJIYA全体"";""TEST"";""TEST2""","","true"

-->

メールアドレス、ユーザー名、招待中か、参加チーム(; 区切り)、ロール、Adminかどうか、...おおむね必要な情報はありそうですね。 [1]

というわけで、これを使ってユーザー棚卸しする方法を考えます。

csv 加工

構造化データなので SQL で処理するのが手っ取り早いでしょう。ではここに DuckDB を召喚します。

Docker コンテナのソースコード

Dockerfile

FROM datacatering/duckdb:v1.3.1

WORKDIR /app

COPY init.sql /app/

EXPOSE 3000

CMD ["duckdb", "-c", ".read init.sql"]

docker-compose.yml

version: '3.8'

services:
  duckdb:
    build: .
    container_name: duckdb-container
    ports:
      - "3000:3000"
    volumes:
      - ./data:/app/data
    stdin_open: true
    tty: true

init.sql

-- Initialize DuckDB and load CSV file
CREATE TEMPORARY TABLE members AS SELECT * FROM read_csv_auto('data/input.csv');

COPY (
SELECT 
    "Unique ID" AS "ユーザーID",
    "Name" AS "氏名", 
    "Email" AS "メールアドレス",
    REPLACE("Teams", ';', ' | ') AS "所属チーム",
    "Role" AS "ロール",
    '' AS "最終ログイン",
    CASE 
        WHEN "Active" = true THEN '〇'
        ELSE '✕'
    END AS "アクティブ",
    '' AS "備考"
FROM
    members 
) TO 'data/output.csv' (
    HEADER,
    DELIMITER ','
) 
;

結果

最終ログインは、このCSVだけでは取れなさそうなので一旦空欄。
アクティブか否かは、招待中かどうか(Inviting)からとったほうが良いかも?

方法(2) TROCCO Backlog コネクタを使う

準備編

Backlog API キー作成

Backlog 側でAPIキーを作成しておきます。作成の際は管理者ユーザーを使います。

https://support-ja.backlog.com/hc/ja/articles/360035641754-APIの設定

TROCCO

Backlog 接続情報作成

先ほど取得した API キーを指定して、Backlog 接続情報を作成します。ホスト名は対象の Backlog の URL から取得。

転送設定作成

ここまで来たら、転送設定は選ぶだけです。
「ユーザー一覧」「チーム一覧」それぞれの転送設定を作成。

転送します。継続的に取得するならワークフロー化するのがいいですね。

Snowflake

ビューを作ります。

クエリ
create or replace view backlog_user_list as 
with teams as (
    SELECT
      t."name" as "所属チーム",
      -- tmp_f.*,
      f.value:lastLoginTime as "最終ログイン",
      f.value:mailAddress as "メールアドレス",
      f.value:name as "氏名",
      f.value:userId as "ユーザーID",
    FROM
      BACKLOG_TEAMS AS t
      , LATERAL FLATTEN(input => parse_json(t."members"), outer => true) AS f
),
users as (
    SELECT
      t."userId" as "ユーザーID", -- ほんとは uniqueId のほうが
      t."name" as "氏名",
      case
        when t."roleType" = 1 then 'Admin'
        when t."roleType" = 2 then 'Member, Guest'
        when t."roleType" = 3 then 'Member, Guest (Add Issues Only)'
        when t."roleType" = 4 then 'Member, Guest (View Issues Only)'
        else ''
      end as "ロール",
      t."mailAddress" as "メールアドレス",
      t."lastLoginTime" as "最終ログイン",
      -- tmp_f.*,
    FROM
      BACKLOG_USERS AS t
),
final as (
    select
        bu."ユーザーID",
        bu."氏名",
        bu."メールアドレス",
        listagg(bt."所属チーム", ' | ') as "所属チーム",
        bu."ロール",
        max(bu."最終ログイン") as "最終ログイン",
        iff(max(bu."最終ログイン") is not null, '〇', '✕') as "アクティブ",
        '' as "備考"
    from
        users bu
    inner join
        teams bt
    on
        bu."ユーザーID" = bt."ユーザーID" 
    group by
        bu."ユーザーID"
        , bu."氏名"
        , bu."メールアドレス"        
        , bu."ロール"
)
select * from final;

結果

だいたいの情報をとれているので、これでよさそうです!

おわりに(小ネタ)

ユーザー作成時のcsvの内容を都度管理していくのも最適解な気がしますが、、、
クラウドサービス管理にはクラウドサービス管理用の製品を使うのが一番ですが、TROCCO があるならこんな方法もあるよという話でした。

脚注
  1. 欲深い人間なので、最終ログイン日や MFA 有効化済みか否かも欲しい気がしています ↩︎

DATUM STUDIO

Discussion