Kerberosを使ったJavaのシングル・サインオン

概説

Java SEセキュリティ・アーキテクチャの重要な拡張機能は、Kerberos Version 5を使用したシングル・サインオンを実現する機能です。シングル・サインオン・ソリューションを利用すると、ユーザーは、1回のみの認証で、複数のどのシステムに存在する情報にもアクセスできるようになります。これを実現するため、認証および承認にはJAASを、ピア・アプリケーションとの通信用のセキュアなコンテキストの確立にはJava GSS-APIを、それぞれ使用します。ここでは、シングル・サインオンの基盤となるセキュリティ・メカニズムとしてKerberos V5に注目して解説します。ただし、将来、他のセキュリティ・メカニズムも追加される可能性があります。

概要

分散システムの使用が増加するにつれて、ユーザーがリモートのリソースにアクセスする必要性が高まっています。従来の方法では、ユーザーは複数のシステムにサイン・オンしなければならず、しかもシステムごとに使用するユーザー名や認証技術が異なる場合もあります。一方、シングル・サインオンを利用すると、ユーザーが一度認証を行うだけで、認証された識別情報がセキュアにネットワーク内を通過し、ユーザーに代わってリソースへのアクセスが行われます。

このドキュメントでは、Kerberos V5プロトコルに基づいたシングル・サインオンを使用する方法を説明します。Kerberosに対するプリンシパルの認証、および識別情報を証明するクレデンシャルの取得には、Java認証・承認サービス(JAAS)を使用します。OracleによるKerberosログイン・モジュールを実装して、ネイティブのKerberosをサポートするプラットフォーム上の既存のキャッシュからクレデンシャルを読み取る方法を示します。次に、Java Generic Security Service API (Java GSS-API)および取得済みのKerberosクレデンシャルを使用して、リモート・ピアを認証します。また、多層環境でシングル・サインオンのKerberosクレデンシャルを委譲する方法も示します。

Kerberos V5

Kerberos V5は、サード・パーティによる信頼性の高いネットワーク認証プロトコルで、秘密キー暗号化を使用する強力な認証を提供します。Kerberos V5を使用すると、Kerberos V5の管理時を除き、ユーザーのパスワード(暗号化された状態も含む)がネットワーク内でやり取りされることがなくなります。Kerberosは、1980年代半ばにMITのProject Athenaの一環として開発されました。Kerberos V5プロトコルの完全な解説は、このドキュメントの目的ではありません。Kerberos V5プロトコルの詳細は、[1]および[2]を参照してください。

Kerberos V5は、成熟したプロトコルで、広範囲に実装されています。Cによる無料のリファレンス実装が、MITにより提供されています。Java SEにおけるシングル・サインオンの基盤となる技術としてKerberos V5が選択されているのは、こうした理由によります。

JAAS (Java Authentication and Authorization Service)

使用されるJava SEセキュリティ・アーキテクチャが特権を決定する根拠は、コードの出所およびコード署名者に一致する公開キー証明書だけでした。しかし、複数ユーザー環境では、コードを実行するユーザーの認証済み識別情報に基づいて、特権をさらに指定するのが望ましい方法です。

JAASが提供するのは、この機能です。JAASは、認証および認証済みの識別情報に基づくアクセス制御に特化した、プラガブルなフレームワークおよびプログラミング・インタフェースです。

プラグインおよびスタック可能なフレームワーク

JAAS認証フレームワークは、Pluggable Authentication Module (PAM)に基づいています([3]および[4]を参照)。JAASの認証はプラガブルな方法で行われるため、システム管理者は適切な認証モジュールを追加できます。これにより、Javaアプリケーションは基盤となる認証技術に依存せずに済みます。また、アプリケーション自体を変更することなく、新規または更新された認証技術をシームレスに構成できます。

JAAS認証フレームワークは、認証モジュールのスタックもサポートします。複数のモジュールを指定し、指定順にモジュールをJAASフレームワークから呼び出すことができます。認証全体が成功するかどうかは、個別の認証モジュールの結果に依存しています。

認証と認可

JAASフレームワークは、認証コンポーネントと承認コンポーネントの2つに分けることができます。

JAAS認証コンポーネントは、コードがアプリケーション、アプレット、Bean、サーブレットとして稼動しているかに関係なく、Javaコードを実行しているユーザーを確実かつセキュアに判定する機能を提供します。

JAAS承認コンポーネントは、コード・ソースおよびコードを実行するユーザーに基づき、Javaコードが慎重を要するタスクの実行を制限する手段を提供して、既存のJavaセキュリティ・フレームワークを補完します。

サブジェクト

JAASでは、「サブジェクト」という語は、リソースへのアクセス要求のソースであるエンティティを表すために使用されます。サブジェクトは、ユーザーの場合もあれば、サービスの場合もあります。1つのエンティティは、多数の名前やプリンシパルを保持することが可能であるため、JAASは、サブジェクトを、エンティティ当たり複数の名前を処理する特別な抽象レイヤーとして使用します。このため、サブジェクトは一連のプリンシパルで構成されます。プリンシパル名には、制限が一切課されません。

サブジェクトは、認証済みのプリンシパルによってのみ生成されます。認証には、通常、アイデンティティを証明するためにユーザーが提供する証拠(パスワードなど)が含まれます。

さらに、サブジェクトは、「クレデンシャル」と呼ばれるセキュリティ関連の属性も保持します。クレデンシャルは、publicあるいはprivateである場合もあります。非公開暗号化キーなどのサブジェクトの機密なクレデンシャルは、サブジェクトのprivateクレデンシャル・セット内に格納されます。

Subjectクラスは、プリンシパル、およびプリンシパルに関連付けられたpublicクレデンシャルやprivateクレデンシャルを取得するメソッドを保持します。

これらのクラスを操作するには、異なるアクセス権が必要な場合があります。たとえば、サブジェクトのプリンシパル・セットを変更するには、AuthPermission("modifyPrincipals")が必要な場合があります。publicクレデンシャルやprivateクレデンシャルの変更、および現行のサブジェクトの取得にも、同様のアクセス権が必要です。

doAsおよびdoAsPrivileged

Java SEは、java.lang.SecurityManagerを介して実行時アクセス制御を実行します。SecurityManagerは、重要な操作が試行されるたびに参照されます。SecurityManagerは、このタスクをjava.security.AccessControllerに委譲します。AccessControllerは、AccessControlContextの現行のイメージを取得して、AccessControlContextが要求された操作を実行可能なアクセス権を保持していることを確認します。

JAASは、2つのメソッドdoAsおよびdoAsPrivilegedを提供します。これらのメソッドを使用すると、認証済のサブジェクトをAccessControlContextに動的に関連付けることができます。

doAsメソッドは、サブジェクトを現行スレッドのアクセス制御コンテキストに関連付けます。その後のアクセス制御は、実行中のコードおよびそれを実行するサブジェクトに基づいて行われます。

