AWSへアクセスする際は使用するIAMでは、ユーザー管理機能が提供されていますが、外部のIDプロバイダー(IdP)で管理されているユーザーにAWSへのアクセス許可を与えることが可能です。
IAMがサポートする外部IdPは以下の2つです。
- SAML 2.0 (Security Assertion Markup Language 2.0)
- OpenID Connect (OIDC)
外部IdPとしてAuth0を使用し、OpenID Connectでの連携を行う方法を紹介します。
設定手順
- Auth0にユーザー追加
- Auth0にアプリケーションを作成
- Identifierを取得
- IAMの外部IDプロバイダーを登録
- IAMロールを作成
Auth0にユーザー追加
Auth0の管理画面を開き、Auth0にユーザーを追加します。
Auth0にアプリケーションを作成
Applicationの管理画面へ移動します。Create Application
ボタンをクリックします。
任意のName
を入力し、アプリケーションのタイプとしてNative
を選択し、Create
ボタンをクリックします。
Settings
タブのDomain
とClient ID
をメモします。
Settings
タブの最下部にAdvanced Settings
セクションがあります。初期状態では折りたたまれてます。
Advanced Settings
セクションを開き、Grant Types
タブを選択します。Device Code
にチェックを入れ、Save Changes
ボタンをクリックします。
Identifierを取得
APIs
メニューを選択し、Auth0 Management API
を選択します。
General Settings
セクションのIdentifier
をコピーします。
IAMの外部IDプロバイダーを登録
ここからはAWSのマネジメントコンソールで操作します。
IAMの管理画面のIDプロバイダ
メニューに移動し、プロバイダを追加
ボタンをクリックします。
プロバイダのタイプ
としてOpenID Connect
を選択し、プロバイダのURL
に前の手順でメモしたDomain
を入力します。
末尾に/を含めるように入力する必要があります ので注意してください。
入力したらサムプリントを取得
ボタンをクリックします。
対象者
に前の手順でメモしたClient ID
を入力し、プロバイダを追加
ボタンをクリックします。
IAMロールを作成
登録後のプロバイダの詳細画面を表示します。
ロールの割り当て
ボタンをクリックし、新しいロールを作成
を選択して次へ
ボタンをクリックします。
IAMロール作成画面に遷移します。
エンティティの種類やIDプロバイダーは自動で入力されます。Audience
を選択し、次のステップ
ボタンをクリックします。
このさきは通常のIAMロール作成と変わりません。割り当てるポリシーを選択し、名前をつけてIAMロールを作成します。
以上で設定完了です。
AWS環境へアクセス
AWS環境へアクセスします。
CLIでアクセス
OAuth 2.0のDevice Authorization FlowにそってIDトークンを取得し、取得したIDトークンを使用してAWSの認証情報を取得します。
コマンドを順に実行していきます。
- 変数を定義
DOMAIN={ドメイン名}
CLIENTID={クライアントID}
SCOPE=openid
AUDIENCE={Identifier}
verification_uri
を取得
curl --request POST \
--url "https://${DOMAIN}/oauth/device/code" \
--header "content-type: application/x-www-form-urlencoded" \
--data "client_id=${CLIENTID}" \
--data "scope=${SCOPE}" \
--data "audience=${AUDIENCE}"
{
"device_code": "QEZAmEcj4eFsElb6oh4WKSQp",
"user_code": "LBJX-WZVT",
"verification_uri": "https://dev-xyfgnyiti57ob5ja-oidc.us.auth0.com/activate",
"expires_in": 900,
"interval": 5,
"verification_uri_complete": "https://dev-xyfgnyiti57ob5ja-oidc.us.auth0.com/activate?user_code=LBJX-WZVT"
}
IDトークンを取得する際にはscpde
にopenid
を指定する必要があります。
verification_uri_complete
にブラウザでアクセス
- トークンを取得
DEVICECODE={verification_uriを取得した際のdevice_code}
curl --request POST \
--url "https://${DOMAIN}/oauth/token" \
--header "content-type: application/x-www-form-urlencoded" \
--data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
--data "device_code=${DEVICECODE}" \
--data "client_id=${CLIENTID}"
{
"access_token": "",
"id_token": "",
"scope": "openid",
"expires_in": 86400,
"token_type": "Bearer"
}
- assume-role-with-web-identityを実行
IDTOKEN=...
aws sts assume-role-with-web-identity \
--role-arn {IAMロールのARN} \
--role-session-name session001 \
--web-identity-token ${IDTOKEN}
{
"Credentials": {
"AccessKeyId": "",
"SecretAccessKey": "",
"SessionToken": "",
"Expiration": ""
},
"SubjectFromWebIdentityToken": "",
"AssumedRoleUser": {
"AssumedRoleId": "",
"Arn": ""
},
"Provider": "",
"Audience": ""
}
aws sts assume-role-with-web-identityリクエストを実行する際にAWSの認証情報は不要です。
AWS CLIで使用するCredentialsの取得ができました。
CLIを実用的に使えるようにする
取得したCredentials情報を~/.aws/config
に手作業でコピーしても良いですが、Credentialsは1時間で期限切れになるため面倒です。 外部スクリプトの結果を使用する仕組みとして用意されているcredential_process
を使用する ことで実用的に使えるようにします。
IAM Roles Anywhereでもcredential_process
の仕組みが使われています
外部スクリプトの結果として、以下のJSONフォーマットを返却することで、認証情報として利用ができます。
{
"Version": 1,
"AccessKeyId": "an AWS access key",
"SecretAccessKey": "your AWS secret access key",
"SessionToken": "the AWS session token for temporary credentials",
"Expiration": "ISO8601 timestamp when the credentials expire"
}
CLIを実用的に使えるようにする手順
まずは/oauth/token
APIのレスポンスをtoken.json
として保存します。
(一度使用したデバイスコードは再利用できないので、手順としてはもう一度/oauth/device/code
APIから実行してください)
curl --request POST \
--url "https://${DOMAIN}/oauth/token" \
--header "content-type: application/x-www-form-urlencoded" \
--data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
--data "device_code=${DEVICECODE}" \
--data "client_id=${CLIENTID}" > token.json
{
"access_token": "",
"id_token": "",
"scope": "openid",
"expires_in": 86400,
"token_type": "Bearer"
}
ファイルにIDトークンを保存しておくことで、任意のタイミングでAWSのCredentialsが取得できます。
aws sts assume-role-with-web-identity \
--role-arn {IAMロールのARN} \
--role-session-name session001 \
--web-identity-token `cat token.json | jq -r .id_token` > aws_credential.json
{
"Credentials": {
"AccessKeyId": "",
"SecretAccessKey": "",
"SessionToken": "",
"Expiration": ""
},
"SubjectFromWebIdentityToken": "",
"AssumedRoleUser": {
"AssumedRoleId": "",
"Arn": ""
},
"Provider": "",
"Audience": ""
}
ここまでできたらあとは~/.aws/config
にcredential_process
を追加します。
[default]
credential_process = jq '{"Version":1, "AccessKeyId":.Credentials.AccessKeyId, "SecretAccessKey":.Credentials.SecretAccessKey, "SessionToken":.Credentials.SessionToken, "Expiration":.Credentials.Expiration}' /home/ec2-user/aws_credential.json
aws_credential.json
のパスは絶対パスで指定する必要があります。
これでAWSのCredentialsが使用でき、かつ、有効期限が切れた際にはIDトークン
を使用してaws_credential.json
を取得するコマンドを実行するだけで、Credentialsの更新が可能です。
マネジメントコンソールでアクセス
CLIで使用するCredentialsをもとにマネジメントコンソールへのアクセスURLを生成できます。
SESSION
としてURLエンコードした文字列を生成します。
SESSION=`jq '{"sessionId":.Credentials.AccessKeyId, "sessionKey":.Credentials.SecretAccessKey, "sessionToken":.Credentials.SessionToken, }' /home/ec2-user/aws_credential.json | jq -r @uri`
federation
APIを実行し、SigninTokenを取得。
curl "https://signin.aws.amazon.com/federation?Action=getSigninToken&SessionDuration=3600&Session=${SESSION}"
{
"SigninToken": ""
}
SigninToken
をセットし、ブラウザで以下のURLにアクセスするとマネジメントコンソールにアクセスできます。
https://ap-northeast-1.signin.aws.amazon.com/federation?Action=login&Destination=https%3A%2F%2Fconsole.aws.amazon.com%2F&SigninToken={SigninToken}