Kerberos

最終更新: 2026-07-31 20:08:54 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

Kerberos は、統合された管理下にあるシステム向けのネットワーク認証プロトコルです。ユーザーは信頼された鍵配布センター(KDC)で認証し、その後、個々のサービス向けの有効期限付きチケットを取得します。サービスはユーザーのパスワードを受け取らずにユーザーの身元を検証でき、クライアントはサービスが期待された秘密情報を保持していることの証明を要求できます。

Kerberos は主に共通鍵暗号を使用します。共通鍵暗号では KDC が中央の信頼アンカーになります。KDC またはそのデータベースが侵害されると、KDC が長期鍵を管理するすべてのプリンシパルが侵害される可能性があります。したがって Kerberos は、分散型の信頼を、集中型の ID 管理、効率的なチケット発行、およびレルム内のシングルサインオンと交換します。

信頼モデルと中核オブジェクト #

レルムは、管理上の認証ドメインです。通常は EXAMPLE.COM のように大文字で表記します。レルム名は DNS ドメインに似ていることがありますが、両者の名前空間は異なります。設定または DNS 探索によって、ホスト名とドメイン名が Kerberos レルムに対応付けられます。

プリンシパルは ID を表します。

text
alice@EXAMPLE.COM
HTTP/web.example.com@EXAMPLE.COM
krbtgt/EXAMPLE.COM@EXAMPLE.COM

プリンシパル名は、1 つ以上のコンポーネントに続いてレルムを含みます。alice はユーザープリンシパルです。HTTP/web.example.com はサービスプリンシパルで、最初のコンポーネントはサービスを、2 番目のコンポーネントはホストを示します。レルム、ユーザー、ホストの各コンポーネントでは運用上の慣例が異なる場合がありますが、プリンシパル文字列は大文字と小文字を区別します。

すべてのプリンシパルには、KDC に登録された 1 つ以上の長期鍵があります。プリンシパルの種類によって、これらの鍵の取得方法は異なります。

  • 人間のプリンシパルは通常、パスワードから、暗号方式固有の string-to-key 関数とソルトを使用して鍵を導出します。
  • サービスプリンシパルは通常、管理者が生成したランダムな鍵を受け取ります。
  • レルムの krbtgt/REALM プリンシパルには、チケット認可チケット(TGT)の暗号化に使用する鍵があります。

keytab には、プリンシパル名、鍵バージョン番号(KVNO)、暗号化タイプ、長期鍵が保存されます。無人サービスはパスワードを入力できないため、デーモンは keytab を使用します。keytab は認証情報であり、公開証明書ではありません。使用可能なサービス鍵を読み取れる者は、そのサービスになりすまし、そのプリンシパル向けに発行されたチケットを復号できます。

KDC は、論理的には次の 2 つのサービスを提供します。

  1. **認証サービス(AS)**は、初回認証後に TGT を発行します。
  2. **チケット認可サービス(TGS)**は、有効な TGT を特定のサービス向けチケットと交換します。

通常、両サービスは同じ KDC プロセスで実行され、同じレルムデータベースを使用します。チケット取得が 1 台のホストに依存しないよう、本番レルムでは冗長 KDC を配置します。一方、データベース管理とレプリケーションには追加の制御が必要です。

プロトコルフロー #

alice@EXAMPLE.COM が HTTP/web.example.com@EXAMPLE.COM にアクセスするとします。必要な認証情報を確立するため、3 つの交換を行います。以下の名前は、アプリケーション固有のパケットではなく、Kerberos プロトコルメッセージを表します。

初回認証: AS-REQ と AS-REP #

クライアントは、krbtgt/EXAMPLE.COM@EXAMPLE.COM 向けの TGT を要求する AS-REQ を送信します。リクエストには、クライアントプリンシパル、要求する有効期間とフラグ、nonce、サポートする暗号化タイプ、および必要に応じて事前認証データが含まれます。

パスワードによる事前認証には通常、Alice のパスワードからローカルで導出した鍵で暗号化した現在時刻が含まれます。KDC は Alice の鍵を検索し、タイムスタンプを検証します。一部のクライアントは、事前認証なしで最初に AS-REQ を送信し、KDC_ERR_PREAUTH_REQUIRED と方式およびソルト情報を受け取った後に再試行します。最初のエラーは認証失敗ではなく、プロトコルネゴシエーションです。

KDC は、関連する 2 つの結果を含む AS-REP を返します。

  • レルムの krbtgt 鍵で暗号化された TGT。クライアントはチケットを保存しますが、保護された内容を復号できません。
  • Alice の長期鍵で暗号化された応答データ。応答には、TGT セッション鍵、チケットの時刻とフラグ、nonce 応答、および関連メタデータが含まれます。

応答の復号に成功することで、クライアントが Alice のパスワードから導出された鍵を知っていることが証明されます。クライアントは、TGT とそのセッション鍵を認証情報キャッシュに格納した後、パスワードを破棄できます。

チケット取得: TGS-REQ と TGS-REP #