public static Object doAs(final Subject subject,
                          final PrivilegedAction action)

public static Object doAs(final Subject subject,
                          final PrivilegedExceptionAction action)
    throws  PrivilegedActionException;

どちらの形式のdoAsメソッドも、まず指定されたサブジェクトを現行スレッドのAccessControlContextに関連付けてから、アクションを実行します。これにより、サブジェクトとしてアクションを実行させる効果を実現します。最初のメソッドでは、実行時例外がスローされる可能性がありますが、通常の実行では、action引数を指定してrun()メソッドを実行して得られたオブジェクトが返されます。2番目のメソッドの動作も同様です。ただし、run()メソッドにより、チェックされたPrivilegedActionExceptionがスローされる可能性がある点が異なります。doAsメソッドを呼び出すには、AuthPermission("doAs")が必要です。

次のメソッドでも、特定のサブジェクトとしてコードが実行されます。

public static Object doAsPrivileged(final Subject subject,
                                    final PrivilegedAction action,
                                    final AccessControlContext  acc);

public static Object doAsPrivileged(final Subject subject,
                                    final PrivilegedExceptionAction action,
                                    final AccessControlContext acc)
    throws PrivilegedActionException;

doAsPrivilegedメソッドの動作は、呼出し側がアクセス制御コンテキストを指定可能である点を除き、doAsと同様です。これにより、現行のAccessControlContextは事実上無視されるため、渡されたAccessControlContextに基づいて承認が決定されます。

AccessControlContextはスレッドごとに設定されるため、JVM内の個別のスレッドは、異なる識別情報を保持するものと見なされます。特定のAccessControlContextに関連付けられたサブジェクトは、次のメソッドを使用して取得できます。

public static Subject getSubject(final AccessControlContext acc);

LoginContext

LoginContextクラスは、サブジェクトの認証に使用する基本的なメソッドを提供します。このクラスを使用すると、アプリケーションを基盤となる認証技術から独立させることができます。LoginContextは、構成を調べて、特定アプリケーション用に構成された認証サービスまたはLoginModulesを判別します。アプリケーションが特定のエントリを保持しない場合、「other」として識別されるデフォルト・エントリが指定されます。

LoginModulesのスタック特性をサポートするために、LoginContextは認証を2段階で実行します。最初のログイン段階では、構成済みの各ログイン・モジュールを呼び出して、認証を試みます。必要なLoginModulesがすべて成功すると、LoginContextは第2段階に入り、各ログイン・モジュールを再度呼び出して認証プロセスを正式にコミットします。この段階で、認証されたプリンシパルおよびそのクレデンシャルを使ってサブジェクトが生成されます。いずれかの段階が失敗すると、LoginContextは構成済の各モジュールを呼び出して、認証全体を中止します。次に、各LoginModuleは、認証に関連する状態をすべてクリーン・アップします。

LoginContextは、インスタンス化に使用可能な4つのコンストラクタを保持します。どのコンストラクタでも、構成エントリ名の引渡しが必要です。さらにサブジェクトやCallbackHandlerをコンストラクタに渡すことも可能です。

コールバック

JAASにより呼び出されるログイン・モジュールは、認証用の情報を呼出し側から収集できなければなりません。たとえば、Kerberosログイン・モジュールは、認証用のKerberosパスワードの入力をユーザーに要求します。

LoginContextを使用すると、基盤となるログイン・モジュールがユーザーとの対話に使用するコールバック・ハンドラをアプリケーションから指定できます。コマンド行ベースとGUIベースの2つのコールバック・ハンドラがあります。

LoginModules

Oracleは、UnixLoginModuleNTLoginModuleJNDILoginModuleKeyStoreLoginModuleおよびKrb5LoginModuleの実装を提供します。

Kerberosログイン・モジュール

com.sun.security.auth.module.Krb5LoginModuleクラスは、OracleによるKerberosバージョン5プロトコル用のログイン・モジュール実装です。認証が成功すると、Ticket Granting Ticket (TGT)がサブジェクトのprivateクレデンシャル・セットに格納され、Kerberosのプリンシパルがサブジェクトのプリンシパル・セットに格納されます。

構成可能な特定のオプションを指定することにより、Krb5LoginModuleでは、既存のクレデンシャル・キャッシュ(オペレーティング・システム内のネイティブ・キャッシュなど)を使用したTGTの取得や、秘密キーを含むkeytabファイルを使用したプリンシパルの暗黙的な認証も実行可能です。SolarisおよびWindowsの両方には、Krb5LoginModuleがTGTの取得に使用可能なクレデンシャル・キャッシュが含まれます。Solarisには、Krb5LoginModuleが秘密キーの取得に使用可能なシステム規模のkeytabファイルも含まれます。Krb5LoginModuleは、すべてのプラットフォームで、選択したチケット・キャッシュまたはkeytabファイルにファイル・パスを設定するオプションをサポートします。サード・パーティ製のKerberosサポートがインストールされており、Javaの統合が望まれる場合、これは有用な方法です。これらのオプションについて学習するには、Krb5LoginModuleのドキュメントを参照してください。ネイティブ・キャッシュまたはkeytabが存在しない場合、ユーザーはKey Distribution Center (KDC)から取得したパスワードおよびTGTの入力を求められます。

次に、クライアント・アプリケーション用JAASログイン構成エントリのサンプルを示します。この例では、Krb5LoginModuleはネイティブ・チケット・キャッシュを使用して、内部で使用可能なTGTを取得します。認証された識別情報は、TGTが所属するKerberosプリンシパルの識別情報になります。

例7-1 クライアント構成エントリのサンプル

// Sample client configuration entry

SampleClient {
    com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true
};

次に、サーバー・アプリケーション用ログイン構成エントリのサンプルを示します。この構成では、プリンシパルnfs/bar.example.comの認証に、キータブから取得した秘密キーが使用されます。また、Kerberos KDCから取得したTGTと秘密キーの両方が、サブジェクトの非公開クレデンシャル・セットに格納されます。格納されたキーは、クライアントから送信されるサービス・チケットの検証に使用できます(Java GSS-APIセクションを参照)。

例7-2 サーバー構成エントリのサンプル

// Sample server configuration entry

SampleServer {
     com.sun.security.auth.module.Krb5LoginModule
         required useKeyTab=true storeKey=true principal="nfs/bar.example.com"
};

次のクライアント・コード例では、LoginContextにより構成エントリSampleClientが使用されます。Kerberosパスワードの入力をユーザーに求めるため、TextCallbackHandlerクラスが使用されます。ユーザーがログインすると、Kerberosプリンシパル名およびTGTを使用してサブジェクトが生成されます。これ以後、ユーザーはLoginContextから取得したサブジェクトに渡すSubject.doAsを使用してコードを実行できます。

例7-3 クライアント・コードのサンプル

// Sample client code

LoginContext lc = null;

try {
        lc = new LoginContext("SampleClient", new TextCallbackHandler());
        // attempt authentication
        lc.login();
} catch (LoginException le) {
    ...
}

