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


AWSのマネージメントコンソールへはADFSサーバを利用してSSOができています。この状況で、新たにIAMユーザを作成してAPI用のクレデンシャルを提供するのはいけてない気がしていて、調べました。

できそうです。AssumeRoleWithSAMLを利用すると良さそうです。

以下のサイトを参考に実際に設定を行ってみました。

[How to Implement Federated API and CLI Access Using SAML2.0 and ADFS - AWS Security Blog](https://blogs.aws.amazon.com/security/post/Tx1LDN0UBGJJ26Q/How-to-Implement-Federated-API-and-CLI-Access-Using-SAML-2-0-and-AD-FS)
[How to Set Up Federated API Access to AWS by Using Windows PowerShell - AWS Security Blog](https://blogs.aws.amazon.com/security/post/Tx2EIWSEN95QD0B/How-to-Set-Up-Federated-API-Access-to-AWS-by-Using-Windows-PowerShell)

今回は、主にこちらを参考にさせていただきました。
いつもありがとうClassMethodさん！
[AssumeRoleWithSAMLを利用してAPI用の一時クレデンシャルを取得する方法](http://dev.classmethod.jp/cloud/aws/assume-role-with-saml-for-api/)

# Mac編
## Pythonスクリプトを利用したAssumeRoleWithSAML
[How to Implement Federated API and CLI Access Using SAML2.0 and ADFS - AWS Security Blog](https://blogs.aws.amazon.com/security/post/Tx1LDN0UBGJJ26Q/How-to-Implement-Federated-API-and-CLI-Access-Using-SAML-2-0-and-AD-FS)で説明されている```samlapi.py```を利用して一時クレデンシャルを取得します。
### 準備
pyenv環境下のpython 2.7.11で検証しました。
pipはインストール済みとします。

```bash
# 何はともあれ、pipのアップデート
$ pyenv exec pip install --upgrade pip

# 必要なパッケージのインストール
$ pyenv exec pip install boto
$ pyenv exec pip install requests-ntlm
$ pyenv exec pip install beautifulsoup4
```
公式ブログにあるとおり、credentialsファイルを作成します。リージョンは、東京を指定して以下のように作成しました。

```~/.aws/credentials
[default]
output = json
region = ap-northeast-1
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
```

samplapi.pyの内容を環境に合わせて編集します。

```samlapi.py
##########################################################################
# Variables
 
# region: The default AWS region that this script will connect
# to for all API calls
region = 'ap-northeast-1' # リージョを設定

# output format: The AWS CLI output format that will be configured in the
# saml profile (affects subsequent CLI calls)
outputformat = 'json'

# awsconfigfile: The file where this script will store the temp
# credentials under the saml profile
awsconfigfile = '/.aws/credentials'

# SSL certificate verification: Whether or not strict certificate
# verification is done, False should only be used for dev/test
#sslverification = True
sslverification = False # 自己証明書を使用したADFSサーバのため、警告を抑止するため証明書のVerify処理を行わないように変更

# idpentryurl: The initial URL that starts the authentication process.
idpentryurl = 'https://<ADFS Server FQDN>/adfs/ls/IdpInitiatedSignon.aspx?loginToRp=urn:amazon:webservices' # ADFSサーバのアドレスを記載する
##########################################################################
```
本体54行目あたり

```samlapi.py
headers = {'User-Agent': 'Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gekko'}		# ADFS3.0のUserAgent判定として追加
session = session.get(idpentryurl, verify=sslverification, headers=headers)	# ADFS3.0のUserAgent判定として変更
```
さらに、本体66行目あたり

```samlapi.py
reload(sys)							# UnicodeEncodeError対応として追加
sys.setdefaultencoding('utf-8')		# UnicodeEncodeError対応として追加
soup = BeautifulSoup(response.text.decode('utf8'),'html.parser')
```
以上で、準備は完了です。

### samlapi.pyの実行
ログインが成功すると連携されているIAMロールの一覧が表示されるので使用したいアカウントを選択します。
Usernameには、Windowsドメインにログインしている時のユーザ名を入力します。ドメイン名\ユーザ名です。
パスワードには、ログイン時に使用するパスワードを入力します。

```bash
$ pyenv exec python samlapi.py
Username: webdev.local\m-okamura
Password:

Please choose the role you would like to assume:
　[ 0 ]:  arn:aws:iam::123456789012:role/adfs-a
　[ 1 ]:  arn:aws:iam::123456789012:role/adfs-b
　[ 2 ]:  arn:aws:iam::123456789012:role/adfs-c
　[ 3 ]:  arn:aws:iam::123456789012:role/adfs-d
　[ 4 ]:  arn:aws:iam::123456789012:role/adfs-e
Selection:  3  


----------------------------------------------------------------
Your new access key pair has been stored in the AWS configuration file /Users/m-okamura/.aws/credentials
under the saml profile.
Note that it will expire at 2016-03-16T09:53:13Z.
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:
[<Bucket: hoge-bucket>, <Bucket: fuga-bucket>, <Bucket: hoga-bucket>]

```
最後のs3バケットの一覧が取得できていると一時クレデンシャルで結果が取得できたとういことです。
また、~/.aws/credentialsの中に[saml]というプロファイル名で認証情報が保存されています。このプロファイルを使用してコマンドを実行できるようになります。

# Windows編
ここでの検証には、Windows10 Proで確認を行いました。他のバージョン・エディションでは、若干違いがあるかもしれません。

## AWS Tools for Windows PowerShellを利用したAssumeRoleWithSAML
### 準備
1. [AWS Tools for Windows PowerShell](https://aws.amazon.com/jp/powershell/)をダウンロードしてインストールする。
1. WindowsPowershell ISEを管理者権限で起動する。
1. 実行権限の変更を行えるように設定を変更
	
	```PowerShell
	PS > Set-ExecutionPolicy RemoteSigned
	```
1. ユーザ権限でPowerShellを起動する。
1. AWSPowerShellモジュールをインポートする。

	```PowerShell
	PS > Import-Module AWSPowerShell
	# 確認コマンドを実行
	PS > 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.52.1
	NestedModules     : {}
	ExportedFunctions : 
	ExportedCmdlets   : {Add-ASAAttachmentsToSet, Add-ASACommunicationToCase, Add-ASInstances, Add-	ASLoadBalancer...}
	ExportedVariables : 
	ExportedAliases   : 
	```
1. PowerShell側でもADFSサーバの自己証明書のエラーを無視するために以下の設定を追加。

	```PowerShell
	PS > [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
	```
	
これで準備完了です。

### Set-AWSSamlRoleProfileの実行
以下のコマンドを実行して、プロファイルを作成します。

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

```

認証情報を入力するダイアログが表示されるので、ドメインの認証情報を入力する。

```PowerShell
PS > Set-AWSSamlRoleProfile -Endpoint $epName -NetworkCredential $credential -StoreAs SAMLDemoProfile

Select Role
Select the role to be assumed wehn this profile is active
[A] A - 123456789012:/role/adfs-a [B] B - 123456789012:/role/adfs-b [?]ヘルプ(規定値は"A"):A
```

これで、SAMLDemoProfileというプロファイル名で認証情報が保存されました。PowerShellでも一時クレデンシャルで認証情報を利用できるようになりました。