クライアントは HTTP/web.example.com@EXAMPLE.COM 向けの TGS-REQ を送信します。リクエストには次が含まれます。

  • 不透明な TGT
  • TGT セッション鍵で暗号化された新しいオーセンティケータ
  • 要求するサービスプリンシパル、有効期間、オプション、nonce、サポートする暗号化タイプ

KDC は krbtgt 鍵で TGT を復号し、TGT セッション鍵を取得します。そして、そのセッション鍵を使用してオーセンティケータを検証します。有効な証明により、リクエストが TGT 内で指定されたクライアントに結び付けられます。

TGS-REP にも、役立つ 2 つの部分があります。

  • HTTP/web.example.com の長期鍵で暗号化されたサービスチケット。Alice は保護されたチケットを復号できません。
  • TGT セッション鍵で暗号化された応答データ。Alice はそのデータを復号して、新しいクライアント・サービス間セッション鍵とチケットメタデータを取得できます。

TGT の提示によって、Alice のパスワードから導出された鍵が TGS に送信されることはありません。ただし、キャッシュには関連するセッション鍵も含まれているため、TGT の窃取は、有効期限または失効制御が適用されるまで、なりすましを可能にします。

サービス認証: AP-REQ と AP-REP #

クライアントは Web サービスに AP-REQ を送信します。そこには次が含まれます。

  • HTTP/web.example.com 向けに暗号化されたサービスチケット
  • クライアント・サービス間セッション鍵で暗号化された新しいオーセンティケータ

サービスは keytab 内で一致するプリンシパル、KVNO、暗号化タイプを検索し、チケットを復号してセッション鍵を取り出し、オーセンティケータを検証します。アプリケーションまたは GSS-API ライブラリは、チケットの時刻、名前、チェックサム、およびその他のポリシー関連フィールドも検証します。

オーセンティケータには、クライアント ID とサブ秒精度のデータを含む現在時刻が含まれます。また、アプリケーションバインディングデータに対するチェックサム、シーケンス番号、クライアントが生成したサブキーを含めることもできます。サービスはリプレイキャッシュを維持し、同じチケットとオーセンティケータの組み合わせがクロックスキューの許容範囲内で繰り返し受け入れられないようにします。サービスチケットは有効期間中に再利用できますが、認証交換ごとに新しいオーセンティケータが必要です。

相互認証が要求されると、サービスはクライアント・サービス間セッション鍵で暗号化した AP-REP を返します。保護されたタイムスタンプ応答、および場合によってはサブキーとシーケンス番号によって、ピアがサービスチケットを復号したことが証明されます。Kerberos は相互認証をサポートしますが、すべての統合が相互認証を行うと仮定せず、アプリケーション側で要求して検証する必要があります。

text
Client                         KDC                         Service
  |--- AS-REQ ----------------->|                             |
  |<-- AS-REP: TGT + Kc,tgs ----|                             |
  |--- TGS-REQ: TGT + auth ---->|                             |
  |<-- TGS-REP: ticket + Kc,s ---|                             |
  |--- AP-REQ: ticket + auth ------------------------------->|
  |<-- AP-REP, when mutual authentication is requested ------|

Kc,tgs は TGT セッション鍵を、Kc,s はクライアント・サービス間セッション鍵を表します。どちらも長期プリンシパル鍵ではなく、プロトコル用途に生成される短期鍵です。

パスワードがサービスに到達しない理由 #

Alice のパスワードは、ローカルの string-to-key 関数への入力です。ソルトと暗号化タイプは結果の鍵に影響するため、同じパスワードでも、異なるレルムまたは異なる enctype 設定では同じ鍵になるとは限りません。KDC はパスワードと同等の鍵素材を保存し、それを使った証明を検証します。一方、Web サービスが保存するのは自身のランダムなサービス鍵だけです。

したがって Web サービスは、Alice のパスワードも Alice の長期鍵も受け取りません。サービス鍵で暗号化されたチケットを受け取り、チケットのセッション鍵で作成されたオーセンティケータを検証します。そのため、サービスが侵害されても、すべてのユーザーのパスワードが直接公開されるわけではありません。

パスワードベースの Kerberos でも、状況によってはオフライン推測が可能です。適切な暗号化されたプロトコル素材を入手した攻撃者は、KDC に繰り返し接続せずにパスワード候補を検証できます。事前認証によって、未認証のリクエストに対する AS-REP の発行は防げますが、暗号化されたタイムスタンプによる事前認証自体がパスワード推測用の素材を提供することがあります。強力なパスワード、保護された KDC データベース、最新の暗号化タイプ、レート制御、およびサポートされる場合の PKINIT や FAST などのより強力な初回認証メカニズムは、そのリスクの異なる部分を低減します。

チケットの内容と暗号化境界 #

Kerberos パケットは、ルーティングとアルゴリズム選択に必要な外側の構造を公開しつつ、ID の主張とセッション鍵を意図された読み手向けに暗号化します。概念的には次のとおりです。

  • チケットは外側のフィールドで宛先レルムとサービスを識別します。暗号化部分には、クライアントプリンシパル、セッション鍵、フラグ、認証時刻と有効期限、オプションの更新可能時刻、通過したレルムの情報、オプションのクライアントアドレス、認可データが含まれます。
  • TGT の暗号化部分は krbtgt 鍵で保護されるため、KDC が読み取れます。
  • サービスチケットの暗号化部分はサービスプリンシパルの長期鍵で保護されるため、対象サービスが読み取れます。
  • パスワード認証されたユーザー向けの AS 応答データは、ユーザーの長期鍵で保護されます。
  • TGS 応答データは、TGT 交換によってすでに利用可能な鍵、通常は TGT セッション鍵で保護されます。
  • オーセンティケータは、提示されたチケットに関連付けられたセッション鍵で保護されます。

