UNIX における Tomcat SecurityManager の設定

SecurityManagerを使用するための Tomcat の設定

tomcat.policy

Java SecurityManager によるセキュリティポリシーの設定は、 tomcat の conf ディレクトリに置かれた tomcat.policy ファイルで行います。  tomcat.policy ファイルは、java.policy ファイルの設定を上書きします。  tomcat.policy ファイルは、テキストエディタを用いて手で編集するか、もしくは、Java 1.2 から標準で付属されたpolicytoolを使って編集します。

tomcat.policy ファイルへの登録は、下記のような java.policy ファイルフォーマットを利用します。
// ポリシーファイルの設定例
grant [signedBy <signer> [,codeBase <code source>] {
    permission <class> [<name> [, <action list>]];
};
パーミッションを許可するとき、signedBycodeBase の記述は省略可能です。

codeBase は、URL 形式と、ファイル URL 形式を使用し、 ディレクトリパスを定義した、${java.home} と ${tomcat.home}プロパティを使うこともできます。

デフォルトの tomcat.policy ファイル
// tomcat のためのパーミッション

// javac
grant codeBase "file:${java.home}/../lib/-" {
  permission java.security.AllPermission;
};

// Tomcat は、すべてのパーミッションを得ます。
grant codeBase "file:${tomcat.home}/lib/-" {
  permission java.security.AllPermission;
};

grant codeBase "file:${tomcat.home}/classes/-" {
  permission java.security.AllPermission;
};

// Webアプリケーションのサンプルのポリシー
// デフォルトでは、Tomcat は、webapp ディレクトリへのアクセスと、line.separator, path.separator, file.separator プロパティを読むことを許可されます。
// あなたがここで許可したパーミッションは、デフォルトに追加されます。
grant codeBase "file:${tomcat.home}/webapps/examples" {
  // すべての Java プロパティに対して、サンプルWebアプリケーションからの読み取りを許可します。
  permission java.util.ProperyPermission "*", "read";
};

下記の例は、Webアプリケーションのサンプルに対してメールを送れるようにする設定を、デフォルトパーミッションに追加します。つまり、localhost の smtp ポートへのアクセスを許可します。
grant codeBase "file:${tomcat.home}/webapps/examples" {
  // examplesというWebアプリケーションにlocalhostのsmtpポートの使用を許可します。
  permission java.net.SocketPermission "localhost:25","connect";
};

もし、すべてのWebアプリケーションのために、デフォルトのポリシーをセットしたいなら、 grantの URL を省略できます。 Tomcat の割り当てに加えて、すべてのアプリケーションを一つ一つ設定することなく、 いくつかのデフォルトのパーミッションの許可したい場合には、次のように書くことができます。
grant {
  // すべてのWebアプリケーションに、すべてのJava プロパティを読むことを許可します。
  permission java.util.ProperyPermission "*", "read";
};

最後に、より複雑なtomcat.policy ファイルを示します。 この例では、いくつかのリモートのWebサーバのために Tomcat をアプリケーションサーバとして使います。 Java SecurityManager を使うことにより、リモートのWebサーバが、Tomcat に接続できるように設定します。
 
// Tomcat のためのパーミッション
// javacのために、この設定が必要です。
grant codeBase "file:${java.home}/lib/-" {
  permission java.security.AllPermission;
};

// IP フィルタリングを設定します。
grant codeBase "file:${tomcat.home}/lib/-" {
  // Tomcat は、すべてのプロパティの読み書きが可能でなければいけません。
  permission java.util.PropertyPermission "*","read,write";
  // Tomcat は、それ自身のディレクトリのファイルを読めなければいけません。
  permission java.io.FilePermission "${tomcat.home}/-","read";
  // Tomcat は、そのログに書き込めなければいけません。
  permission java.io.FilePermission "${tomcat.home}/logs/-","read,write";
  // Tomcat は、conf ディレクトリに書き込めなければいけません。
  permission java.io.FilePermission "${tomcat.home}/conf/-","read,write";
  // Tomcat は、webapps ディレクトリに書き込めなければいけません。
  permission java.io.FilePermission "${tomcat.home}/webapps/-","read,write";
  // Tomcatは、JSPのコードをコンパイルできなければいけません。
  permission java.io.FilePermission "${tomcat.home}/work/-","read,write,delete";
  // Tomcat は、すべての RuntimePermission が必要です。
  permission java.lang.RuntimePermission "*";
  // Tomcat が Context の セキュリティポリシを設定できる必要があります。
  permission java.security.SecurityPermission "*";
  // Tomcat は、リモートのWebサーバからのコネクションを受け付ける必要があります。
  // XXX.XXX.XXX.XXX を リモートのWebサーバの IP アドレスに置き換えて下さい。
  permission java.net.SocketPermission "XXX.XXX.XXX.XXX:1024-","accept,listen,resolve";
  // Tomcat は、localhost のポートを使用できる必要があります。
  permission java.net.SocketPermission "localhost:1024-","connect,accept,listen,resolve";
};

// webapp ポリシーの例
// デフォルトでは、webappディレクトリの読み込みと、
// line.separator プロパティの読み込みを許可します。
grant codeBase "file:${tomcat.home}/webapps/examples" {
  permission java.net.SocketPermission "localhost:1024-","listen";
  permission java.util.PropertyPermission "*","read";
};

server.xml

server.xml 中の ContextInterceptor タグで、クラス名に PolicyInterceptor が定義されている部分のコメントを外して下さい。
 

SecurityManager を用いて Tomcat を起動

SecurityManager を使うために tomcat.policy と server.xml ファイルを設定すると、 bin/startup.sh に -security オプションを書くことで、SecurityManager を使って Tomcat を起動できるようになります。
 

トラブルシューティング tomcat.policy 設定とセキュリティ違反

環境変数 TOMCAT_OPTS=-Djava.security.debug=all を設定すると、Java SecurityManager のデバッグのためにロギングを行うことができます。 デバッグのログは、tomcat.log に出力されます。

同じJVM内のjavac呼び出しを使ってJSP をコンパイルするとき、 "AccessControlException RuntimePermission accessClassInPackage sun.tools.javac" というメッセージを出力して、失敗します。

その時は、JAVA_HOME/jre/lib/security/java.security ファイルの設定を 確認して、"package.access=sun." の行のコメントを外して下さい。

Tomcatの作業用ディレクトリの FilePermission が read の時、 同じJVM内のjavac呼び出しによる JSP のコンパイルがAccessControlException で失敗します。

codeBase に、${java.home} プロパティの代わりに絶対パスで指定してみて下さい。

// javacには、この設定が必要です。
grant codeBase "file:/usr/java/lib/-" {
  permission java.security.AllPermission;
};