🍈

Apache mod_auth_mellon で SAML SP を設定してみる

2024/12/31に公開

Apache mod_auth_mellon で SAML SP の設定

環境

ここでは Docker コンテナ内に apache 環境を構築します。

$ sudo docker run --rm -it -p 443:443 -v /home/debian/docker/mellontest:/opt --name mellontest debian:bookworm-slim bash

(Rapberry pi OS の上にたてたKVM仮想マシンの上で Dockerコンテナを動かして検証しています。)

パッケージの導入

動作に必要なパッケージを導入します。

# apt update
# apt install --no-install-recommends apache2 libapache2-mod-auth-mellon openssl curl

IdP メタデータ作成

mellon_create_metadata の第一引数は Entityid 、第二引数は endpoint 。
作成したらリネームしておく。

# mkdir -p /etc/apache2/mellon
# cd /etc/apache2/mellon
# /usr/sbin/mellon_create_metadata https://192.168.11.40/ "https://192.168.11.40/mellon"

# mv *.key mellon.key
# mv *.cert mellon.cert
# mv *.xml mellon_metadata.xml

SP メタデータ

SP メタデータ mellon_metadata.xml を IdPに登録する。
(IdP は Azure EntraID / KeyCloak について記載しますが、いったん、Azure EntraIDを想定)

mod_auth_mellon の設定ファイルを作成

IdPから取得したメタデータを /etc/apache2/mellon/IdP_metadata.xml に配置する。

設定ファイルを記載する。

/etc/apache2/conf-available/mellon.conf
<location />
MellonSPPrivateKeyFile /etc/apache2/mellon/mellon.key
MellonSPCertFile /etc/apache2/mellon/mellon.cert
MellonSPMetadataFile /etc/apache2/mellon/mellon_metadata.xml
MellonIdPMetadataFile /etc/apache2/mellon/IdP_metadata.xml
MellonEndpointPath /mellon
MellonEnable "auth"
</Location>

TLS接続するための証明書を作成

ここでは自己署名のオレオレ証明書を作成している。
サブジェクト、コモンネームはよしなに。

# openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out /etc/ssl/certs/mywebserver.pem -keyout /etc/ssl/private/mywebserver.key -subj '/C=JP/ST=Tokyo/L=Shinjuku/CN=192.168.11.40'

Apache 設定ファイルを作成

Apache の設定ファイルを作成する。
ServerName はよしなに。

/etc/apache2/sites-available/mywebserver.conf
ServerName 192.168.11.40
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
DocumentRoot /var/www/html
ServerSignature Off
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
LogLevel info ssl:warn

SSLEngine on
SSLCertificateFile /etc/ssl/certs/mywebserver.pem
SSLCertificateKeyFile /etc/ssl/private/mywebserver.key
</VirtualHost>

<Location />
Require valid-user
AuthType "Mellon"
MellonEnable "auth"
MellonDecoder "none"
MellonVariable "cookie"
MellonSecureCookie On
</Location>
</IfModule>

SAML認証によって守られるべきテストコンテンツを作成

# mkdir -p /var/www/html/protected
# date > /var/www/html/protected/index.html

設定を有効化

# apache2ctl configtest
# a2enmod ssl
# a2enconf mellon.conf
# a2ensite mywebserver.conf
# a2dissite 000-default.conf
# apache2ctl graceful

動作確認

WebサーバのURLにアクセスして、設定したIdPのログイン画面に遷移するること、ログインできること、コンテンツを表示できることを確認する。

設定によっては特定のブラウザで動作しない場合があるので、Firefox、Edge など複数のブラウザで、プライベートモード等を含めて動作確認すると確実。
Internal Server Error や Bad Requestのエラーがでたら、Apache の error.log にメッセージを確認する。

IdP として Azure EntraID を利用する

Azure EntraID はフリープランでOK。

参考

https://qiita.com/QGv/items/cd2b863a0bb6f7153ae0

ユーザを追加する

Entra IDの画面へ移動して以下の手順でユーザを作成する。
(SAML設定自体とは関係ないが、前準備として必要に応じて実施)

  1. 左ペインで「ユーザー」へ移動 → 右ペイン上部で「新しいユーザ」 → 「新しいユーザの作成」
  2. ユーザープリンシパル名: 任意のユーザ名 (@xxx.onmicrosoft.com)
  3. 表示名: 任意の表示名
  4. パスワード: 任意
  5. 入力したら「レビューと作成」 → 「作成」

IdPを作成する