クライアントは各チケットと対応するセッション鍵を、別々の暗号化境界を通じて受け取ります。クライアントはオーセンティケータを構築するためにセッション鍵を必要としますが、チケットを復号する必要はありません。同様に、サービスは自身の鍵でサービスチケットを復号できるため、Alice の長期鍵を必要としません。

チケットフラグは、認証情報を使用できる方法を変更します。**転送可能(forwardable)**な TGT は別のホスト向けの転送済み認証情報を生成できます。一方、**更新可能(renewable)**な TGT は、更新可能な上限まで有効期限を後から延長できます。どちらのフラグもチケットを永久にするものではありません。レルムポリシーとチケットにエンコードされた時刻が引き続き優先されます。

運用上の依存関係 #

プロトコルの正しさは、名前、時刻、トランスポート、共有鍵の状態に依存します。そのため、多くの Kerberos 障害は、アプリケーションがユーザー権限を評価する前に発生します。

DNS と名前の正規化 #

サービスプリンシパルにはホスト名がエンコードされるため、DNS エイリアスと正規化がプリンシパル選択に影響します。https://reports.example.com に接続するクライアントは HTTP/reports.example.com@EXAMPLE.COM を要求する場合があります。一方、名前を正規化するライブラリは HTTP/web17.example.com@EXAMPLE.COM を要求する場合があります。KDC と keytab にプロビジョニングされたプリンシパルだけが機能します。

rdns や、サポートするバージョンでは dns_canonicalize_hostname などの MIT Kerberos 設定が、ホスト名の正規化の一部を制御します。rdns = false にすると、逆引き DNS からサービス名を導出しなくなります。正引きの正規化を無効にするとサービス名を予測しやすくできますが、一部のクライアントライブラリやアプリケーションが独自に解決を行うため、すべてのクライアントライブラリとアプリケーションをテストする必要があります。

Kerberos は、_kerberos._udp.example.com や _kerberos._tcp.example.com などの DNS SRV レコードを通じて KDC を探索できます。明示的な [realms] エントリを使用すると、探索の曖昧さを避けられます。アプリケーション、TLS 証明書、Hadoop の _HOST 展開、運用においては、正引きおよび逆引きレコードが一貫したホスト名を持つ必要があります。

時刻同期とリプレイ保護 #

オーセンティケータには現在時刻が含まれ、KDC とサービスは設定されたクロックスキューを適用します。したがって NTP、または認証済みで監視される別の時刻サービスが運用上の依存関係になります。クロックが大きく変化すると、事前認証が無効になったり、KRB_AP_ERR_SKEW が発生したり、有効なチケットがまだ有効でない、または期限切れであると判断されたりします。

リプレイ保護は、短いオーセンティケータ受け入れ期間と、サービス側のリプレイキャッシュを組み合わせます。ファイルシステムや権限の問題を隠すためにリプレイキャッシュを無効化すると、重要なプロトコル防御が失われます。サービスには、プロセスモデルに適した、書き込み可能で非公開かつ安定したリプレイキャッシュの場所が必要です。

UDP、TCP、ファイアウォール #

Kerberos はポート 88 を使用し、現在の実装は TCP をサポートしています。また、多くの実装は UDP もサポートします。グループ情報や認可データによってチケットサイズが増加すると、大きな応答は実用上の UDP 制限を超える場合があります。クライアントは TCP で再試行できますが、ファイアウォールは実装が選択したトランスポートを許可する必要があります。MIT Kerberos の管理者は、TCP を優先するために udp_preference_limit = 1 を設定することがあります。この判断は、互換性とネットワークポリシーに基づく必要があります。管理サービスとパスワード変更サービスには別のポートも使用され、一般的には kadmind が TCP 749、パスワード変更が TCP/UDP 464 を使用します。

クロスレルム信頼 #

クロスレルム信頼を使用すると、レルム A.EXAMPLE のプリンシパルがレルム B.EXAMPLE のサービスチケットを要求できます。KDC は、共有されたクロスレルム krbtgt プリンシパルを通じて経路を確立します。A から B への直接経路では、両レルムが次のようなプリンシパルの一致する鍵素材を保持する必要があります。

text
krbtgt/B.EXAMPLE@A.EXAMPLE

クライアントはまず A からクロスレルム TGT を受け取り、それを B に提示してサービスチケットを取得します。階層型レルム名は経路を暗黙に示すことがあり、[capaths] 設定で非階層型の経路を定義することもできます。チケットの transited フィールドには、ポリシー評価用に経路上のレルムが記録されます。

