久しぶりの登場となりましたマネーフォワードケッサイ(以降MFK)CTOの篠原です。
事業が成長し続ける事で、情報管理、GCPリソース等のアクセス権限や、そしてオペレーションやセキュリティ観点でのリスクコントロールなどを意識する場面が増えてきます。 今回、MFKとして正しいと思う形で正しく運用できているかを保証する為に導入していた仕組みなどを、0から再設計しなおしたお話ができればと思います。
まず今回のテーマである正しいとは何かを書き出したいと思います。
- GCPリソースに対するメンバーの権限は必要最低限に留める事
- 本番環境にデプロイされるソースコードが社内で定める条件を満たしている事
- 社内ツールで読み書き可能なメンバーが必要最低限である事
- またそれぞれで意図通り運用されたことを保証できる事
一部ではありますが開発組織によって定義される正しさは異なると思いますので、ここではMFKの考える 正しさ に基づいていることをご理解いただけると嬉しいです。
まず何をやめたのか
- SREに本番に関する権限が集中することと、SREへの依頼が必要になる事
- 社内アプリケーションそれぞれでのACL管理
- Githubリポジトリ作成のIaC管理、もしくはチケットでの作成依頼
ここからは、これらをやめるために何をしたかをお話していければと思います。
1. SREに本番に関する権限が集中することと、SREへの依頼が必要になる事
やめたこと
弊社ではSREが様々なSaaSのProduction環境の権限を一番強く持っており、基本的に本番環境での作業にはSREへの依頼、もしくはSREに権限の付与依頼が必要でした。まずはこのSREの権限依存をやめました。
なぜやめることにしたのか
- 権限を持つSREが同じ時間に居ないと緊急であっても作業ができない
- なにか1つ調査するためにもSREに権限付与依頼しないといけない
- SREは常に本番を誤操作しないか不安を抱える状態
- そして常時多くの権限がついてるSREのアカウントはクレデンシャル漏洩時のインパクトがとても大きい
- そもそも必要な時に申請しているので、却下することは無い
- チケット化しているのは作業履歴のため
どのようにやめたか
改めて何を守るためだったのかを整理しました。
- 大前提としてメンバーを信頼している
- 障害等で必要なオペレーションのための権限は付与して早く解決したい
- 付与した権限が不要になったら剥奪したい
- 本番の破壊ができてしまうようなインフラの強い権限はSREだけに限定したい
- 誰が何の権限を持って、その期間何をしたかを後で追える状態にしたい
実現したいことは上記の通りであって、都度申請や承認、そしてSREが作業もしくは付与作業する事をしたいことではありませんでした。 そこで条件を満たすメンバーは、事前に定義されている権限の範囲内であれば、任意のタイミングで一定時間だけ権限付与できる仕組みを構築しました。 そして付与してから剥奪されるまでの間の行動はGCPのAudit LogをBigQueryに残すことで監視や調査が行えます。 入口を簡略化して出口に至るまでのすべてを監視する事で、これまでのステップを無くすことに繋がりました。
こちらの画像は、Github Actionsの workflow_dispatch
を利用して運用しているツールの画面です。
付与処理が完了したらSlackに通知されます。
細かい仕組みに関しては、別途ブログで紹介できればと思います。このツールの登場でSREの作業待ちの時間が短縮され、そしてSREも自分たちの作業に集中できる状態が作れました。
2. 社内アプリケーションそれぞれでのACL管理
やめたこと
事業成長によりMFK社内には様々な社内アプリケーションが登場しました。社内ツールでは重要な情報の参照や更新も発生する為、IAPを利用して社内メンバーに限定していました。 ですがIAPのみでは読み書きのコントロールはできません。そのためアプリケーション自身で誰に何を許可する等の実装を行っていました。 そして社内アプリケーションにユーザと権限を意識させることをやめました。
なぜやめることにしたのか
- 社内アプリケーションごとに誰にと何を許可するかしないかを管理しないといけない
- 言語が同じならモジュールを使い回す事は可能かもしれないが、作成時期や内容に応じて言語を選択している為、それぞれで実装が必要
- 退職・移動などの人事イベント発生時にそれぞれのアプリケーションで棚卸しが必要になる
どのようにやめたか
IAPのおかげで簡単に社内メンバーに限定する事が可能となります。そのためIAPとアプリケーションの間に、IAPのユーザ情報を利用してACLを行うReverseProxyを作る事にしました。
プロキシにACLに関する責務が移動した事で、アプリケーションがACLや監査を意識する必要がなくなりました。 そしてプロキシをそれぞれの手前に配置する事で、全てのアプリケーションで同じフォーマットの行動ログやアクセス許可履歴を取得できる状態になりました。
upstream: http://127.0.0.1:9000
ignore:
- /healthz
acl:
get:
- name: Allow all GET requests
member: ["*"]
post:
- name: Allow /hoge to [email protected]
path:
- /hoge
member: ["[email protected]"]
- name: Allow all POST requests
member: ["*"]
上記の設定により以下のACLが実現しています。
- ignoreはチェックしない対象のパス
- memberが*の場合は全ユーザ許可
- postは
/hoge
の場合は[email protected]
しか許可しない。/hoge
がマッチした場合つぎのステップには進まない - postは
/hoge
以外の場合に限り全ユーザのアクセスを許可
仕組みや実装などの詳細に関しては、別途ブログでご紹介、そしてコア部分をOSSとして公開できればと思っています。
3. GithubのリポジトリをIaCでの管理、もしくはチケットでの依頼
やめたこと
MFKでは初期の頃は依頼ベースで作成、途中からTerraformのGithub ProvidorをGitOpsを取り入れて管理と更新を実現していました。 Terraformの導入により誰でもリポジトリを作成できて、誰が作っても同じ設定を反映できたので、とても便利でしたがTerraformで管理する事をやめました。
なぜやめることにしたのか
- リポジトリの数が増えれば増えるほどTerraformの実行時間が長くなる
- Githubのリポジトリを管理したいだけなのに、Terraformのバージョンアップによる
*.tf
の仕様変更に追従が必要になる - 仕様変更によりリソースに不要な変更が入ることも稀にある(差分はない)
- github.comでポチポチする楽さに憧れる
どのようにやめたか
そもそもIaCがやりたい事ではないので、Terraformを一旦忘れて何を解決したかったのか?を考えました。
- セキュリティ関連の設定を強制したい
- 作業依頼でGithub Admin権限を持ってる人がポチポチしたくない
- 全てのリポジトリでポリシーが守られている事を保証したい
例えばプライベートのみ作成可能などある程度の事はORGの設定で実現可能ですが、Protectedは必ず main
で設定、マージするための条件などは強制できません。
大前提としてリポジトリの管理がやりたいことではないので、IaCの採用はやめました。Github Actionsのworkflow_dispatchをUIとして採用して、リポジトリの作成とポリシーチェックを行うGo制のスクリプトを作成しました。
以下は実際の画面になります。
ポチポチするより少ない手順でリポジトリが作成できるようになり、また守りたい項目も実装側で強制できました。更にAdmin権限所有者が勝手に変更加えたとしても毎日全リポジトリをチェックする仕組みもActionsで動かしているため、ポリシー違反の早期発見と修復が可能になりました。
こちらの仕組みに関してもいずれご紹介できればと思います。
これからに思いを馳せて
僕がCTOの間にもっと色々な、これまで当たり前のように追加してきた様々なオペレーションをなくしていきたいと思っています。それぞれの目的は重要なので、何かをする事自体はなくならないと思います(なくせるなら無くす)。今後も過去の経験をもとに惰性で運用してる仕組みがあれば、今回と同じく生産性を上げていくために変化を起こしていきたいと思っています。