Speee DEVELOPER BLOG

Speee開発陣による技術情報発信ブログです。 メディア開発・運用、スマートフォンアプリ開発、Webマーケティング、アドテクなどで培った技術ノウハウを発信していきます!

Cloud Runを用いたIDaaSのID情報更新システム

こんにちは。開発基盤ユニットの森岡 (@selmertsx) です。Speeeでは全社的なセキュリティの向上として、社員のアクセス管理にIDaaS(Identity as a service)を導入しています。このブログではIDaaS導入の背景と、Cloud Runを用いたIDaaSへのID情報反映の自動化の仕組みについて、またその監視やCI/CDについて説明していきます。

IDaaS導入及び設定自動化の背景

IDaaSという言葉についてあまり馴染みがない方もおられるかも知れませんが、SSO(Single Sign On)という言葉についてはみなさん耳にしたことがあるのではないでしょうか。実はSSOはIDaaSというサービスの機能のごく一部でして、他にもIDaaSは、従業員のID管理、ユーザープロビジョニング、アクセス管理、多要素認証、リスクベース認証、SAML認証や監査対応のためのレポート作成などといった多くの機能を備えています。近年では、従業員だけでなく顧客のID管理にもIDaaSが利用されるようになり、ますます存在感を増してきています。

JNSAによる2018年のレポート*1によると、 多くの個人情報漏洩は不正アクセスによるものです。 そして不正アクセスの多くはフィッシングやパスワードリスト攻撃によって行われます。 GoogleのTransparency Report*2によると、 マルウェアを作成するコストが上がったため、相対的にフィッシングによる攻撃件数が増えてきていると報告されています。 また、NTTデータのレポート*3では、 暗号通貨の市場価格が下落したことにより不正マイニングの費用対効果が悪くなり、攻撃者は不正送金を狙ったビジネスメール詐欺や、不正に取得した情報を元に脅迫するなどの利益獲得手段に切り替えることが増えるだろうと報告されています。フィッシングやパスワードリスト攻撃に対する対策として、多要素認証やリスクベース認証の利用が推奨されていますが、多要素認証の中でよく利用されているOTPでは、フィッシング対策としては不十分であるという調査結果もあります。*4 *5

こういった状況の中で、企業としてセキュリティの対策をしていく上で、従業員のID管理や多要素認証の方式、アクセス可能なサービスなどについて、会社として一元管理できる状態にすることが重要です。 また、従業員のオンボーディング・オフボーディングや異動に関わる多くの手作業についても何か間違いを起こしてしまえばセキュリティを脅かしてしまいます。 そのため、自動化できる部分については、プログラムで自動化することによって事故を減らしていくことも大切になります。 そこで私達はIDaaSを導入し、そのID管理をCloud Runを用いて自動で行う仕組みを作りました。

アーキテクチャ概要

f:id:selmertsx:20190704162849p:plain

上の図は、IDaaS上のID情報を更新するための仕組みです。 IDaaSにはAzure AD、ID情報の保持はBigQueryを利用しています。

関連するSaaSから情報を集めて社員マスターを構築する役割と、社員マスターをIDaaSに反映する役割とで別のGCPプロジェクトに分割しています。 これは、社員マスターを保持するGCPプロジェクトが、将来様々な社内サービスと連携する予定があるからです。 そのため、IDaaSに社員情報を反映させるGCPプロジェクトには、必要な情報を絞り込み、かつ権限管理も行われたBigQueryのViewに切り出して参照させるようにしています。

データのクレンジングや前処理にはDataprep、IDaaSへのID情報の反映や整合性の確認などについてはCloud FunctionsやCloud Runを利用しています。 Cloud FunctionsやCloud Runを用いたIDaaSへのID情報の反映については、冪等性を持って処理できるように実装しています。 Azure ADには社員マスターのロールバック機能などはありませんが、自前で実装することによってそのような用途にも対応が可能となります。

Cloud FunctionsやCloud RunのランタイムにはNode.jsを利用し、TypeScriptで書いています。 残っているCloud Functionsについては、将来Cloud Runに置き換えていく可能性があります。

今回は分かりやすさのために記載していませんが、IDaaSが意図したように利用されているかを計測するシステムもCloud Runを利用して構築しています。 そのあたりについては、いつかお話をできればと思います。

Cloud Runを採用した理由

今回 Cloud Runを採用した理由としては、GCPにおいてプロジェクトを跨いでCloud Pub/Subを利用し、セキュアに処理を実行していく上で、Cloud Runの方が設定が容易だったからです。