// Now try to execute ClientAction as the authenticated Subject

Subject mySubject = lc.getSubject();
PrivilegedAction action = new ClientAction();
Subject.doAs(mySubject, action);

ClientActionアクションを、指定された値を保持する認証済のKerberosクライアント・プリンシパルにのみ許可できます。

次に、サーバー側のサンプル・コードを示します。これは、アプリケーションのエントリ名およびPrivilegedActionを除いて、例7-3に類似しています。

例7-4 サーバー・コードのサンプル

// Sample server code

LoginContext lc = null;

try {
        lc = new LoginContext("SampleServer", new TextCallbackHandler());
        // attempt authentication
        lc.login();
} catch (LoginException le) {
   ...
}

// Now try to execute ServerAction as the authenticated Subject

Subject mySubject = lc.getSubject();
PrivilegedAction action = new ServerAction();
Subject.doAs(mySubject, action);

Kerberosクラス

他のベンダーがJava GSS-APIで使用可能な独自のKerberosログイン・モジュール実装を提供できるようにするため、javax.security.auth.kerberosパッケージに3つの標準Kerberosクラスが導入されました。これらは、Kerberosプリンシパル用のKerberosPrincipal、長期のKerberos秘密キー用のKerberosKey、およびKerberosチケット用のKerberosTicketです。Kerberosログイン・モジュールのすべての実装で、これらのクラスを使用して、プリンシパル、キー、およびチケットをサブジェクト内に格納する必要があります。

認可

サブジェクトの認証が成功したら、認証されたサブジェクトに関連付けられたプリンシパルに基づいてアクセス制御を実行できます。JAASプリンシパルベースのアクセス制御は、Java SEのCodeSourceアクセス制御を強化します。サブジェクトに付与されるアクセス権は、システム規模のアクセス制御ポリシーを表す抽象クラスであるPolicyで構成されます。Oracleは、Policyクラスの実装をファイルベースで提供します。Policyクラスはプロバイダ・ベースであるため、他者が独自のポリシー実装を提供することが可能です。

Java Generic Security Service Application Program Interface (Java GSS-API)

Generic Security Service API (GSS-API)

エンタープライズ・アプリケーションは、多くの場合、様々なセキュリティ要件を保持し、この実現のため、広範な基盤のテクノロジを配備します。このようなシナリオでは、あるテクノロジから別のテクノロジに簡単に移行できるように、クライアント/サーバー・アプリケーションをどのように開発すればよいでしょうか。この問題を解決するため、IETFのCommon Authentication Technologyワーキング・グループで、呼出し元を基盤のテクノロジの詳細から分離するピア・ツー・ピア認証およびセキュアな通信のための統一のアプリケーション・プログラミング・インタフェースを提供することによって、GSS-APIが設計されました。

RFC 2743 [6]にあるように、このAPIは言語非依存の形式で記述されており、認証、メッセージ機密性および整合性、保護されたメッセージの順序付け、再実行の検出およびクレデンシャルの委譲などのセキュリティ・サービスに対応します。使用する基盤となるセキュリティ・テクノロジまたは「セキュリティ・メカニズム」では、本質的な一方向認証に加え、これらの機能の1つ以上をサポートするように選択できます。脚注1

IETFにより定義された標準セキュリティ・メカニズムには、Kerberos V5 [6]およびSimple Public Key Mechanism (SPKM) [8]の2つが存在します。

こうしたAPIの設計により、実装で複数のメカニズムを同時にサポートできるため、アプリケーションは実行時にいずれかのメカニズムを選択できます。ただし、相互に通信するクライアント・アプリケーションとサーバー・アプリケーションは、同じセキュリティ・メカニズムを使用する必要があります。図7-1に、これを示します。セキュアな通信のために、GSS-APIを使用するクライアント/サーバー・アプリケーションを示しています。GSSフレームワークを使用すると、このアプリケーションは、複数のセキュリティ・メカニズム(この例では、Kerberos V5およびSPKM)をサポートできます。GSS-APIがクライアント・アプリケーションまたはサーバー・アプリケーション(この例では、Kerberos V5)のセキュリティ・メカニズムをネゴシエートすると、もう一方は同じものを使用する必要があります。

図7-1 複数メカニズムGSS-API実装

この図の説明は周辺の本文にあります。

メカニズムは、IANAに登録された一意のオブジェクト識別子(OID)により識別されます。たとえば、Kerberos V5メカニズムは、{iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) krb5(2)}というOIDで識別されます

このAPIの別の重要な特徴は、これがトークン・ベースである点です。つまり、APIの呼び出しにより、不透明なオクテットが生成され、アプリケーションはそれをそのピアに転送する必要があります。これにより、APIをトランスポートから独立させることができます。

Java GSS-API

Generic Security Service用のJava APIもIETFで定義されており、RFC 2853 [10]にドキュメント化されています。Oracleは、Java Community Process (JCP) [11]の下でこのAPIの標準化を目指しており、またリファレンス実装の提供を計画しています。JCPは、この外部で定義されたAPIを単に支持するだけです。IETFにより割り当てられたパッケージ名前空間org.ietf.jgssは、引き続きJ2SE 1.4内に保持されます。

初期出荷段階では、OracleによるJava GSS-API実装は、Kerberos V5メカニズムのみをサポートします。Kerberos V5メカニズムのサポートは、Java SEのすべてのJava GSS-API実装で義務付けられています。他のメカニズムをサポートするかどうかは任意です。将来のリリースでは、Service Provider Interface (SPI)が追加され、新たなメカニズムを静的または実行時に構成できるようになります。現在でも、リファレンス実装はモジュール化されており、非公開のプロバイダSPIをサポートします。非公開のプロバイダSPIは、標準化の際、公開に変換されます。

Java GSS-APIフレームワーク自体はthinであるため、セキュリティ関連の機能はすべて、基盤となるメカニズムから取得したコンポーネントへ委譲されます。GSSManagerクラスは、インストール済のメカニズム・プロバイダをすべて認識するため、プロバイダを呼び出してこれらのコンポーネントを取得できます。

Java SEに含まれるデフォルトのGSSManager実装は、次の方法で取得できます。

GSSManager manager = GSSManager.getInstance();

GSSManagerは新規プロバイダを構成したり、現存するすべてのメカニズムをリストするために使用されます。GSSManagerは、3つの重要なインタフェース、GSSNameGSSCredentialおよびGSSContextのファクトリ・クラスとしても機能します。後続の項では、これらのインタフェースとその実装をインスタンス化するメソッドについて説明します。API仕様全体については、[9]および[11]を参照してください。

大半のJava GSS-API呼出しでは、GSS-APIフレームワーク内およびメカニズム・プロバイダ内の両方で発生する問題をカプセル化するGSSExceptionがスローされます。

GSSNameインタフェース

