Skip to content

Instantly share code, notes, and snippets.

@ktsugita
Last active November 11, 2018 01:59
Show Gist options
  • Save ktsugita/acbc2f92210ea2e06d2f2cf4fbf32d39 to your computer and use it in GitHub Desktop.
Save ktsugita/acbc2f92210ea2e06d2f2cf4fbf32d39 to your computer and use it in GitHub Desktop.
AWS Powershell で MFA入力を減らしてみる

AWS PowerShell 使ってますか?

awscliはMFA対応がちゃんとしていて、一度MFA入力したらしばらく大丈夫ですが、AWSPowerShellだと入力の都度求められて嫌になりますよね。

PowerShellでもスクリプトスコープの変数にSessionTokenを突っ込めばイケそうなきがしたので実装してみました。

インストール方法

モジュール内部からAWSPowerShellを使うのでインストールしておいてください。 msi版でもよいですが、PowerShell v5.x(Windows10)ならinstall-module awspowershellでもインストールできます。

スクリプトモジュールとして実装したので、 STSHelper.psm1 をダウンロードして、BOM付きUTF-8で保存して、下記の要領でインストールしてください。

$destdir = Join-Path $env:PSModulePath.split(';')[0] "STSHelper"
if (Test-Path $destdir) {} else { mkdir $destdir }
copy-item STSHelper.psm1 $destdir

使用方法

準備

認証情報をプロファイルに保存します

  • <ソースプロファイル> IAMアカウントのアクセスキーを指定したプロファイル

     Set-AWSCredential -StoreAs <ソースプロファイル> -AccessKey <アクセスキー> -SecretKey <シークレットキー>
  • <ターゲットプロファイル> AssumeRole先を指定したプロファイル

     Set-AWSCredential -StoreAs <ターゲットプロファイル> -SourceProfile <ソースプロファイル> -RoleArn <ロールのARN> -MfaSerial <MFAのARN>

毎回起動時に設定するのは大変なので下記のprofile.ps1に書いておくのがおすすめ

$env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

profile.ps1について詳しく知りたい場合は PowerShell で Profile を利用して スクリプトの自動読み込みをしてみよう が詳しいです。

利用

import-module STSHelper
New-STSCredential <ターゲットプロファイル> <ソースプロファイル>
iex (Update-STSCredential)

以降はiex ... だけで更新されます。

iex (Update-STSCredential)

プロセス起動毎に初回利用時または期限切れのときはMFA入力が求められます。 それ以外は新たなMFA入力無しで1時間延長です。 メモリ(スクリプトスコープの変数)に保存しているのでランタイム毎に必要です。 スクリプト内でプロファイル保存しても呼び出し元に反映されないのでiexしてます。

期限の確認

Get-STSCredential

課題

ファイルに保存すればランタイムをまたげると思うのですが、生で保存したくないので実装していません。

awscliみたいに無効時に必要に応じて自動的に呼び出せるようにしたいかな。

#Requires -Modules AWSPowerShell
$script:STSProfileName = 'STS'
$script:ProfileName = $null
$script:TargetName = $null
$script:TargetRole = $null
$script:Role = $null
Function New-STSCredenital {
<#
.SYNOPSIS
New-STSCredential [特権プロファイル [通常プロファイル名 [一時プロファイル名]]]
.DESCRIPTION
STSを使って特権プロファイルにAssumeRoleするためのプロファイルを指定する
.EXAMPLE
New-STSCredential NegitAdmin Negit
.PARAMETER TargetProfile
取得したい特権を指定したプロファイル
.PARAMETER SourceProfile
取得したい特権にAssumeRoleするための通常プロファイル
.PARAMETER STSProfile
取得したSTS認証情報を保存するプロファイル(デフォルトはSTS)
#>
param (
[parameter(mandatory = $true)][string]$TargetProfile,
[parameter(mandatory = $true)][string]$SourceProfile,
[string]$STSProfile = $null
)
$script:TargetName = $TargetProfile
$script:TargetRole = Get-AWSCredential -ProfileName $script:TargetName
$script:ProfileName = $SourceProfile
$script:Role = $null
if ( $STSProfile ) { $script:STSProfileName = $STSProfile }
Write-Host ("SourceProfile:{0}" -f $script:ProfileName)
Write-Host ("TargetProfile:{0}" -f $script:TargetName)
Write-Host 'iex (Update-STSCredential) を実行してください'
}
Export-ModuleMember -Function New-STSCredenital
Function Update-STSCredential {
<#
.SYNOPSIS
Update-STSCredential [MFAコード] [必要な残り時間]
.DESCRIPTION
STSを使って特権プロファイルにAssumeRoleする
SessionTokenの残り時間があるときはMFA入力しないで更新する
それ以外はMFAコードの入力を求められる
.EXAMPLE
iex (Update-STSCredential)
.PARAMETER Force
現在のSessionTokenを破棄して新たに取得する
MFAコードの入力を求められる
#>
param ([switch]$Force)
if ( ! $script:TargetName ) { Write-Error "New-STSCredential を実行してください"; return 'Write-Error "New-STSCredential を実行してください"' }
if ( ! $script:TargetRole ) { $script:TargetRole = Get-AWSCredential -ProfileName $script:TargetName }
if ( ! $script:ProfileName ) { Write-Error "New-STSCredential を実行してください"; return 'Write-Error "New-STSCredential を実行してください"' }
if ($Force) { $script:Role = $null }
if ( $script:Role -and ((Get-Date) -lt ($script:Role.Credentials.Expiration))) {
$script:Role = Use-STSRole -RoleArn $script:TargetRole.RoleArn -RoleSessionName $script:TargetRole.RoleSessionName -ProfileName $script:STSProfileName
} else {
$script:Role = Use-STSRole -RoleArn $script:TargetRole.RoleArn -RoleSessionName $script:TargetRole.RoleSessionName -ProfileName $script:ProfileName -SerialNumber $script:TargetRole.Options.MfaSerialNumber -TokenCode (Read-Host -Prompt 'MFA Code')
}
if ( $script:Role ) {
Set-AWSCredential -StoreAs $script:STSProfileName -AccessKey $script:Role.Credentials.AccessKeyId -SecretKey $script:Role.Credentials.SecretAccessKey -SessionToken $script:Role.Credentials.SessionToken
return ("Set-AWSCredential -ProfileName {0}" -f $script:STSProfileName)
}
}
Export-ModuleMember -Function Update-STSCredential
Function Get-STSCredential {
<#
.SYNOPSIS
Get-STSCredential
.DESCRIPTION
SessionTokenを格納するプロファイル、AssumeRoleするためのプロファイル、SessionTokenの残り時間を得る
.EXAMPLE
Get-STSCredential
#>
[PSCustomObject]@{
STSProfileName = $script:STSProfileName
SourceProfile = $script:ProfileName
TargetProfile = $script:TargetName
Expiration = $script:Role.Credentials.Expiration
}
}
Export-ModuleMember -Function Get-STSCredential
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment