AssumeRoleWithSAMLを利用してAPI用の一時クレデンシャルを取得する方法

2016.02.18

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

西澤です。ADFSサーバを利用したAWSマネージメントコンソールへのSSOについて以前に書きましたが、APIを利用する方法が整理できていないことが課題となっていました。SAMLを利用したAPI認証の方法については藤本さんが詳しく書いてくれています。

この方法は理解の為には良いのですが、そのまま運用で使うにはやや手順が複雑な印象を受けたので、これをもう少し簡単に利用する方法がないかとさらに情報を漁ってみたところ、公式ブログでツールとその利用手順が紹介されていました。今回はこちらを試してみたいと思います。

  1. How to Implement Federated API and CLI Access Using SAML 2.0 and AD FS - AWS Security Blog
  2. How to Set Up Federated API Access to AWS by Using Windows PowerShell - AWS Security Blog

AssumeRoleWithSAMLを利用した認証方式

こちらも公式ブログの図を拝借させていただきました。詳しくはSAMLを勉強しなければいけませんが、大きな流れとしては以下の通りです。

  1. ADFSがFederatedユーザを認証
  2. ADFSからSAML assertionを取得
  3. STSにAssumeRoleWithSAMLをリクエスト
  4. 一時クレデンシャルを取得
  5. 一時クレデンシャルを利用してAPIコール(AWSリソースにアクセス)

事前準備

AWSと連携済のADFSサーバと接続用のADアカウントは事前に準備しておきます。詳細な手順は以前の記事をご覧ください。これがなかなか骨が折れるところではあるのですが。

1. pythonスクリプトを利用したAssumeRoleWithSAML

まずは始めにご紹介した公式ブログ1で説明されているsamlapi.pyを利用した一時クレデンシャルの取得手順を試してみます。再現可能な手順をご紹介したかったので、今回は最新版のAmazon Linux環境で1からセットアップしてみました。

samlapi.py実行前の準備

まずは前提のパッケージをpipコマンドを利用してインストールしておきます。Amazon Linuxでなければ、Python SDK(boto)も必要です。

$ sudo pip install beautifulsoup4
You are using pip version 6.1.1, however version 8.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting beautifulsoup4
Downloading beautifulsoup4-4.4.1-py2-none-any.whl (81kB)
100% |################################| 81kB 4.7MB/s
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.4.1

$ sudo pip install requests-ntlm
You are using pip version 6.1.1, however version 8.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting requests-ntlm
Downloading requests_ntlm-0.2.0.tar.gz
Collecting requests>=2.0.0 (from requests-ntlm)
Downloading requests-2.9.1-py2.py3-none-any.whl (501kB)
100% |################################| 503kB 1.0MB/s
Collecting python-ntlm3 (from requests-ntlm)
Downloading python_ntlm3-1.0.2-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): six in /usr/lib/python2.7/dist-packages (from python-ntlm3->requests-ntlm)
Installing collected packages: requests, python-ntlm3, requests-ntlm
Found existing installation: requests 1.2.3
Uninstalling requests-1.2.3:
Successfully uninstalled requests-1.2.3
Running setup.py install for requests-ntlm
Successfully installed python-ntlm3-1.0.2 requests-2.9.1 requests-ntlm-0.2.0

公式ブログにも記載がありますが、事前にcredentialsファイルを作成する必要がありました。今回はリージョンはOregon(us-west-2)を指定しました。アクセスキーやシークレットアクセスキーは空の状態で問題ありません。

$ cat ~/.aws/credentials
[default]
output = json
region = us-west-2
aws_access_key_id =
aws_secret_access_key =

続けて、用意されているsamlapi.pyをダウンロードして実行権限を付与します。

$ curl -s -O https://s3.amazonaws.com/awsiammedia/public/sample/SAMLAPICLIADFS/samlapi.py
$ chmod u+x samlapi.py

これをそのまま実行できれば一番良いのですが、接続先の修正や警告を回避する為、少しだけ手を加えました。

$ diff samlapi.py samlapi.py.org
36c36
< idpentryurl = 'https://xxx.xxx.xxx.xxx/adfs/ls/IdpInitiatedSignOn.aspx?loginToRp=urn:amazon:webservices' --- > idpentryurl = 'https:///adfs/ls/IdpInitiatedSignOn.aspx?loginToRp=urn:amazon:webservices'
54,55c54
< requests.packages.urllib3.disable_warnings()
< response = session.get(idpentryurl, verify=False) --- > response = session.get(idpentryurl, verify=sslverification)
67c66
< soup = BeautifulSoup(response.text.decode('utf8'), 'html.parser') --- > soup = BeautifulSoup(response.text.decode('utf8'))
  • idpentryurlをADFSサーバのFQDNまたはIPアドレスに変更する必要があります
  • 自己署名証明書を利用したADFSサーバ環境だった為、警告を抑止しつつ証明書のVerifyをしないように変更しました
  • BeautifulSoupでparser指定が無いとの警告が出たので明示的に指定するようにしました

