case_609 SaaS・IT

入退社のSaaSアカウント削除漏れをClaude Codeで棚卸しする実装

入退社のSaaSアカウント削除漏れをClaude Codeで棚卸しする実装

退職者のSaaSアカウント削除漏れは情報漏えいと無駄なライセンス費の温床。人事名簿と各SaaSの利用者一覧をClaude Codeで突合し、削除漏れ・権限過剰を検知する棚卸しの実装パターンを解説。

結論:退職者のSaaSアカウント削除漏れは「気をつける」では防げません。人事名簿を正、各SaaSの利用者一覧を従とする突合スクリプトをClaude Codeに書かせ、削除漏れ・名簿外アカウント・権限過剰の3種類を毎週レポートさせる仕組みに変えるのが本記事の提案です。削除の実行は人間に残し、検知だけをコードに持たせます。

  • 要点1:削除漏れの根因は担当者の注意力ではなく構造。SaaSごとに管理画面が分かれ、退職連絡の経路(人事→情シス)とアカウントの実体(各SaaSの管理コンソール)が分離しているため、SaaSが増えるほど「出口」の漏れは統計的に必ず発生する
  • 要点2:放置のコストはセキュリティだけではない。使われないライセンスの支払い、内部統制・監査対応での指摘、そして漏えい時には個人情報保護法上の報告義務(個人情報保護委員会)まで連鎖する
  • 要点3:実装の核は「CSVの正規化と突合」というClaude Codeが最も得意な処理。各SaaSからエクスポートした利用者一覧を共通形式に揃え、社員IDまたはメールアドレスをキーに名簿と突合するだけで、初回から棚卸し台帳が手に入る

対象読者:情報システム・総務部門の担当者と、社内のAI活用を進める開発者・PM・経営企画

今日やること:直近3か月の退職者を3名書き出し、その人のアカウントが「会社で使っているSaaSのうち何個で消えているか」を確認する。全部即答できなければ、本記事の仕組みが役に立ちます

先に断っておくと、本記事は複数の導入支援経験をもとに一般化した実装パターン解説です。記事中の工数・コスト・効果の数値はすべて想定モデルの試算であり、実測値ではありません。また、アカウント管理の具体的な運用は各社の情報セキュリティ規程・個人情報の取扱規程に従い、判断に迷う場合は自社のセキュリティ責任者や顧問の専門家に確認してください。本記事は「棚卸しという反復作業をどうコードに落とすか」という実装側の話に絞ります。

企業向けのAI研修で情報システム部門の方と話すと、かなりの確率で出てくる相談があります。「退職者のアカウント、全部消えているか正直自信がない」。入社時の発行はまだいいんです。本人から「使えない」と連絡が来るから漏れが露見する。問題は退職時で、こちらは誰からも催促が来ません。消し忘れたアカウントは、誰にも気づかれないまま静かに残り続けます。そしてこの「複数のCSVを突き合わせて差分を見つける」仕事は、まさにClaude Codeのようなコーディングエージェントの得意分野です。

なぜ削除漏れは起きるのか——「入口」は1つでも「出口」はSaaSの数だけある

削除漏れを担当者の怠慢として片づけると、対策が「チェックリストを作って気をつける」で止まり、また漏れます。構造から見たほうが正確です。

入社時のアカウント発行は、業務が始められないという強いフィードバックがあるため自然に完了します。一方、退職時の削除にはフィードバックがありません。さらに、退職の情報は人事部門に発生し、アカウントの実体は各SaaSの管理コンソールに散らばっています。人事から情シスへの連絡が1日遅れる、連絡は来たがSaaSリストが古く新しく契約したツールが載っていない、部門が勝手に契約したツールがそもそも情シスの管理外——どれもよくある話です。

つまり、退職処理は「1つのイベントをN個のシステムに反映する」分散処理であり、Nが増えるほど反映漏れの確率は上がります。中堅企業でも利用SaaSが数十個に達することは珍しくなく、この規模になると人力チェックリストは現実的に破綻します。必要なのは注意力ではなく、「現在のあるべき状態(人事名簿)」と「実際の状態(各SaaSの利用者一覧)」を機械的に比較し続ける仕組みです。

