これは、なにをしたくて書いたもの?
Infinispan Serverを使った、認証・認可まわりについて、ちゃんと設定したことがなかった気がするので、少しやってみようかなと。
ServerNGになって、ユーザーを追加するためのスクリプトも変わったりしているので、確認の機会としても良いでしょう。
認証・認可といっても、今回はHot Rodでのケースにフォーカスしてみていきます。
Infinispan Server(Hot Rod)の認証・認可まわりの設定
なんの話かというと、Infinispan Serverへアクセスする際、認証・認可をどのように設定するか、という話ですね。
Infinispan Serverを使った認証・認可まわりの設定は、大きく以下のことをする必要があります。
- Infinispan Server
- Cache Containerの認可設定
- Cacheの認可設定
- Security Realmの設定
- Endpointの認証設定
- Infinispan Client
- 認証設定
今回は、上記のRealmまわりを除いて扱っていきます。また、SSL/TLSや認証方法も絞ったり外したりします。
認証・認可に関する、Infinispan Serverのドキュメントはこちら。
ざっくり、認証、認可まわりの設定の流れを書いていきます。
ユーザーはInfinispan Server組み込みのプロパティファイルで管理する場合、コマンドでユーザーを作成し、所属するグループを指定します。
ここで、ユーザーが属するグループに対して、権限を割り当てます。
※後述しますが、1番シンプルな権限の管理方法の場合、です
割り当てられる権限は、設定要素「infinispan/cache-container/security/authorization/role」で指定していきます。
一覧は、以下に記載があります。
- LIFECYCLE … Cacheのライフサイクルをコントロールすることを許可(たとえば、Cacheの起動・停止)
- READ … Cacheからのデータの読み込みを許可
- WRITE … Cacheへのデータの書き込みを許可
- EXEC … Cache上でのタスクの実行を許可(たとえば、Executorsなど)
- LISTEN … CacheへのListenerのアタッチを許可
- BULK_READ … バルクRead操作を許可(たとえば、Cacheの全キーを取得するなど)
- BULK_WRITE … バルクWrite操作を許可(たとえば、Cacheをクリアするなど)
- ADMIN … キャッシュに対する管理上の操作を許可する
- ALL … すべての権限をまとめた
- ALL_READ … Readに関する権限をまとめたもの(READとBULK_READ)
- ALL_WRITE … Writeに関する権限をまとめたもの(WRITEとBULK_WRITE)
- NONE … なにも権限を持っていないことを表す権限
ここで作成したユーザーを使って、Hot Rod Clientからアクセスします。
Configuring Authentication Mechanisms for Hot Rod Clients
この時、認証メカニズムの指定が必要です。
Hot Rod Endpoint Authentication Mechanisms
認証メカニズムは、ざっと以下の種類があります(*がある部分は細かい種類を省略しています)。
- PLAIN
- DIGEST-*
- SCRAM-*
- GSSAPI
- GS2-KRB5
- EXTERNAL
- OAUTHBEARER
認証時にどのようなメカニズムをクライアントが指定できるかは、Infinspan Server側のEndpointで設定します。
Setting Up Hot Rod Authentication
今回は、いろいろあってPLAINとDIGEST-*を試しています(ソースコードとして載せているのはPLAINだけですが)。
では、設定していってみましょう。
環境
今回の環境は、こちらです。
$ java --version openjdk 11.0.6 2020-01-14 OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1) OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing) $ mvn --version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.6, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.3.0-40-generic", arch: "amd64", family: "unix"
Infinispan Serverは、10.1.3.Finalを使用し、動作しているホストのIPアドレスは172.17.0.2とします。
準備
クライアント側で使用する、Maven依存関係とプラグインはこちら。
<dependencies> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-client-hotrod</artifactId> <version>10.1.3.Final</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.15.0</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build>
クライアントは、infinispan-client-hotrodを使用します。あとは、JUnit 5とAssertJをテストコード用に追加して、合わせてMaven Surefire Pluginも設定。
また、サーバー側については、デフォルトのInfinispan Serverの設定ファイル「server/conf/infinispan.xml」を確認しておきましょう。
特に関連しそうな箇所を見ておきます。
Cache Container/Cacheの設定(Cacheはまだありませんが)。
<cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/> <metrics gauges="true" histograms="true"/> </cache-container>
Security Realmの設定(今回は触りません)。
<security> <security-realms> <security-realm name="default"> <!-- Uncomment to enable TLS on the realm --> <!-- server-identities> <ssl> <keystore path="application.keystore" relative-to="infinispan.server.config.path" keystore-password="password" alias="server" key-password="password" generate-self-signed-certificate-host="localhost"/> </ssl> </server-identities--> <properties-realm groups-attribute="Roles"> <user-properties path="users.properties" relative-to="infinispan.server.config.path" plain-text="true"/> <group-properties path="groups.properties" relative-to="infinispan.server.config.path" /> </properties-realm> </security-realm> </security-realms> </security>
Endpointの設定。
<endpoints socket-binding="default" security-realm="default"> <hotrod-connector name="hotrod"/> <rest-connector name="rest"/> </endpoints>
テストコードの雛形
Infinispan Serverへのアクセスは、Hot Rod Clientを使ったテストコードで見ていくことにします。
雛形は、こんな感じで。
src/test/java/org/littlewings/infinispan/authentication/AuthnAuthzTest.java
package org.littlewings.infinispan.authentication; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.configuration.Configuration; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class AuthnAuthzTest { // ここに、テストを書く! }
まずは、認証・認可なしで
最初は、認証・認可に関する設定を行わずに確認してみましょう。
ひとつ、シンプルなCacheを追加。
※まだCLIを使いこなせいないので、今回は手で作成…(ServerNGで、このあたりができるかどうかもわかっていません)
<cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/> <metrics gauges="true" histograms="true"/> <distributed-cache name="plainCache"/> </cache-container>
1度、Infinispan Serverを再起動します。
このCacheを使うテストコードを書いてみます。
@Test public void plainCache() { Configuration configuration = new ConfigurationBuilder() .addServers("172.17.0.2:11222") .build(); RemoteCacheManager manager = new RemoteCacheManager(configuration); try { RemoteCache<String, String> cache = manager.getCache("plainCache"); cache.put("key1", "value1"); assertThat(cache.get("key1")).isEqualTo("value1"); assertThat(cache.size()).isEqualTo(1L); cache.clear(); assertThat(cache.size()).isEqualTo(0L); } finally { manager.stop(); } }
まあ、こちらはふつうに動きます。
Infinispan Serverに、認証・認可設定を行う
では、Infinispan Serverに認証・認可まわりの設定を行っていきます。
まず、(設定がわかりやすいので)Cacheに対する認可設定を行いましょう。
以下のドキュメントを見つつ。
Cache Authorization Configuration
以下のように、「cache-container/security/authorization」要素内にroleを作成して、「cache-container/cache/security/authorization」要素から
参照するように設定します。
<cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/> <metrics gauges="true" histograms="true"/> <security> <authorization> <identity-role-mapper/> <role name="admin" permissions="ALL"/> <role name="reader-writer" permissions="READ WRITE"/> <role name="writer" permissions="WRITE"/> <role name="reader" permissions="READ"/> </authorization> </security> <distributed-cache name="plainCache"/> <distributed-cache name="securedCache"> <security> <authorization roles="admin reader-writer writer reader"/> </security> </distributed-cache> </cache-container>
ロールの設定はこちらですね。
<security> <authorization> <identity-role-mapper/> <role name="admin" permissions="ALL"/> <role name="reader-writer" permissions="READ WRITE"/> <role name="writer" permissions="WRITE"/> <role name="reader" permissions="READ"/> </authorization> </security>
ロール名は任意で、ロールに対してどのような権限を割り当てるかをpermissions属性で指定します。複数の権限を指定する場合は、
スペース区切りで記載します。
作成したロールを、Cacheに対して割り当てます。「security/authorization」要素のrolesで指定します。複数のroleを指定する場合は、
スペース区切りで指定します。
<distributed-cache name="securedCache"> <security> <authorization roles="admin reader-writer writer reader"/> </security> </distributed-cache>
「identity-role-mapper」というのは、ロールとユーザーの紐付けに関する設定です。
PrincipalRoleMapper (Infinispan JavaDoc All 10.1.3.Final API)
「identity-role-mapper」は1番シンプルな設定で、ロール名をPrincipalの名前(グループ名)と紐付けます。
IdentityRoleMapper (Infinispan JavaDoc All 10.1.3.Final API)
他には、「common-name-role-mapper」や「cluster-role-mapper」、自分でPrincipalRoleMapper自体を指定する「custom-role-mapper」が
指定できます。
指定方法自体はこちら。
実装は、こちら。
というわけで、今回は「identity-role-mapper」を使っているので、ユーザーの所属するグループがそのままロールの名前になります。
次に、ユーザーを作成します。今回は、Infinispan Serverでデフォルトで使える、プロパティファイルでのユーザー・グループの管理とします。
Adding Users to Property Realms
先ほど記載したとおり、グループ名がそのままロール名になるため、ロールに合わせた形でグループを管理していけばOKです。
以下のスクリプトを使うことになります。
$ bin/user-tool.sh -h Infinispan User Tool 10.1.3.Final (Turia) Copyright (C) Red Hat Inc. and/or its affiliates and other contributors License Apache License, v. 2.0. http://www.apache.org/licenses/LICENSE-2.0 Usage: -u, --user=<name> Specifies the name of the user to add. -p, --password=<password> Specifies the password for the user. -d, --digest Store passwords in digest format (WARN: works only with DIGEST-MD5/Digest authentication). -g, --groups=<group1[,group2...]> Adds the user to a comma-separated list of groups. -f, --users-file=<file> Sets the name of the users properties file relative to the server configuration path. Defaults to `users.properties`. -w, --groups-file=<file> Sets the name of the groups properties file relative to the server configuration path. Defaults to `groups.properties`. -r, --realm=<realm> Sets the name of the realm. Defaults to `default`. -s, --server-root=<path> Specifies the root path for the server. Defaults to `server`. -b, --batch-mode Do not ask for confirmation when overwriting existing users. -h, --help Displays usage information and exits. -v, --version Displays version information and exits.
先ほど作成したロールを、グループにマッピングしてユーザーを登録していきます。先にヘルプで表示したとおり、「-u」でユーザー名、
「-p」でパスワード、「-g」で所属するグループを指定します。グループは、カンマ区切りで複数指定することができます。
# 「admin」グループに属するユーザー $ bin/user-tool.sh -u admin -p password -g admin # 「reader」グループに属するユーザー $ bin/user-tool.sh -u read-only-user -p password -g reader # 「writer」グループに属するユーザー $ bin/user-tool.sh -u write-only-user -p password -g writer # 「reader-writer」グループに属するユーザー $ bin/user-tool.sh -u read-write-user-simple -p password -g reader-writer # 「reader」と「writer」グループの両方に属するユーザー $ bin/user-tool.sh -u read-write-user-multi -p password -g reader,writer
ところで、ここで作成したユーザーおよびグループは、Security Realmに記載してあった以下のファイルに追加されます。
<properties-realm groups-attribute="Roles"> <user-properties path="users.properties" relative-to="infinispan.server.config.path" plain-text="true"/> <group-properties path="groups.properties" relative-to="infinispan.server.config.path" /> </properties-realm>
ちょっとファイルを見てみましょう。
server/conf/groups.properties
#Sun Mar 01 03:45:38 UTC 2020 write-only-user=writer read-write-user-multi=reader,writer read-write-user-simple=reader-writer read-only-user=reader admin=admin
server/conf/users.properties
#$REALM_NAME=default$ #Sun Mar 01 03:45:38 UTC 2020 write-only-user=password read-write-user-multi=password read-write-user-simple=password read-only-user=password admin=password
とってもシンプル。
その他のRealmを使いたい場合は、こちらを参照して設定していくようですが、今回はパスです。
Defining Infinispan Server Security Realms
最後に、Hot Rod Endpointの設定を行います。こちらで認証メカニズムの設定を行います。
Setting Up Hot Rod Authentication
ドキュメント通りですが、以下のように設定。
<endpoints socket-binding="default" security-realm="default"> <hotrod-connector name="hotrod"> <authentication> <sasl mechanisms="SCRAM-SHA-512 SCRAM-SHA-384 SCRAM-SHA-256 SCRAM-SHA-1 DIGEST-SHA-512 DIGEST-SHA-384 DIGEST-SHA-256 DIGEST-SHA DIGEST-MD5 PLAIN" server-name="infinispan" qop="auth"/> </authentication> </hotrod-connector> <rest-connector name="rest"/> </endpoints>
このmechanismsで列挙したのが、クライアントから指定する認証メカニズムで、クライアントはこの中からひとつ選んで使うことに
なります。
server-nameは、クライアントから見た時のサーバー名で、クライアントが認識しているサーバー名と一致させておくべきだとか。
※接続先のサーバーリストとして指定するものとはまた別で、認証に特化したものです
qopというのは、Quality of Protectionの略です。
Ldapwiki: Quality of Protection
HTTP クライアントを作ってみよう(6) - Digest 認証編 -
security-reamについては、今回は触らないと記載したSecurity Reamの設定と参照関係にありそうな気がしますが、今回は追って
いません。クライアント側でもRealmの指定はできそうなので、関連がまだ見えていません…。
ここまで設定したら、Infinispan Serverを再起動します。
ちなみに、このHot Rod Endpointの設定をした時点で、Cacheへのアクセスに認証・認可設定が必要になってしまい、最初に書いた
Cacheとコードは使えなくなるのでテストは無効にしておきます。
@Disabled @Test public void plainCache() {
そのままにしておくと、こんな感じにエラーになります。どちらかというと、認可で弾かれているようですね。
Cacheの「authorization」要素の「enabled」属性をfalseにしても、この挙動は変わりません。
org.infinispan.client.hotrod.exceptions.HotRodClientException:Request for messageId=84 returned server error (status=0x85): java.lang.SecurityException: ISPN006017: Unauthorized 'PUT' operation
Endpointに認証設定を入れると、Cacheには認可設定が必須になるのだなぁ、という感じでしょうかね。
Hot Rod Clientを使って認証設定を行う
では、認証設定を使ったコードを書いていってみます。
認証の確認
まずは簡単に、認証できるパターンとそうでないパターンを。
@Test public void authentication() { RemoteCacheManager manager1 = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { assertThat(manager1.getCache("securedCache")).isNotNull(); } finally { manager1.stop(); } ////////////////////// RemoteCacheManager manager2 = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("unknown") .password("bad-password") .build()); try { assertThatThrownBy(() -> manager2.getCache("securedCache")) .hasMessage("org.infinispan.client.hotrod.exceptions.HotRodClientException:Request for messageId=80 returned server error (status=0x84): javax.security.sasl.SaslException: ELY05013: Authentication mechanism password not verified"); } finally { manager2.stop(); } }
最初に、「admin」ユーザーで認証を行うコードを書いています。認証メカニズムは、「PLAIN」を選択。認可設定を行ったCacheを、
問題なく取得することが確認できます。
RemoteCacheManager manager1 = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { assertThat(manager1.getCache("securedCache")).isNotNull(); } finally { manager1.stop(); }
反対に、認証に失敗するように存在しないユーザーを指定すると、Cacheの取得時に失敗します。
RemoteCacheManager manager2 = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("unknown") .password("bad-password") .build()); try { assertThatThrownBy(() -> manager2.getCache("securedCache")) .hasMessage("org.infinispan.client.hotrod.exceptions.HotRodClientException:Request for messageId=80 returned server error (status=0x84): javax.security.sasl.SaslException: ELY05013: Authentication mechanism password not verified"); } finally { manager2.stop(); }
どうやら、認証についてもCacheを取得する時がポイントになるようですね。
認可の確認1
次に、認可についてを見ていきましょう。
「read-only-user」と「write-only-user」の読み込み、書き込みのどちらかしかできないユーザーを使って確認。
@Test public void readWriteOnlyUser() { RemoteCacheManager manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); assertThatThrownBy(() -> cache.put("key1", "value1")) .hasMessage("java.lang.SecurityException: ISPN000287: Unauthorized access: subject 'Subject with principal(s): [read-only-user, RolePrincipal{name='reader'}, InetAddressPrincipal [address=172.17.0.1/172.17.0.1]]' lacks 'WRITE' permission"); } finally { manager.stop(); } ////////////////////// manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("write-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.put("key1", "value1"); assertThatThrownBy(() -> cache.get("key1")) .hasMessage("java.lang.SecurityException: ISPN000287: Unauthorized access: subject 'Subject with principal(s): [write-only-user, RolePrincipal{name='writer'}, InetAddressPrincipal [address=172.17.0.1/172.17.0.1]]' lacks 'READ' permission"); } finally { manager.stop(); } ////////////////////// manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); assertThat(cache.get("key1")).isEqualTo("value1"); } finally { manager.stop(); } ////////////////////// manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.clear(); } finally { manager.stop(); } }
まず、READ権限しか持たない「read-only-user」では、Cache自体の取得はできるものの、書き込みができないことを確認。
RemoteCacheManager manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); assertThatThrownBy(() -> cache.put("key1", "value1")) .hasMessage("java.lang.SecurityException: ISPN000287: Unauthorized access: subject 'Subject with principal(s): [read-only-user, RolePrincipal{name='reader'}, InetAddressPrincipal [address=172.17.0.1/172.17.0.1]]' lacks 'WRITE' permission"); } finally { manager.stop(); }
「write-only-user」であれば、WRITE権限があるので書き込みが可能です。ですが、READ権限がないので、登録したエントリの
取得には失敗します。
manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("write-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.put("key1", "value1"); assertThatThrownBy(() -> cache.get("key1")) .hasMessage("java.lang.SecurityException: ISPN000287: Unauthorized access: subject 'Subject with principal(s): [write-only-user, RolePrincipal{name='writer'}, InetAddressPrincipal [address=172.17.0.1/172.17.0.1]]' lacks 'READ' permission"); } finally { manager.stop(); }
Cacheに登録したエントリの取得は、「read-only-user」で。
manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-only-user") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); assertThat(cache.get("key1")).isEqualTo("value1"); } finally { manager.stop(); }
最後にCacheエントリのクリアをしているのですが、これにはBULK_WRITE権限が必要なので、今回は「admin」ユーザーで行っています。
manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.clear(); } finally { manager.stop(); }
認可の確認2
続いて、READ権限とWRITE権限の両方を持たせたロール(グループ)に所属するユーザーで、READもWRITEもできることを確認。
@Test public void readWriteRole1() { RemoteCacheManager manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-write-user-simple") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.put("key1", "value1"); assertThat(cache.get("key1")).isEqualTo("value1"); } finally { manager.stop(); } ////////////////////// manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.clear(); } finally { manager.stop(); } }
もう1パターン。ユーザーを複数のロール(グループ)に所属させるパターン。
@Test public void readWriteRole2() { RemoteCacheManager manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("read-write-user-multi") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.put("key1", "value1"); assertThat(cache.get("key1")).isEqualTo("value1"); } finally { manager.stop(); } ////////////////////// manager = new RemoteCacheManager( new ConfigurationBuilder() .addServers("172.17.0.2:11222") .security() .authentication() .saslMechanism("PLAIN") .username("admin") .password("password") .build()); try { RemoteCache<String, String> cache = manager.getCache("securedCache"); cache.clear(); } finally { manager.stop(); } }
いずれも、CacheへのWRITE、READができることが確認できました。
簡単な認証・認可の確認としては、こんなところでしょうか?
権限について
ここまで、Cache#putならWRITE、Cache#getならREAD、Cache#clearならBULK_WRITEとドキュメントからの記載や類推から
使ってきましたが、これを正確にマッピングを取りたい場合は、ソースコードを見るのかなぁと思います。
SecureCacheの実装を見ればよいと思います。
各メソッドが、どのような権限を必要とするかがわかります。
@Override public String getVersion() { authzManager.checkPermission(subject, AuthorizationPermission.ADMIN); return delegate.getVersion(); } @Override public V put(K key, V value) { authzManager.checkPermission(subject, AuthorizationPermission.WRITE); return delegate.put(key, value); } @Override public CompletableFuture<Void> putAllAsync(Map<? extends K, ? extends V> data) { authzManager.checkPermission(subject, AuthorizationPermission.WRITE); return delegate.putAllAsync(data); }
認証メカニズムについて
ところで、今回は認証メカニズムを「PLAIN」と明示しました。
Infinispan 10.1.3.Finalでは、認証メカニズムを指定しない場合、デフォルトでは「SCRAM-SHA-512」が使われます。
なのですが、なにも考えずに使うとこんな感じで怒られるので、今回は1度パスしました…。
org.infinispan.client.hotrod.exceptions.TransportException:: javax.security.sasl.SaslException: ELY05051: Callback handler does not support credential acquisition [Caused by java.security.NoSuchAlgorithmException: class configured for PasswordFactory (provider: WildFlyElytron) cannot be found.]
今回は、とりあえずなんらかの形でも認証・認可の設定をまとめることを目標に、としたので。
まとめ
今回は、Infinispan Serverを使った認証・認可の設定を行ってみました。
最初、Hot Rod Connectorの部分の設定を見落としていてけっこうハマったのですが、今回で設定として必要な要素は概ね把握できた
気がするので、いったんこれでOKかなと。
気が向いたら、もうちょっと深堀りしてみましょう。
今回作成したソースコードは、こちらに置いています。
https://github.com/kazuhira-r/infinispan-getting-started/tree/master/remote-authn-authz