メインコンテンツまでスキップ

外部IdPを使用してAWSにアクセスする(OpenID Connect編)

· 約8分
moritalous

AWSへアクセスする際は使用するIAMでは、ユーザー管理機能が提供されていますが、外部のIDプロバイダー(IdP)で管理されているユーザーにAWSへのアクセス許可を与えることが可能です。

ID プロバイダーとフェデレーション - AWS Identity and Access Management
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers.html

IAMがサポートする外部IdPは以下の2つです。

  • SAML 2.0 (Security Assertion Markup Language 2.0)
  • OpenID Connect (OIDC)

外部IdPとしてAuth0を使用し、OpenID Connectでの連携を行う方法を紹介します。

設定手順

  1. Auth0にユーザー追加
  2. Auth0にアプリケーションを作成
  3. Identifierを取得
  4. IAMの外部IDプロバイダーを登録
  5. IAMロールを作成

Auth0にユーザー追加

Auth0の管理画面を開き、Auth0にユーザーを追加します。

image.png

Auth0にアプリケーションを作成

Applicationの管理画面へ移動します。Create Applicationボタンをクリックします。

image.png

任意のNameを入力し、アプリケーションのタイプとしてNativeを選択し、Createボタンをクリックします。

image.png

SettingsタブのDomainClient IDをメモします。

image.png

Settingsタブの最下部にAdvanced Settingsセクションがあります。初期状態では折りたたまれてます。

image.png

Advanced Settingsセクションを開き、Grant Typesタブを選択します。Device Codeにチェックを入れ、Save Changesボタンをクリックします。

image.png

Identifierを取得

APIsメニューを選択し、Auth0 Management APIを選択します。

image.png

General SettingsセクションのIdentifierをコピーします。

image.png

IAMの外部IDプロバイダーを登録

ここからはAWSのマネジメントコンソールで操作します。 IAMの管理画面のIDプロバイダメニューに移動し、プロバイダを追加ボタンをクリックします。

image.png

プロバイダのタイプとしてOpenID Connectを選択し、プロバイダのURLに前の手順でメモしたDomainを入力します。

末尾に/を含めるように入力する必要があります ので注意してください。

入力したらサムプリントを取得ボタンをクリックします。

image.png

対象者に前の手順でメモしたClient IDを入力し、プロバイダを追加ボタンをクリックします。

image.png

IAMロールを作成

登録後のプロバイダの詳細画面を表示します。 ロールの割り当てボタンをクリックし、新しいロールを作成を選択して次へボタンをクリックします。 IAMロール作成画面に遷移します。

image.png

エンティティの種類やIDプロバイダーは自動で入力されます。Audienceを選択し、次のステップボタンをクリックします。

image.png

このさきは通常のIAMロール作成と変わりません。割り当てるポリシーを選択し、名前をつけてIAMロールを作成します。

image.png

image.png

以上で設定完了です。

AWS環境へアクセス

AWS環境へアクセスします。

CLIでアクセス

OAuth 2.0のDevice Authorization FlowにそってIDトークンを取得し、取得したIDトークンを使用してAWSの認証情報を取得します。

コマンドを順に実行していきます。

  • 変数を定義
shell
DOMAIN={ドメイン名}
CLIENTID={クライアントID}
SCOPE=openid
AUDIENCE={Identifier}
  • verification_uriを取得
shell
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トークンを取得する際にはscpdeopenidを指定する必要があります。

  • verification_uri_completeにブラウザでアクセス

image.png

image.png

image.png

image.png

  • トークンを取得
shell
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を実行
shell
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を使用する ことで実用的に使えるようにします。

外部プロセスを使用した認証情報の調達 - AWS Command Line Interface
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-sourcing-external.html
注記

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/tokenAPIのレスポンスをtoken.jsonとして保存します。 (一度使用したデバイスコードは再利用できないので、手順としてはもう一度/oauth/device/codeAPIから実行してください)

shell
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
token.json
{
"access_token": "",
"id_token": "",
"scope": "openid",
"expires_in": 86400,
"token_type": "Bearer"
}

ファイルにIDトークンを保存しておくことで、任意のタイミングでAWSのCredentialsが取得できます。

shell
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
aws_credential.json
{
"Credentials": {
"AccessKeyId": "",
"SecretAccessKey": "",
"SessionToken": "",
"Expiration": ""
},
"SubjectFromWebIdentityToken": "",
"AssumedRoleUser": {
"AssumedRoleId": "",
"Arn": ""
},
"Provider": "",
"Audience": ""
}

ここまでできたらあとは~/.aws/configcredential_processを追加します。

~/.aws/config
[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を生成できます。

カスタム ID ブローカーに対する AWS コンソールへのアクセスの許可 - AWS Identity and Access Management
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html

SESSIONとしてURLエンコードした文字列を生成します。

SESSION=`jq '{"sessionId":.Credentials.AccessKeyId, "sessionKey":.Credentials.SecretAccessKey, "sessionToken":.Credentials.SessionToken, }' /home/ec2-user/aws_credential.json | jq -r @uri`

federationAPIを実行し、SigninTokenを取得。

shell
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}

image.png