このチュートリアルでは、2 つのサンプルアプリケーションを使って、Java GSS-API の使用方法を説明します。この API は、アプリケーション間のセキュアなメッセージ交換を可能にします。このチュートリアルで使用するサンプルのクライアントアプリケーションおよびサーバーアプリケーションは次の 2 つです。
内容:
SampleServer
プログラムの実行この一連のチュートリアルでは、Kerberos を認証およびアプリケーションのセキュアな通信をサポートする基幹技術として使用しています。「Kerberos 要件」を参照してください。
このチュートリアルで使用するアプリケーションの名前は、SampleClient
および SampleServer
です。
各アプリケーションは、このチュートリアルで提供する Login ユーティリティーを実行して呼び出します。引数には、アプリケーションの名前 (SampleClient
または SampleServer
) とアプリケーションが必要とする引数を指定します。Login ユーティリティーは、JAAS LoginContext を使って、Kerberos を使用するユーザーを認証します。最後に、Login ユーティリティーはアプリケーションクラス (ここでは SampleClient
または SampleServer
) の main
メソッドを呼び出して、アプリケーションに引数を渡します。
次に、SampleClient
および SampleServer
アプリケーションの実行方法のサマリーを示します。
SampleServer
」、続いて SampleServer
プログラム用の引数を指定して Login ユーティリティーを実行することにより、SampleServer
アプリケーションを実行します。Login ユーティリティーにより、SampleServer
を実行するプリンシパルのパスワード入力が求められます。(「Kerberos ユーザー名およびサービスプリンシパル名」を参照)。認証完了後に、SampleServer
が実行されます。
SampleClient
」、続いて SampleClient
プログラム用の引数を指定して Login ユーティリティーを実行することにより、SampleClient
アプリケーションを実行します (通常別のマシンを使用)。Login ユーティリティーにより、Kerberos 名およびパスワードの入力が求められます。認証完了後に、SampleClient
が実行されます。次のとおりです。
SampleServer
を表す Kerberos プリンシパルの名前 (「Kerberos ユーザー名およびサービスプリンシパル名」を参照)、(2) SampleServer
を実行中のホスト (マシン) の名前、(3) SampleServer
がクライアント接続を待機するポート番号を確認します。SampleServer
へのソケット接続を試みます。SampleServer
により受け入れられます。両方のアプリケーションが、ソケット入力および出力ストリームからの DataInputStream および DataOutputStream を初期化して、将来のデータ交換に使用します。SampleClient
および SampleServer
は、それぞれ GSSContext をインスタンス化し、以後のセキュアなデータ交換を可能にする共有コンテキストを確立します。SampleClient
および SampleServer
は、メッセージをセキュアに交換できます。SampleClient
および SampleServer
は、メッセージ交換の完了後に、クリーンアップ操作を実行します。SampleClient
および SampleServer
コード」のセクションで詳しく解説します。
このチュートリアルでは、ベースとなる認証およびセキュアな通信技術として Kerberos V5 が使用されているため、ユーザーまたはサービスが要求される場合、常に Kerberos スタイルのプリンシパル名が使用されます。
たとえば、SampleClient
を実行する場合、ユーザー名の指定が求められます。Kerberos スタイルのユーザー名は、Kerberos 認証用だけに割り当てられたユーザー名です。このユーザー名は、ベースユーザー名 (例、「mjones」)、「@」、およびレルムの順序で構成されます (例、「mjones@KRBNT-OPERATIONS.EXAMPLE.COM」)。
通常、SampleServer
などのサーバープログラムは、「サービス」を提供し、特定の「サービスプリンシパル」に代わって実行されるプログラムと見なされます。SampleServer
のサービスプリンシパル名が必要とされるのは、次の場合です。
SampleServer
の実行時に、適切なサービスプリンシパルとしてログインする必要があります。このチュートリアルのログイン構成ファイルは、実際にサービスプリンシパル名を指定します (Krb5LoginModule のオプションとして)。このため、JAAS 認証 (Login ユーティリティーによって実行される) は、サービスプリンシパルのパスワードの指定のみをユーザーに求めます。適切なパスワードを指定すると、認証に成功し、サービスプリンシパル名からプリンシパルを含むサブジェクトが作成され、新しいアクセス制御コンテキストがサブジェクトに関連付けられます。そのあとに実行されるコード (SampleServer
コード) は、指定されたプリンシパルに代わって実行されたと見なされます。SampleClient
の実行時に、引数の 1 つにサービスプリンシパル名を指定します。これは必須です。このため、SampleClient
は適切なサービスを使用してセキュリティーコンテキストの確立を開始できます。このドキュメントおよび付属のログイン構成ファイルやポリシーファイルを通じて、
service_principal@your_realmという形式で記述された部分は、自分の環境で使用する実際の名前で置き換えてください。サービスプリンシパル名として、任意の Kerberos プリンシパルを実際に使用できます。このため、このチュートリアルを実行してみる場合、クライアントユーザー名とサービスプリンシパル名の両方に自分のユーザー名を使用できます。
通常、本番稼動環境では、システム管理者は、サーバーを特定のプリンシパルのみで実行し、特定の名前を割り当てて使用します。たいてい、割り当てる Kerberos 形式のサービスプリンシパル名は、次のようになります。
service_name/machine_name@realm;
たとえば、「KRBNT-OPERATIONS.EXAMPLE.COM」というレルム内の「raven」という名前のマシンで nfs サービスを実行する場合、サービスプリンシパル名は次のようになります
nfs/raven@KRBNT-OPERATIONS.EXAMPLE.COM
ただし、このようなマルチコンポーネント名は必須ではありません。ユーザープリンシパル名のような、シングルコンポーネント名も使用できます。たとえば、インストールによって、レルム内のすべての ftp サーバーで同じ ftp サービスプリンシパル ftp@realm
を使用する場合と、ftp サーバーごとに異なる ftp プリンシパルを使用する (たとえば、マシン host1
、host2
の ftp プリンシパルがそれぞれ ftp/host1@realm
、ftp/host2@realm
となる) 場合があります。
ユーザーまたはサービスプリンシパル名のレルムがデフォルトレルムの場合は (「Kerberos 要件」を参照)、Kerberos にログインする際、ユーザー名を求めるプロンプトが表示された時点で、必ずしもレルムを指定する必要はありません。このため、たとえばユーザー名が「mjones@KRBNT-OPERATIONS.EXAMPLE.COM」で、SampleClient
を実行する場合、ユーザー名が要求されたら、レルムを省略して「mjones」とだけ入力できます。名前は Kerberos プリンシパル名のコンテキストで解釈され、必要に応じてデフォルトのレルムが付けられます。
GSSManager の createName
メソッドにより、プリンシパル名が GSSName に変換される場合にも、レルムの指定を省略できます。たとえば、SampleClient
の実行時に、引数の 1 つにサーバーサービスプリンシパル名を指定します。この場合、SampleClient
が名前を createName
メソッドなどに渡し、このメソッドが必要に応じてデフォルトのレルムを追加するため、名前を指定する際にレルムを省略できます。
プリンシパル名をログイン構成ファイルおよびポリシーファイルで使用する場合は、常にレルムを含めて名前を指定することをお勧めします。理由は、これらのファイルのパーサーの動作が実装に依存しないため、プリンシパル名の使用前にデフォルトのレルムが追加される場合と、追加されない場合があるためです。名前にレルムが指定されていない場合、以降のアクションは失敗します。
JAAS を使用する場合は常に、使用する認証テクノロジをログイン構成ファイルに指定する必要があります。ログイン構成ファイルの詳細は、「JAAS ログイン構成ファイル」を参照してください。ログイン構成ファイルに、クライアント側が使用するエントリとサーバー側が使用するエントリの 2 つが含まれる場合、SampleClient
と SampleServer
の両方で同じログイン構成ファイルを使用できます。
このチュートリアルで使用するログイン構成ファイル csLogin.conf を、次に示します。
SampleClient { com.sun.security.auth.module.Krb5LoginModule required; }; SampleServer { com.sun.security.auth.module.Krb5LoginModule required storeKey=true principal="service_principal@your_realm"; };
各エントリの名前は、2 つのトップレベルアプリケーション SampleClient
および SampleServer
のクラス名にそれぞれ一致します。これは、アプリケーション用の JAAS 操作を実行する Login ユーティリティーに渡される名前でもあることに留意してください。Login ユーティリティーがログイン構成ファイル内で検索するエントリ名は、渡されたエントリ名と同じになります。
両方のエントリでは、ユーザー認証の成功のため、Sun の Kerberos V5 ログインモジュールを使用する必要があることが指定されています。Krb5LoginModule が成功するのは、指定されたエンティティーでの Kerberos KDC へのログインが成功した場合だけです。SampleClient
の場合、ユーザーは名前とパスワードの入力を求められます。SampleServer
の場合、ログイン構成ファイルに名前 (指定されたプリンシパル、詳細は後述) が指定されているため、SampleServer
を実行するユーザーにはその名前で指定されたエンティティーのパスワードの入力だけが求められます。認証が成功するには、正確なパスワードを指定する必要があります。
SampleServer
のエントリ storeKey=true
は、ログイン時に指定されたパスワードから秘密鍵を計算すること、およびログインにより作成されたサブジェクトの private クレデンシャルに秘密鍵を格納することを意味します。この鍵は、SampleClient
と SampleServer
との間でセキュリティーコンテキストを確立する際、相互認証に利用されます。
Krb5LoginModule には principal
オプションを指定できます。このオプションを使用すると、指定されたプリンシパル (エンティティー/ユーザー) だけが決められたプログラムにログインするよう指定できます。ここでは、SampleClient
エントリにプリンシパルが指定されていない (必要に応じて指定可能) ため、ユーザーはユーザー名およびパスワードの入力を求められます。有効なユーザー名およびパスワードを保持するユーザーならだれでも SampleClient
を実行できます。一方、SampleServer
には特定のプリンシパルが指定されています。通常、システム管理者は、サーバーを特定のプリンシパルとして実行することを好みます。この場合、SampleServer
を実行するユーザーは、プリンシパルのパスワードの入力を求められます。認証が成功するには、適正なパスワードを指定する必要があります。
「service_principal@your_realm」を、SampleServer
を表すサービスプリンシパルの名前で置き換える必要があります。(「Kerberos ユーザー名およびサービスプリンシパル名」を参照)。
Krb5LoginModule に引き渡し可能なすべてのオプションの詳細は、Krb5LoginModule ドキュメントを参照してください。
SampleClient
の実行時に使用されるポリシーファイルは client.policy、SampleServer
の実行時に使用されるポリシーファイルは server.policy です。各ファイルの内容を、以降で説明します。
Login.java
(Login および MyAction) 内のクラスでは、多数のアクセス権が必要です。Login の使用に関する前のチュートリアルで推奨したように、Login.class
および MyAction.class
ファイルを含む JAR ファイル Login.jar
を作成し、ポリシーファイル client.policy
で Login.jar AllPermission
を付与します。
grant codebase "file:./Login.jar" { permission java.security.AllPermission; };
SampleClient
に必要なアクセス権SampleClient
コードは、アクセス権の必要な 2 つのタイプの操作を実行します。次のとおりです。
SampleServer
アプリケーションを実行するホストマシンとのソケット接続を確立します。SampleServer
とのセキュリティーコンテキストの確立を開始します。ソケット接続を開くのに必要なアクセス権を、次に示します。
permission java.net.SocketPermission "*", "connect";
"*" は、SampleServer
を実行するマシンのホスト名または IP アドレスで置き換えることができます。
セキュリティーコンテキストの確立を開始するために必要なアクセス権は、基盤となるメカニズムによって異なります。このチュートリアルでは、基盤となるメカニズムとして Kerberos を使用します。このため、アクセス権 javax.security.auth.kerberos.ServicePermission
が 2 つ必要になります。ServicePermission には、サービスプリンシパル名およびアクション (またはアクションのリスト) が必要です。セキュリティーコンテキストの確立を開始するには、アクション「initiate」を指定して 2 つの ServicePermission を使用する必要があります。ServicePermission の名前により、次が指定されます。
SampleServer
を表すサービスプリンシパル名。(「Kerberos ユーザー名およびサービスプリンシパル名」を参照)。このアクセス権を付与することにより、Kerberos を使ってサービス SampleServer
と対話できるようになります。SampleClient
を実行する、認証済みの特定ユーザーにアクセス権を付与します。このために、SampleClient
のコード位置 (SampleClient.jar
内)、およびユーザー名とユーザー (SampleClient
を実行するユーザー) のレルムを示すプリンシパル指示部の両方を指定します。プリンシパル指示部を含むポリシーファイル grant
文の詳細は、このシリーズの 2 番目のチュートリアルの「プリンシパルベースのポリシーファイル文の作成方法」を参照してください。
grant
文の基本的な書式を、次に示します。
grant CodeBase "file:./SampleClient.jar", Principal javax.security.auth.kerberos.KerberosPrincipal "your_user_name@your_realm" { permission java.net.SocketPermission "*", "connect"; permission javax.security.auth.kerberos.ServicePermission "krbtgt/your_realm@your_realm", "initiate"; permission javax.security.auth.kerberos.ServicePermission "service_principal@your_realm", "initiate"; };
「your_user_name@your_realm
」には、使用する Kerberos ユーザー名、「@」、およびレルムを指定する必要があります。たとえば、ユーザー名が「mjones」、レルムが「KRBNT-OPERATIONS.EXAMPLE.COM」の場合、"mjones@KRBNT-OPERATIONS.EXAMPLE.COM" (引用符も付ける) を指定します。
また、「service_principal@your_realm
」を、「krbtgt/your_realm@your_realm」内のレルムおよびサーバーを表すサービスプリンシパルの名前で置き換える必要もあります。前者が「krbtgt/KRBNT-OPERATIONS.EXAMPLE.COM@KRBNT-OPERATIONS.EXAMPLE.COM」、後者が「sample/raven.example.com@KRBNT-OPERATIONS.EXAMPLE.COM」、ユーザー名が前の段落で指定したのと同じである場合を考えます。この場合、grant
文は次のようになります
grant CodeBase "file:./SampleClient.jar", Principal javax.security.auth.kerberos.KerberosPrincipal "mjones@KRBNT-OPERATIONS.EXAMPLE.COM" { permission java.net.SocketPermission "*", "connect"; permission javax.security.auth.kerberos.ServicePermission "krbtgt/KRBNT-OPERATIONS.EXAMPLE.COM@KRBNT-OPERATIONS.EXAMPLE.COM", "initiate"; permission javax.security.auth.kerberos.ServicePermission "sample/raven.example.com@KRBNT-OPERATIONS.EXAMPLE.COM", "initiate"; };
サーバーポリシーファイル内の Login クラス用 grant
文は、クライアントポリシーファイル内の grant 文とまったく同じです (「Login ユーティリティークラスに必要なアクセス権」を参照)。
grant codebase "file:./Login.jar" { permission java.security.AllPermission; };
SampleServer
に必要なアクセス権SampleServer
コードは、アクセス権の必要な 2 つのタイプの操作を実行します。次のとおりです。
ソケット接続の受け入れに必要なアクセス権を、次に示します。
permission java.net.SocketPermission "*", "accept";
"*" は、SampleClient
を実行するマシンのホスト名または IP アドレスで置き換えることができます。
セキュリティーコンテキストの確立を受け入れるのに必要なアクセス権を、次に示します。
permission javax.security.auth.kerberos.ServicePermission "service_principal@your_realm", "accept";ここで、"service_principal@your_realm" は、
SampleServer
を表すサービスプリンシパルの Kerberos 名です。
SampleServer
を実行する特定の認証済みユーザー (SampleServer
を表すと見なされるサービスプリンシパル) にアクセス権を付与するため、SampleServer
のコード位置 (SampleServer.jar
内) およびサービスプリンシパルを表すプリンシパル指示部の両方を指定します。この名前が、「sample/raven.example.com@KRBNT-OPERATIONS.EXAMPLE.COM」である場合を考えましょう。この場合、grant
文は次のようになります
grant CodeBase "file:./SampleServer.jar" Principal javax.security.auth.kerberos.KerberosPrincipal "sample/raven.example.com@KRBNT-OPERATIONS.EXAMPLE.COM" { permission java.net.SocketPermission "*", "accept"; permission javax.security.auth.kerberos.ServicePermission "sample/raven.example.com@KRBNT-OPERATIONS.EXAMPLE.COM", "accept"; };
SampleClient
および SampleServer
プログラムの実行SampleClient
および SampleServer
プログラムを実行するには、次の操作を行います。
SampleServer
の実行準備SampleServer
の実行準備では、次の操作を行います。
SampleServer
を実行するマシンからアクセス可能なディレクトリにコピーします。
csLogin.conf
の「service_principal@your_realm」を、SampleServer
を表すサービスプリンシパルの名前で置き換えます。server.policy
の「service_principal@your_realm」を、SampleServer
を表すサービスプリンシパルの Kerberos 名で置き換えてください。これは、ログイン構成ファイルで使用する名前と同じ名前です。Login.java
と SampleServer.java
をコンパイルします。
javac Login.java SampleServer.java
Login.java
には 2 つのクラスが含まれるため、Login.java
をコンパイルすると Login.class
および MyAction.class
が生成されます。
Login.class and MyAction.class
を含む Login.jar
という名前の JAR ファイルを作成します。
jar -cvf Login.jar Login.class MyAction.class
SampleServer.class
を含む SampleServer.jar
という名前の JAR ファイルを作成します。
jar -cvf SampleServer.jar SampleServer.class
SampleClient
の実行準備SampleClient
の実行準備では、次の操作を行います。
SampleClient
を実行するマシンからアクセス可能なディレクトリにコピーします。
client.policy
の各部を置き換えます。
your_realm
を、実際のレルムで置き換えます。SampleServer
を表すサービスプリンシパルの Kerberos 名で置き換えます。Login.java
と SampleClient.java
をコンパイルします。
javac Login.java SampleClient.java
Login.class and MyAction.class
を含む Login.jar
という名前の JAR ファイルを作成します。
jar -cvf Login.jar Login.class MyAction.class
SampleClient.class
を含む SampleClient.jar
という名前の JAR ファイルを作成します。
jar -cvf SampleClient.jar SampleClient.class
SampleServer
の実行SampleClient
を実行する前に、必ず SampleServer
を実行してください。SampleClient
は SampleServer
へのソケット接続を試みるため、SampleServer
が稼動していないとソケット接続が受け付けられず、失敗します。
SampleServer
を実行する場合、SampleServer を稼動する予定のマシンで実行してください。このマシン名 (ホスト名) は、SampleClient
の引数として指定します。サービスプリンシパル名は、ログイン構成ファイルやポリシーファイルなど、いくつかの場所に表示されます。
SampleServer
の実行用に準備したディレクトリに移動します。次を指定して、Login
クラスを実行します。
-classpath
節 (Login.jar
および SampleServer.jar
JAR ファイル内のクラスを検索するため)。-Djava.security.manager
。セキュリティーマネージャーのインストールを指定します。-Djava.security.krb5.realm=<your_realm>
(使用する Kerberos レルム)。たとえば、レルムが「KRBNT-OPERATIONS.EXAMPLE.COM」の場合、-Djava.security.krb5.realm=KRBNT-OPERATIONS.EXAMPLE.COM
のように指定します。-Djava.security.krb5.kdc=<your_kdc>
(使用する Kerberos KDC)。たとえば、KDC が「samplekdc.example.com」の場合、-Djava.security.krb5.kdc=samplekdc.example.com
のように指定します。-Djava.security.policy=server.policy
。使用するポリシーファイルとして server.policy
を指定します。-Djava.security.auth.login.config=csLogin.conf
。使用するログイン構成ファイルとして csLogin.conf
を指定します。Login の引数として、アプリケーションの名前 (ここでは「SampleServer
」) を渡します。次に、アプリケーションに必要なすべての引数を追加します。SampleServer
の場合、クライアント接続の待機に使用するポート番号を引数として指定します。通常は使用しない大きなポート番号であれば、どの番号でも選択できます。(例、4444)。
次に、Microsoft Windows および Unix システムの両方で使用可能なすべてのコマンドを示します。classpath 項目の区切りとして、UNIX システムではコロンを使用するのに対し、Microsoft Windows システムではセミコロンを使用する点だけが異なります。
重要: これらのコマンドの、<port_number>
を適切なポート番号に、<your_realm>
を使用する Kerberos レルムに、<your_kdc>
を使用する Kerberos KDC にそれぞれ置き換えてください。
次に、Microsoft Windows システムのコマンドを示します。
java -classpath Login.jar;SampleServer.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=server.policy -Djava.security.auth.login.config=csLogin.conf Login SampleServer <port_number>
次に、UNIX システムのコマンドを示します。
java -classpath Login.jar:SampleServer.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=server.policy -Djava.security.auth.login.config=csLogin.conf Login SampleServer <port_number>
コマンド全体を 1 行で入力してください。ここでは、読みやすくするために複数行に分けて表示してあります。コマンドが長すぎる場合は、.bat ファイル (Microsoft Windows) または .sh ファイル (UNIX) に記述します。このファイルを実行することで、コマンドを実行できます。
サービスプリンシパルの Kerberos パスワードの入力が求められます。ログイン構成ファイルで指定された基盤となる Kerberos 認証メカニズムにより、サービスプリンシパルの Kerberos へのログインが行われます。認証が成功すると、SampleServer
のコードがサービスプリンシパルに代わって実行されます。このコードは、指定されたポート上でソケット接続を待機します。
ログイン時のトラブルシューティングについては、「トラブルシューティング」を参照してください。
SampleClient
の実行SampleClient
を実行するため、SampleClient
の実行準備を行なったディレクトリに移動します。次に、次を指定して、Login
クラスを実行します。
-classpath
節 (Login.jar
および SampleClient.jar
JAR ファイル内のクラスを検索するため)。-Djava.security.manager
。セキュリティーマネージャーのインストールを指定します。-Djava.security.krb5.realm=<your_realm>
(使用する Kerberos レルム)。-Djava.security.krb5.kdc=<your_kdc>
(使用する Kerberos KDC)。-Djava.security.policy=client.policy
。使用するポリシーファイルとして client.policy
を指定します。-Djava.security.auth.login.config=csLogin.conf
。使用するログイン構成ファイルとして csLogin.conf
を指定します。Login に、アプリケーションの名前 (「SampleClient
」)、そのあと SampleClient
に必要な引数を渡します。SampleClient
の引数は、(1) SampleServer
を表すサービスプリンシパルの Kerberos 名、(2) SampleServer
を実行するホスト (マシン) の名前、(3) SampleServer
がクライアント接続を待機するポート番号です。
次に、Microsoft Windows および Unix システムの両方で使用可能なすべてのコマンドを示します。
重要: これらのコマンドの <service_principal>
、<host>
、<port_number>
、<your_realm>
、および <your_kdc>
の位置には、適切な値を指定してください (ポート番号は、SampleServer
の引数として渡したポート番号と同じにする)。値を引用符で囲む必要はありません。
次に、Microsoft Windows システムのコマンドを示します。
java -classpath Login.jar;SampleClient.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=client.policy -Djava.security.auth.login.config=csLogin.conf Login SampleClient <service_principal> <host> <port_number>
次に、UNIX システムのコマンドを示します。
java -classpath Login.jar:SampleClient.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=client.policy -Djava.security.auth.login.config=csLogin.conf Login SampleClient <service_principal> <host> <port_number>
コマンド全体を 1 行で入力してください。ここでは、読みやすくするために複数行に分けて表示してあります。SampleServer
を実行するコマンドと同様、コマンドウィンドウに直接入力するにはコマンドが長すぎる場合、.bat ファイル (Windows) または .sh ファイル (UNIX) に記述して、そのファイルを実行してください。
入力が求められたら、Kerberos ユーザー名およびパスワードを入力します。ログイン構成ファイルで指定された基盤となる Kerberos 認証メカニズムにより、Kerberos へのログインが行われます。認証が成功すると、SampleClient
のコードがユーザーに代わって実行されます。このコードは、SampleServer
とのソケット接続を要求します。SampleServer
が接続を受け付けると、SampleClient
および SampleServer
により、このチュートリアルで解説した方法で、共有コンテキストの確立およびメッセージの交換が行われます。
ログイン時のトラブルシューティングについては、「トラブルシューティング」を参照してください。