放置のコストは3つ——セキュリティ・ライセンス費・監査対応

削除漏れアカウントのリスクとして最初に想像されるのはセキュリティです。退職者のアカウントが生きたままなら、本人による持ち出しにも、第三者による乗っ取りにも使えます。IPA(情報処理推進機構)の「情報セキュリティ10大脅威 2025」組織編でも「内部不正による情報漏えい等の被害」が10大脅威の一つに選出されており(IPA公式・2026年7月参照)、退職者アカウントの放置はその典型的な入口として挙げられ続けています。また、万一そのアカウント経由で個人データの漏えいが起きれば、事案によっては個人情報保護委員会への報告と本人への通知が法律上の義務になります(個人情報保護法・詳細は個人情報保護委員会の公式サイトを確認してください)。

2つ目は、地味に効くライセンス費です。有料SaaSの多くはアカウント数課金なので、削除漏れはそのまま毎月の無駄払いになります。仮に1人あたり月1,500円のSaaSを5個契約している会社で、退職者10名分の削除が漏れたままなら月75,000円、年間90万円——これはあくまで説明用の試算ですが、棚卸しを初めて実施した会社が「浮いたライセンス費だけで取り組みの元が取れた」という話は珍しくありません(想定モデルの試算です)。

3つ目は監査対応です。内部統制の整備・運用状況を確認される場面では、「退職者のアクセス権が適時に削除されているか」は定番の確認項目です。棚卸しの記録が残っていなければ、指摘への回答にも時間がかかります。逆に、後述する突合レポートを日付つきで蓄積しておけば、それ自体が「定期的に棚卸しを実施している」証跡になります。

実装の全体像——人事名簿を「正」、SaaSを「従」とする突合

作るものはシンプルで、次の3点だけです。

  1. 収集 — 各SaaSの管理コンソールから利用者一覧をCSVでエクスポートし、決めたフォルダに置く(Google WorkspaceやMicrosoft 365、Slackなど主要サービスは管理者権限があれば一覧をエクスポートできます。手順は各サービスの公式ヘルプを確認してください)
  2. 正規化 — SaaSごとに列名も形式もバラバラな一覧を、共通形式(社員ID・メールアドレス・表示名・権限・最終ログイン・サービス名)に変換する
  3. 突合 — 人事名簿(在籍者・退職者と退職日)と共通形式の一覧を突き合わせ、異常を3分類でレポートする

リポジトリ構成の例です。

account-audit/
├── CLAUDE.md            # 突合ルール・社内の前提を記述
├── roster/
│   └── roster.csv       # 人事名簿(社員ID・氏名・メール・在籍状況・退職日)
├── exports/             # 各SaaSからのエクスポート置き場
│   ├── google_workspace.csv
│   ├── m365.csv
│   └── slack.csv
├── config/
│   └── services.yaml    # サービスごとの列名マッピング・単価
├── scripts/
│   ├── normalize.py     # 共通形式への正規化
│   └── reconcile.py     # 名簿との突合とレポート生成
└── reports/             # 日付つき棚卸しレポートの蓄積

CLAUDE.mdには、Claude Codeに毎回口頭で伝えなくて済むよう、社内の前提を書いておきます。

# CLAUDE.md(抜粋)
## このリポジトリの目的
人事名簿と各SaaSの利用者一覧を突合し、アカウントの棚卸しレポートを作る。

## ルール
- 突合キーは社員ID。無い場合はメールアドレスの小文字化で代用
- 名簿の在籍状況が「退職」かつSaaS側にアカウントが存在 → 「削除漏れ」
- SaaS側に存在するが名簿に居ない → 「名簿外アカウント」(共有用・システム用は config/services.yaml の除外リストで管理)
- 権限列が admin/owner 相当 → 管理者一覧として別表に出す
- アカウントの削除・停止操作は絶対にしない。レポート生成のみ

最後の1行が重要です。この仕組みの役割は検知までで、削除の実行は必ず人間が各SaaSの管理画面で行います。理由は失敗パターンの節で詳しく説明します。

