ヤフー株式会社は、2023年10月1日にLINEヤフー株式会社になりました。LINEヤフー株式会社の新しいブログはこちらです。LINEヤフー Tech Blog

テクノロジー

SSHCA: 証明書利用による安全性と利便性を両立したサーバログイン

本記事は2022年11月に開催した「Tech-Verse 2022」で発表したセッションを要約したものです。アーカイブ動画を文末に掲載しています。質疑応答の様子も収録されていますのでぜひご覧ください。

私が所属しているVersatile Authenticationチーム(以下、VAチーム)では、取り扱っている代表的なプロダクトとして社内でのIdP、PKI、そしてSSHCAがあり、それぞれ企画開発・運用を行っています。

IdPでは、社内の各サービスに対してユーザーの認証認可プラットフォームを提供しています。PKIでは社内CAを提供し、各社内サービスに対して証明書の発行や運用を行っています。SSHCAでは、サーバログインに関して証明書ベースでの認証プラットフォームを提供しています。

VAチームでは、多様な認証認可プラットフォームを取り扱い、ユーザーやサービス、サーバなど、あらゆる対象をセキュアにすることを目指しています。今回はSSHCAについて紹介します。

サーバログインの必要性とは

まず、サーバログインの必要性について確認したいと思います。管理の容易さなどから、昨今はKubernetesをはじめとするコンテナ化や、PaaSなどサーバレス化が進んでおり、サーバへログインする機会は、これらが普及する前と比べると減ってきています。

しかし、ヤフーにおいてはセキュリティやソフトウェア、ネットワークなど、要件や制約の問題から、コンテナやサーバレスの環境がフィットしないケースも一定数存在しています。そのような場合は、実機サーバ環境やIaaS環境などが選択されるため、サーバへログインする必要性が依然として残っています。

また、IaaS環境はその自由度の高さから、開発環境や検証環境などとしても利用されています。開発者の皆さんも、完全にサーバにログインする機会がなくなったという方は、実際のところ少ないのではないでしょうか。ヤフーでは依然としてSSHによるサーバログインの必要性が存在しています。ここでは、そのセキュリティに関する取り組みについて紹介します。

SSHにきめ細やかな認可制御が必要な理由

SSHにおけるきめ細やかな認可制御の重要性について見ていきます。まずは、サーバログインでのアクセス制限についてです。通常、SSHでの公開鍵認証では、各ユーザーが自身でキーペアを生成し、公開鍵をディスティネーションサーバへ登録します。ユーザーは秘密鍵でログインを試行し、サーバは公開鍵でその検証を行います。

このとき、もしあるユーザーの秘密鍵が漏えいしてしまった場合には、そのユーザーの公開鍵が設定された全てのサーバに対し、第三者によって不正ログインが可能となってしまいます。特にログイン先のサーバがセンシティブな情報を扱っているような場合、大きなリスクとなり得ます。

このようなケースでの漏えい対策として、キーペアの定期的な更新が考えられますが、現実的に考えて頻繁なキーペアの更新は手間がかかる作業です。また、秘密鍵にパスフレーズをかけるなどの対策もありますが、パスフレーズの強度が十分である保証はありませんし、キーペアの更新頻度が低ければ、破られるリスクも高まっていきます。

各ユーザーの秘密鍵の管理やパスフレーズの強度などは、実際にシステム管理者は把握できず、結果として各ユーザーの性善説に依存してしまうという問題があります。

秘密鍵のようなクレデンシャルは漏えいしないに越したことはありませんが、仮に漏えいしてしまった場合の対策は求められます。ここでSSHにおいて、柔軟な認可制御が必要だと考えています。求められる要件としては、「権限に有効期限を設けること」「権限自体を必要最小限にすること」の2点です。言い換えると、「いつ誰がどこにアクセスできるかを制御する必要がある」ということです。

柔軟な認可制御を実現するためにSSHCAで「いつ」「誰が」「どこ」を制御

柔軟な認可制限についてですが、SSHでは証明書ベースでの制御仕様もサポートされており、この仕組みを用いることで実現できます。まずSSHの証明書ベースでの認証について簡単に説明します。

