Edited at

Keycloakでリバプロ型構成を組んでみる(Security Proxy編)

More than 1 year has passed since last update.


今日やること

Keycloakアドベンドカレンダー7日目の今回は、KeycloakのSecurity Proxyを試してみます。

Security Proxyは、Javaで実装されたシンプルなリバースプロキシ(以後、リバプロ)サーバーの一種です。このリバプロサーバー自体がKeycloakのクライアント・アダプターの代わりとなり、プロキシ先のコンテンツの保護や、URLごとのアクセス制御を行うことが可能になります。

アプリケーションサーバーがOpenID ConnectやSAMLに対応していない場合や、クライアント・アダプターの導入が難しい場合、もしくはクライアント・アダプターが対応していない環境の場合の利用に適しています。

主な機能は以下のとおりです。


  • HTTP(S)のリバプロ機能

  • KeycloakサーバーとのOpenID Connect連携

  • 特定パスごとのコンテンツ保護


    • 認証要求によるアクセス制御

    • 特定のHTTPメソッドの許可、拒否

    • 認証済みユーザーのロールによるアクセス制御

    • 特定URLのアクセスを拒否

    • 認証不要でアクセスできるURLの指定



  • HTTPヘッダによる認証済みユーザーの情報連携

今回はTomcat 8の素のサンプルアプリに対して、Security Proxyで保護をかける際の手順を試してみます。


動作確認用のサーバー構成

今回のお試し環境はこのような感じです。

Keycloakサーバーには、demoレルムが作成されており(3日目の記事を参照)、以下のようなロールをもつユーザーが存在していることが前提となります。

FQDN
OS
JDK
構成
LISTEN ポート

kc-server.example.com
CentOS 7.4.1708
OpenJDK 1.8.0.151
・Keycloakサーバー 3.3.0.CR2
8443

kc-proxy.example.com
CentOS 7.4.1708
OpenJDK 1.8.0.151
・Security Proxy 3.3.0.CR2
・Tomcat 8.5.23
・18443(Security Proxy)
・8080(Tomcat)

ユーザー
ロール

user001
user

admin001
user,admin

Tomcatに付属するexapmlesアプリケーションでは、以下のようなアクセス制御をかけることを想定します。

動作確認時の各サーバーへのアクセスポートは以下のとおりです。


Keycloakサーバー側の設定


クライアントの追加・設定


  1. Keycloakの管理コンソールにログインします。

  2. 左メニューバーから、demoレルムを選択します。

  3. 左メニューバーで クライアント をクリックします。クライアント一覧が表示されます。

  4. 右上の 作成 ボタンを押下します。

  5. 以下のようなクライアント設定値を入力し、保存 ボタンを押下します



  6. 引き続き kc-proxy の設定画面が表示されるので以下のような設定を行い、保存 ボタンを押下します。


    • アクセスタイプ: confidential

    • 有効なリダイレクトURI(1つ目): https://kc-proxy.example.com:18443/

    • 有効なリダイレクトURI(2つ目): https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml

      :information_source: 有効なリダイレクトURIは、Keycloak上ではワイルドカードによる指定も可能です。ただし、OIDCの仕様上では、redirect_uriと厳密に一致することが必須となっているため、ここではリダイレクト先となりえるURLはすべて指定しています。そのため、ここで指定していないURLへは未ログイン状態から直接遷移できません。




  7. クレデンシャル タブを押下します。


  8. シークレット として表示されている値を控えます。



Security Proxy側の設定と起動


サンプルアプリケーションの導入

連携確認用のサンプルアプリケーションとして、Tomcat 8.0を導入して起動しておきます。

cd  /tmp

wget http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-8/v8.5.23/bin/apache-tomcat-8.5.23.tar.gz
tar zxvf apache-tomcat-8.5.23.tar.gz -C /usr/local
cd /usr/local/apache-tomcat-8.5.23/
./bin/startup.sh