実装コード例1:バラバラなエクスポートを共通形式に正規化する

最初の壁は、SaaSごとにCSVの列名も値の形式も違うことです。メールアドレスの列が「Email Address」だったり「primaryEmail」だったり、権限が「Admin」「owner」「管理者」だったりします。これを1つずつ手で直すのではなく、サービスごとの違いを設定ファイルに寄せて、変換コードはClaude Codeに書かせます。

# config/services.yaml(例)
google_workspace:
  file: exports/google_workspace.csv
  columns:
    email: "Email Address [Required]"
    name: "First Name [Required]"
    admin_flag: "Admin Role"
  monthly_cost_jpy: 1360   # 参考: 自社契約プランの1人あたり単価を入れる
slack:
  file: exports/slack.csv
  columns:
    email: "email"
    name: "fullname"
    admin_flag: "role"
  exclude_accounts:        # 共有・システム用の除外リスト
    - "[email protected]"
    - "[email protected]"

Claude Codeへの依頼はこう書きます。

exports/ 配下の各CSVを config/services.yaml のマッピングに従って読み込み、
共通形式(service, email, name, is_admin, source_row)のDataFrameに正規化する
scripts/normalize.py を書いてください。

- メールアドレスは小文字化し、前後の空白を除去する
- admin_flag は yaml側で定義した値との照合で is_admin を True/False にする
- exclude_accounts に載っているメールは除外し、除外した件数をログに出す
- マッピングに無い列が来ても落ちないようにし、警告として出力する
- 不足している情報があれば、最初に質問してから作業を開始してください

最後の一行はどのプロンプトにも入れている定型です。前提を勝手に仮定して進むのを防ぎ、たとえば「Slackのroleにはguestという値もありますが、ゲストは管理者扱いにしませんね?」といった確認が先に返ってきます。この確認の往復こそが、後工程の手戻りを減らします。

実装コード例2:名簿と突合し「3種類の異常」を検知する

正規化ができたら、突合は単純なマージです。ポイントは、出力を「削除漏れ」「名簿外アカウント」「権限過剰の疑い」の3分類に固定すること。分類が固定されていると、毎週のレポートが定型になり、対応フローも決めやすくなります。

# scripts/reconcile.py(Claude Codeに生成させた骨子・抜粋)
import pandas as pd
from datetime import date

roster = pd.read_csv("roster/roster.csv")          # 社員ID, 氏名, メール, 在籍状況, 退職日
accounts = load_normalized_accounts()               # normalize.py の出力

roster["email"] = roster["メール"].str.strip().str.lower()
merged = accounts.merge(
    roster[["email", "在籍状況", "退職日"]], on="email", how="left"
)

# 1) 削除漏れ: 退職者なのにアカウントが存在する
leaks = merged[merged["在籍状況"] == "退職"]

# 2) 名簿外アカウント: SaaS側に居るが名簿に居ない
unknown = merged[merged["在籍状況"].isna()]

# 3) 権限過剰の疑い: 管理者権限の一覧(人数と顔ぶれを毎回確認する)
admins = merged[merged["is_admin"] == True]

write_report(date.today(), leaks, unknown, admins)  # reports/YYYY-MM-DD.md に出力

実際に最初の突合を回すと、多くの現場でまず「名簿外アカウント」が大量に出ます。中身は退職者だけでなく、共有アカウント、テスト用、外部の業務委託メンバー、旧姓のメールアドレスなど玉石混交です。ここで焦って分類をコードに詰め込みすぎず、判明したものから config/services.yaml の除外リストや別名対応表に移していくのが現実的です。この「例外を設定ファイルに追い出していく」反復も、Claude Codeに「unknownに分類されたこの20件のうち、roster.csv と姓が一致し名がローマ字表記だけ違うものを候補として列挙して」と依頼すれば、かなりの部分を整理してくれます。

実装コード例3:ヘッドレスモードで毎週回す——棚卸しを「行事」から「日常」へ

