JAAS 承認チュートリアル



このチュートリアルでは、「JAAS 認証」チュートリアルで開発したプログラムおよびポリシーファイルを拡張して、JAAS 承認コンポーネントの働きを示します。JAAS 承認コンポーネントは、認証された呼び出し側が、その後のセキュリティ関連の操作に必要なアクセス制御権 (アクセス権) を保持することを保証します。 承認されたコンポーネントでは、ユーザ認証が完了していることが最初に要求されます。このため、「JAAS 認証」チュートリアルを先にお読みください。

このチュートリアルは、次のセクションで構成されます。

チュートリアルのコードを最初に実行してみる場合、「承認チュートリアルコードの実行」を先に読んでから、最初に戻り、学習を続けてください。

JAAS 承認とは

JAAS 承認は、セキュリティポリシーを使用して実行コードに付与するアクセス権を指定する、既存の Java セキュリティアーキテクチャを拡張します。 これは、Java 2 プラットフォームで導入された、「コード中心」のアーキテクチャです。 つまり、アクセス権はコードの特性 (コードの出所、デジタル署名されているかどうか、デジタル署名されている場合はその署名者) に基づいて付与されます。 具体例としては、「JAAS 認証」チュートリアルで使用される sampleacn.policy ファイルがあります。 このファイルには、以下が含まれます。

grant codebase "file:./SampleAcn.jar" {

   permission javax.security.auth.AuthPermission
                    "createLoginContext.Sample";
};

これにより、現行ディレクトリの SampleAcn.jar ファイル内のコードに、指定されたアクセス権が付与されます。 署名者は指定されていないため、コードが署名されているかどうかは問題となりません。

JAAS 承認は、既存のコード中心のアクセス制御を「ユーザ中心」のアクセス制御で補強します。 どのコードが実行されているかだけではなく、どの「ユーザ」が実行しているかに基づいて、アクセス制御を実行できるようになっています。

アプリケーションが JAAS 認証を使ってユーザまたはその他のエンティティ (サービスなど) を認証すると、結果としてサブジェクトが生成されます。 サブジェクトは、認証されたユーザを表します。 サブジェクトは、そのユーザの識別情報を表すプリンシパルのセットで構成されます。 さらに、自身をその他のサブジェクトから区別する名前のプリンシパル (「Susan Smith」) や社会保障番号のプリンシパル (「987-65-4321」) などを持つことができます。

ポリシー内で特定のプリンシパルにアクセス権を付与することができます。 ユーザの認証後、アプリケーションはサブジェクトと現在のアクセス制御コンテキストを関連付けることができます。 その後、セキュリティチェックの対象となる操作 (ローカルファイルアクセスなど) のたびに、Java ランタイムにより、ポリシー内で特定のプリンシパルだけに必要なアクセス権が付与されているかどうかの自動確認が行われます。そして、アクセス制御コンテキストに関連付けられたサブジェクトに指定のプリンシパルが含まれている場合にかぎり、その操作が許可されます。

JAAS 承認の実行手順

JAAS 承認を実行する前に、次のようにします。

プリンシパルのポリシーファイル文の作成方法

ポリシーファイルgrant 文に、1 つ以上の Principal フィールドをオプションで含めることができるようになりました。 Principal フィールドは、指定されたプリンシパルで表される (指定されたコードを実行する) ユーザまたはその他のエンティティが、特定のアクセス権を保持することを表します。

このため、grant 文の基本的な書式は次のようになります。

grant <signer(s) field>, <codeBase URL>
  <Principal field(s)> {
    permission perm_class_name "target_name", "action";
    ....
    permission perm_class_name "target_name", "action";
  };
signer、codeBase、Principal の各フィールドはオプションであり、各フィールドの順序は重要ではありません。

Principal フィールドは、次のようになります。

Principal Principal_class "principal_name"

つまり、"Principal" という語 (大文字、小文字は区別されない) に続き、完全修飾の Principal クラス名およびプリンシパル名を指定します。

Principal クラスは、java.security.Principal インタフェースを実装するクラスです。 すべての Principal オブジェクトは、getName メソッドの呼び出しによって取得できる関連名を持っています。 名前に使用される書式は、Principal 実装によって異なります。