Cloud Pub/SubにおいてSubscriptionはpush型とpull型の2つのタイプが存在します。pull型は定期的にメッセージを受け取りに行くタイプのSubscriptionです。 push型はpublisherから受け取ったメッセージを指定されたURLに送信するタイプのSubscriptionです。 Cloud RunやCloud Functionsをkickするために利用するのであれば、pull型の場合は定期的にCloud RunやCloud Functionsを実行し、messageが送信されていないか確認しなくてはなりません。 そのためpush型のSubscriptionの方が、今回の用途に適していると言えます。

ただし、Cloud Functionsでは別のプロジェクトのtopicをトリガーにする場合、HTTP呼び出しができるようにする必要がありました。 僕が開発していた当時、Cloud FunctionsのHTTP呼び出しにおいて、IAMを利用したアクセスコントロールは機能として提供されていませんでした。 (2019年6月26日のリリースで解決済み)

Cloud Runであれば、IAMを利用したHTTP呼び出しのアクセスコントロールを簡単な設定で実現することができました。 そのため、僕は今回のシステムにCloud Runを利用することを決めました。 当初はCloud Functionsを利用してシステムを構築していましたが、監視やCI/CD周りまで含めて1週間程度でCloud Runに移行することができました。 実際にCloud Runに置き換えてみると、コンテナ上でwebサーバーが動いているだけなので、ローカル環境での確認も容易です。 これまで Cloud Functionsをローカルで実行する際にはエミュレーターを利用する必要がありましたが、Cloud Runではその必要はありません。 また、Cloud Functionsのbuildには、これまでwebpackを利用していましたが、 ライブラリの中にはwebpackでの利用を想定していないものもあります。 そのためwebpackを利用すると、googleが公式で提供しているライブラリの一部が使えず、自分でAPIを叩く必要もありました。 Cloud Runのbuildではwebpackなどを利用する必要がありません。 そのため、webpackの初期設定を省くことができますし、webpackに対応していない一部の公式ライブラリも利用できます。

CI/CDについて

f:id:selmertsx:20190704163107p:plain

上の図がCloud RunのCD環境になります。GitHubとCloud Source Repositoriesがミラーリングされており、任意の命名規則に従ったtagのpushをトリガーとしてCloud Buildが実行されます。 Cloud Runを実行する上で必要とされる環境変数はKMSで暗号化されており、Cloud Runをデプロイするときに渡されます。 それらの設定はTerraformで管理されており、環境変数の変更はTerraformのapplyにより反映されます。

基本的にすべてのインフラリソースはTerraformで管理しています。 サーバレスで実行される一連のフローを少しでも可視化するためです。 ただし、一部のリソースは完全にTerraformに対応している訳ではありません。 例えば、Terraformのgoogle_pubsub_subscription リソースなどは、pushする際のサービスアカウントを指定することが出来ません。 その場合は手動で作成したリソースをTerraformでimportしたり、Terraformで作成したリソースの一部をgcloudコマンドで修正するといった運用を行っています。 そして、その旨をTerraformのコードに記載しておきます。

Terraformのapplyは、現在手元で行っています。 それはインフラの設定をしているエンジニアが現在1人だけなので、Cloud Buildに任せるメリットが小さく、今の所はまだ優先度が低いからです。 とはいえ、将来のことを考えると、Terraformによるインフラの更新も自動で行われるようにする必要があるでしょう。

監視について

本システムが正しく動いているというには、少なくとも下記の項目を満たす必要があります。

  • 社員マスター管理のプロジェクトは、社員マスターが更新された際にIDaaSプロジェクトに正しく通知出来ている
  • IDaaSプロジェクトは、社員マスター管理プロジェクトからのmessageを受け取り、IDaaS Viewの内容を元に正しくID情報を更新できている

他にも数多くの項目があるかと思いますが、今は上記2点にフォーカスして監視を行っています。 上記が満たせていることを確認するために、下記の項目について監視をしています。

  • Cloud Runのエラー監視
  • Cloud Functionsのエラー監視
  • Cloud Runのメモリ使用量
  • Cloud Functionsのメモリ使用量
  • PubSub TopicのSend Request
  • PubSub Subscriptionの Push Request

また、これらの監視とは別に、定期的にBigQueryとAzure ADのID情報を突き合わせて、差異がないことを確認する機能をCloud Runにて動かしています。 これらの仕組みによって、システムが正しく動いていることを確認しています。

監視にはStackdriver Error ReportingとStackdriver Monitoringを利用しています。 まずエラー監視で利用しているStackdriver Error Reportingについてです。 Stackdriver Error Reportingは、デフォルトでCloud Functionsに対応しています。 よって、特に何もせずともCloud Functionsはエラー監視されるようになります。 ただし、現在Cloud Runについては、Stackdriver Error Reportingが対応しておりません。 そのため@google-cloud/error-reportingを利用し、自分で設定しています。