このインタフェースは、Java GSS-APIにおけるエンティティを表します。このインタフェース実装は、次の方法でインスタンス化されます。

GSSName GSSManager.createName(String name, Oid nameType)
    throws GSSException

たとえば:

GSSName clientName = manager.createName("duke", GSSName.NT_USER_NAME);

この呼出しにより、GSSNameが返されます。これは、メカニズム非依存レベルのユーザー・プリンシパルdukeを表します。内部的には、サポートされる各メカニズムが、ユーザーの汎用表現をよりメカニズム固有の形式にマッピングすることを前提としています。たとえば、Kerberos V5メカニズム・プロバイダは、この名前をduke@EXAMPLE.COMにマッピングできます(EXAMPLE.COMはローカルのKerberosレルム)。同様に、公開キー・ベースのメカニズム・プロバイダは、この名前をX.509識別名にマッピングします。

このドキュメントで、ユーザー以外の何らかのサービスとしてのプリンシパルに言及する場合、メカニズムがそれを異なる方法で解釈できるようにJava GSS-API呼出しを行うことを意味しています。

例:

GSSName serverName = manager.createName("nfs@bar.example.com",
                                         GSSName.NT_HOSTBASED_SERVICE);

Kerberos V5メカニズムは、この名前をKerberos固有の形式nfs/bar.example.com@EXAMPLE.COMにマッピングします(EXAMPLE.COMはプリンシパルのレルム)。このプリンシパルは、ホスト・マシンbar.example.comで稼動中のnfsサービスを表します。

OracleによるGSSNameインタフェースの実装は、コンテナ・クラスです。コンテナ・クラスは、メカニズムの使用時にマッピングを行い、マッピングされた各要素をプリンシパル・セットに格納するよう、各プロバイダに適宜要求します。この面で、GSSNameの実装はサブジェクトに格納されたプリンシパル・セットに似ています。この実装には、サブジェクトのプリンシパル・セット内の要素と同じものを含めることもできますが、用途はJava GSS-APIのコンテキストに限定されています。

Oracle Kerberos V5プロバイダにより格納される名前要素は、javax.security.auth.kerberos.KerberosPrincipalのサブクラスのインスタンスです。

GSSCredentialインタフェース

このインタフェースは、任意の1つのエンティティが所有するクレデンシャルをカプセル化します。GSSNameと同様、このインタフェースも複数メカニズム・コンテナです。

この実装は、次の方法でインスタンス化されます。

GSSCredential createCredential(GSSName name,
                               int lifetime,
                               Oid[] desiredMechs,
                               int usage)
    throws GSSException

クライアント側での呼出し例を、次に示します。

GSSCredential clientCreds =
    manager.createCredential(clientName,
                             8*3600,
                             desiredMechs,
                             GSSCredential.INITIATE_ONLY);

GSSManagerdesiredMechsにリストされたメカニズムのプロバイダを呼び出して、GSSName clientNameに所属するクレデンシャルを要求します。さらに、8時間のライフ・タイムを要求し、アウト・バウンド要求を開始可能なクレデンシャル(クライアント・クレデンシャル)でなければならないという制限を課します。返されるオブジェクトには、この条件を満たすために使用可能なクレデンシャルを保持するdesiredMechsのサブセットの要素が含まれます。Kerberos V5メカニズムにより格納される要素は、ユーザーに属するTGTを含むjavax.security.auth.kerberos.KerberosTicketのサブクラスのインスタンスです。

サーバー側でのクレデンシャル取得は、次のように実行されます。

GSSCredential serverCreds =
    manager.createCredential(serverName,
                             GSSCredential.INDEFINITE_LIFETIME,
                             desiredMechs,
                             GSSCredential.ACCEPT_ONLY);

クライアントに対する動作も同様です。ただし、要求されるクレデンシャルの種類が、着信要求(サーバークレデンシャル)を受け付けられるものである点が異なります。さらに、通常サーバーは長期にわたり稼動するため、存続期間の長いクレデンシャル(ここに示したINDEFINITE_LIFETIMEなど)を要求します。格納されたKerberos V5メカニズムの要素は、サーバーの秘密キーを含むjavax.security.auth.kerberos.KerberosKeyのサブクラスのインスタンスです。

このステップでは、高い負荷がかかることがあります。さらに、通常、アプリケーションは、ライフ・タイムの間に使用する可能性のあるすべてのクレデンシャルへの参照を初期化時に取得します。

GSSContextインタフェース

GSSContextインタフェースの実装は、2つのピアにセキュリティ・サービスを提供します。

クライアント側では、次のAPI呼出しでGSSContext実装が取得されます。

GSSContext GSSManager.createContext(GSSName peer,
                                    Oid mech,
                                    GSSCredential clientCreds,
                                    int lifetime)
    throws GSSException

これにより、通信先のピアおよび通信に使用するメカニズムを認識する、初期化済みのセキュリティ・コンテキストが返されます。クライアントのクレデンシャルは、ピアの認証に必要です。

サーバー側では、次の方法でGSSContextを取得できます。

GSSContext GSSManager.createContext(GSSCredential serverCreds)
    throws GSSException

これにより、受け入れ側の初期化済みセキュリティ・コンテキストが返されます。この時点では、コンテキスト確立要求を送信するピア(クライアント)の名前、および使用する基盤となるメカニズムでさえも不明です。ただし、着信要求がクレデンシャルserverCredsにより表されるサービス・プリンシパル用でないか、クライアント側が要求する基盤となるメカニズムがserverCreds内にクレデンシャル要素を保持しない場合、要求は失敗します。

GSSContextをセキュリティ・サービスで使用する前に、2つのピア間でトークンを交換してGSSContextを確立する必要があります。コンテキスト確立メソッドへの各呼出しにより、不透明なトークンが生成され、アプリケーションは、このトークンを選択した通信チャネルを使用してピアに送信する必要があります。

クライアントは、次のAPI呼出しを使用してコンテキストを確立します。

byte[] GSSContext.initSecContext(byte[] inToken,
                                 int offset,
                                 int len)

   throws GSSException

サーバーは次の呼出しを使用します。

byte[] acceptSecContext(byte[] inToken,
                        int offset,
                        int len)

   throws GSSException

これら2つのメソッドは相補的な関係にあり、一方で生成された出力が、他方で入力として受け入れられます。クライアントが初めてinitSecContextを呼び出すと、最初のトークンが生成されます。呼出し時に、このメソッドの引数は無視されます。最後に生成されるトークンは、使用するセキュリティ・メカニズムの詳細、および確立されたコンテキストのプロパティによって異なります。

ピアの認証に必要なGSS-APIトークンの往復回数は、メカニズムごと、また特性ごと(相互認証か一方向の認証かなど)に異なります。このため、アプリケーションの各側は、コンテキスト確立メソッドの呼出しを、プロセスが完了するまで、ループ内で継続して実行する必要があります。