このチュートリアルで使用する、基本的な認証機構により作成されるサブジェクト内に配置されるプリンシパルのタイプは、SamplePrincipal です。これが、grant 文のプリンシパル指示部の Principal_class で使用されます。 SamplePrincipal のユーザ名は name の形式になります。このチュートリアルで使用可能なユーザ名は testUser だけです。したがって、grant 文の指示部 Principal_class では testUser を使用します。

単一の grant 文内に複数の Principal フィールドを含めることも可能です。 複数の Principal フィールドを指定する場合、現行のアクセス制御コンテキストに関連付けられたサブジェクトにこれらのプリンシパルすべてが含まれる場合にのみ、grant 文のアクセス権が付与されます。

複数のプリンシパルに同じアクセス権のセットを付与するには、複数の grant 文を作成し、各文にアクセス権のリストとどちらかのプリンシパルを指し示す単一の Principal フィールドを含めます。

このチュートリアルのポリシーファイルでは、Principal フィールドに 1 つの grant 文が含まれます。

grant codebase "file:./SampleAction.jar",
        Principal sample.principal.SamplePrincipal "testUser" {

   permission java.util.PropertyPermission "java.home", "read";
   permission java.util.PropertyPermission "user.home", "read";
   permission java.io.FilePermission "foo.txt", "read";
};

これは、指定したアクセス権を、SampleAction.jar 内のコードを実行する指定されたプリンシパルに付与することを示します。 注: SamplePrincipal クラスは sample.principal パッケージ内にあります。

サブジェクトのアクセス制御コンテキストへの関連付け

サブジェクトを作成し、現在のアクセス制御コンテキストに関連付けるには、次のようにします。

承認チュートリアルコード

このチュートリアルのコードは、4 つのファイルで構成されます。

SampleLoginModule.java ファイルと SamplePrincipal.java ファイルについては「JAAS 認証」チュートリアルで取り上げているので、ここでは詳しい説明を省略します。 その他のソースファイルについては、以下のセクションを参照してください。

SampleAzn.java

SampleAcn と同様に、SampleAzn クラスは LoginContext lc をインスタンス化し、login メソッドを呼び出して認証を実行します。 認証に成功した場合は、LoginContext の getSubject メソッドを呼び出すことにより、認証されたサブジェクト (ユーザを表す SamplePrincipal を含む) を取得します。

Subject mySubject = lc.getSubject();

main メソッドは、サブジェクトに関する情報 (たとえばそのサブジェクトのプリンシパル情報) をユーザに提供したあと、Subject.doAsPrivileged を呼び出し、以下のように、認証されたサブジェクト mySubject、PrivilegedAction (SampleAction)、null AccessControlContext を渡します。

SampleAction クラスは、次の方法でインスタンス化されます。

PrivilegedAction action = new SampleAction();

Subject.doAsPrivileged の呼び出しは、次の方法で行われます。

Subject.doAsPrivileged(mySubject, action, null);

次に、doAsPrivileged メソッドは、PrivilegedAction action (SampleAction) の run メソッドを呼び出して、サブジェクト mySubject の代わりに実行される残りのコードの実行を開始します。

AccessControlContext の 3 番目の引数として doAsPrivilegednull を渡すことにより、mySubject が新しい空の AccessControlContext に関連付けられることを示します。 その結果、SampleAction の実行時のセキュリティチェックでは、mySubject として実行される SampleAction コード自体 (またはこのコードによって呼び出されるその他のコード) のアクセス権のみが必要になります。 doAsPrivileged の呼び出し側 (および doAsPrivileged が呼び出された時点で実行スタック上に存在していた呼び出し側) は、アクションが実行されている間、アクセス権を必要としません。

SampleAction.java

SampleAction.java には、SampleAction クラスが含まれます。 このクラスは java.security.PrivilegedAction クラスを実装し、サブジェクト mySubject として実行するすべてのコードを含む run メソッドを持っています。 このチュートリアルでは、3 つの操作を実行します。どの操作の場合も、あらかじめ必須アクセス権としてコードを付与しておく必要があります。 以下の操作を実行します。

以下に、コードを示します。

package sample;

import java.io.File;
import java.security.PrivilegedAction;

public class SampleAction implements PrivilegedAction {