ここでの認証では、公開鍵認証のときには登場しなかったCAという存在が新たに登場します。まずCAでは自身のキーペア、CA公開鍵、秘密鍵を生成します。そして、ディスティネーションサーバにCA公開鍵を設置し、それがソースユーザーからのログインリクエスト時の検証に用いられます。

ソースユーザー側では、ログインのために証明書を取得する必要があります。そのために、まずキーペア、ユーザー公開鍵・秘密鍵を生成、そしてユーザー公開鍵をCA秘密鍵を用いて署名し、証明書を発行します。最終的にユーザーは発行された証明書を用いて、ディスティネーションサーバへリクエストする流れです。CAでの署名の際に、証明書に制御情報を付与することによって、CAによる細かな認可制御が可能です。

CAでの制御情報の付与について具体的に説明します。まず「いつ」の制御についてですが、これは有効期限情報を証明書に付与することによって制御できます。具体的なSSH証明書でのプロパティには、有効期限に関するValidの項目が存在します。有効期限はfrom-toで定義されており、ログイン試行はこの期限内である必要があります。

この制御により、仮に漏えいが起きてしまった場合でも、有効期限外であればそのクレデンシャルはもはや意味をなさないものとなり、リスクを最小限に抑えることができます。設定する期限は運用に支障がない、必要最低限に短くしておくことが望ましいです。

次に、「誰が」「どこに」の制御について見ていきます。これに関しては、プリンシパルという識別子を証明書に付与することで制御できます。あらかじめディスティネーションサーバ側では許可するプリンシパル識別子を定義しておきます。これは複数定義でき、認可プリンシパルと呼ばれます。

そしてソースユーザー側では、ログインの際に証明書を用いてリクエストしますが、その証明書内のプリンシパル識別子がサーバ側での認可プリンシパルのいずれかに該当すれば、そのログインリクエストは有効と判定されます。

プリンシパル自体はシンプルな文字列ですが、証明書を発行するCAと、認可プリンシパルを設定するディスティネーションの双方でルールを取り決めておくことで、柔軟な認可制御が可能です。

プリンシパルの付与による制御のフロー図

例えば、ユーザーaliceについて、あるサーバのみログイン許可を出したい場合について考えます。上図では左のケースに該当します。この場合、AliceがCAに証明書の発行を要求した際に、CAでは証明書にプリンシパルとして「alice:severA」を設定します。

そして各サーバ側では認可プリンシパルとして、「Username:Servername」の規則で設定しておきます。このようにあらかじめ取り決めておくことで、CAがaliceに対して発行した証明書では、aliceがserverAへのみログイン可能になるような制御を実現できます。

また、この場合ではサーバごとに証明書発行が必要となり、使い勝手に問題があるかもしれません。そんなときは、上図の右の例のようにサーバをグルーピングしておき、そのグループ名を「alice:」以降に設定しておくことで、汎用性をもたせることができます。このように状況に応じてCA-ディスティネーションであらかじめルールを取り決めておくことで、柔軟な制御を行うことができます。

ヤフーにおけるSSHCAの導入

ここからは、SSHの証明書ベースでの認証をどのようにヤフー社内に適用したのかについて説明していきます。

社内において実際に証明書ベースでの認証を適用しようとする場合、どのようなことを考慮する必要があるでしょうか。CAにより証明書を発行しますが、ソースユーザーからの証明書リクエストにそのまま応じてしまっては、何の制御にもなりません。システムとして必要なことは、証明書発行までのプロセスを構築することです。

具体的には、「どこからのリクエストを対象とするか」「どのように認証するか」「どのような認可情報を付与するか」の3点が重要なポイントです。この3点は導入するシーンに応じて、その都度適切に設定する必要があります。

ヤフーでは現在、次に挙げる二つのシーンでSSHCAを導入しています。一つ目が、「セキュアな情報を取り扱うサーバでのオペレーション」です。これは人によるログインであり、サーバへの単純なデプロイ作業のほか、障害時の調査やそのほかの運用作業などを行います。

二つ目が、「CI/CDツールを介したサーバへのデプロイ」です。これは人ではなく、アプリケーションアカウントによるログインであり、基本的にデプロイ用途での利用です。

これら二つのケースで、それぞれアクセスの対象や用途が異なり、そこでの制御も状況に応じて適切に設定していく必要があります。

まず、「セキュアな情報を取り扱うサーバでのオペレーション」のケースです。センシティブなデータを扱うコンポーネントへのアクセスであり、かつログインユーザーはデプロイ操作のほか、運用や調査で任意のコマンドが実行できる必要性があるため、証明書発行には細心の注意を払う必要があります。

ログインを行うユーザー自身の認証が必要なのはもちろんですが、一人の人間の裁量のみで証明書の発行から対象サーバへのアクセスまでされてしまっては問題があります。また作業時間やログイン先、作業内容などの妥当性のレビューも必要です。これらの要件を満たすようにシステムを検討してきました。

また、考慮すべきもう一つの点として、ヤフーではすでに社内システムとして確立しているインフラの存在があります。全てゼロベースからのシステム構成とは異なり、既存の社内インフラとの親和性なども加味していく必要があります。ここで取り扱っているSSHCAに関連する既存の社内システムには、サーバ管理システム、インハウスIdP、承認管理システムがあります。

サーバ管理システムでは、ヤフー社内の全サーバが管理されており、各サーバのアカウントからSSHDの設定に至るまで、各種設定の配布・同期が行われています。SSHCAの導入に当たって、ディスティネーションサーバでの検証に必要なCA公開鍵や認可プリンシパルの配布は、このシステムを用いて行います。

インハウスIdPは、名前の通り社内で利用しているIdPであり、社内ツールにおけるOIDCでのユーザー認証に利用されています。SSHCAでの証明書リクエストの際の認証も、このシステムを利用してユーザー認証を行います。

最後に承認管理システムですが、これは任意の申請フォーム、承認フローを構築できるシステムです。承認者のアクションに応じてWebhookデータを受け取り、そのデータに応じた制御を行うことなどが可能です。

SSHCAでは、セキュアサーバへのログイン、作業の妥当性のレビューにこのシステムを利用します。これら既存のシステムとうまく統合活用することで、無駄なシステムの再開発コストを削減でき、またユーザーは日頃から使い慣れたシステムを通してSSHCAを利用できるといった利点があります。

実際にシステムを構築するにあたって、選択肢はいくつか考えられます。例えば、SaaSを利用する、OSSを活用する、あるいはフルスクラッチで開発することなどが考えられます。それぞれに開発コストやカスタマイズ性などにメリットとデメリットがあります。

ヤフーでは前述の通り、すでに社内システムとして確立しているインフラが多くあり、それらとの親和性が重要です。また、多様なケースに柔軟に対応できるカスタマイズ性も求められ、かつ車輪の再発明は極力避けたいという考えもありました。

それらを加味した結果、CAサーバはCA機能にフィーチャーしたOSSを活用するという選択になりました。具体的には、「smallstep/certificates」というOSSをベースに、社内の要件に応じた独自仕様や既存インフラとのつなぎ込みなどのカスタマイズを行うことで、システムを構築しました。

また、証明書リクエストを行うクライアントサイドでは、CAに利用しているOSSの対となるクライアントCLIの「step CLI」を利用することで、1コマンドで証明書の発行からSSHCAエージェントの登録まで完結でき、クライアント側での使い勝手も改善できます。

以上のように適切にOSSを活用することで、開発効率やカスタマイズ性の高さを実現しています。

続いて、システム構成の概要を示し、ログインまでの全体のフローを説明します。最初に、ディスティネーションサーバへの各種設定は、事前にインスタンス生成時のブート設定や、サーバ管理システムによって行われます。

セキュアサーバへログインしたいユーザーは、承認管理システムから申請を上げ、上長や管理者による申請内容のレビュー・承認を得ます。これらの申請データや承認結果はWebhookを通じてCAに連携されます。承認後、ユーザーはCAへ証明書リクエストを行い、CAは認証後、申請内容に応じて証明書を発行します。最後にユーザーは発行された証明書を用いてログインを行います。

詳細を説明します。まず、ディスティネーションサーバへの設定です。認可プリンシパルは、例えば「Username:情報区分」のような規則で設定しておきます。Usernameはサーバカウント、情報区分はセキュアサーバをいくつか扱う情報の度合いに応じてグルーピングしておき、そのサーバの所属する区分名を設定しておきます。

続いて、承認管理システムでの申請、承認部分の詳細です。最終的に、ここでの申請内容に応じて、CAでは証明書に有効期限やプリンシパルを付与します。ユーザーはWeb UI上の申請フォームから、セキュア作業の申請を行います。

申請時の指定項目としては、アクセス開始時刻やアクセス時間、アクセス対象の情報区分、作業内容などがあります。申請後、上長や管理者に対して申請内容に対する承認要求が送られます。上長や管理者は申請内容の妥当性をレビューし、問題がなければ承認します。承認結果はWebhookによってCAに連携、ストアされ、CA側では以降の証明書発行時に参照・利用します。以上が承認管理システムでの簡単なフローです。

次に、証明書リクエストから対象サーバへのログインまでを説明します。ソースユーザーである作業者は、事前に上げた申請が承認済みであることを確認し、CAへ証明書をリクエストします。リクエスト時には、まず作業者の認証が行われます。SSHCAでは、ユーザー認証の部分はOIDCでインハウスIdPに委譲する形をとっています。これにより、容易にパスワードのほか、SMSやセキュアトークン、FIDOなど、柔軟な認証方式をサポートすることが可能です。

IdPでの認証後、CAでは対象ユーザーの認証情報から、そのユーザーの検証と先ほどの承認管理システムでの登録データを照合し、証明書発行の可否、または証明書に含める認可情報の有効期限やプリンシパルなどを決定します。ユーザー側では、証明書の取得後に自身のSSHCAエージェントにそれを登録し、対象のサーバにログインが可能となります。

もし事前の申請が未承認だったり、リジェクトされていたりすればリクエストはフェイルしますし、ログインできるサーバは、申請時に指定した情報区分のサーバに限定されます。このCAのリクエストからSSHエージェントへの証明書登録までは、step CLIの1コマンドで行われます。ここまでがセキュアサーバへのログインでの一般的なフローです。

ここまで見て、関連コンポーネントが多くなっていることに気づくと思います。通常の公開鍵認証であれば、ログイン時に関係するコンポーネントはソースとディスティネーションの二者ですが、SSHCAを導入することで承認管理システムやIdPなど、関連コンポーネントが増えます。

このままでは障害点が増えて可用性が下がってしまいます。もし、これらのコンポーネントがメンテナンス中であったり、障害が発生していたりすると、ユーザーは必要なときに対象サーバへログイン・運用できず、大きな損害をもたらす可能性があります。

このような場合に備えて、システムとしてFallbackに設計しておくことが大切になります。SSHCAではそのための仕組みとして、緊急時用のフローを用意しています。

例えば、承認管理システムなど各コンポーネントの障害で証明書発行が難しい場合、上図に示すように別経路で発行が行えるようFallbackを整備しています。

ただ、緊急用に別の口を設けることは、セキュリティの低下を招いてしまいます。そこで、ユーザーのログインに関しては、ログ監査を徹底することでカバーしています。ログインに関するログは特定のSyslogサーバへ転送し、SOCチームにてリアルタイムで監視を行っています。これらの監視は通常フローでの異常のほか、先に挙げたような緊急用のフローでのアクティビティなどに対しても行われ、異常検知した際にはそれぞれ適した対応がとられます。

特に緊急用のフローでは、本人と上長へのヒアリングなどは即座に行われるようになっています。また、ここでの各種異常なイベントの識別には、証明書プロパティのKey IDが活用されています。証明書発行時、Key IDプロパティに任意の識別子やメッセージを入れておくことで、この値はログイン時のディスティネーションサーバのログとして出力されます。

この仕組みにより、CAではリクエストに応じてKey IDを適切に設定して、監査チーム側では正確にアクティビティを検知識別し、しかるべきアクションを取ることを可能としています。このようにしてセキュリティを担保しつつ、可用性を維持できるようにしています。

以上がセキュアな情報を取り扱うサーバでのオペレーションのケースです。

CI/CDツールを介したサーバへのデプロイ

ここからは、CI/CDツールを介したサーバへのデプロイについてです。一つ前のケースと共通の部分も多くありますが、ログインのリクエスト元が人ではない、用途がデプロイに限定されているといった点が大きな違いとなります。

まず、ヤフー社内でのCI/CDツールについて簡単に説明します。ヤフー社内ではCI/CDツールとして、ヤフーとVerizon Mediaが共同開発している「Screwdriver.cd」を利用しています。これはアプリケーションのビルドやテストに限らず、さまざまな環境への継続的デプロイも行っています。Screwdriver.cdではSSHCAとの連携によって、実機・IaaS環境に対する継続的デプロイを実現しています。

ここでのデプロイにおいて取り組むべき課題を見ていきます。まず、ツール上からのデプロイとなるため、対象サーバへログインするソースはアプリケーションアカウントです。基本的にログインの用途はデプロイのみに一貫しており、実行されるコマンドも限定されるはずです。

そのため、アプリケーションアカウントの実行権限は最低限に絞られておくべきです。また、CI/CDツール上には多くのパイプラインが存在しますが、認可を絞るとすると、特定のパイプラインでは特定の対象サーバへのログイン権限のみが付与されるべきです。

一つ目の課題に関しては、サーバ管理システムによりsudoersを設定することで対応できます。二つ目の課題については、各パイプラインでのデプロイ対象の制限をSSHCAによって対処していきます。

CI/CDツールを通したデプロイまでの外観を上の図で示しています。開発者は、最初にCI/CDツール上にパイプラインを作成します。そして、デプロイ対象のサーバへのアプリケーションアカウントやCA公開鍵、認可プリンシパルについて、サーバ管理システム上で設定を行い、各デプロイ先サーバへ同期します。

あるパイプラインに関してデプロイが行われるとき、CI/CDツール内部ではCAへ証明書リクエストが行われます。ここでリクエストが無事に認証されると、適切な認可情報を含んだ証明書が返されます。最終的に、CI/CDツールでは取得した証明書を用いて対象のサーバへデプロイを行います。

ポイントは二つあります。一つ目はプリンシパルの設定、二つ目はCAに対する証明書リクエストの際の認証です。

プリンシパルの設定に関して実施したい制御は、特定のパイプラインにおいては特定のサーバへのログイン権限のみを付与するということです。これを実現するため、パイプラインごとにユニークな識別子であるPipelineIDを利用します。これは、CI/CDツールで各パイプライン生成時に発行されるものです。任意のパイプラインのジョブ実行時、CI/CDツールでは各パイプラインに対応するPipelineIDをCAへリクエストします。

CAではそのPipelineIDをプリンシパルとして利用し、証明書を発行します。そしてデプロイジョブの際に、その発行された証明書が各サーバへのアクセスで利用されます。また、ディスティネーションでの認可プリンシパルの設定も必要ですが、これはサーバ管理システムによって行われます。

開発者は発行されたPipelineIDをサーバ管理システム上で対象のサーバに対して登録し、その後サーバ管理者のレビュー・承認を経て設定が反映されます。以上のようにして、パイプラインごとのユニークなIDを用いて各パイプラインでのアクセスの制御を実現しています。

次に、CAの証明書リクエストの際の認証について紹介します。人によるログインのケースとは異なり、アプリケーションアカウントによるアクセスとなるため、IdPを利用したOIDCの認証はフィットしません。

このケースではx509クライアント認証を採用し、この場合プリンシパルのフォーマットもCI/CD用のみを受け付けるよう制御しています。このようにして、CI/CDツールのケースにおいても安全なアクセス制御を実現しています。

ここまで二つのケースを見てきましたが、ケースに応じて証明書発行のための認証方式であったり、プリンシパルへの認可方式を柔軟に切り替えて対応しています。また、それぞれのケースで既存の社内インフラを多く活用していることも、お分かりいただけると思います。

ここまでヤフー社内におけるSSHCAへの導入について紹介しました。これらは主にセキュリティを高めるための施策として進められてきましたが、まだ道半ばであり、他にもさまざまなシーンで活用できると考えています。

セキュリティと利便性の両立を追求

それでは最後に、今後のToBeについて紹介します。まず一つ目が、証明書ベースでのホスト認証があります。SSHでは、これまで見てきたようにディスティネーションでのユーザー認証がフィーチャーされがちですが、ログイン時はそれと同時にソースユーザー側でもディスティネーションサーバの検証が行われています。

通常は、この検証も公開鍵認証が使われることが多いですが、ここも証明書ベースに置き換えることが可能です。公開鍵認証での検証では、ログイン時にしばしばfingerprintの確認ダイアログが表示され、とりあえず「Yes」で続行してしまう、またインスタンス再生成などでホストキーが変わって、特に問題がないのに検証に失敗してしまう、そもそも検証をスキップしてしまう、といった経験をお持ちの方もいるのではないでしょうか。

このように、あまり検証の意味をなさず、ユーザビリティも下げているような問題を証明書ベースの認証に置き換えることで、意味のある検証がなされ、ユーザビリティも改善できると考えています。

2つ目に、SSHCAの対象範囲の拡大があります。これまで紹介してきたヤフーでの事例では、特定のシーンにおいて主にセキュリティを高める施策として導入を進めてきました。SSHCAではセキュリティを高める用途のほか、スタティックな秘密鍵からインスタントな証明書に置き換えることで、各ユーザーでの秘密鍵の管理コストを軽減、あるいは無くすことができると考えています。

まだヤフー社内では公開鍵認証が使われているシーンも多くあるため、それらにも適応していくことで、セキュリティ、ユーザビリティの両立が実現できると考えています。

ほかにSSHの鍵が使われるシーンとしては、Gitリポジトリへのアクセスがあると思います。ヤフー社内では、ソースコード管理は主にGitHub Enterpriseが利用されており、これもSSH証明書認証をサポートしています。対象にCA公開鍵を登録しておき、ユーザーの証明書にエクステンションプロパティを設定しておくことで利用できます。

ここで挙げた例のほかにも、SSHCA秘密鍵を使うケースがあるかもしれませんが、基本的にはSSHCAによって証明書による制御に置き換えられるものが多くあります。秘密鍵から証明書に置き換えることによって、開発者そして運用者にとっては秘密鍵の管理コストの軽減が期待できます。また、システム管理者から見ても、各開発者や運用者による鍵管理に懸念が残る状況でしたが、その懸念を取り除くことができます。

そして、SSHCAによってセキュリティが高められることで、ヤフーのサービスを利用しているユーザーがより安心してサービスを利用できればと考えています。秘密鍵管理に関する懸念を取り払い、最終的には各ユーザーが意識せずともセキュアが担保されるような世界を目指していきます。

最後にまとめです。今回は、サーバへのアクセスを証明書ベースでの制限によって実現するSSHCAについて、いくつか具体的な事例を交えて紹介しました。SSHCAでは、シーンや条件に応じて柔軟に認可制御を施すことで、セキュリティの強化を実現します。

また、ユーザーにおける秘密鍵の管理コストを軽減し、利便性の向上をもたらします。しばしばセキュリティと利便性はトレードオフと言われることが多くありますが、SSHCAではその両立を目指しています。利便性の実現に関しては社内でも道半ばですが、これからもセキュリティはもちろん、利便性も妥協することなく追求していきます。

ヤフーでのサービス基盤を支え、ユーザーが安心してヤフーのサービスを利用できるよう日々研鑽していきます。

アーカイブ動画

こちらの記事のご感想を聞かせください。

  • 学びがある
  • わかりやすい
  • 新しい視点

ご感想ありがとうございました


紺谷 将也
セキュリティエンジニア
セキュリティエンジニアとしてヤフー社内におけるID管理、PKI、サーバログイン周りなど認証・認可にかかわる開発・運用に従事。

このページの先頭へ