Kerberos V5メカニズムの場合、コンテキスト確立時にトークンは1往復するだけです。クライアントは、最初にinitSecContext()により生成されたトークン(Kerberos AP-REQ message [2]を含む)を送信します。AP-REQメッセージを生成するために、Kerberosプロバイダは、クライアントのTGTを使用してターゲット・サーバー用のサービス・チケットを取得します。サービス・チケットは、サーバーの長期秘密キーを使用して暗号化され、AP-REQメッセージの一部としてカプセル化されます。サーバーはこのトークンを受け取ると、acceptSecContext()メソッドに送信します。このメソッドにより、サービス・チケットの復号化およびクライアントの認証が行われます。相互認証が要求されなかった場合、クライアント側とサーバー側の両方のコンテキストが確立されます。サーバー側のacceptSecContext()は出力を生成しません。

ただし、相互認証が有効な場合、サーバーのacceptSecContext()はKerberos AP-REP [2]メッセージを含む出力トークンを生成します。このトークンをクライアントに送り返し、initSecContext()を使用して処理を行ってから、クライアント側コンテキストを確立する必要があります。

クライアント側でGSSContextを初期化する際、どの基盤となるメカニズムを使用するかは明白です。Java GSS-APIフレームワークは、適切なメカニズム・プロバイダからのコンテキスト実装を取得できます。このため、GSSContextオブジェクトに対する呼出しはすべて、メカニズムのコンテキスト実装に委譲されます。サーバー側の場合、クライアント側からの最初のトークンが到着するまで、使用するメカニズムは決定されません。

次のクラスは、アプリケーションのクライアント側をコード化する方法を示します。これは、Kerberosログイン・モジュールの項で、サンプル・クライアント・コードdoAsメソッドを使用して実行されたClientActionクラスです。

例7-5 Java GSS-APIを使用したクライアントのサンプル

// Sample client using Java GSS-API

class ClientAction implements PrivilegedAction {

    public Object run() {
        ...
        ...
        try {
            GSSManager manager = GSSManager.getInstance();
            GSSName clientName =
                manager.createName("duke", GSSName.NT_USER_NAME);
            GSSCredential clientCreds =
                manager.createCredential(clientName,
                                          8*3600,
                                          desiredMechs,
                                          GSSCredential.INITIATE_ONLY);
            GSSName peerName =
                manager.createName("nfs@bar.example.com",
                                    GSSName.NT_HOSTBASED_SERVICE);
            GSSContext secContext =
                manager.createContext(peerName,
                                      krb5Oid,
                                      clientCreds,
                                      GSSContext.DEFAULT_LIFETIME);
            secContext.requestMutualAuth(true);

            // The first input token is ignored
            byte[] inToken = new byte[0];

            byte[] outToken = null;

            boolean established = false;

           // Loop while the context is still not established
           while (!established) {
               outToken =
                   secContext.initSecContext(inToken, 0, inToken.length);

               // Send a token to the peer if one was generated
               if (outToken != null)
                  sendToken(outToken);

               if (!secContext.isEstablished()) {
                  inToken = readToken();
               else
                  established = true;
            }
        } catch (GSSException e) {
             ....
        }
        ...
        ...
    }
}

Kerberosログイン・モジュールの項の、サンプル・サーバー・コードServerActionクラスを実行する、サーバー側の対応するコード・セクション:

例7-6 Java GSS-APIを使用したサーバーのサンプル

// Sample server using Java GSS-API

class ServerAction implelemts PrivilegedAction {

