500個以上の共有アカウントをどう管理し、2要素認証を運用しているか
はじめに
アカウント管理をする上で、社内アカウントについては「一人1アカウントが大原則、アカウントの共有はダメ、ゼッタイ!」となるわけですが、業務で利用するツールや外部サービスとなると、そもそもメンバー管理機能がなかったりして、誰かが登録したID・パスワードを皆で利用する「共有アカウント」が次々と生まれてゆきます。
GMOメディアにはそうしてできた共有アカウントが500個以上もあり、共有アカウントとは相性の悪い「2要素認証」も必要に応じて設定しているのですが、それらをどのように管理し、運用しているのかについて紹介したいと思います。
共有アカウントの問題点
共有アカウントを使うにあたり、真っ先に出てくるのが「パスワード管理」の問題です。
「必要に応じてシェアする」とか「共有ドキュメントに書いておく」とか、「いつもの覚えやすいパスワードにする」といった運用になりがちで、誰が知っているのか把握できなくなり、必要なタイミングで更新することもできず、「ログインできる退職者がいるかもしれない」といった状況に陥ります。(陥ってました。)
また、重要なアカウントには2要素認証を設定したいところですが、誰かのスマートフォンに紐づけることになるので取り回しが悪く、設定してもらえないことも多いです。
逆に、設定したのはいいものの、私用のスマートフォンに紐づけられてしまい、「設定者が退職したのでログインできなくなった」というような事故も起きかねません。(起きました。)
他にも、アカウントを共有すると「いつ誰が何の操作をしたのか分からず、万が一不正があっても調査できない」といった問題もあります。メンバー管理機能がないサービスには監査ログもまずないので、なおさら悪いです。(重要な共有アカウントはアクセス権をできるだけ絞ることでリスクを軽減しています。)
共有アカウントの管理方法
パスワードを共有しなくていいように、弊社ではOneLoginというクラウド型ID管理サービスを利用しています。
元々はSAMLが利用できるサービスでSSOを実現するために導入したものですが、指定したサイトのログインフォームに自動でID・パスワードを入力する機能もあったので、これを利用してパスワードを知らなくても必要なサービスにログインできるようにしています。
アイコンをクリックするだけで各サービスにログインできるOneLoginのポータル画面
ロールベースで権限を管理
「誰が何にログインできるのか」という権限の管理は、「人×サービス」で行うと膨大になってしまいますが、OneLoginの「ロール」機能を使うと「人×ロール」「サービス×ロール」という形で管理することができるので、部署やチームごとにロールを作成することで管理対象を大幅に減らしています。
また、それぞれの権限付与状況はスプレッドシートで管理し、シートから権限を申請できるようにしています。申請するとGAS(Google Apps Script)によってSlackに通知が飛ぶので、問題ないか確認した上で権限を付与する、という形で運用しています。
「人×ロール」の設定状況を管理・申請するスプレッドシート
退職ドリブンでパスワードを変更
「パスワードを知らなくてもログインできる」とは言え、実際にはブラウザ拡張機能が代理で入力・送信しているだけなので、知ろうと思えばパスワードを知るのは簡単です。そのため、重要なアカウントについては退職処理にパスワード変更を組み込んでいます。
重要でないアカウントについては「要更新」のマークを付けておき、半年ごとに実施している「共有アカウントのパスワード更新」の際に変更してもらっています。(共有アカウントが非常に多いので、立て続けに退職者が出た際の負荷を下げるため、このような運用にしています。)
2要素認証の運用方法
はじめは部門やチームごとにスマートフォンを購入して設定しようと考えましたが、コストや端末管理の手間、リモートワーク時に利用しにくいなどの点から断念しました。
また、外部サービスの2要素認証の多くはOATH-TOTP方式[2]なので、コード生成の元となる「シード」[3]を保管しておき、必要なメンバーに配るようにすれば上記の課題を解決できると考えましたが、シードの共有方法や不要になった人に破棄させる手間を考えると、運用は難しいと感じました。
認証アプリを作る
ふと、OATH-TOTPの認証コードを生成するWebアプリを作れば、シードを配布することによる課題も解消するのでは?と思い立ち、GASで作ってみました。
GASを採用した理由は以下の通りです。
- サーバ不要で手軽に作れ、コストもかからない。
- Webアプリなのでリモートワークしてても使える。
- Google Workspaceの設定により自社メンバーしかアクセスできないので安心。
- Google Workspaceで認証されているので認証機能も必要ない。
- シードをスプレッドシートで管理したい。
- アカウントの追加などの運用が簡単。
- 共有ドライブなら強制アクセス制御[4]が可能なので、シードへのアクセス権を厳格にコントロールできる。
そうして生み出された認証アプリ
利用している技術など
OATH-TOTPはオープンな仕様であるとはいえ自前で書くのは大変なので、authenticatorというNode.js用のライブラリを使いました。そのままではGASで使えないので、以下のプラグインを利用してwebpackでビルドしています。
-
gas-webpack-plugin
-
doGet()
やdoPost()
といったGASアプリのエンドポイントとなる関数をトップレベル[5]に書き出してくれる。
-
-
node-polyfill-webpack-plugin
- authenticatorが内部で利用する標準モジュールの
crypto
がGASにないため、そのPolyfillを読み込むために利用。
- authenticatorが内部で利用する標準モジュールの
以下に認証コードの生成~ページ出力までの全体像を示します。
global.doPost = (e) => {
// テンプレートで使うデータの設定
const data = { ... };
// スプレッドシートからシード情報を読み込む
const sheet = SpreadsheetApp.getActive().getSheetByName("secret-key");
const sheetData = sheet.getRange(`A2:C${ sheet.getLastRow() }`).getValues();
// 指定されたサービス/アカウントのシードを使って認証コードを生成
for (const [service, account, secret] of sheetData) {
if (service == e.parameter.service && account == e.parameter.account) {
data.token = authenticator.generateToken(secret);
break;
}
}
// テンプレートを読み込んで出力
const template = HtmlService.createTemplateFromFile("index");
template.data = JSON.stringify(data);
return template.evaluate();
};
まとめ
GMOメディアでの共有アカウントの管理と運用方法について紹介しました。
また、共有アカウントとは相性の悪い2要素認証も、認証アプリをWebアプリ化することで様々な課題が解決し、利用しやすくなることを示しました。
これだけですべての課題が解決するわけではありませんが、共有アカウントの管理を行う上で、少しでも参考になるところがあったなら幸いです。
Discussion