年1回の大掃除的な棚卸しは、実施した瞬間から陳腐化が始まります。突合の実行そのものは、Claude Codeのヘッドレスモード(claude -p、正式には --print)で非対話に実行できるので、週次の定期実行に落とし込めます(フラグの詳細は公式CLIリファレンスを確認してください)。

# 週次で実行するシェルの例(cron や社内のジョブ基盤に登録)
cd /path/to/account-audit
claude -p "exports/ 配下の最新CSVを normalize.py と reconcile.py で処理し、\
本日付の棚卸しレポートを reports/ に生成してください。\
前回レポートとの差分(新たに検知された削除漏れ・解消された件数)も冒頭にまとめてください。\
アカウントの削除・停止・変更にあたる操作は絶対にしないでください。" \
  --allowedTools "Read" "Bash(python3:*)" "Write"

ここでのポイントは2つあります。1つは--allowedToolsで使えるツールを絞ること。読み取り・スクリプト実行・レポート書き出しに必要な範囲だけを許可し、それ以外は許可しません。もう1つは「前回との差分」を出させることです。毎週同じ形式の一覧が届いても人は読まなくなりますが、「今週新たに2件検知」なら読みます。差分をSlackの情シスチャンネルに投稿するところまでつなげば、棚卸しは誰かの記憶に頼らない定常運用になります。定期実行の設計パターンはヘッドレス自動実行ガイドで詳しく扱っています。

コピペして使えるプロンプト6本

実装と運用の各段階で実際に使う形のプロンプトです。社名・サービス名を差し替えて使ってください。

1. 初回の設計相談

社内で使っているSaaSのアカウント棚卸しを仕組み化したいです。
人事名簿(CSV)と各SaaSの利用者一覧(CSV)を突合し、退職者の削除漏れを
検知するリポジトリの構成と実装手順を提案してください。
まず私の環境について不足している情報を質問してから始めてください。

2. エクスポート手順の整理

Google Workspace・Microsoft 365・Slackの3つについて、管理者が利用者一覧を
CSVでエクスポートする標準的な手順を整理してください。
各サービスの公式ヘルプで最新の手順を確認できるよう、確認先も添えてください。
不確かな点は「要確認」と明記してください。

3. 表記揺れの調査

reports/ の最新レポートで「名簿外アカウント」に分類された一覧について、
roster.csv との類似度(姓の一致・ドメイン・ローマ字表記の揺れ)から
「同一人物の可能性が高い」候補を理由つきで列挙してください。
断定はせず、候補と根拠の提示までにしてください。

4. 管理者権限の棚卸し

共通形式の一覧から is_admin=True のアカウントをサービス別に集計し、
前回レポートと比較して増減を一覧にしてください。
新たに管理者になったアカウントには「付与日と付与理由の確認が必要」と
注記を付けてください。

5. ライセンス費の試算

config/services.yaml の monthly_cost_jpy を使い、今回検知した削除漏れを
放置した場合の月額・年額コストを試算してください。
出力には「契約単価は自社設定値に基づく試算」と必ず明記してください。

6. オフボーディング手順書の生成

config/services.yaml に登録された全サービスについて、退職時に実施する
アカウント削除・データ引き継ぎのチェックリストをMarkdownで生成してください。
実施者・実施期限(最終出社日当日/翌営業日)・確認者の欄を設けてください。
仮定した点は必ず「仮定」と明記してください。

安全設計——人事データを扱う以上、「読むだけ」から始める

このリポジトリは人事名簿という個人データを扱います。便利さより先に、境界の設計をやっておくべきです。

まずデータの最小化。名簿からコピーするのは突合に必要な列(社員ID・氏名・メールアドレス・在籍状況・退職日)だけにし、住所・電話番号・給与などの列は最初から持ち込みません。突合に不要な個人データを置かないことが、事故時の影響範囲をそのまま小さくします。社外サービスへ個人データを渡すこと自体の可否は、自社の個人情報取扱規程と契約プランのデータ取り扱い条件を先に確認してください(Claude Code側のセキュリティ設計は公式ドキュメントのセキュリティページにまとまっています)。