    public Object run() {
        ...
        ...
        try {
            GSSManager manager = GSSManager.getInstance();
            GSSName serverName =
                manager.createName("nfs@bar.example.com",
                                    GSSName.NT_HOSTBASED_SERVICE);
            GSSCredential serverCreds =
             manager.createCredential(serverName,
                                       GSSCredential.INDEFINITE_LIFETIME,
                                       desiredMechs,
                                       GSSCredential.ACCEPT_ONLY);
            GSSContext secContext = manager.createContext(serverCreds);

            byte[] inToken = null;
            byte[] outToken = null;

            // Loop while the context is still not established
            while (!secContext.isEstablished()) {
                 inToken = readToken();
                 outToken =
                     secContext.acceptSecContext(inToken, 0, inToken.length);

                  // Send a token to the peer if one was generated
                  if (outToken != null)
                      sendToken(outToken);
            }
        } catch (GSSException e) {
          ...
        }
        ...
        ...
   }
}

メッセージの保護

セキュリティ・コンテキストを確立すると、それを使用してメッセージを保護できるようになります。Java GSS-APIは、メッセージの整合性および機密性の両方を提供します。これを実現する2つの呼出しを、次に示します。

byte[] GSSContext.wrap(byte[] clearText,
                       int offset,
                       int len,
                       MessageProp properties)
    throws GSSException

および

byte[] unwrap(byte[] inToken,
              int offset,
              int len,
              MessageProp properties)
    throws GSSException

wrapメソッドを使用して、クリアテキスト・メッセージをトークン内にカプセル化し、整合性を保護します。MessagePropオブジェクトを介してこれを要求することにより、メッセージを暗号化することもできます(オプション)。wrapメソッドは、不透明なトークンを返し、呼出し元がそのピアに送信します。トークンがピアに渡されると、ピアのunwrapメソッドにより元のクリアテキストが返されます。unwrap側のMessagePropオブジェクトは、メッセージの整合性が保護されているだけなのか、暗号化も行われているかを示す情報を返します。これには順序付けと重複したトークンの警告が含まれます。

クレデンシャルの委譲

Java GSS-APIを使用すると、クライアントがクレデンシャルをサーバーにセキュアに委譲できるようになるため、サーバーはクライアントのためにほかのセキュリティ・コンテキストを開始できます。この機能は、多層環境でシングル・サインオンを実行する場合に有用です。図7-2に、これを示します。

図7-2 従来のクレデンシャルの委譲

図7-2の説明が続きます
「図7-2 従来のクレデンシャルの委譲」の説明

クライアントは、initSecContext()の呼出しを最初に実行する前に、クレデンシャルの委譲を要求します。

void GSSContext.requestCredDeleg(boolean state)
    throws GSSException

statetrueに設定します。

サーバーは、コンテキストの確立後に、委譲されたクレデンシャルを受け取ります。

GSSCredential GSSContext.getDelegCred() throws GSSException

次に、サーバーはクライアントを装って、このGSSCredentialGSSManager.createContext()に渡すことができます。

Kerberos V5メカニズムの場合、委譲されるクレデンシャルとは、クライアントからサーバーに送信される最初のトークンの一部としてカプセル化される転送されたTGTです。このTGTを使用して、サーバーはクライアントに代わり、ほかのサービス用のサービス・チケットを取得できます。

MS-SFU Kerberosの拡張機能

MS-SFUは、サービスがクライアントにかわってKerberosサービス・チケットを取得できるMicrosoft Kerberos 5の拡張機能を表します。Microsoftではこの機能を制約付き委任と呼びます。これは、Kerberosによってクライアントとこのサービス間の認証が確立されない(したがって標準Kerberos委任を使用できない)が、サービスがクライアントの名前でKerberosでセキュリティ保護されたバックエンドサーバーにアクセスする必要がある場合に便利です。

MS-SFUでは、そのプロトコルに2つの拡張を追加しており、Service for User to Self (S4U2self)はフロントエンド・サービスがユーザーの代わりに自分自身へのKerberosサービス・チケットを取得できるようにし、Service for User to Proxy (S4U2proxy)はユーザーの代わりに2番目のバックエンド・サービスへのサービス・チケットを取得できるようにします。これらの2つの拡張はともに、フロントエンド・サービスがユーザーに代わってKerberosサービス・チケットを取得できるようにします。結果のサービス・チケットはローカルまたはリモート・マシンのその他のサービスへのアクセスに使用できます。com.sun.security.jgssパッケージのpublicメソッドExtendedGSSCredential::impersonateがこれらの拡張機能を実装します。

この機能はセキュアなエンタープライズ・デプロイできわめて便利です。たとえば、一般的なネットワーク・サービスで、フロント・エンド(Webサーバーなど)は、クライアントの代わりにバックエンド(データベース・サーバーなど)にアクセスする必要がある場合があります。標準のKerberos 5は委任をサポートしますが、このチェーン内のすべてのレイヤーが各ステップで明示的にKerberos認証を使用することを必要するため、これは常に可能で、望ましいとは限らない場合があります。

たとえば、クライアントがDigest認証を使用して、Webサーバーにログインした場合、委任されるKerberosクレデンシャルがないため、通常のステップを追ったKerberos 5認証を行うことができません。ただし、MS-SFUでは、フロント・エンドがクライアントのKerberosクレデンシャルを提示しなくてもクライアントの代わりにバック・エンドにアクセスすることができるように、Service for User (S4U2self)拡張を定義しているため、MS-SFUはこの状況でも認証を提供できます。図7-3に、これを示します。

図7-3 S4U2selfによる制約付き委任

図7-3の説明が続きます
「図7-3 S4U2selfによる制約付き委任」の説明

さらに、標準Kerberos 5委任メカニズム(Microsoftではこれをオープン委任と呼ぶ)には、潜在的なセキュリティ・ギャップがあります。このメカニズムでは、サービス・アカウントがクライアントの委任されたクレデンシャルを持っていると、任意のサービスにアクセスできます。そのため、オープン委任には十分に注意する必要があります。

これに対して、MS-SFU委譲(S4U2proxyに実装)を使用すると、管理者は、特定のサービスがクライアントのかわりにアクセスできるサービスを厳密に制御できます。図7-4に、これを示します。

図7-4 S4U2proxyによる制約付き委任

図7-4の説明が続きます
「図7-4 S4U2proxyによる制約付き委任」の説明

ノート:

このドキュメントのRFCで指定されているクレデンシャルを委譲するには、従来の委譲を使用する必要があります。制約付き委任では、クライアントはそれ自体のクレデンシャルを委譲できるかどうかを決定できません。このことは、KDCにより決定されるためです。

デフォルト・クレデンシャル取得モデル

アプリケーションが、GSSManager.createCredential()メソッドを使用して、GSSCredentialオブジェクトにメカニズム固有のクレデンシャルを追加する方法については、すでに説明しました。次の2つの項では、Java GSS-APIメカニズムを使用してこれらのクレデンシャルを取得する方法に重点を置いて説明します。メカニズム自体が、ユーザーのログインを実行することはありません。Java GSS-APIを使用する前にログインを実行することおよびメカニズム・プロバイダにとって既知のキャッシュ内にクレデンシャルが格納されていることが前提となっています。GSSManager.createCredential()メソッドは、これらのクレデンシャルへの参照を取得し、GSSを中心とするコンテナであるGSSCredentialに格納して返すにすぎません。

Java SEでは、Java GSS-APIメカニズム・プロバイダがこれらの要素の取得に使用するクレデンシャル・キャッシュはすべて、現行のアクセス制御コンテキストのサブジェクト内のpublicおよびprivateクレデンシャル・セットでなければなりません。

このモデルには、アプリケーションの観点から、クレデンシャル管理が単純で予測しやすいという利点があります。適切なアクセス権を付与されたアプリケーションは、サブジェクト内のクレデンシャルを取り除いたり、標準Java APIを使用してクレデンシャルを更新したりできます。クレデンシャルを取り除いた場合にはJava GSS-APIメカニズムは失敗し、時間ベースのクレデンシャルを更新した場合にはメカニズムは成功します。

例7-3および例7-5のクライアント・アプリケーションがKerberos V5のメカニズムを使用する場合の、クレデンシャル取得関連のイベントの発生順序を、次に示します。

  1. アプリケーションがJAASログインを呼び出し、JAASログインが構成済のKrb5LoginModuleを呼び出します
  2. Krb5LoginModuleは、KDCまたは既存のチケット・キャッシュからユーザー用のTGT (KerberosTicketのインスタンス)を取得して、TGTをサブジェクトのprivateクレデンシャル・セットに格納します。

    ノート:

    Krb5LoginModuleは、クレデンシャル・キャッシュ(MIT krb 5スタイルのKerberosクレデンシャル・キャッシュ(ccache)ファイル、またはWindows Local Security Authority (LSA)などのネイティブ・サービス)内で初期TGTを検索し、TGTを所有するプリンシパルのクレデンシャルを作成できます。

    また、クレデンシャル・キャッシュがproxy_impersonator構成キーを含むMIT krb 5 ccacheファイル(クレデンシャル・キャッシュ・ファイル形式を参照)である場合、Krb5LoginModuleは同じccacheファイルからエビデンス・チケットを読み取り、かわりにこのエビデンス・チケットを所有するプリンシパルの委譲されたクレデンシャルを作成します。この委譲されたクレデンシャルは、制約付き委任に使用できます。

    クレデンシャルの所有者を取得するには、取得したクレデンシャルからGSSCredenial.getName()メソッドを呼び出すか、このクレデンシャルによって作成された確立済のGSSContextオブジェクトのgetSrcName()メソッドを呼び出します。