Security Proxyのダウンロードと展開

Security Proxyをダウンロードして /usr/local に解凍し、展開したディレクトリに移動しておきます。

cd  /tmp

wget https://downloads.jboss.org/keycloak/3.3.0.CR2/keycloak-proxy-3.3.0.CR2.zip
unzip keycloak-proxy-3.3.0.CR2.zip -d /usr/local
cd /usr/local/keycloak-proxy-3.3.0.CR2/


Security Proxyの設定ファイル作成

Security Proxyを動作させるために、以下のような設定ファイルを作成します。


/usr/local/keycloak-proxy-3.3.0.CR2/proxy.json

{

"target-url": "http://localhost:8080",
"send-access-token": true,
"bind-address": "{バインドするIPアドレス・DNS名}",
"http-port": "18080",
"https-port": "18443",
"applications": [
{
"base-path": "/",
"adapter-config": {
"realm": "demo",
"resource": "kc-proxy",
"auth-server-url": "https://kc-server.example.com:8443/auth",
"ssl-required" : "external",
"credentials": {
"secret": "{Keycloakサーバー側のシークレットの値}"
}
},
"constraints": [
{
"pattern": "/*",
"authenticate": true
},
{
"pattern": "/examples/jsp/*",
"permit": true
},
{
"pattern": "/examples/websocket/*",
"roles-allowed": [
"admin"
]
}
]
}
]
}

proxy.json内の設定パラメータの意味ついて、以下に記載します。


基本設定

パラメータ名
必須
説明

target-url

リバプロ転送先URLを指定します。

send-access-token

KEYCLOAK_ACCESS_TOKENというヘッダ名でアクセストークンをプロキシ先に送信するかどうかを指定します。

bind-address

プロキシサーバーのソケットにバインドするためのDNS名もしくはIPアドレスを指定します。外部から接続する場合は、ループバックアドレス以外を指定します。

http-port

HTTPとしてLISTENするポート番号を指定します。ただし、HTTPのアクセスが許可されるかどうかは、後述のadapter-configssl-requiredの設定値に依存します。

https-port

HTTPSとしてLISTENするポート番号を指定します。

keystore

HTTPSを受け付ける場合に利用されるキーストアを指定。キーストアを指定しなかった場合は自動生成された一時的な自己署名サーバー証明書が利用されます。

keystore-password

キーストアを指定した場合のキーストアパスワードを指定します。

key-password

利用されるサーバ証明書のキーパスワードを指定します。

buffer-size

HTTPサーバーのソケットバッファサイズを指定します。通常デフォルトのままで問題ありません。

buffers-per-region

HTTPサーバーのリージョンごとのソケットバッファ数を指定します。通常デフォルトのままで問題ありません。

io-threads

IOを処理するスレッド数を指定します。通常デフォルトのままで問題ありません。

worker-threads

リクエストを処理するスレッド数を指定します。通常デフォルトのままで問題ありません。


applicationsの設定

パラメータ名
必須
説明

base-path

アプリケーションのコンテキストルートを指定します。"/"で始まる必要があります。

error-page

エラーが発生した場合(アクセスを拒否した場合も含む)に表示するエラーページを指定します。base-pathからの相対パスを指定します。

adapter-config

後述します。


adapter-configの設定

パラメータ名
必須
説明

realm

Keycloak側のレルム名を指定します。

resource

Keycloak側のクライアント設定のクライアントID(client-id)を指定します。

auth-server-url

Keycloak側のベースURLを指定します。1

credentials

Keycloak側のアクセスタイプで"confidential"を指定した場合は必須です。

ssl-required

HTTPSでのアクセスを強制するかどうか指定します。"all", "external", "none" のいずれかを指定します。デフォルトは、"external"なので、外部からはHTTPのアクセスは許可されません。

:information_source: adapter-configの設定は非常に多くあるため、動作確認に必要な最低限の項目のみ記載しています。その他のパラメータに関しては、参考資料の"Java Adapter Config"を参照ください。