次にツール権限の制限。プロジェクトの .claude/settings.json で、危険side effectにつながる操作を明示的に拒否しておきます。

{
  "permissions": {
    "deny": [
      "Bash(curl:*)",
      "Bash(rm:*)",
      "Read(./roster/raw/**)"
    ]
  }
}

外部送信につながるコマンドと削除系コマンドを拒否し、生の名簿ファイルを置くフォルダは読み取り自体を禁止して、最小化済みのCSVだけを読ませる——という構えです(設定の書式は公式のsettingsドキュメントを参照してください)。チーム全体でこの種の統制を配る方法は全社ガバナンスの記事で扱っています。導入時のチェック観点全体は法人導入セキュリティチェックリストも参照してください。

そして繰り返しになりますが、SaaS側への書き込みはさせない。各SaaSのAPIキーをこのリポジトリに置かず、そもそも削除操作を実行できない状態にしておくのが、権限設計として最も単純で強い形です。

【要注意】よくある失敗パターンと回避策

失敗1:検知と削除を一気に自動化する

❌「退職者のアカウントを検知したらAPIで自動削除」
⭕「検知と差分レポートまでを自動化し、削除は人間が管理画面で実行」

なぜ重要か:突合には必ず誤検知があります(休職者、雇用形態の変更、名簿の更新遅れ)。誤って在籍者のアカウントを消せば業務が止まり、最悪データも失われます。削除は件数が少ない作業なので自動化の利得も小さい。リスクとリターンが釣り合いません。

失敗2:氏名で突合する

❌「氏名の文字列一致で名簿とSaaSを突き合わせる」
⭕「社員IDを第一キー、小文字化したメールアドレスを第二キーにする」

なぜ重要か:氏名は旧姓・ローマ字・ミドルネーム・機種依存文字で必ず揺れます。同姓同名もあります。一意なキーで突合し、キーで繋がらなかったものだけを「候補提示」としてAIに整理させる、という役割分担が安全です。

失敗3:名簿を丸ごとAIに渡す

❌「人事システムのエクスポートを列も削らずそのまま置く」
⭕「突合に必要な5列だけの最小化CSVを作ってから扱う」

なぜ重要か:必要のない個人データを持ち込むことは、AI利用の是非以前にデータ管理として筋が悪い。規程上の確認も「この5列を渡してよいか」まで絞ったほうが、社内の承認も通しやすくなります。

失敗4:初回の大掃除で満足して終わる

❌「年度末に1回棚卸しして一覧をきれいにした」
⭕「週次のヘッドレス実行と差分通知で、汚れが溜まる前に検知する」

なぜ重要か:アカウントの状態は毎月変わります。1回の棚卸しの価値は数か月で失われ、翌年また同じ工数がかかります。仕組み化の本体は初回の突合ではなく、差分を回し続ける定期実行のほうです。

想定効果の試算——工数と「見えなかったもの」

以下は「利用SaaS 20個・従業員150名・年間退職者15名」という想定モデルでの試算です(実測値ではありません。自社の条件で置き換えてください)。

項目 従来(人力・想定) 仕組み化後(想定) 備考
棚卸し1回の工数 約2〜3人日(20サービスを目視確認) 約1〜2時間(エクスポートと結果確認のみ) 試算
実施頻度 年1回できれば良いほう 週1回(ヘッドレス実行) 検知までの平均時間が大幅短縮
削除漏れの発見 棚卸し時にまとめて発覚 翌週のレポートで差分検知 試算
監査対応 その都度証跡を再構成 reports/ の日付つきレポートを提示 棚卸し実施の証跡が自動蓄積

もう1つの効果は、数字にしにくい「見えなかったものが見える」ことです。名簿外アカウントの一覧は、情シスが把握していなかった部門契約のSaaSや、退職済み委託先の共有アカウントを浮かび上がらせます。初回レポートは、アカウント管理だけでなくシャドーITの実態調査としても機能します。

よくある質問

Q. SSO(シングルサインオン)やIDaaSを導入していれば、この仕組みは不要ですか?