Entra IDの画面へ移動して以下の手順でIdPを作成する。

  1. 左ペインで「エンタープライズアプリケーション」へ移動 → 右ペイン上部で「新しいアプリケーション」 → 「独自のアプリケーションの作成」
  2. お使いのアプリケーション名: 任意の名前
  3. 「ギャラリーに見つからないその他のアプリケーションを統合します (ギャラリー以外)」にチェック
  4. 入力したら「作成」をクリック

ユーザーの追加

  1. 左ペイン「概要」で「1. ユーザーとグループの割り当て」の「ユーザまたはグループの追加」 → 画面上部で「ユーザまたはグループの追加」 → 「ユーザ」の「選択されていません」をクリック
  2. 追加したいユーザをチェックして、「選択」をクリック → 「割り当て」をクリック

シングルサインオンの設定

  1. 左ペイン「概要」で「2. シングル サインオンの設定」の「作業の開始」 → 「シングルサインオン方式」で SAML を選択
  2. 画面上部で「メタデータ ファイルをアップロードする」 → SP メタデータ mellon_metadata.xml をアップロードする
  3. 「基本的な SAML 構成」が開くので「保存」をクリック。(サインインのテストは実施しない)

IdP メタデータダウンロード

  1. 「SAML証明書」→ 「フェデレーション メタデータ XML」をダウンロード。
  2. ダウンロードしたxmlファイルを、/etc/apache2/mellon/IdP_metadata.xml として SP 側に保存する。

動作確認

WebサーバのURLにアクセスして、Azureのログイン画面に遷移すること、作成したユーザーのプリンシパル名(ユーザ名@xxx.onmicrosoft.com) でログインできること、コンテンツを表示できることを確認する。

サインインログ

サインインの履歴は「アクティビティ」 → 「サインインログ」で確認できる。

IdP として Azure KeyCloak を利用する

KeyCloak は例によって Docker で準備する。

証明書の準備

KeyCloak を TLS化するために適当な証明書を準備する

$ mkdir keycloak
$ openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out keycloak/example.crt -keyout keycloak/example.key -subj '/C=JP/ST=Tokyo/L=Shinjuku/CN=192.168.11.40'

docker compose で起動

sudo docker compose up -d で起動する。

compose.yaml
services:
  postgres:
    image: postgres:16
    volumes:
      - ./postgresql:/var/lib/postgresql
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
  keycloak:
    image: quay.io/keycloak/keycloak:26.0
    volumes:
      - ./keycloak:/work/keycloak
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: password
      KC_DB: postgres
      KC_DB_PASSWORD: password
      KC_DB_USERNAME: keycloak
      KC_DB_URL_PORT: 5432
      KC_DB_URL_HOST: postgres
      KC_DB_URL_DATABASE: keycloak
      KC_HTTPS_CERTIFICATE_FILE: /work/keycloak/example.crt
      KC_HTTPS_CERTIFICATE_KEY_FILE: /work/keycloak/example.key
    command:
      - "start-dev"
    ports:
      - 8080:8080
      - 8443:8443
    depends_on:
      - postgres

sudo docker compose ps で起動していることを確認する。停止する等の不具合があれば、
sudo docker compose logs (-f) で確認する。

Realm 作成

  1. KeyCloakのURL(https://アドレス:8443/)を開き、Username は KEYCLOAK_ADMIN の値、 Password は KEYCLOAK_ADMIN_PASSWORDでログイン。
  2. トップ画面から Create realmRealm name に 適当な名前を入力して、Create を押下。

IdP 作成

  1. 左ペインの Clients を押下 → 右ペインで Import client を押下
  2. Resource file: Browse を押下して mellon_metadata.xml を読み込む
  3. Name に任意の名前を入力して、Save を押下

ユーザ作成

  1. 左ペインの Users を押下 → 右ペインで Create new user を押下
  2. Username に任意のユーザー名を入力して、 Create を押下
  3. Credentials タブへ移動して、Set password を押下
  4. Password、Password confirmation に適当なパスワードを入力
  5. Temporaryを Off にして Save を押下 → Save password を押下

IdP メタデータダウンロード

Apache サーバ側で以下を実行して、IdP メタデータをダウンロードして、設定反映

# curl -k -s https://192.168.11.40:8443/realms/<Realm名>/protocol/saml/descriptor -o /etc/apache2/mellon/IdP_metadata.xml
# apachectl graceful

動作確認

WebサーバのURLにアクセスして、KeyCloak のログイン画面に遷移すること、作成したユーザー名でログインできること、コンテンツを表示できることを確認する。

おわりに

気が向くことがあれば、IdPとして SimpleSAMLphp を利用する場合の設定についても記載したい。

GitHubで編集を提案

Discussion