AWS CLIをAWS IAM Identity Center(SSO)で認証させるには?

2023.01.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS OrganizationsのAWS IAM Identity Center(旧AWS Single Sign-On;AWS SSO)を利用すると、Organizations配下のAWSアカウントにSSOできます。

本記事では、同機能をAWS CLIから利用する方法を紹介します。

AWS IAM Identity Centerの詳細は次のブログを参照ください。

なお、本記事ではAWS Identity Center directoryでユーザー管理しているものとします。

ポイント

  • IAM Identity CenterにはAWS CLI v2が対応。v1は未対応
  • 設定ファイルはAWS CLIだけでなくAWS SDK全般で流用可能
  • IAM Identity Centerはリージョナル・サービス
  • IAM ユーザーのように永続的なアクセスキーは存在せず一時的な認証情報を利用
  • 各アカウントへの操作はスイッチロールベース
  • 一時認証情報は2段構成
    1. IAM Identity Centerの認証に対する一時認証情報(aws sso-oidc create-token)
    2. この一時認証情報を利用して取得する、各アカウントへのスイッチロール用一時認証情報(aws sso get-role-credentials)
  • セッション時間(デフォルト8時間)はIAM Identity Centerで管理。その間は各アカウント向けの一時認証情報はリフレッシュされる

AWS CLIのSSO向け設定

1. [必須]AWS CLI v2のインストール

AWS CLIはv2しかIAM Identity Centerに対応していません。

クライアント環境でバージョンチェックし、"aws-cli/2.*" と2以降であることを確認してください。

$ aws --version
aws-cli/2.7.24 Python/3.8.8 Linux/4.14.133-113.105.amzn2.x86_64 botocore/1.13

バージョンが1系(aws-cli/1.*)だった場合、次のドキュメントに従って CLI v2をインストールして下さい。

https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html

IAM Identity Centerに対応していないAWS CLI v1の出力例です。

$ aws --version
aws-cli/1.27.52 Python/3.10.8 Darwin/21.3.0 botocore/1.29.52

$ aws sso
Note: AWS CLI version 2, the latest major version of the AWS CLI, is now stable and recommended for general use. For more information, see the AWS CLI version 2 installation instructions at: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help
aws: error: the following arguments are required: operation

また、本記事では、AWS CLIがセッション機能に対応した v2.9 以降を対象とします。

2系であっても、古いバージョンをお使いの場合は、より新しいバージョンに更新してください。

2. ウィザード形式で設定ファイルを生成

本記事では、Identity Center directoryでユーザー管理しているものとします。

$ aws configure sso を実行し、ウィザードに従って

  • セッション名(Identity Centerを識別するため)
  • スタートURL
  • リージョン

などを指定してください。

なお、IAM Identity Centerは特定のIdPに依存しません。 外部IdPを利用している場合は、適宜読み替えてください。

~$ aws configure sso
SSO session name (Recommended): my-sso
SSO start URL [None]: https://d-1234.awsapps.com/start
SSO region [None]: us-east-1
SSO registration scopes [sso:account:access]:
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.us-east-1.amazonaws.com/   ← 認証用URL

Then enter the code:

ABCD-EFGH ← 認証コード

初期入力が終わると、クライアント環境でブラウザがIdentity Center認証用URL認証コードとともに開くので、ユーザー名・パスワード等を入力します。

IAM Identity Centerとの認証が成功すると、操作先AWSアカウントを選択します。

~$ aws configure sso
SSO session name (Recommended): my-sso
SSO start URL [None]: https://d-1234.awsapps.com/start
SSO region [None]: us-east-1
SSO registration scopes [sso:account:access]:
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.us-east-1.amazonaws.com/

Then enter the code:

ABCD-EFGH
There are 2 AWS accounts available to you.
  foo, web@example.com (11111111)
> bar, main@example.com (22222222)

AWSアカウントとロールを選択すると、プロファイルが作成されます。

~$ aws configure sso
SSO session name (Recommended): my-sso
SSO start URL [None]: https://d-1234.awsapps.com/start
SSO region [None]: us-east-1
SSO registration scopes [sso:account:access]:
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.us-east-1.amazonaws.com/

Then enter the code:

ABCD-EFGH
There are 2 AWS accounts available to you.
Using the account ID 22222222
The only role available to you is: AdministratorAccess
Using the role name "AdministratorAccess"
CLI default client Region [ap-northeast-1]:
CLI default output format :
CLI profile name [AdministratorAccess-22222222]:

To use this profile, specify the profile name using --profile, as shown:

aws s3 ls --profile AdministratorAccess-22222222

メッセージに従い、プロファイルを指定してS3バケット一覧を表示してみましょう。

~$ aws s3 ls --profile AdministratorAccess-22222222
2022-11-28 21:14:50 your-bucket-name

sts::get-caller-identity を呼ぶと、このAWSアカウントのロールにスイッチしていることがわかります。

~$ aws sts get-caller-identity --profile AdministratorAccess-22222222
{
    "UserId": "AROXXXXXXXXX:test",
    "Account": "22222222",
    "Arn": "arn:aws:sts::22222222:assumed-role/AWSReservedSSO_AdministratorAccess_abcdef/test"
}

3. 生成された設定ファイルを確認

~/.aws/config に IAM Identity CenterとAWSアカウント用の設定が追記されます。

この設定ファイルは、AWS CLIだけでなく、公式のAWS SDK全般で共通です。

~/.aws/config

[default]
region = ap-northeast-1
output = json

; AWSアカウント向け設定
[profile AdministratorAccess-22222222]
sso_session = my-sso
sso_account_id = 22222222
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json

; IAM Identity Center向け設定
[sso-session my-sso]
sso_start_url = https://d-1234.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access

プロファイル「AdministratorAccess-22222222」の sso_session フィールドから、このAWSアカウントはセッション名 my_sso で指定した Identity Center配下とわかります。

操作対象のAWSアカウントを増やすには、profile セクションの設定をコピーします。

[default]
region = ap-northeast-1
output = json

[profile AdministratorAccess-22222222]
sso_session = my-sso
sso_account_id = 22222222
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json

[profile AdministratorAccess-11111111]
sso_session = my-sso
sso_account_id = 11111111
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json

; IAM Identity Center向け設定
[sso-session my-sso]
sso_start_url = https://d-1234.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access

追加した新しいAWSアカウントに対して操作すると、AWS CLIが一時認証情報を暗黙的に取得します。

$ aws s3 ls --profile 設定を追記したアカウントのプロファイル

[オプション]IAM Identity Centerのセッションの有効期間を変更

IAM Identity Centerと認証すると、一時アクセスキー(OIDC トークン)が発行され、このアクセスキーを利用して、各AWSアカウントにスイッチロールするための一時認証情報を取得します。

このトークンが有効な間は各AWSアカウント向け一時認証情報もリフレッシュされ、失効すると、IAM Identity Centerとの再認証が求められます。

$ aws s3 ls --profile YOUR-PROFILE

Error when retrieving token from sso: Token has expired and refresh failed

デフォルトではこのセッション期間は8時間で、AWSコンソールのIAM Identity Center→Settings→Sessionから変更可能です。

IAM Identity Centerでの認証からスイッチロールまでの流れを確認

IAM Identity Centerを利用すると、ユーザーに対して永続的なアクセスキーの発行は不要で、IAM Identity Centerと認証したあと、操作対象のAWSアカウント・ロールに対する一時認証情報が発行されます。

この流れを確認します。

$ aws configure sso のウィザードでAWSアカウント向けのプロファイルを作成すると、~/.aws ディレクトリのファイル階層は以下のとおりです。

.aws/
├── cli
│   └── cache
│       └── 123.json
├── config
└── sso
    └── cache
        ├── 456.json
        └── 789.json

一連のフローをSSOサービスに限ってCloudTrailログと突き合わせると、IAM Identity Center関連では以下の順でAPIが呼ばれています。

  1. SSO:Authenticate(Identity Centerとの認証)
  2. SSO-OIDC:CreateToken(AWSアカウント向け認証情報を発行するための一時アクセスキー発行)
  3. SSO:GetRoleCredentials(AssumeRoleする一時認証情報発行)

1. IAM Identity Centerとの認証

ウィザードの入力情報をもとに、IAM Identity Centerと認証します。

このステップにおいて、後続の(特に次に呼び出される)SSO-OIDC:CreateToken APIのリクエストパラメーターに必要な情報が返却されていると思われます。

具体的には

  • clientId
  • clientSecret
  • refreshToken

などです。