  public Object run() {

    System.out.println("¥nYour java.home property value is: "
                + System.getProperty("java.home"));

    System.out.println("¥nYour user.home property value is: "
                + System.getProperty("user.home"));

    File f = new File("foo.txt");
    System.out.print("¥nfoo.txt does ");
    if (!f.exists())
        System.out.print("not ");
    System.out.println("exist in the current working directory.");
    return null;
  }
}

ログイン構成ファイル

このチュートリアルで使用するログイン構成ファイルを、「JAAS 認証」チュートリアルで使用するものと全く同じにできます。 このため、1 つのエントリのみを含む sample_jaas.config を使用できます。

Sample {
  sample.module.SampleLoginModule required debug=true;
};

このエントリの名前は "Sample" です。チュートリアルアプリケーション SampleAcn および SampleAzn がこのエントリを参照する際、この名前を使用します。 このエントリは、ユーザ認証に使用するログインモジュールが sample.module パッケージ内の SampleLoginModule であること、認証が成功したと見なされるためにはこの SampleLoginModule が「成功する」必要があることを示します。 SampleLoginModule は、ユーザから提供された名前とパスワードが正しい (testUser と testPassword である) 場合にかぎり成功します。

SampleLoginModule はデバッグオプションも定義します (true に設定可能)。 このオプションの値を true に設定すると、SampleLoginModule により、認証の進捗に関する追加情報が出力されます。

ポリシーファイル

この承認チュートリアルのアプリケーションは、SampleAznSampleAction の 2 つのクラスで構成されます。 各クラスのコードにはセキュリティ関連操作が含まれるため、操作を実行するには、ポリシーファイル内に関連するアクセス権を指定する必要があります。

このチュートリアルで使用するログインモジュール (SampleLoginModule) にも、アクセス権を必要とする操作が含まれています。

これらの各クラスが必要とするアクセス権については以下で説明します。続いて、完全なポリシーファイルへのリンクを示します。

SampleAznに必要なアクセス権

SampleAzn クラスの main メソッドは、アクセス権の必要な次の 2 つの操作を実行します。

LoginContext の作成方法は、認証チュートリアルの場合とまったく同じです。このため、ターゲットの "createLoginContext.Sample" と同じ javax.security.auth.AuthPermission アクセス権が必要です。

Subject クラスの doAsPrivileged メソッドを呼び出すには、ターゲットの「doAsPrivileged」を保持する javax.security.auth.AuthPermission が必要です。

SampleAzn クラスが、SampleAzn.jar という名前の JAR ファイルに配置されている場合を考えましょう。ポリシーファイル内の次の grant 文を使って、これらのアクセス権を SampleAzn コードに付与できます。

grant codebase "file:./SampleAzn.jar" {
   permission javax.security.auth.AuthPermission 
                    "createLoginContext.Sample";
   permission javax.security.auth.AuthPermission "doAsPrivileged";
};

SampleAction に必要なアクセス権

SampleAction コードは、アクセス権の必要な次の 3 つの操作を実行します。

これらの操作には、次のアクセス権が必要です。

permission java.util.PropertyPermission "java.home", "read";
permission java.util.PropertyPermission "user.home", "read";
permission java.io.FilePermission "foo.txt", "read";

これらのアクセス権を SampleAction.class 内のコードに付与する必要があります。このファイルは、SampleAction.jar という名前の JAR ファイル内に配置されます。 ただし、この grant 文の場合、アクセス権を「コード」だけではなく、コードを実行する特定のユーザにも付与することにより、特定のユーザへのアクセスを制限する方法を示します。

このため、「プリンシパルベースのポリシーファイル文の作成方法」で説明したように、grant 文は次のようになります。

grant codebase "file:./SampleAction.jar",
	Principal sample.principal.SamplePrincipal "testUser" {

   permission java.util.PropertyPermission "java.home", "read";
   permission java.util.PropertyPermission "user.home", "read";
   permission java.io.FilePermission "foo.txt", "read";
};

SampleLoginModule に必要なアクセス権

SampleLoginModule コードは、アクセス権の必要な操作を 1 つ実行します。 Subject に Principal を追加するには、modifyPrincipals をターゲットとする javax.security.auth.AuthPermission が必要です。 grant 文は次のようになります。

grant codebase "file:./SampleLM.jar" {
    permission javax.security.auth.AuthPermission "modifyPrincipals";
};

完全なポリシーファイル

完全なポリシーファイルは、sampleazn.policy です。