  3. アプリケーションは、追加先のサブジェクトを取得してから、Subject.doAs/doAsPrivilegedを呼び出して、ClientActionを実行するスレッドのアクセス制御コンテキストにこのサブジェクトを配置します
  4. ClientActionGSSManager.createCredentialメソッドを呼び出して、desiredMechs内のKerberos V5 OIDを渡します。
  5. GSSManager.createCredentialはKerberos V5 GSS-APIプロバイダを呼び出して、セキュリティ・コンテキストを開始するためのKerberosクレデンシャルを要求します。
  6. Kerberosプロバイダは、現行のアクセス制御コンテキストからサブジェクトを取得し、そのprivateクレデンシャル・セットでユーザーのTGTを表す有効なKerberosTicketを検索します。
  7. KerberosTicketGSSManagerに返されます。GSSManagerはKerberosTicketをGSSCredentialコンテナ・インスタンス内に格納して、呼出し側に返します。

サーバー側では、ステップ2のKerberosログインが成功すると、Krb5LoginModuleが、KerberosTicketに加え、サーバー用のKerberosKeyをサブジェクト内に格納します。そのあと、ステップ5 - 7で取得されるKerberosKeyを使用して、クライアントから送信されるサービス・チケットの暗号解読が行われます。

モデルの例外

Java GSS-API用のデフォルト・クレデンシャル取得モデルでは、クレデンシャルが現行のサブジェクト内に存在する必要があります。一般に、JAASログイン後、クレデンシャルはアプリケーションによりこの場所に配置されます。

時には、アプリケーションで、サブジェクト外のKerberosクレデンシャルを使用することが望まれる場合があります。この場合、Krb5LoginModuleが読取りを行うように構成するか、読取りを行うカスタム・ログイン・モジュールを記述して、この種のクレデンシャルを初期JAASログインの一部として読み取ることが推奨されています。ただし、アプリケーションの中には、Java GSS-APIを呼び出す前にJAASを使用できない、または現行のサブジェクトからクレデンシャルを取得しないKerberosメカニズム・プロバイダの使用を強制されるものがあります。

システム・プロパティjavax.security.auth.useSubjectCredsOnlyでは、このような場合に対処すると同時に、他の場合に備えて標準モデルを維持できます。これはboolean型のシステム・プロパティで、値がtrueの場合は標準クレデンシャル取得モデルが使用され、falseの場合はプロバイダに任意のキャッシュの使用が許可されます。このプロパティのデフォルト値(設定しない場合)は、trueです。

現行のサブジェクト内に有効なKerberosクレデンシャルが存在せず、このプロパティがtrueの場合、KerberosメカニズムはGSSExceptionをスローします。このプロパティをfalseに設定しても、プロバイダが現行のサブジェクト以外のキャッシュを使用しなければならないわけではなく、必要な場合には使用可能であることを意味するに過ぎません。

Kerberos V5 GSS-APIメカニズム用のOracleプロバイダは、常にサブジェクトからクレデンシャルを取得します。現行のサブジェクトに有効なクレデンシャルが存在せず、このプロパティがfalseに設定されている場合、プロバイダはJAASログイン自体を呼び出すことにより、一時的なサブジェクトから新規クレデンシャルの取得を試みます。ユーザーとの入力/出力にはテキスト・コールバック・ハンドラが使用され、使用するモジュールおよびオプションのリストには「other」で識別されるJAAS構成エントリが使用されます。(最初に、クライアントに対してJAAS構成エントリcom.sun.security.jgss.initiateの使用、サーバーに対してcom.sun.security.jgss.acceptの使用が試みられます。これらのエントリが存在しない場合は、「other」のエントリが使用されます。これにより、システム管理者は、その動作をより細かく制御できるようになります。)

Kerberos V5 GSS-APIメカニズムのOracleプロバイダでは、これらのモジュールのいずれかがKerberosログイン・モジュールになることが前提です。「other」の下にリストされたモジュールを構成して既存のキャッシュの読取りを行い、Java GSS-APIの呼出し中にユーザーが予期しない方法でパスワードの入力を求められることがないようにできます。このログインにより生成された新規サブジェクトは、要求されたクレデンシャルが取得されるとすぐに、Kerberos GSS-APIメカニズムにより破棄されます。

セキュリティ・リスク

シングル・サインオンによる利便性向上により、新たな危険も生まれます。悪意のあるユーザーが、だれも操作していないデスクトップにアクセスし、通常のユーザーと同様にアプレットを起動できるとしたらどうでしょうか。また、悪意のあるアプレットが、通常のユーザーと同様にサービスへのサイン・オンを実行する場合、しかも悪意のあるアプレットによるサービスへのサイン・オンが想定されていないとしたらどうでしょうか。

前者の場合、ユーザーに対し、ワークステーションをロックせずに席を立つことがないよう注意する以外に解決策はありません。後者の場合、多数の承認チェックが配備されています。

アクセス権モデルの詳細を理解するため、ブラウザが起動時にJAASログインを実行し、サブジェクトをその内部で実行するすべてのアプレットに関連付けた場合を考えましょう。

サブジェクトは、javax.security.auth.AuthPermissionクラスにより、破壊行為を行うアプレットから保護されます。コードにより、いずれかのアクセス制御コンテキストに関連付けられたサブジェクトへの参照取得が試みられる場合、常にこのアクセス権のチェックが行われます。

アプレットがサブジェクトへのアクセス権を付与されている場合でも、その内部に格納された機密のprivateクレデンシャルを実際に読み取るには、javax.security.auth.PrivateCredentialPermissionが必要になります。

クレデンシャルの所有者に代わって、クレデンシャルの読み取りおよびセキュリティ・コンテキストの確立を行う場合、Java GSS-APIメカニズム・プロバイダにより、ほかの種類のチェックも行う必要があります。Kerberos V5メカニズムをサポートするため、次の2つのアクセス権クラスがjavax.security.auth.kerberosパッケージに新たに追加されました。

ServicePermission(String servicePrinicipal, String action)
DelegationPermission(String principals)

新規GSS-APIメカニズムはJava SE用に標準化されているため、このメカニズムのプロバイダに対応した関連するアクセス権クラスを含む、より多くのパッケージが今後追加される予定です。

Kerberos GSS-APIメカニズムでは、プログラム実行時に、次のポイントでアクセス権チェックが行われます。

クレデンシャルの取得

GSSManager.createCredential()メソッドは、現行のサブジェクトなどのキャッシュからメカニズム固有のクレデンシャル要素を取得して、GSSCredentialコンテナに格納します。GSSCredentialの自由な取得をアプレットに許可することは、アプレットがGSSCredentialを使用して多くのことを行えないとしても、望ましいことではありません。そうすることは、ユーザーおよびサービス・プリンシパルの存在に関する情報をリークしてしまうことになります。このため、アプリケーションが、内部のいずれかのKerberosクレデンシャル要素を使用してGSSCredentialを取得する前に、ServicePermissionのチェックが行われます。

クライアント側では、GSSCredential取得成功は、キャッシュからTGTへのアクセスが行われたことを意味します。このため、次のServicePermissionがチェックされます。

ServicePermission("krbtgt/EXAMPLE.COM@EXAMPLE.COM", "initiate");

サービス・プリンシパルkrbtgt/EXAMPLE.COM@EXAMPLE.COMは、KerberosレルムEXAMPLE.COM内のチケット交付サービス(TGS)を表します。また、アクション「initiate」は、このサービスへのチケットがアクセス中であることを示します。クライアント側のクレデンシャル取得時に、このアクセス権チェックでTGSサービス・プリンシパルが常に使用されます。

サーバー側では、GSSCredential取得成功は、キャッシュから秘密キーへのアクセスが行われたことを意味します。このため、次のServicePermissionがチェックされます。

ServicePermission("nfs/bar.example.com@EXAMPLE.COM", "accept");

ここで、サービス・プリンシパルnfs/bar.example.comはKerberosサービス・プリンシパルを、アクション"accept"はこのサービスの秘密キーが要求されていることを、それぞれ表します。

コンテキストの確立

特定サーバー(例、LDAPサーバー)への接続用アクセス権を保持するアプレットは、別のサーバー(例、FTPサーバー)に接続してはいけません。当然、SocketPermissionの働きにより、アプレットがこの種の動作を行うことは制限されます。ただし、ネットワーク接続が許可された場合でも、ServicePermissionを使用して、識別情報による認証を制限することは可能です。

Kerberosメカニズム・プロバイダは、コンテキストの確立を開始する際に、ServicePermissionをチェックします。

ServicePermission("ftp@EXAMPLE.COM", "initiate");

これにより、承認されていないコードによる、プリンシパルftp@EXAMPLE.COMに対するKerberosサービス・チケットの取得および使用を防ぐことができます。

このアクセス権を使用して、特定のサービス・プリンシパルへの制限されたアクセスを提供することは、やはり危険です。ダウンロードされたコードには、コードの出所であるホストとの通信が許可されます。悪意のあるアプレットが、ターゲット・サービス・プリンシパルの長期秘密キーで暗号化されたKerberosTicketを含む初期GSS-API出力トークンを送り返す可能性があります。このため、オフラインの辞書攻撃にさらされる危険性があります。この理由で、信頼できないサイトからダウンロードされたコードに、「initiate」ServicePermissionを付与することは、お薦めできません。

サーバー側では、着信するセキュリティ・コンテキスト確立要求を秘密キーを使用して受け入れるためのアクセス権は、クレデンシャル取得時にチェック済みです。このため、コンテキスト確立段階では、チェックは行われません。

クレデンシャルの委譲

ユーザーに代わってサーバーとのセキュリティ・コンテキストを確立するアクセス権を保持するアプレットは、サーバーへのクレデンシャルの委譲を要求できます。ただし、すべてのサーバーが、クレデンシャルを委譲できるだけの信頼性を保持するわけではありません。このため、Kerberosプロバイダは、委譲されたクレデンシャルを取得してピアに送信する前に、次のアクセス権をチェックします。

DelegationPermission(" \"ftp@EXAMPLE.COM\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\" ");

このアクセス権により、Kerberosサービス・プリンシパルftp@EXAMPLE.COMは、転送されたTGT (チケット交付サービスkrbtgt/EXAMPLE.COM@EXAMPLE.COMにより表される)を受信できます。脚注2

結論

このドキュメントでは、Javaでシングル・サインオンを可能にするフレームワークについて解説しました。これには、初期認証を行ってクレデンシャルを取得するJAASと、それらのクレデンシャルを使用してセキュアな回線通信を行うJava GSS-APIとの間で、クレデンシャルの共有が必要です。ここでは、基盤となるセキュリティ・システムとして、Kerberos V5に焦点を当てて説明しました。ただし、JAASのスタック・アーキテクチャおよびJava GSS-APIの複数メカニズム対応のために、任意の数の異なるメカニズムを同時に使用できます。

JAAS用のKerberosログイン・モジュールは、ネイティブ・キャッシュの読取りが可能であるため、Kerberosをサポートするプラットフォームのデスクトップにログインする場合以外、ユーザーは自らを認証する必要がありません。さらに、Java GSS-API用のKerberos V5メカニズムを使用することにより、クレデンシャルを委譲して、多層環境へのシングル・サインオンを可能にできます。

最後に、Kerberosの提供するシングル・サインオン機能が承認なしで使用されることを防ぐ、多数のアクセス権チェックを紹介しました。

謝辞

Kerberosシングル・サインオン・プロジェクトの各段階での貢献に対し、Gary Ellison、Charlie Lai、およびJeff Nisewangerに感謝します。JAAS 1.0は、Charlieにより、J2SE 1.3のオプション・パッケージとして実装されました。Kerberos Java GSS-APIメカニズムのアクセス権モデルを設計する際、Garyが尽力してくれました。JAAS 1.0の統合に関してフィードバックを送ってくれたBob Scheiflerに、またKeyStoreLoginModuleおよびCallbackHandler実装に関して尽力してくれたTim Blackmanに感謝します。また、コメントや提案をくださった、Bruce Rich、Tony Nadalin、Thomas Owusu、Yanni Zhangの諸氏にも感謝します。ドキュメントやチュートリアルの面で援助してくれたMary Dagefordeに感謝します。Sriramulu Lakkaraju、Stuart Ke、およびShital Shisodeは、プロジェクトのテストを担当してくれました。Maxine Erlundは、プロジェクト管理をサポートしてくれました。

参考資料

