##Keycloakを構築してセキュリティ検証
Keycloakはシングルサインオン(SSO)やAPIアクセスの認証・認可制御をするオープンソースソフトウェアです。
今回は案件で使用する可能性があるので、2021/2頃にAWS上で構築して検証してみました。
検証用に構築したEC2インスタンス上にWildflyをセットアップしてサンプルアプリケーションをデプロイし、クライアントアダプターを適用してSSOが適用されるように設定していきます。
##検証環境情報
今回はAWSで環境を構築したので、一通りの環境情報をまとめてみました。
(AWS上でなくても検証は可能)
費用があまりかからないよう、基本的に無料枠ベースで構築していきます。
###Keycloak
環境情報 | バージョン・タイプ |
---|---|
keycloak | 12.0.2 |
※検証開始時点での最新を使用
###VPC
環境情報 | バージョン・タイプ |
---|---|
IPv4 CIDR ブロック | 10.0.0.0/24 |
テナンシー | デフォルト |
サブネット | パブリック |
パブリックサブネットなので、インターネットゲートウェイをルートテーブルに追加してパブリックIPの割り当てを有効化しておきます。
デフォルトのサブネットを使う場合は特に準備は不要です。
###EC2
環境情報 | バージョン・タイプ |
---|---|
プラットフォーム | Amazon Linux 64ビット |
インスタンスタイプ | t2.micro |
ストレージ | EBS 汎用SSD 8G |
Java | OpenJDK 1.8 |
Wildfly | 22.0.0.Final |
Maven | 3.6.1 |
Git | 2.23.3 |
EC2は上記のVPC上に構築したパブリックサブネット上にアタッチし、念の為終了保護を有効化しておきます。
また、MavenとGitに関してはセキュリティ保護の検証用アプリをクローン・ビルドするためのものなので、Keycloakの動作としては必須ではないです。
###セキュリティグループ
タイプ | プロトコル | ポート | 用途 |
---|---|---|---|
SSH | TCP | 22 | SSH接続用 |
HTTP | TCP | 80 | HTTPアクセス用 |
カスタム TCP | TCP | 8080 | セキュリティー保護のサンプルアプリケーション用 |
カスタム TCP | TCP | 8180 | Keycloakアクセス用 |
フルオープンだと全世界からアクセス可能になるため、基本それぞれポート毎に有効なIPアドレスの範囲を設定する必要があります。
Keycloakアクセス用の8180ポートについてはEC2インスタンスのグローバルIPアドレスに対してリクエストされ、JSONのレスポンスが返却されるため、設定時に注意が必要です。
使用しているネットワークのグローバルIPアドレス以外に、EC2へ直接リクエストできるようにしないといけないです。
##EC2セットアップ
※前提として操作は全てルートユーザーで行う想定
ec2-userのworkディレクトリを使用するため、EC2以外の場合は適宜読み替えが必要
1.作業用フォルダを作成してkeycloakをダウンロード・解凍する
mkdir /home/ec2-user/work
cd /home/ec2-user/work
wget https://github.com/keycloak/keycloak/releases/download/12.0.2/keycloak-12.0.2.zip
unzip keycloak-12.0.2.zip -d /opt
2.Java8をインストールしてバージョンを確認する
yum -y install java-1.8.0-openjdk-devel
java -version
3.Mavenをダウンロードしてシンボリックリンク作成後に配置し、パスを追加する
cd /home/ec2-user/work
curl https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz | tar zxv
mkdir /opt/maven
mv apache-maven-3.6.1 /opt/maven/
ln -s /opt/maven/apache-maven-3.6.1 /opt/maven/default
echo 'export PATH=$PATH:/opt/maven/default/bin' | sudo tee -a /etc/profile
source /etc/profile
mvn --version
4.Gitをインストールしてバージョンを確認する
yum install git-all
git --version
※Keycloakの起動時に80番ポートを使用するため、Apacheはインストールしない
インストールすると以降の手順でKeycloakが起動しなくなるため注意
##Keycloakセットアップ
1.Keycloak用のログディレクトリを作成する
mkdir /var/log/keycloak
※Keycloakの起動等でエラーになった場合はこちらに出力されているログを確認する
2.Keycloakのサービスを作成
vim /etc/systemd/system/keycloak.service
コマンド実行後、エディタが起動するので以下をそのまま貼り付けて保存する
※「-Djboss.http.port=80」で起動時のポートを指定している
[Unit]
Description=Jboss Application Server After=network.target
After=network.target
[Service]
Type=idle Environment=JBOSS_HOME=/opt/keycloak-12.0.2
JBOSS_LOG_DIR=/var/log/keycloak "JAVA_OPTS=-server -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true"
User=root
Group=root
ExecStart=/opt/keycloak-12.0.2/bin/standalone.sh -Djboss.http.port=80
TimeoutStartSec=600
TimeoutStopSec=600
[Install]
WantedBy=multi-user.target
3.Keycloakの設定ファイルを再読み込みおよび自動起動の有効化する
systemctl daemon-reload
systemctl enable keycloak
4.Keycloakに内包されているWildflyの設定ファイルを編集し、外部からアクセスできるように設定する
vi /opt/keycloak-12.0.2/standalone/configuration/standalone.xml
viエディタが起動するので以下のように編集する
※設定するIPアドレスはEC2インスタンスのプライベートIPアドレスなので、グローバルIPアドレスと間違えないよう注意
<interface name="management">
<inet-address value="${jboss.bind.address.management:<EC2インスタンスのプライベートIPアドレス>}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:<EC2インスタンスのプライベートIPアドレス>}"/>
</interface>
※viエディターのコマンドモード「/」で「interface name="management"」・「interface name="public"」を検索してペーストすると簡単に編集可能
5.Keycloakを起動する
systemctl start keycloak
6.起動後に管理アカウントを作成する
※以下は管理者ID/PASSをadmin/passwordとする場合の例
./bin/add-user-keycloak.sh -r master -u admin -p password
7.Keycloakを再起動する
systemctl daemon-reload
systemctl restart keycloak
8.Keycloakにログインする
※以下は管理者ID/PASSをadmin/passwordとする場合の一例
./bin/kcadm.sh config credentials --server http://<EC2インスタンスのプライベートIPアドレス>/auth --realm master --user admin --password password
9.外部からのアクセス時にHTTPでアクセスできるように設定を変更する
./bin/kcadm.sh update realms/master -s sslRequired=NONE
10.以下のURLでブラウザからアクセスし、作成した管理者ユーザーでログインする
http://<EC2インスタンスのグローバルIPアドレス>/auth/admin/
###日本語化手順
必要に応じて日本語化の設定が可能です。
以降の手順についても日本語化を前提として記載しています。
1.MasterのThemesタブを開き、赤字のオプションをONにして「Save」押下
2.ヘッダー右上のManege accountをクリックすると有効化される
##レルム・ユーザー追加
構築初回のログインはmasterレルムでログインされているため、別のレルムを作成していきます。
レルム作成後は紐づくユーザーを作成し、実際のログイン時に作成したユーザー情報を使用します。
###レルム作成
1.レルムの追加をクリックする
2.任意の名前を入力して「作成」押下
3.レルムが作成される
※サイドバーの上でレルムの切り替えができる
※デフォルトだとSSLのリクエストが強要されてしまうので、HTTPでアクセスできるように設定を変更しておく
###ユーザー作成
1.サイドバーのユーザーをクリックして「ユーザーの追加」を押下
2.任意の名前を入力して「保存」を押下
3.作成したユーザーにパスワードを設定する
※以下の場合はワンタイムパスワードにしているため、ログイン後にパスワード変更を求められる
4.一度サインアウトして以下のURLへアクセスし、作成したユーザーでログインする
※ログイン後にパスワード変更を求められる
http://<EC2インスタンスのグローバルIPアドレス>/auth/realms/<作成したレノム名>/account
##検証用Wildflyのセットアップ
###Wildflyのインストール
1.Wildflyをダウンロードして解凍する
cd /home/ec2-user/work
wget https://download.jboss.org/wildfly/22.0.0.Final/wildfly-22.0.0.Final.zip
unzip wildfly-22.0.0.Final.zip -d /opt
2.Keycloakを起動する
cd /opt/keycloak-12.0.2
./bin/standalone.sh -Djboss.socket.binding.port-offset=100
3.以下のURLでアクセスできることを確認する
http://<EC2インスタンスのグローバルIPアドレス>:8180/auth/admin/
###WildFlyクライアント・アダプターのセットアップ
1.WildFly OpenID Connect Client Adapter の配布物をダウンロードしてWildflyのルートディレクトリに解凍する
cd /home/ec2-user/work
wget https://github.com/keycloak/keycloak/releases/download/12.0.2/keycloak-oidc-wildfly-adapter-12.0.2.zip
unzip keycloak-oidc-wildfly-adapter-12.0.2.zip -d /opt/wildfly-22.0.0.Final
2.以下のスクリプトを実行する
cd /opt/wildfly-22.0.0.Final
./bin/jboss-cli.sh --file=adapter-elytron-install-offline.cli
3.Wildflyを起動する
./bin/standalone.sh
###WildFlyアプリケーションの登録
1.以下のURLにアクセスして管理者ユーザーでログイン
http://<EC2インスタンスのグローバルIPアドレス>:8180/auth/admin/
2.先ほど作成したレルムを選択してサイドバーのクライアントをクリックし、「作成」を押下
※以下はレルムはDemoで作成する場合の例
2.以下のように入力して「保存」を押下
※ルートURLにはグローバルIPアドレスを指定
3.認証用のJSONファイルを自動生成してダウンロードする
※セキュリティ検証時にサンプルアプリケーションの中に組み込んで使用する
※XMLでもセキュリティ保護設定用に自動生成することができる
###WildFlyのセキュリティ保護設定
1.standalone.xmlを開く
vi /opt/wildfly-22.0.0.Final/standalone/configuration/standalone.xml
エディタが起動後、以下のように編集
①EC2のグローバルIPアドレス・レルムを指定してセキュリティ保護設定を追加する
■編集前
<subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
■編集後
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<secure-deployment name="vanilla.war">
<realm>demo</realm>
<auth-server-url>http://<EC2インスタンスのグローバルIPアドレス>:8180/auth</auth-server-url>
<public-client>true</public-client>
<ssl-required>NONE</ssl-required>
<resource>vanilla</resource>
</secure-deployment>
</subsystem>
※viエディターのコマンドモード「/」で「urn:jboss:domain:keycloak:1.1」を検索してペーストすると簡単に編集可能
また、上記の場合はレルムはdemoを指定する例
②外部アクセスを許可されるように設定を変更する
<interface name="management">
<inet-address value="${jboss.bind.address.management:<EC2インスタンスのプライベートIPアドレス>}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:<EC2インスタンスのプライベートIPアドレス>}"/>
</interface>
※①と同じくviエディターのコマンドモード「/」で「interface name="management"」・「interface name="public"」を検索してペーストすると簡単に編集可能
2.Wildflyを再度起動する
cd /opt/wildfly-22.0.0.Final
./bin/standalone.sh
※失敗する場合は起動したプロセスが残っている可能性があるので終了させる
lsof -i:8080
kill -9 <プロセスID>
##サンプルアプリケーションのクローン・ビルド
1.アプリケーションのサンプルコードをGitからクローンする
cd /home/ec2-user/work
git clone https://github.com/keycloak/keycloak-quickstarts
2.以下のコマンドでディレクトリを移動し、クライアント作成時に保存した認証用のJSONファイルを配置する
cd /home/ec2-user/work/keycloak-quickstarts/app-profile-jee-vanilla/config
3.以下のコマンドでディレクトリを移動し、アプリケーションをデプロイする
cd /home/ec2-user/work/keycloak-quickstarts/app-profile-jee-vanilla
mvn clean wildfly:deploy
※Wildflyが起動している状態で行う必要がある
また、JAVA_HOMEに設定のパスがJREの場合はビルドに失敗するのでJDKが設定されていることを確認する
##セキュリティ検証
1.以下のURLからデプロイされた検証用のアプリケーションにアクセスする
http://<EC2インスタンスのグローバルIPアドレス>:8080/vanilla
2.Keycloakの認証を求められるので、作成したユーザーとパスワードを入力してログインする
3.Keycloakを使用してサンプルアプリケーションがセキュリティー保護されていることが確認できる
##まとめ
Keycloakをセットアップ後にSSOの対象となるアプリケーションがデプロイされているAPサーバーにセキュリティ保護設定を加えることで、作成したレルム内のユーザー情報をもとにログインできることが確認できました。
今回はWildflyを使用して検証を行いましたが、別のAPサーバー用にクライアント・アダプターが提供されているのでTomcat等でも同じように導入可能です。
業務上ではアプリケーションの実装面でセキュリティを意識することがありましたが、外部と連携する形でセキュリティ強化することも非常に重要だと感じました。
近年だとAWS Cognitoなどで簡単にユーザープールを管理できたりする仕組みもありますが、Keycloakに関してもチラホラみかけるようになったので使い方を知っておいても損はないと思います。
また、今回の検証環境構築は進めるうちにAPサーバーの設定についても少し強くなれた気がします。
気になった方は是非試してみてください。
##参考