信頼の方向、鍵の配布、暗号化タイプの互換性、プリンシパルのマッピングには、明示的な管理が必要です。信頼経路を越えた認証によってアプリケーションへのアクセス権が付与されるわけではありません。レルム B と対象サービスは、引き続きローカルの認可ポリシーを適用します。

小規模な MIT Kerberos レルムの構築 #

以下の Debian または Ubuntu の例では、KDC kdc01.example.com を使用して EXAMPLE.COM を作成します。パッケージ名、パス、サービスユニット、デフォルト値はディストリビューションによって異なるため、パッケージのドキュメントが優先されます。本番 KDC には、専用ホスト、バックアップ、レプリケーション、監視、制限された管理を使用してください。

パッケージのインストール #

bash
sudo apt-get update
sudo apt-get install krb5-kdc krb5-admin-server krb5-user

パッケージ設定で、デフォルトレルムと KDC の入力を求められる場合があります。以下のファイルでは、例を明示的に設定します。

クライアントとレルムマッピングの設定 #

KDC、クライアント、サービスホストに /etc/krb5.conf を作成します。

ini
[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = false
    rdns = false
    dns_canonicalize_hostname = false
    ticket_lifetime = 10h
    renew_lifetime = 7d
    forwardable = false

[realms]
    EXAMPLE.COM = {
        kdc = kdc01.example.com
        admin_server = kdc01.example.com
        kpasswd_server = kdc01.example.com
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

forwardable = false によって、クライアントのデフォルトが最小権限になります。委任が必要なワークフローでは、明示的に要求できます。DNS による KDC 探索を使用するサイトでは、明示的な KDC ホストを省略し、SRV レコードを公開して検証した後に探索オプションを設定できます。

KDC の設定 #

一般的な Debian 派生パッケージでは、/etc/krb5kdc/kdc.conf に次を記述できます。

ini
[kdcdefaults]
    kdc_ports = 88
    kdc_tcp_ports = 88

[realms]
    EXAMPLE.COM = {
        database_name = /var/lib/krb5kdc/principal
        admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
        acl_file = /etc/krb5kdc/kadm5.acl
        key_stash_file = /etc/krb5kdc/stash
        kadmin_port = 749
        max_life = 10h
        max_renewable_life = 7d
        default_principal_flags = +preauth
        supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal
    }

暗号化タイプは、必要とされる最も古いクライアントおよびサービスと一致させる必要があります。AES-SHA2 enctype は新しい Kerberos スタックで利用できますが、古い導入済みソフトウェアは AES-SHA1 とのみ相互運用できる場合があります。管理者は互換性を棚卸しし、文書化された要件なしに古いアルゴリズムを有効化するのではなく、計画的に移行すべきです。

/etc/krb5kdc/kadm5.acl で、専用の管理クラスに広範な権限を付与します。

text
*/admin@EXAMPLE.COM *

より厳格な ACL では、自動化や運用担当者に必要な操作だけを委任してください。KDC の設定、データベース、stash、ACL ファイルは、root 所有と制限された権限で保護します。

データベースとプリンシパルの初期化 #

レルムデータベースを作成し、データベースマスター鍵を stash に保存します。

bash
sudo kdb5_util create -s -r EXAMPLE.COM
sudo kadmin.local -q "addprinc admin/admin@EXAMPLE.COM"
sudo kadmin.local -q "addprinc alice@EXAMPLE.COM"

kdb5_util create はデータベースマスターパスワードの入力を求めます。addprinc は各人間プリンシパルのパスワードを求めます。kadmin.local はローカルデータベースに直接アクセスするため、初期ブートストラップに適しています。リモートの kadmin は管理プリンシパルとして認証し、kadm5.acl の管理下に置かれます。

データベースが存在してからサービスを起動します。

bash
sudo systemctl enable --now krb5-kdc
sudo systemctl enable --now krb5-admin-server
sudo systemctl status krb5-kdc krb5-admin-server

ユニット名はパッケージによって異なります。クライアントからポート 88 に到達できることを確認し、管理ポートは必要とする管理ネットワークだけに公開してください。

サービスプリンシパルと keytab の作成 #

ローカルサービスアカウント websvc が HTTP アプリケーションを実行するとします。

bash
sudo install -d -m 0750 -o root -g websvc /etc/security/keytabs
sudo kadmin.local \
  -q "addprinc -randkey HTTP/web.example.com@EXAMPLE.COM"
sudo kadmin.local \
  -q "ktadd -k /etc/security/keytabs/web.keytab HTTP/web.example.com@EXAMPLE.COM"
sudo chown websvc:websvc /etc/security/keytabs/web.keytab
sudo chmod 0600 /etc/security/keytabs/web.keytab
sudo klist -k -e -t /etc/security/keytabs/web.keytab

ktadd は通常、keytab に書き込む際に新しい鍵バージョンを作成します。鍵を変更する動作を理解せずに再実行すると、すでに配布されたコピーが無効になる可能性があります。レプリケートされたサービスでは、サイトのツールに従って制御された 1 つの鍵バージョンを生成または抽出し、保護されたチャネルで配布し、すべての場所で KVNO を検証してから転送時の成果物を削除してください。keytab をソース管理、コンテナイメージレイヤー、または制限されていない設定ストアに置いてはいけません。

サービスアカウントの権限は、そのプロセスに必要な keytab エントリだけを読み取れるようにします。サービスプリンシパルと keytab を分離すると、1 つのデーモンまたはホストが侵害された場合の影響を抑えられます。

Kerberos クライアントの使用 #

TGT を取得して確認します。

bash
kinit alice@EXAMPLE.COM
klist -ef

klist -e は暗号化タイプを表示し、-f はチケットフラグを表示します。アプリケーションをテストする前に、サービスチケットを要求してプリンシパル選択が機能することを確認します。

bash
kvno HTTP/web.example.com@EXAMPLE.COM
klist

kvno は KDC に指定されたサービスチケットを要求し、その KVNO を報告します。成功すれば、クライアントが KDC を検索し、TGT を使用し、サービスプリンシパルを見つけられることが確認できます。ただし、サーバーの keytab に同じ鍵が含まれていることや、アプリケーションがチケットを受け入れることまでは証明されません。

その他の中核操作は次のとおりです。

bash
# Kerberos パスワードサービスを通じてプリンシパルのパスワードを変更します。
kpasswd alice@EXAMPLE.COM

# 10 時間有効で、最大 7 日間更新可能な転送可能 TGT を取得します。
kinit -f -l 10h -r 7d alice@EXAMPLE.COM

# まだ有効な更新可能 TGT を更新します。
kinit -R

# keytab からデーモンまたは診断プロセスを認証します。
kinit -k -t /etc/security/keytabs/web.keytab \
  HTTP/web.example.com@EXAMPLE.COM

# アクティブな認証情報キャッシュを削除します。
kdestroy

レルムポリシーによって、要求された有効期間が短縮されたり、要求されたフラグが拒否されたりすることがあります。転送可能な認証情報は、ワークフローで委任が必要な場合にだけ有効にしてください。侵害された中間ホストが、認証情報の有効期限までユーザーとしてそれらを使用できるためです。

認証情報キャッシュとコレクション #

Kerberos クライアントは、チケットとセッション鍵を認証情報キャッシュに保存します。KRB5CCNAME でタイプと場所を選択できます。

bash
export KRB5CCNAME=FILE:/run/user/$(id -u)/krb5cc_example
kinit alice@EXAMPLE.COM
klist
kdestroy

一般的なキャッシュタイプには、FILE、DIR、カーネルキーリング、KCM がありますが、オペレーティングシステムと Kerberos ビルドによって異なります。FILE キャッシュは 1 つのプライマリ認証情報セットを保持します。コレクションをサポートするタイプでは、複数のプリンシパルの認証情報を保持し、プライマリキャッシュを選択できます。対応する操作をサポートする MIT Kerberos バージョンでは、klist -l がコレクションメンバーを一覧表示し、klist -A がすべてのキャッシュを表示し、kdestroy -A がコレクションを破棄します。

スクリプトは、キャッシュパスが通常のファイルであると仮定すべきではありません。コンテナ、sudo、systemd サービス、ユーザー名前空間、SSH セッションによって、キャッシュの可視性と所有権が変わることがあります。自動化には明示的な非公開キャッシュを設定し、終了時に削除し、無関係なプロセス間で 1 つの可変キャッシュを共有しないでください。

アプリケーションとの統合 #

アプリケーションが AS、TGS、AP メッセージを直接構築することはほとんどありません。一般的な統合レイヤーには次があります。

  • GSS-API。セキュリティコンテキスト、相互認証、完全性、オプションの機密性を提供し、Kerberos メッセージの詳細を隠蔽します。
  • SPNEGO。GSS-API メカニズムをネゴシエートし、HTTP Negotiate の基盤になります。
  • SASL/GSSAPI。LDAP、Kafka、データベース接続などのプロトコルに Kerberos 認証を追加します。

HTTP Negotiate では、ブラウザーまたはコマンドラインクライアントがまずチャレンジを受け取ります。

http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Negotiate

GSS-API 対応の curl は、現在の認証情報キャッシュを使用できます。

bash
kinit alice@EXAMPLE.COM
curl --negotiate -u : https://web.example.com/protected

curl は、GSS-API 交換を含む Authorization: Negotiate ... トークンを送信します。サーバーは HTTP/web.example.com@EXAMPLE.COM を含む keytab を読み込み、セキュリティコンテキストを受け入れ、認証されたプリンシパルをアプリケーション ID にマッピングします。サーバープロセスは通常、次のような実装固有の設定から keytab の場所を受け取ります。

bash
KRB5_KTNAME=FILE:/etc/security/keytabs/web.keytab ./web-server

本番のサービスマネージャーでは、その環境変数と keytab の権限を設定し、無関係なプロセスに公開しないでください。

GSS-API のホストベース名は、HTTP@web.example.com のように表現されることが多く、Kerberos メカニズムはこの形式を HTTP/web.example.com@EXAMPLE.COM のようなサービスプリンシパルにマッピングします。クライアントは、プロビジョニングされたプリンシパルが対象とするホスト名を使用する必要があります。したがって、ロードバランサー名と DNS エイリアスには、偶然の正規化に依存せず、対応するサービスプリンシパルの計画が必要です。

GSS-API は、アプリケーションが完全性または機密性を要求した場合、メッセージを保護できます。HTTP Negotiate は通常、接続を認証し、HTTPS は HTTP ヘッダーと本文を保護します。GSS でラップされたメッセージの外部におけるサーバー証明書の検証、通信の機密性、Cookie、ベアラートークン、アプリケーションデータの保護には、引き続き TLS が必要です。

Kerberized Beeline から Kyuubi への接続を追跡する #

組織固有の名前が匿名化されている mycompany の Kyuubi エンドポイントを考えます。

text
jdbc:hive2://kyuubi.hadoop.vip.mycompany.com:10010/default;ssl=true;principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM?kyuubi.session.cluster=analytics-prod#spark.yarn.queue=analytics-high-memory

Beeline の起動時には、; と # がシェルで意味を持つため、URL 全体を引用符で囲みます。

bash
kinit alice@PROD.MYCOMPANY.COM
klist
kvno kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM

beeline -u \
  'jdbc:hive2://kyuubi.hadoop.vip.mycompany.com:10010/default;ssl=true;principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM?kyuubi.session.cluster=analytics-prod#spark.yarn.queue=analytics-high-memory'

URL には、独立した複数の役割があります。

  • kyuubi.hadoop.vip.mycompany.com:10010/default は、Kyuubi リスナーと初期データベースを選択します。
  • ssl=true は、トランスポート暗号化とサーバー証明書検証のために TLS を有効にします。TLS は Kerberos 認証とは別のものです。
  • principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM は、クライアントが Kyuubi サーバーに証明を期待する Kerberos ID を指定します。これは Alice のプリンシパルでもパスワードでもありません。
  • kyuubi.session.cluster=analytics-prod は、デプロイメント固有の Kyuubi セッションクラスターを選択します。
  • spark.yarn.queue=analytics-high-memory は、セッションの Spark エンジン用の YARN キューを要求します。

Kyuubi JDBC ドライバーは、? または # の後にセッションプロパティを受け付けます。古い Hive JDBC URL パーサーは、設定サフィックスと変数サフィックスをより限定的に区別します。そのため、両方の区切り文字を使用する URL はデプロイメント契約になります。インストールされた Beeline ドライバーと Kyuubi のバージョンが、これらのプロパティの転送方法について一致している必要があります。どちらのプロパティも Kerberos サービスプリンシパルを変更しません。

Kerberos は次のように接続に参加します。

  1. kinit は Alice の TGT を取得し、セッション鍵とともに認証情報キャッシュへ保存します。Beeline は URL から Alice のパスワードを取得しません。
  2. JDBC ドライバーはキャッシュを読み取り、kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM のサービスチケットを要求します。チケットがキャッシュにない場合、Kerberos ライブラリは Alice の TGT を使用して TGS-REQ を送信します。
  3. レルムの TGS は、Kyuubi プリンシパル向けに暗号化されたサービスチケットと、Alice の Kerberos ライブラリが読み取れるクライアント・サービス間セッション鍵を返します。
  4. JDBC トランスポートの SASL/GSSAPI ネゴシエーション中に、Beeline はそのサービスチケットと新しいオーセンティケータを含む AP-REQ を送信します。
  5. Kyuubi は保護された keytab を読み取り、一致するプリンシパル、KVNO、暗号化タイプを選択し、チケットを復号してオーセンティケータを検証します。相互認証により、Beeline はピアが期待された Kyuubi サービス鍵を保持していることを検証できます。
  6. Kyuubi は Alice の認証済み Kerberos ID を取得します。認可ルールによって、Alice がセッションを開き、analytics-prod を選択し、要求された YARN キューを使用し、データにアクセスできるかどうかが決まります。
  7. Kyuubi が Spark エンジンを起動または再利用するとき、Hadoop 委任トークンによって、Alice の認可済み HDFS および YARN アクセスを分散アプリケーションへ渡せます。これにより、Alice の TGT をすべてのエグゼキューターへコピーする必要がなくなります。

ホスト名はネットワークアドレスとサービスプリンシパルの両方に現れますが、2 つの検証は別々です。TLS は kyuubi.hadoop.vip.mycompany.com の証明書を検証し、Kerberos は kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM の鍵を保持していることを検証します。DNS 正規化、レルムマッピング、KDC データベース、Kyuubi の設定済みプリンシパル、keytab は、その ID に関して一致している必要があります。

コマンドシーケンスを使用して、一般的な障害を切り分けます。

  • 有効な TGT がない状態での klist は、サービスチケットを要求する前の障害を示します。
  • kvno が「server not found in Kerberos database」を報告する場合、プリンシパル、レルム、DNS、またはプロビジョニングの不一致を示します。
  • kvno が成功する一方で Beeline がサーバープリンシパルまたは完全性エラーを報告する場合、Kyuubi の keytab、KVNO、暗号化タイプ、または設定されたサーバー名を確認します。
  • Kerberos が成功して TLS が失敗する場合、証明書チェーン、トラストストア、または証明書ホスト名を確認します。
  • 認証が成功してセッションまたはクエリが拒否される場合、Kyuubi ポリシー、YARN キューの認可、SQL 認可、またはストレージ権限を確認します。

Hadoop エコシステムにおける Kerberos #

安全な Hadoop デプロイメントでは、Kerberos を使用して HDFS、YARN、Hive、および関連サービス全体のデーモンとユーザーの ID を確立します。代表的なサービスプリンシパルには次があります。

text
nn/nn01.example.com@EXAMPLE.COM
dn/dn01.example.com@EXAMPLE.COM
rm/rm01.example.com@EXAMPLE.COM
nm/nm01.example.com@EXAMPLE.COM
hive/hive01.example.com@EXAMPLE.COM
HTTP/nn01.example.com@EXAMPLE.COM

Hadoop の設定では、_HOST を使用することがよくあります。

xml
<property>
  <name>hadoop.security.authentication</name>
  <value>kerberos</value>
</property>
<property>
  <name>dfs.namenode.kerberos.principal</name>
  <value>nn/_HOST@EXAMPLE.COM</value>
</property>
<property>
  <name>dfs.namenode.keytab.file</name>
  <value>/etc/security/keytabs/nn.service.keytab</value>
</property>

実行時に Hadoop は _HOST を、ホストの解決済み正規名に置き換えます。したがって DNS、ホスト名設定、実際の KDC プリンシパルは一致する必要があります。nn/nn01.example.com の keytab は、両方のプリンシパル名が意図どおりプロビジョニングされていない限り、nn/namenode-alias.example.com に対する要求を満たせません。

NameNode、DataNode、ResourceManager、NodeManager、HiveServer2、HTTP エンドポイントには、各コンポーネントのセキュリティドキュメントで規定されたサービスプリンシパルと keytab エントリが必要です。すべてのデーモンで 1 つの keytab を共有すると、侵害時の影響範囲が広がり、ローテーションも難しくなります。

Hadoop クライアントはまず Kerberos で認証し、その後、サポートされるサービス向けの 委任トークンを取得できます。委任トークンは、Hadoop サービスのシークレットマネージャーが発行・検証する、有効期限付きのベアラ形式の認証情報です。トークンによって、分散ジョブはすべての RPC で KDC に接続せず、ユーザーの TGT をすべてのタスクにコピーすることなく、HDFS やその他のサービスへアクセスできます。トークンのスコープ、更新、取り消し、最大有効期間はサービス固有であり、盗難されたトークンはその範囲と有効期間内で使用できます。

Kerberos は接続を開始したプリンシパルを示します。HDFS の権限と ACL、YARN キューのポリシー、Hive または SQL の権限、プロキシユーザー規則、外部認可システムによって、そのプリンシパルが実行できる操作が決まります。Hadoop の auth_to_local マッピングのようなプリンシパルからローカル名への規則も確認が必要です。予期しないマッピングによって、異なる Kerberos ID が 1 つのローカルアカウントに統合される可能性があります。

セキュリティプラクティス #

Kerberos デプロイメントでは、すべての長期鍵と再利用可能な認証情報を制御する必要があります。

  • 各 keytab をサービスアカウントに制限し、必要なプリンシパルだけを含め、無関係なホストへ 1 つの keytab をコピーしない。
  • KVNO の伝播、実行中のプロセス、レプリケートされたホスト、以前の鍵で発行されたチケットを考慮した手順でサービス鍵をローテーションする。古い鍵を急に削除すると、期限切れでないチケットが壊れる可能性がある。
  • クライアント、KDC、サービスの暗号化タイプのサポートに互換性を持たせる。enctype を無効にする前に、チケットと keytab の両方を検査する。
  • レビュー済みのメカニズムが例外を必要とする場合を除き、パスワードプリンシパルには事前認証を要求する。脅威モデルが必要とする場合は、強力なパスワードポリシーとより強力な事前認証メカニズムを使用する。
  • 認証情報キャッシュと転送済み認証情報を保護する。SSH の認証情報委任とアプリケーションのなりすまし機能によって、ユーザーとして動作できるホストが増える。
  • KDC にパッチを適用して分離し、管理アクセスを制限し、レルムデータベースとマスター鍵素材を安全にバックアップし、復元をテストする。
  • パスワード、keytab、KDC データベースダンプ、stash ファイル、認証情報キャッシュを、リポジトリ、ログ、サポートバンドル、イメージレイヤーに保存しない。
  • Kerberos がピアを認証する場合でも TLS を使用する。Kerberos は、すべてのアプリケーションのトランスポートを自動的に暗号化するわけではない。

鍵のローテーションには重複期間の計画が必要です。KDC は KVNO と enctype で区別される複数のサービス鍵を保持でき、keytab も複数のエントリを含められます。正確なロールオーバー動作は KDC のツールとアプリケーションの keytab 再読み込み動作に依存するため、新しいチケット、古くてまだ有効なチケット、すべてのレプリカを検証してから以前の鍵を廃止してください。

因果レイヤー別のトラブルシューティング #

アプリケーションレイヤーより下から開始します。ブラウザーエラーや一般的な GSS 例外には、レルム、DNS、クロック、キャッシュ、keytab の障害が含まれていることがあります。

チケット取得の追跡 #

MIT Kerberos では、ライブラリの判断を追跡できます。

bash
env KRB5_TRACE=/dev/stderr kinit alice@EXAMPLE.COM
env KRB5_TRACE=/dev/stderr \
  kvno HTTP/web.example.com@EXAMPLE.COM

トレース出力には、設定ファイル、KDC 選択、事前認証ネゴシエーション、キャッシュ操作、リファーラル、ホスト名の判断、トランスポートの再試行が表示されます。トレースにはプリンシパル名や運用メタデータが含まれる可能性があるため、共有前にサニタイズしてください。

認証情報とサーバー鍵を検査します。

bash
klist -ef
sudo klist -k -e -t /etc/security/keytabs/web.keytab
kvno HTTP/web.example.com@EXAMPLE.COM

取得したチケットに報告されたサービスプリンシパル、KVNO、enctype と、デーモンが利用できるエントリを比較します。また、実行中のプロセスが、運用担当者が検査した keytab ではなく、別のパスや古いコンテナシークレットを読み込んでいないことも確認します。

名前、時刻、トランスポートの検証 #

bash
hostname -f
getent hosts web.example.com
dig +short -x 192.0.2.20
dig +short SRV _kerberos._tcp.example.com
timedatectl status

正引き、逆引き、設定されたサービスホスト名、TLS 名、KDC プリンシパルは、設計によっては常に同一である必要はありません。ただし、相違は意図的であり、クライアントの正規化規則でサポートされている必要があります。必要なトランスポートでポート 88 を確認し、小さなリクエストは機能するのに大きな応答が失敗する場合は、ファイアウォールを検査します。

一般的なエラーを原因に対応付ける #

エラーまたは症状原因に関する確認項目
Cannot find KDC for realmレルムの綴り、[realms]、[domain_realm]、DNS SRV レコード、リゾルバーの状態、ネットワーク到達性
Client not found in Kerberos databaseクライアントプリンシパルの綴り、レルム選択、削除されたアカウント、意図しないエンタープライズプリンシパルマッピング
Preauthentication failedパスワードの誤り、古いクライアントのソルト前提、無効または互換性のない事前認証方式、プリンシパル鍵の不一致
Clock skew too great / KRB_AP_ERR_SKEWクライアント、KDC、サービスのクロック、NTP の状態、VM の再開またはクロックジャンプ
Server not found in Kerberos database要求されたホスト名、サービスクラス、レルム、DNS 正規化、ロードバランサーエイリアス、サービスプリンシパルの欠落
No key table entry found誤った keytab パス、プリンシパルの欠落、未サポートの enctype、読み取り不能な keytab、別の ID を使用するデーモン
KRB_AP_ERR_MODIFIED / チケットを復号できない古い keytab、KVNO の不一致、誤ったホスト上の重複プリンシパル、対応する鍵を持たないホストへ DNS がトラフィックを送信、enctype の不一致
Replay cache エラー再利用されたオーセンティケータ、共有または書き込み不能なリプレイキャッシュパス、複製されたプロセス状態、実際のリプレイ
認証情報キャッシュがない、または期限切れKRB5CCNAME、プロセス UID、コンテナまたは sudo の境界、チケット時刻、更新可能上限、破棄されたキャッシュ
大きなチケットでのみ失敗UDP の断片化、ブロックされた TCP/88、プロキシまたはファイアウォールの制限、増大した認可データ
認証は成功するがアクセスが拒否されるアプリケーション ID マッピング、ローカルアカウントマッピング、ACL、HDFS 権限、YARN キュー、Hive 権限、その他の認可ポリシー

エラーテキストは実装によって異なります。KRB5_TRACE、KDC ログ、サービスログ、klist、kvno、DNS ツール、同期されたタイムスタンプから得られる証拠は、複数の設定オプションを同時に変更するよりも信頼性の高い診断材料になります。

境界と制限 #

Kerberos は、設定された信頼関係内で認証と共有セッション鍵の確立を提供します。Kerberos 単独では、次を提供しません。

  • 認可: アプリケーションは引き続き権限、ロール、ACL、ポリシーを適用する必要があります。
  • 普遍的なトランスポート暗号化: アプリケーションは GSS の機密性を要求するか、TLS などのトランスポートを使用する必要があります。
  • ディレクトリサービス: LDAP、Active Directory、データベース、またはローカルマッピングが、プロファイル、グループ、属性を保存する場合があります。
  • インターネット全体の公開鍵 ID: レルムには事前の KDC と信頼の設定が必要です。Kerberos は Web PKI の代替ではありません。
  • 侵害への耐性: 盗まれた keytab、認証情報キャッシュ、KDC 鍵、委任トークンは、その範囲と有効期間内で引き続き使用可能な認証情報です。

集中管理は、Kerberos の価値と運用上の負担の両方を説明します。サービスは、KDC が暗号化されたチケットを通じてプリンシパルを保証するため、ユーザーのパスワードを収集せずに済みます。しかし、信頼できる認証は、KDC のセキュリティ、鍵の配布、プリンシパル名、DNS の動作、時刻同期、アプリケーションレベルの検証に依存します。

公式リファレンス #

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)