2021年6月21日月曜日

Apache2 + mod_auth_openidc + Keycloak でディレクトリごとにアクセス制限をかけたい

既存の静的サイトに、後付けで以下のようなアクセス制限をかけたい。

site/
    +- index.html       : インデックスページ。ログインしていれば誰でも表示できる
    +- user1/           : user1 用ディレクトリ。この中のファイルは user1 しか表示できない
    |   +- profile.html
    +- user2/           : user2 用ディレクトリ。この中のファイルは user2 しか表示できない
        +- profile.html

前回 は、Keycloakzmartzone/mod_auth_openidc の組み合わせを試してダメだったので、今回は Apache2 の mod_auth_openidc を試す。

前提

構築イメージ

+----------+
| Keycloak |
+----------+
 ↑ localhost:8080
+---------+
| Apache2 |
+---------+
 ↑ localhost:18080
+---------+
| Browser |
+---------+

Keycloak の準備

docker-compose.yaml の取得

Invoke-WebRequest -OutFile docker-compose.yaml -Uri https://raw.githubusercontent.com/keycloak/keycloak-containers/master/docker-compose-examples/keycloak-postgres.yml

とりあえず今回は管理者情報含めてこのまま使う。

Keycloak コンテナ起動

docker compose up

Realm 追加

  1. http://localhost:8080 へ接続
  2. ログイン
    • Username : admin
    • Password : Pa55w0rd
  3. 左上の Master にマウスオーバーしたときに表示される Add realm を押下
  4. Add realm ページが表示されるので、必要事項を記入して Create ボタン押下
    • Name : MyApp
    • Enabled : ON

OAuth クライアントの追加

  1. Clients -> Create ボタン押下
  2. Add Client ページが表示されるので、必要事項を記入して Save ボタン押下
    • Client ID : Apache2
    • Client Protocol : openid-connect
    • Root URL : http://localhost:18080
  3. Apache2 の設定ページが表示されるため、必要な項目を更新して Save ボタン押下
    • Access Type : confidential
  4. Mappers タブ -> Create ボタン押下、必要事項を記入して Save ボタン押下
    • Name: User Realm Role
    • Mapper Type: User Realm Role
    • Token Claim Name: role
  5. Installation タブ -> Format OptionKeycloak OIDC JSON に変更 -> 値を控える

ロール・グループ・ユーザーの設定

ロール作成

  1. ログイン済みユーザーのロールを追加
    1. Roles -> Add Role ボタン押下
    2. Add Role ページが表示されるので、必要事項を記入して Save ボタンを押下
      • Role Name: authorized
  2. user1 のロールを追加
    1. Roles -> Add Role ボタン押下
    2. Add Role ページが表示されるので、必要事項を記入して Save ボタンを押下
      • Role Name: user1
  3. user2 のロールを追加
    1. Roles -> Add Role ボタン押下
    2. Add Role ページが表示されるので、必要事項を記入して Save ボタンを押下
      • Role Name: user2

グループ作成

  1. Groups -> New ボタン押下
  2. Create group ページが表示されるので、必要事項を記入して Save ボタン押下
    • Name: authorized
  3. Role Mapping タブを開く
    1. Available Roles を選択し、 add selected> ボタン押下。 Assigned Rolesauthorized が追加されたことを確認

ユーザー作成

  1. usre1 を追加
    1. Users -> Add user ボタン押下
    2. Add user ページが表示されるので、必要事項を記入して Save ボタン押下
      • username: user1
      • Email: user1@example.com
    3. Credentials タブを開き、パスワード設定を行い Set Password ボタンを押下
      • Password, Password Confirmation を入力
      • Temporary: OFF へ変更
    4. Role Mappings タブを開き、ロール設定を行う
      • Available Roles から user1 を選択し、 Add selected> ボタンを押下
    5. Groups タブを開き、グループ設定を行う
      • Available Groups から authorized を選択し、 join ボタンを押下
  2. usre1 を追加
    1. Users -> Add user ボタン押下
    2. Add user ページが表示されるので、必要事項を記入して Save ボタン押下
      • username: user2
      • Email: user2@example.com
    3. Credentials タブを開き、パスワード設定を行い Set Password ボタンを押下
      • Password, Password Confirmation を入力
      • Temporary: OFF へ変更
    4. Role Mappings タブを開き、ロール設定を行う
      • Available Roles から user2 を選択し、 Add selected> ボタンを押下
    5. Groups タブを開き、グループ設定を行う
      • Available Groups から authorized を選択し、 join ボタンを押下

Apache2 の準備

Docker イメージ作成

httpd:2.4.48 をベースに、 mod_auth_openidc をインストールした Docker イメージを作成する。

See: https://github.com/mikoto2000/docker-images/blob/master/httpd/Dockerfile

設定ファイル作成

httpd.conf

イメージ内のデフォルトの設定ファイルをコピー。

docker run -d --rm --name httpd mikoto2000/httpd:latest
docker cp httpd:/usr/local/apache2/conf/httpd.conf ./httpd.conf.original
docker kill httpd

コピーした http.conf.original を基に、 httpd.conf を作成する。 その差分を以下に示す。

httpd.conf の差分