(2016/03/08追記) 下記の変更も追加しました。

:::
reload(sys) ###UnicodeEncodeError対応として追加
sys.setdefaultencoding('utf-8') ###UnicodeEncodeError対応として追加
soup = BeautifulSoup(response.text.decode('utf8'), 'html.parser')
:::
:::
headers = {'User-Agent': 'Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'} ###ADFS3.0のUserAgent判定対応として追加
response = session.get(idpentryurl, verify=False, headers=headers) ###ADFS3.0のUserAgent判定対応として変更
:::

samlapi.pyの実行

これで利用できる環境が整いましたので実行してみます。遷移できるIAMロールが表示されますので、先頭の数字を1つ選んで入力します。

$ ./samlapi.py
Username: adfs\testuser
Password:

Please choose the role you would like to assume:
[ 0 ]: arn:aws:iam::123456789012:role/ADFS-Develop
[ 1 ]: arn:aws:iam::123456789012:role/ADFS-Production
Selection: 1

----------------------------------------------------------------
Your new access key pair has been stored in the AWS configuration file /home/ec2-user/.aws/credentials under the saml profile.
Note that it will expire at 2016-02-17T12:58:27Z.
After this time you may safely rerun this script to refresh your access key pair.
To use this credential call the AWS CLI with the --profile option (e.g. aws --profile saml ec2 describe-instances).
----------------------------------------------------------------

Simple API example listing all s3 buckets:
[, , AWS Tools for Windows PowerShell 3.1.31.0
> Release Date: 2015-12-01
> Summary of Changes
> Added information to the Getting Started section about new cmdlets that use Security Assertion Markup Language (SAML) to support configuring federated identity for users.

PS C:> Get-Module -Name AWSPowerShell | Format-List Name : AWSPowerShell Path : C:\Program Files (x86)\AWS Tools\PowerShell\AWSPowerShell\AWSPowerShell.dll Description : The AWS Tools for Windows PowerShell lets developers and administrators manage their AWS services from the Windows PowerShell scripting environment. ModuleType : Binary Version : 3.1.44.0 NestedModules : {} ExportedFunctions : ExportedCmdlets : {Add-ASAAttachmentsToSet, Add-ASACommunicationToCase, Add-ASInstances, Add-ASLoadBalancer...} ExportedVariables : ExportedAliases :

<br />### Set-AWSSamlRoleProfileの実行

こちらでもADFSサーバの自己署名証明書によりエラーが発生しましたので、それを無視する手順を加えることで回避しました。

PS C:> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

<br />以降は、公式ブログに記載の通りです。ADFSサーバと同じドメインに所属しているアカウントを利用すればもう少し簡単ですが、下記手順ではドメインに参加していない状態で手動でアカウント情報を入力します。

PS C:> $endpoint = "https://xxx.xxx.xxx.xxx/adfs/ls/IdpInitiatedSignOn.aspx?loginToRp=urn:amazon:webservices" PS C:> $epName = Set-AWSSamlEndpoint -Endpoint $endpoint -StoreAs ADFS-Demo -AuthenticationType NTLM PS C:> $credential = Get-Credential -Message "Enter the domain credentials for the endpoint"

<br />ここで認証情報の入力を要求されます。

<a href="https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2016/02/saml_credentials.png"><img class="alignnone size-full wp-image-183042" src="https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2016/02/saml_credentials.png" alt="saml_credentials" width="385" height="301" /></a>

入力した認証情報を利用して、Set-AWSSamlRoleProfileを実行すると、こちらでも遷移可能なIAMロールを選ぶことができました。

PS C:> Set-AWSSamlRoleProfile -EndpointName $epName -NetworkCredential $credential -StoreAs SAMLDemoProfile

Select Role Select the role to be assumed when this profile is active [A] A - 123456789012:role/ADFS-Develop [B] B - 123456789012:role/ADFS-Production [?] ヘルプ (既定値は "A"): B SAMLDemoProfile

<br />``SAMLDemoProfile``というプロファイル名で認証情報が保存されました。これでPowershellでも一時クレデンシャルの期限切れまでこの認証情報を利用できます。

PS C:> Set-AWSCredentials -ProfileName SAMLDemoProfile PS C:> Get-AWSCredentials CustomCallbackState : Amazon.PowerShell.Common.SAMLCredentialCallbackState RequestUserCredentialCallback : Amazon.SecurityToken.SAML.StoredProfileSAMLCredentials+RequestUserCredential ProfileName : SAMLDemoProfile ProfilesLocation : ProfileData : Amazon.Util.SAMLRoleProfile ```

まとめ

今回は2種類のAssumeRoleWithSAML利用方法をご紹介しました。このような便利なツールがあれば、SAML経由でのAPI利用も問題なしです。AD環境を構築するひと手間は変わりませんが、一度用意さえしてしまえば、ほぼ全ての権限管理をADアカウントに集約できそうですね。ぜひ活用してみてください。