constraintの設定

パラメータ名
必須
説明

pattern

URLパターンを指定。"/"で始まる必要があり、ワイルドカード(*)は最後でのみ指定が可能です。
有効なパターン: /foo/bar/* および /foo/*.txt
無効なパターン: /*/foo/*

roles-allowed

特定のロールをもつユーザーのみアクセスを許可する設定です。配列で複数の指定可能です。

methods

許可するHTTPメソッド名を配列で指定します。

excluded-methods

拒否するHTTPメソッド名を配列で指定します。

deny

アクセスを拒否する場合にはtrueを設定します(Keycoak Security Proxy経由ではアクセスさせたくないURLなど)。

permit

認証不要でアクセス可能にする場合にはtrueを設定します。

permit-and-inject

認証不要でアクセス可能にする場合にはtrueを設定します。ただし、認証済みでアクセスされた場合はヘッダにユーザー情報を付加します。

authenticate

ロールに関係なく、認証のみでアクセス可能にする場合にはtrueを設定します。

proxy.jsonを作成したら、以下のコマンドからSecurity Proxyが起動できます。

cd /usr/local/keycloak-proxy-3.3.0.CR2/

java -jar bin/launcher.jar proxy.json

設定ファイルに問題がなければ、以下のような起動メッセージが表示されます。

Home directory: /usr/local/keycloak-proxy-3.3.0.CR2

11 24, 2017 6:44:37 午後 org.keycloak.proxy.ProxyServerBuilder initConnections
WARN: Generating temporary SSL cert
11 24, 2017 6:44:45 午後 org.xnio.Xnio <clinit>
INFO: XNIO version 3.3.6.Final
11 24, 2017 6:44:45 午後 org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.6.Final


動作確認


認証が必要なURL


  1. 認証が必要な https://kc-proxy.example.com:18443/ にアクセスします。

  2. Keycloakに未ログインであるため、ログイン画面にリダイレクトが発生します。

  3. ID/PWでログインします。

  4. Tomcatのトップ画面が表示されます。


  5. https://kc-proxy.example.com:18443/examples/servlets/servlet/RequestHeaderExample にアクセスします。

  6. HTTPヘッダにKeycloakのユーザー情報が連携されているのが分かります。



認証が不要なURL


  1. 認証が不要な https://kc-proxy.example.com:18443/examples/jsp/ にアクセスします。

  2. 認証していなくてもページを参照できるのが分かります。



admin ロールが必要なURL


  1. adminロールが必要な https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml にアクセスします。

  2. adminロールを持つユーザーのID/PWでログインします。


  3. https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml が表示される。(admin ロールを持たないユーザーでログインした場合は403エラーとなります)



まとめ

今回はKeycloakとSecurity ProxyをID連携させる方法を確認しました。

基本的に設定用のjsonファイルを1つ配置するだけで、KeycloakとのID連携を確認できるため、リバプロ型の簡易的な動作確認としては有用かと思います。

ですが、Security Proxyを本格的にシステムに組み込む場合は、リバプロとして機能的に不足している点がいくつかあります。


  • プロキシ転送先が1サーバーしか指定できない

  • アクセスログがない

  • Apacheのような細かな制御(URL置換やヘッダ置換、ロードバランシングなどなど)ができない

  • HTTPヘッダとして連携できる項目が限られている

そのためリバプロ型構成を利用する場合は、8日目の記事で私が解説する「Keycloakでリバプロ型構成を組んでみる(mod_auth_openidc編)」を使用することにより、上記の不足点を補いつつ、リバプロとして柔軟な設定が利用可能となります。


参考資料


脚注





  1. Keycloakサーバーとのssl接続で自己署名サーバー証明書を利用する場合にはSecurity Proxy側のJavaのtruststoreにサーバー証明書の取り込みが必要です。(Security Proxyが、Keycloakサーバーと直接SSL通信するため)