> diff.exe -u .\httpd.conf.original .\httpd.conf
--- ".\\httpd.conf.original"    2021-05-26 09:23:52.000000000 +0900
+++ ".\\httpd.conf"     2021-06-21 01:10:11.138620400 +0900
@@ -49,7 +49,7 @@
 # prevent Apache from glomming onto all bound IP addresses.
 #
 #Listen 12.34.56.78:80
-Listen 80
+Listen 18080

 #
 # Dynamic Shared Object (DSO) Support
@@ -139,10 +139,10 @@
 LoadModule setenvif_module modules/mod_setenvif.so
 LoadModule version_module modules/mod_version.so
 #LoadModule remoteip_module modules/mod_remoteip.so
-#LoadModule proxy_module modules/mod_proxy.so
+LoadModule proxy_module modules/mod_proxy.so
 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
 #LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
-#LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
 #LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
 #LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
 #LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
@@ -196,7 +196,9 @@
 #LoadModule speling_module modules/mod_speling.so
 #LoadModule userdir_module modules/mod_userdir.so
 LoadModule alias_module modules/mod_alias.so
-#LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule auth_openidc_module /usr/lib/apache2/modules/mod_auth_openidc.so
+

 <IfModule unixd_module>
 #
@@ -549,3 +551,8 @@
 SSLRandomSeed connect builtin
 </IfModule>

+<IfModule auth_openidc_module>
+Include conf/extra/oidc.conf
+</IfModule>
+
+

oidc.conf

以下を参考に oidc でのアクセス制限設定を行う。

  • https://github.com/openstandia/keycloak-dockerfiles/blob/master/reverse_proxy-based-arch-examples/kc-mod_auth_openidc-example/reverse_proxy/proxy.conf

oidc.conf という名前で以下設定ファイルを保存。

oidc.conf

########################################################################################
#
# Common Settings
#
########################################################################################

# バーチャルホスト設定
NameVirtualHost *:18080

# keepAlive設定
KeepAlive On

# [mod_auth_openidc] OpenID Connectのレスポンスタイプ設定(code = Authorization Code Grant)
OIDCResponseType "code"

# [mod_auth_openidc] Cookieやキャッシュの暗号化で使用されるパスフレーズの設定
OIDCCryptoPassphrase OuY94OFtB+cF0n1mhjV5zg==

# [mod_auth_openidc] RP(mod_auth_openidc)のセッションクッキーが設定されるドメインの設定
OIDCCookieDomain localhost

# [mod_auth_openidc] OP(Keycloak)との通信時にSSLを使用する際の、有効なサーバー証明書チェック有無の設定
OIDCSSLValidateServer Off

# [mod_auth_openidc] OP(Keycloak)のメタデータURLの設定
OIDCProviderMetadataURL http://host.docker.internal:8080/auth/realms/MyApp/.well-known/openid-configuration

# [mod_auth_openidc] クレームの連携方法の設定
OIDCPassClaimsAs headers

# [mod_auth_openidc] クレームのプレフィックスの設定
#OIDCClaimPrefix ""

<VirtualHost *:18080>
    ServerName    localhost
    RewriteEngine On
    RewriteOptions inherit

    OIDCScope "openid"

    # [mod_auth_openidc] リダイレクトURIの設定
    OIDCRedirectURI  http://localhost:18080/oidc-redirect

    # [mod_auth_openidc] OP(Keycloak)に設定されているクライアントIDの設定
    OIDCClientID Apache2

    # [mod_auth_openidc] OP(Keycloak)に設定されているクライアントIDに対応するクライアントsecretの設定
    OIDCClientSecret 75700c2f-7b91-470a-8104-47a7f62c30d3

    # 認証ロケーション設定(/)
    # 一旦、"/"以降を全て認証対象とし、対象から外す場合は、以下に別途記載する。
    # ログインしていれば誰でも表示できる
    <Location />
        AuthType openid-connect
        Require claim "role:authorized"
    </Location>


    # リダイレクト URL の設定
    <Location /oidc-redirect>
        AuthType openid-connect
        Require valid-user
    </Location>

    # 制限ロケーション設定(/user1/)
    # roleにuser1が設定されているユーザのみがアクセス可能
    <Location /user1/>
        AuthType openid-connect
        Require claim "role:user1"
    </Location>

    # 制限ロケーション設定(/user2/)
    # roleにuser2が設定されているユーザのみがアクセス可能
    <Location /user2/>
        AuthType openid-connect
        Require claim "role:user2"
    </Location>

    # favicon.ico対策
    <Location /favicon.ico>
        Require all granted
    </Location>

</VirtualHost>

Apache2 起動

作成した設定ファイルを適切に配置して Docker コンテナを起動。

docker run -it --rm --name httpd `
-v "$(pwd)/site:/usr/local/apache2/htdocs" `
-v "$(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf" `
-v "$(pwd)/oidc.conf:/usr/local/apache2/conf/extra/oidc.conf" `
-p "18080:18080" mikoto2000/httpd:latest

動作確認

http://localhost:18080/index.html へアクセスすると、 Keycloak のログイン画面が表示される。

冒頭で説明した通りのアクセス制限ができていることを確認。

以上。

参考資料

0 件のコメント:

コメントを投稿