.aws/sso/cache ディレクトリには2種類のファイルがあります。 そのうち、accessToken含まない次の形式のファイルがこのステップの処理に相当すると思われます。

{
  "clientId": "your-client-id",
  "clientSecret": "xxx.yyyy.zzz-in-jwt-format",
  "expiresAt": "2023-04-28T08:39:08Z",
  "scopes": [
    "sso:account:access"
  ]
}

SSO:Authenticate はCloudTrailには出力されますが、ドキュメント化されていないAPIです。

2. AWSアカウント向け認証情報を発行するための一時アクセスキー発行

このAPIは、スイッチロールするための一時認証情報を要求するための一時アクセスキーを発行します。APIドキュメントには"Creates and returns an access token for the authorized client. The access token issued will be used to fetch short-term credentials for the assigned roles in the AWS account."とあります。

.aws/sso/cache ディレクトリには2種類のファイルがあります。 そのうち、accessToken含む次の形式のファイルがこのAPIのレスポンスに相当します。

{
  "startUrl": "https://d-123.awsapps.com/start",
  "region": "us-east-1",
  "accessToken": "your-access-token",
  "expiresAt": "2023-01-30T09:41:21Z",
  "clientId": "your-client-id",
  "clientSecret": "secret.in.jwt",
  "refreshToken": "your-refresh-token"
}

clientSecret は JWT で HS384(HMAC using SHA-384) で署名されています。

3. AssumeRoleする一時認証情報発行

aws sso get-role-credentials API を利用すると、操作対象のAWSアカウントのロールをassumeするための一時認証を取得できます。APIドキュメントには"Returns the STS short-term credentials for a given role name that is assigned to the user."とあります。

このAPIは従来の STS::AssumeRole API の IAM Identity Center 版とみなせます。

API呼び出し時には、操作対象のAWSアカウントID・ロールとともに、先程の SSO-OIDC:CreateToken API で取得したアクセストークン(accessToken)を渡します。

$ aws sso get-role-credentials \
  --account-id 111111111111 \
  --role-name AdministratorAccess \
  --access-token "your-access-token" \
  --region us-east-1

{
    "roleCredentials": {
        "accessKeyId": "your-access-key",
        "secretAccessKey": "your-secret-access-key",
        "sessionToken": "your-session-token",
        "expiration": 1674899972000
    }
}

返却されるroleCredentials は、AWSマネコンの "Command line or programmatic access" で取得する一時認証情報と同等です。

この認証情報を環境変数に設定して利用することもできます。

$ export AWS_ACCESS_KEY_ID=AS...
$ export AWS_SECRET_ACCESS_KEY=your-secret-access-key
$ export AWS_SESSION_TOKEN=your-session-token

$ aws sts get-caller-identity --profile AdministratorAccess-111111111111
{
    "UserId": "DUMMY:foo",
    "Account": "111111111111",
    "Arn": "arn:aws:sts::111111111111:assumed-role/AWSReservedSSO_AdministratorAccess_xxx/foo"
}

$ aws s3 ls
...

.aws/cli/cache ディレクトリには、このAPIのレスポンスがキャッシュ化されています。

~$ ls -1 ~/.aws/cli/cache
123.json

~$ cat ~/.aws/cli/cache/123.json | jq .
{
  "ProviderType": "sso",
  "Credentials": {
    "AccessKeyId": "aaa",
    "SecretAccessKey": "bbb",
    "SessionToken": "...",
    "Expiration": "2023-01-30T09:42:53Z"
  }
}

フォーマットが同じですね。

まとめ

AWS CLIはv2からIAM Identity Centerとシームレスに連携します。

IAM Identity Centerとの認証後にAWS CLI(SDK)用の一時認証情報が払い出され、従来のIAMユーザーに紐づくアクセスキーのような永続的な認証情報は存在しません。

一時認証情報は以下の2種類があります。

  1. AWSアカウントのIAMロールをassumeするための認証情報(SSO:GetRoleCredentials で取得)
  2. 上記認証情報を取得するために利用される、IAM Identity Centerが払い出す認証情報(SSO-OIDC:CreateToken で取得)

なお、IAM Identity Centerと同じく、一時認証情報でAWS APIを呼び出すサービスとして、証明書で一時認証情報を取得するIAM Roles Anywhereがあります。システマティックに一時認証情報を取得できるため、AWSとのシステム連携に最適です。

参考