  1. Neuman, CliffordおよびTso, Theodore(1994年)。『Kerberos: An Authentication Service for Computer Networks』IEEE Communications、第39巻33 - 38ページ
  2. J.KohlおよびC.Neuman。『The Kerberos Network Authentication Service (V5)』、Internet Engineering Task Force、1993年9月RFC 1510
  3. V.SamarおよびC.Lai。『Making Login Services Independent from Authentication Technologies』『In Proceedings of the SunSoft Developer's Conference』1996年3月。
  4. 『X/Open Single Sign-On Service (XSSO) - Pluggable Authentication』。仮仕様702ページ、The Open Group、1997年6月。https://www.opengroup.org
  5. L.GauteronとP.Girard。『A Smart Card Login Module for Java Authentication and Authorization Service』。Gemplus Developer Conference、モンペリエ、フランス、2000年6月20–21日。
  6. J.Linn。『Generic Security Service Application Program Interface,Version 2』、Internet Engineering Task Force、2000年1月RFC 2743
  7. J.Linn。『The Kerberos Version 5 GSS-API Mechanism』Internet Engineering Task Force、1996年6月RFC 1964
  8. C.Adams。『The Simple Public-Key GSS-API Mechanism (SPKM)』Internet Engineering Task Force、1996年10月RFC 2025
  9. J.KabatおよびM.Upadhyay。『Generic Security Service API Version 2: Java Bindings』Internet Engineering Task Force、1997年1月RFC 2853
  10. 『JSR 000072 Generic Security Services API』
  11. Java Platform, Standard Edition API仕様


脚注の説明

脚注1: GSS-API Kerberosメカニズムは、少なくともクライアント認証を実行します。
脚注2: この権限で2つのプリンシパル名を使用すると、よりきめの細かい委譲を行えます。たとえば、TGTに転送される無条件の許可とは異なる、特定のサービス用のプロキシ・チケットなどが可能になります。GSS-APIがプロキシ・チケットを許可しない場合でも、別のAPI (JSSEなど)が将来この機能をサポートする可能性があります。