TDD は一休みして、たまたま PowerShell を触る機会があったので、忘れないように記述しておこうと思います。
今回のお題は、Json に格納された Key/Value の値を、Azure の KeyVault にぶち込むための、PowerShell です。私は次のような PowerShell を書きました。
KeyVault に key/value のセットをぶち込む PowerShell
データのファイルはこんな感じです。
secret.json
{
"ApplicationId": "SOME APPLICATION ID",
"ApplicationKey": "SOME APPLICATION KEY",
"SubscriptionId": "SOME SUBSCRIPTION ID",
"ActiveDirectoryTenantId": "ACTIVE DIRECTORY TENANT ID",
:
}
こういうシークレットをまとめて KeyVault にぶち込むコードです。
<#
.SYNOPSIS
Import JSON file into Azure KeyVault
.DESCRIPTION
Create `secrets.json` on the current directory then execute this.
You need to modify the $keyVaultName to fit your KeyVault
I encode "" into [empty]. '' is not allowed for KeyVault Secret.
I decode it on the KeyVaultHelper.cs
.NOTE
File Name : ImportSecret.ps1
Author : Tsuyoshi Ushio
Prerequisite: Azure PowerShell
# >
$keyVaultName = "XXXXKey"
Login-AzureRmAccount
$secretJson = Get-Content .\secrets.json -Encoding UTF8 -Raw
$secrets = (New-Object System.Web.Script.Serialization.JavaScriptSerializer).Deserialize($secretJson, [System.Collections.HashTable])
$secrets.GetEnumerator() | ForEach-Object {
Write-Host "$($_.Key) : $($_.Value)"
IF ($_.Value -eq '') {
$_.Value = "[empty]"
}
$secretValue = ConvertTo-SecureString -String $_.Value -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $keyVaultName -Name $_.Key -SecretValue $secretValue
}
初めから解説していきます。
Login
最初にログインして、サブスクリプションを取得します。サブスクリプションが複数ある人はこれではうまくいなかないかもしれません。また、ブラウザが起動するので、完全に自動化したい人には向いていません。
Login-AzureRmAccount
ちなみに、自動化したい場合は次の感じで実施すれば OK. ログインした状態で、コンテキストを保存すればいいです。
$pwd = Get-Location
$azurejson = $pwd.Path + "\azure.json"
Save-AzureRmContext -Path $azurejson -Force
実際にログインするときは
$pwd = Get-Location
$azurejson = $pwd.Path + "\azure.json"
Import-AzureRmContext -Path
的な感じでいいです。昔は、コンテキストを保存するのが、Save-AzureRmProfile
だったのが、なくなったみたいではまりました。補完ででてくるのが、またハマりを長引かせましたw
Save-AzureRmProfile
Save-AzureRmProfile : The term 'Save-AzureRmProfile' is not recognized as the name of a cmd
let, function, script file, or operable program. Check the spelling of the name, or if a pa
th was included, verify that the path is correct and try again.
JSON の渋い読み込み
$secretJson = Get-Content .\secrets.json -Encoding UTF8 -Raw
$secrets = (New-Object System.Web.Script.Serialization.JavaScriptSerializer).Deserialize($secretJson, [System.Collections.HashTable])
ちなみに、JSON の読み込みをインターネットで検索すると、Convert-FromJSON とかいうコマンドレットがありますが、あえて使いません。というのも、普通に、JSONをパースすると、$secrets.ApplicationId
みたいな形でアクセスする必要があるようになるので、ループで処理するのができないからです。だからここは、読み込んで、HashTable に変換する方法を用いています。カッコいい!
ループと空文字
後はHash にしたものを、ForEach-Object でループしています。KeyVault に値をセットするには、ConvertTo-SecureString で型変換する必要があります。あとは、Set-AzureKeyVaultSecret
をたたけば終わりで簡単です。一点だけポイントは、"" 空文字が、KeyVault の Secret には受け入れられないので、空文字が来たら[empty]
にして格納して、アプリのライブラリで対応するようにしました。
$secrets.GetEnumerator() | ForEach-Object {
Write-Host "$($_.Key) : $($_.Value)"
IF ($_.Value -eq '') {
$_.Value = "[empty]"
}
$secretValue = ConvertTo-SecureString -String $_.Value -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $keyVaultName -Name $_.Key -SecretValue $secretValue
}
実行するとしっかり格納されている(過去に同じ名前のものがあれば、更新される)ちなみに、見たとおり、Azure Key Vault の Secret は、過去のバージョンをみんな格納しています。いい感じですね。何も指定しなければカレントバージョンを取得します。
おわりに
まだまだ、PowerShell は練度が足りませんがちょっとづつがんばります。