承認チュートリアルコードの実行

JAAS 承認チュートリアルコードを実行するには、次の操作を行う必要があります。

  1. 次のファイルを 1 つのディレクトリ内に格納します。

  2. 最上位ディレクトリの下に sample という名前のサブディレクトリを作成し、ここに以下のファイルを格納します (注: SampleAzn および SampleAction クラスは sample パッケージ内にある)。

  3. sample ディレクトリのサブディレクトリを作成し、module という名前を付けます。 ここに以下のファイルを格納します (注: SampleLoginModule クラスは sample.module パッケージ内にある)。

  4. sample ディレクトリのサブディレクトリをもう 1 つ作成し、principal という名前を付けます。 ここに以下のファイルを格納します (注: SamplePrincipal クラスは sample.principal パッケージ内にある)。

  5. 最上位のディレクトリですべてのソースファイルをコンパイルします。
    javac sample/SampleAction.java sample/SampleAzn.java
    sample/module/SampleLoginModule.java sample/principal/SamplePrincipal.java
    
    コマンド全体を 1 行に入力してください。

  6. SampleAzn.class および MyCallbackHandler.class を含む JAR ファイル SampleAzn.jar を作成します (注: これらのクラスのソースファイルは SampleAzn.java 内にある)。
    jar -cvf SampleAzn.jar sample/SampleAzn.class
    sample/MyCallbackHandler.class
    

    コマンド全体を 1 行に入力してください。

  7. SampleAction.class を含む SampleAction.jar という名前の JAR ファイルを作成します。
    jar -cvf SampleAction.jar sample/SampleAction.class
    
  8. SampleLoginModule.classSamplePrincipal.class を含む JAR ファイルを作成します。
    jar -cvf SampleLM.jar sample/module/SampleLoginModule.class
    sample/principal/SamplePrincipal.class
    

  9. 次の情報を指定して、SampleAzn アプリケーションを実行します。

    1. 適切な -classpath 句。SampleAzn.jarSampleAction.jar、および SampleLM.jar JAR ファイル内でクラスの検索が行われるようにします。

    2. -Djava.security.manager。セキュリティマネージャのインストールを指定します。

    3. -Djava.security.policy==sampleazn.policy。使用するポリシーファイルとして sampleazn.policy を指定します。

    4. -Djava.security.auth.login.config==sample_jaas.config。使用するログイン構成ファイルとして、sample_jaas.config を指定します。

    以下に、Win32 および Unix システムの両方で使用可能なすべてのコマンドを示します。 classpath 項目の区切りとして、UNIX システムでは コロンを使用するのに対し、Win32 システムではセミコロンを使用する点だけが異なります。

    以下に Win32 システムの全コマンドを示します。

    java -classpath SampleAzn.jar;SampleAction.jar;SampleLM.jar
     -Djava.security.manager
     -Djava.security.policy==sampleazn.policy
     -Djava.security.auth.login.config==sample_jaas.config sample.SampleAzn
    

    以下に UNIX システムの全コマンドを示します。

    java -classpath SampleAzn.jar:SampleAction.jar:SampleLM.jar
     -Djava.security.manager
     -Djava.security.policy==sampleazn.policy
     -Djava.security.auth.login.config==sample_jaas.config sample.SampleAzn
    

    コマンド全体を 1 行で入力してください。 ここでは、読みやすくするために複数行に分けて表示してあります。 コマンドが長すぎる場合は、.bat ファイル (Win32) または .sh ファイル (UNIX) に記述します。このファイルを実行することで、コマンドを実行できます。

    要求に応じてユーザ名 (testUser) とパスワード (testPassword) を入力すると、ログイン構成ファイルに指定された SampleLoginModule により、入力された名前とパスワードのチェックが行われます。 ログインに成功すると「Authentication succeeded!」というメッセージが表示されます。失敗した場合は「Authentication failed.」というメッセージと失敗の理由が表示されます。

    認証が完了すると、プログラム (SampleAction 内) の他の部分がユーザに代わって実行されます。このため、ユーザは適切なアクセス権をあらかじめ保持している必要があります。 ポリシーファイル sampleazn.policy により、必要なアクセス権が付与されます。このため、java.home および user.home システムプロパティの値、および foo.txt という名前のファイルが現在のディレクトリに存在するかどうかを示す文が表示されます。