IdP(IDプロバイダ)連携済みのサービスについては、IdP側の無効化で一括処理できるため削除漏れは大きく減ります。ただし実務では、SSO非対応のプランで契約しているツールや、部門が個別契約したツールなどIdPの外にあるアカウントが必ず残り、漏れはまさにそこで起きます。本記事の突合は、IdP管理下かどうかに関係なく「実際に存在するアカウント」を横断で見るための仕組みなので、SSO導入済みの会社でも監査的な意味があります。

Q. どのSaaSから始めるべきですか?

「全社で使っている」「管理者権限で利用者一覧をエクスポートできる」「アカウント単価が高い」の3条件で3〜5サービスに絞って始めるのがおすすめです。多くの会社ではグループウェア(Google WorkspaceまたはMicrosoft 365)とチャット(Slackなど)が最初の候補になります。仕組みが回り始めてから対象を増やすほうが、最初から全部を狙うより結果的に早く進みます。

Q. 人事名簿はどうやって用意しますか?

人事労務システムからのエクスポートが基本です。重要なのは「毎回同じ形式で出せる」ことと、突合に必要な列(社員ID・氏名・メール・在籍状況・退職日)だけに絞ることの2点です。名簿データの持ち出し・利用については、自社の個人情報取扱規程に沿って人事部門と合意してから始めてください。

Q. 個人情報をClaude Codeに渡して問題ないのですか?

一律の答えはなく、自社の規程と契約しているプランのデータ取り扱い条件によります。本記事の設計では、①渡すデータを突合に必要な最小限の列に絞る、②生の名簿は読み取り禁止フォルダに隔離する、③外部送信系のコマンドを設定で拒否する、の3点でリスクを下げています。法人利用時のデータの扱いはAnthropicの公式ドキュメントで最新の条件を確認し、判断はセキュリティ責任者を通してください。

Q. 削除の実行まで自動化できますか?

各SaaSのAPIを使えば技術的には可能ですが、本記事では推奨していません。誤検知による在籍者アカウントの削除は影響が大きすぎる一方、削除自体は月に数件の軽い作業だからです。「検知は毎週自動、削除は人間が承認して実行」という分担が、リスクと工数のバランスとして現実的です。

Q. 導入にどれくらいかかりますか?

想定モデルの試算では、最初の1サービス(正規化・突合・レポートの骨格づくり)で半日〜1日、2サービス目以降は設定ファイルの追記が中心になるため1サービスあたり1〜2時間程度です。初回レポート後の「名簿外アカウント」の整理に、会社の歴史の長さに比例した時間がかかる——というのが体感に近いところです。

まとめ:今日から始める3つのアクション

  1. 今日やること:直近の退職者3名について、利用SaaSごとのアカウント有無を実際に確認する。1件でも「残っていた」が見つかれば、それがこの取り組みの社内説明で最も説得力のある材料になります
  2. 今週中:全社利用のSaaSを3〜5個選び、管理コンソールから利用者一覧をエクスポートして exports/ に置く。人事名簿の最小化CSVの提供について人事部門と合意する
  3. 今月中:正規化と突合の初回レポートを回し、「削除漏れ」「名簿外アカウント」「管理者一覧」の3表を情シス定例に出す。そのうえで週次のヘッドレス実行を登録する

この仕組みは、経費精算の規程照合と同じ「あるべき状態をデータで固定し、実態との差分だけを人間が見る」パターンのアカウント管理版です。コードを書いた経験が少ない担当者でも、非エンジニア向けの入門記事で紹介している進め方なら、Claude Codeとの対話だけで骨格まで到達できます。


著者:佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー約10万人。100社以上の企業向けAI研修・導入支援。著書『AIエージェント仕事術』(SBクリエイティブ)。

参考・出典

ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。

Next Step

この事例を、自社の業務に置き換える。

対象業務、利用データ、評価基準、社内展開の順番まで整理すると、AI開発ツール導入の失敗を減らせます。

導入を相談する

チームで学ぶなら: Claude Code 法人研修(2日間ハンズオン) / 1人で習得するなら: 個別指導(週1マンツーマン)