Keycloakを使ってAWSにSSO接続する方法
みなさんこんにちは。@ryuzeeです。
たくさんのAWSアカウントを持っていたり、さまざまな外部サービスを使っていたりすると面倒なのが、アカウント自体の管理です。 今日はKeycloakを使って、たくさんのAWSアカウントにSSO接続するようにしてみたいと思います。
Keycloakとは
Keycloakは認証・認可のためのオープンソースソフトウェアです。最新のバージョンは4.1.0です。 より詳細については@ITの記事がわかりやすいです。
Keycloakの導入
KeycloakはJavaで書かれており、動作にはアプリケーションサーバが必要です。 アプリケーションで利用可能なデータベースは、MySQL、PostgreSQL、MariaDB、そして主に開発や試用用途のH2です。
また、公式のDockerイメージも用意されており、それを使えばアプリケーションサーバの設定などは不要です。 今回は簡単にするため、Dockerを使ってみましょう。
docker-composeを使うのが簡単で、以下から入手できます。
- MySQL用:https://github.com/jboss-dockerfiles/keycloak/blob/master/docker-compose-examples/keycloak-mysql.yml
- PostgreSQL用:https://github.com/jboss-dockerfiles/keycloak/blob/master/docker-compose-examples/keycloak-postgres.yml
ここでは、PostgreSQLを使います。
wget https://github.com/jboss-dockerfiles/keycloak/raw/master/docker-compose-examples/keycloak-postgres.yml
docker-compose -f keycloak-postgres.yml
とすれば起動します。起動後にhttp://localhost:8080
にアクセスして以下のような画面が表示されればOKです。
Keycloakへのログイン
画面のAdministration Console
をクリックして管理者画面にログインします。 管理者アカウントの初期ユーザーとパスワードはdocker-composeの中で、KEYCLOAK_USER
とKEYCLOAK_PASSWORD
で定義されているので、それを使います。
ログイン後には以下のような画面が表示されます。
ここは特にいじる箇所がないので、AWSのSSOの設定に進みましょう。
AWSのSAML情報を取得する
まず、AWSのSAML情報を以下のコマンドで取得し、ローカルに保存します。
wget https://signin.aws.amazon.com/static/saml-metadata.xml
クライアントを追加する
Clientsにアクセスすると、以下のようにクライアントの一覧が表示されます。 画面右側にあるCreate
ボタンをクリックします。
クライアントの追加画面が下のように表示されます。
Import
を選択し、先程ダウンロードしたsaml-metadata.xml
を指定します- Base URLには
/auth/realms/master/protocol/saml/clients/amazon-aws
を指定します - IDP Initiated SSO URL Nameには
amazon-aws
を指定します
それが終わったらSave
ボタンをクリックします。 以下のような画面が表示されるはずです。
AWSのSAML Provider用の設定ファイルを取得する
Installation タブにアクセスし、SAML Metadata IDPSSODescriptor
を選択します。 以下のように表示されますので、Download
をクリックしてファイルを保存します。 client-tailored-saml-idp-metadata.xml
という名前のファイルができたことを確認しておきます。
AWS(統合したいアカウントそれぞれ)上でSAML Providerの設定をする
SSO接続したいAWSアカウントの設定を行います。
- マネジメントコンソールでIAMにアクセスし、
Identity providers
(日本語だとIDプロバイダ)を選択します Create Provider
をクリック。Provider Type
でSAML
を選択しますProvider Name
には適当な名前を指定しますMetadata Document
には先ほどKeycloakからダウンロードしたXML(client-tailored-saml-idp-metadata.xml)を指定します
なお、awscliを利用する場合は以下のようなコマンドで作成できます(nameオプションは自分の好みにします)。
aws iam create-saml-provider --saml-metadata-document file://./client-tailored-saml-idp-metadata.xml --name docker-keycloak
ここで作成されたSAMP ProviderのARN(arn:aws:iam::211111666666:saml-provider/docker-keycloak
のようなもの)は後で使いますので控えておきます(※1)。
AWS(統合したいアカウントそれぞれ)上にIAM Roleを作成する
次に、SSO経由でログインしたユーザーに割り当てるIAM Roleを作成します。
またIAM Roleの画面で信頼関係を編集し、以下のようなポリシードキュメントに更新します。 Principalの値は各自異なります(アカウント番号やSAM Provierの名前など自分のものに合わせます)。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::211111666666:saml-provider/docker-keycloak"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
}
なお、CloudFormationで作成したい場合は、こちらからスクリプトをダウンロードし、中身を書き換えて(RoleNameなど)以下のように実行すると良いでしょう。
aws cloudformation create-stack --capabilities CAPABILITY_NAMED_IAM --stack-name sso-roles --template-body file://./sso-roles-cfn.yaml
ここで作成したIAM RoleのARNもあとで使いますので控えておきます(※2)。
以上ができたらKeycloak側に戻ります。
ロールの作成
新規でロールを作成するためにAdd Role
を選択します。 以下のような画面が表示されるので、
- Nameの箇所にIAM RoleのARN、SAML ProviderのARNをカンマで結合して入力します(※1と※2を結合します)。
- Descriptionの箇所は説明なので、適当に入れておきます。
入力が終わったらSave
をクリックします。
この作業もSSO対象のAWSアカウントの数だけ繰り返します。
Mapperの定義
次にMapperを定義します。Mappers
を選択して、Create
をクリックして3つの設定を作成します。
- Session Role
- Name:Session Role
- Mapper Type:Role list
- Role attribute name:https://aws.amazon.com/SAML/Attributes/Role
- Friendly Name:Session Role
- SAML Attribute Name Format:Basic
- Single Role Attribute:ON
- Session Name
- Name:Session Name
- Mapper Type:User Property
- Property:username
- Friendly Name:Session Name
- SAML Attribute Name:https://aws.amazon.com/SAML/Attributes/RoleSessionName
- SAML Attribute Name Format:Basic
- Session Duration
- Name:Session Duration
- Mapper Type:Hardcoded attribute
- Friendly Name:Session Duration
- SAML Attribute Name:https://aws.amazon.com/SAML/Attributes/SessionDuration
- SAML Attribute Name Format:Basic
- Attribute value:28800
入力の結果、以下のようになればOKです。
続いてClient Scopes
を選択し、Assigned Default Client Scopesの中にrole_list
がある場合はRemove selected
をクリックして選択を解除します。 以下のようになれば大丈夫です。
スコープの設定
次にScope
にアクセスし、Full Scope Allowed をOff
に設定します。
以上で、クライアントの設定は終了です。
ユーザー作成
続いてユーザーを作成して、権限を割り当てていきます。
左ナビゲーションのUsers
を選択すると、一覧画面が表示されるので、Add user
をクリックします。 そこで必要な情報を入力してSave
します。以下のような画面が表示されるはずです。
Rolle Mappings
タブに移動すると、左側にClient Roles
のプルダウンからurn:amazon:webservices
を選択します。 Available Roles
の中から当該のアカウントに割り当てたいロールを選択して、Add selected
を選択します。
この作業は利用するAWSアカウント分繰り返します。
また初期パスワードも設定します。Credentials
タブに移動して、Manage Password
の項目を設定しておきます。
準備完了
以上で準備完了です。
http://localhost:8080/auth/realms/master/protocol/saml/clients/amazon-awsにアクセスして、ログインすると、AWSの画面が次のような感じで表示されれば成功です。
おまけ
このままだと、ローカルのPC上なので実用できないので、Azure上に環境を用意します。
Azure上に環境を作るときは、Azure Cloud Shellを活用するのが便利です。以下を貼り付けると10分くらいで環境が出来上がります(※パスワードなどは適宜変更します)。 なお、追加のパラメータでJDBCの設定をしておくとよさそうです。
export rand=$RANDOM
export resourcegroup=keycloak-$rand
export appservice_plan=appserviceplan$rand
export appservice_name=keycloak-app-$rand
export region='Japan West'
export appservice_instance=B1
export db_server_name=db$rand
export db_admin_user=adminuser
# !!!CHANGE VALUE!!!
export db_admin_password=CHANGE_ME_CHANGE_ME!
export db_sku=B_Gen4_1
export db_firewall_rule=db$rand
export db_name=keycloak$rand
export db_addr="$db_server_name.postgres.database.azure.com"
export db_vendor=postgres
export container_image=jboss/keycloak
export keycloak_user=admin
# !!!CHANGE VALUE!!!
export keycloak_password=CHANGE_ME_CHANGE_ME!
az group create \
--name "$resourcegroup" \
--location "$region"
az appservice plan create \
--name "$appservice_plan" \
--resource-group "$resourcegroup" \
--sku "$appservice_instance" \
--is-linux
az postgres server create \
--resource-group "$resourcegroup" \
--name "$db_server_name" \
--location "$region" \
--admin-user "$db_admin_user" \
--admin-password "$db_admin_password" \
--sku-name "$db_sku" \
--storage-size 51200 \
--version "9.6" \
--ssl-enforcement "Disabled"
az postgres server firewall-rule create \
--name "$db_firewall_rule" \
--server "$db_server_name" \
--resource-group "$resourcegroup" \
--start-ip-address 0.0.0.0 \
--end-ip-address 255.255.255.255
az postgres db create \
--resource-group "$resourcegroup" \
--server-name "$db_server_name" \
--name "$db_name"
az webapp create \
--resource-group "$resourcegroup" \
--plan "$appservice_plan" \
--name "$appservice_name" \
--deployment-container-image-name "$container_image"
az webapp config appsettings set \
--resource-group "$resourcegroup" \
--name "$appservice_name" \
--settings \
PROXY_ADDRESS_FORWARDING=true \
DB_VENDOR=$db_vendor \
DB_DATABASE="$db_name" \
DB_ADDR="$db_addr" \
DB_USER="$db_admin_user@$db_server_name" \
DB_PASSWORD="$db_admin_password" \
KEYCLOAK_USER="$keycloak_user" \
KEYCLOAK_PASSWORD="$keycloak_password" \
JDBC_PARAMS="autoReconnect=true"
それでは。