リソース監視やPubSubの監視に利用しているStackdriver Monitoringについてです。 Cloud FunctionsもCloud Runも256MB以上のメモリを利用すると、処理の途中で終了してしまうことがあります。 そのため、それらのメモリ使用率についてはモニタリングしています。 また、PubSubのTopicやSubscriptionについてもモニタリングをしており、 メッセージの送信、受信に問題があったとき、エンジニアが把握できる仕組みを作っています。

PubSubのTopic、Subscriptionの監視では、具体的には topic/send_request_countsubscription/push_request_countの2つのメトリクスを見ています。 これらのメトリクスがsuccess以外のレスポンスを1度でも返したときは、エンジニアに対してアラートを投げるようにしています。 この設定では、存在しないTopicに対してメッセージを送信してしまったときの問題をメトリクスから検知出来ませんが、 IDaaS用GCPプロジェクトへのメッセージの送信はCloud Functionsで行われています。 そのため、もしもメッセージが送信できなかった場合は、Cloud Functionsのエラー監視で検知することができます。

こなれているとは言える状態では全くありませんが、運用をしながら少しずつこのあたりの監視方法を改善しようと考えています。

最後に

この記事には書ききれなかったのですが、GCPのプロジェクトだけでなく、Azure AD、GSuiteもstaging環境を作成しています。 そこで動作確認が取れたものを、本番環境にデプロイしています。

今回初めて、すべてマネージドサービスを利用してシステムを作りました。 利用している一つ一つのマネージドサービスに対して、ドキュメントを読んで理解し実験を重ねて挙動を把握していく必要があり、 そういった面で初期コストがやや高い印象を受けましたが、元気に動くようになってからは運用コストの低さにありがたみを感じています。 各処理は一つ一つ独立しているので、今回の開発している最中で部分的にCloud Functionsから Cloud Runへ移行をしましたが、驚くほど容易にできました。 将来、もしCloud Runで利用する言語を変えたいとなったとしても、一つ一つの処理のINPUT/OUTPUTは既に定形化されていますし、一度に移行する必要が無いので容易に対応できるかと思われます。

しかしながら、自分自身でterraformで作って各要素の関係性などをコード化していたとしても、 久しぶりに見たときにはピタゴラスイッチか何かのように感じられてしまうこともあります。 システムは運用フェーズに入ってからが本番なので、実際のところのメリット・デメリットはこれから先分かってくるでしょう。 そのときにまた、このブログで報告できればと考えています!

以上、Cloud Runを用いたIDaaSのID情報更新システムについて、森岡からの報告でした〜。

小ネタ

ここから下は、森岡がオンボーディング・オフボーディングプロセスの自動化にあたって色々と考えたことを書いてます。 僕は今回はじめて、オンボーディング・オフボーディングプロセスに関わったので、何か間違いがあるかも知れません。 その場合はコメントいただけるとありがたいです!

社員番号はUUIDにしてしまう

これは弊社で実際にあったことなのですが、当初役員が 001xxx 番台の社員番号で表現されていました。 この管理方法だと、近い未来に入社される人たちが自動的に役員になってしまいそうだったので、このルールを途中で改めることにしました。

また会社では、途中で雇用形態が変わる従業員の人もいます。 その場合、社員番号で雇用形態を表現してしまっていたら、どうするのが良いのでしょうか。 また、一度退職された人が別の雇用形態で再雇用されることもあります。 社員番号を途中で変えてしまう場合、これまで連携していた各種ツールで変更する必要が出てきます。

最近の社員マスターを提供しているSaaSでは、雇用形態やその他様々な属性を管理できるようになっています。 そのため、社員番号はすべてUUIDで管理し、その他社員番号で表現したくなった要素は、 すべて適切な属性で管理すると良いのではないかと思います。

オンボーディング・オフボーディングの自動化は早いほど良い

従業員のオンボーディング・オフボーディングプロセスは、多くの部署が関わるものです。 ここを手動で行っていた場合、部署ごとに運用が行われるようになります。 例えば、trelloでオンボーディング・オフボーディングのタスクを管理している部署があったり、 slack上でやりとりして作業を進めている部署があったりします。 時間が経てば経つほど、それらの作業は個別最適が進んでいきます。 手作業に事故はつきものです。 例えば過去所属していた人と同性同名の人が入社されたときに、同じメールアドレスを誤って付与してしまうという事故も起こりえます。 また、オフボーディングの際に、どこか一つの部署でも設定を忘れてしまうことがあれば、そこがセキュリティリスクとなります。 手作業によって発生する事故は、きっと数多く挙げることができるでしょう。

いざ自動化しようとなったとき、 これまでそれぞれの部署が何をどのようにしてオンボーディング・オフボーディングプロセスをしているのかを紐解き。 自動化後のプロセスについて合意をして。 これまでの業務が滞らないよう、少しずつ進んでいくことになります。

自動化が早ければ早いほど、このコストは小さくなることが期待されます。