1. はじめに
IBM Security Verifyは、IBMが提供しているIDaaS製品です。OktaやAzure ADと同様に、IDaaS製品として豊富な機能とAPIが用意されています。
IBM Security Verifyでは、CSVでユーザー情報一覧を一括登録するAPIはありますが、CSVで全ユーザーの属性情報一覧をダウンロードするAPIは提供されていません。(2023/5/20現在)
そこで、IBM Security Verifyの全ユーザー情報を取得し、CSVで出力するPowerShellスクリプトを紹介します。
2. 実装前に2つの注意点
IBM Security Verifyの既存APIである、ユーザーリスト取得APIを活用します。APIリファレンスはこちら
このAPIを使い、IBM Security Verifyのユーザー情報を全件取得するにあたり、以下2点の注意があります。
2.1. 全件取得するためのアルゴリズム
ユーザーリスト取得APIは1回の実行で取得できるユーザー件数が2500件までという制限があります。そのため、2500件以上のユーザー数を出力させるためには、API実行を繰り返す必要がありますが、そのアルゴリズムが特殊です。詳細はこちら
2.2. カスタム属性の取得
ISVのデフォルトの属性だけでなく、カスタム属性として追加した属性をCSVエクスポートに含めたいケースも多いと思います。カスタム属性は、ユーザー情報取得APIの返り値のjsonの中で、以下のようにデータが格納されています。
"customAttributes": [
{
"values": [
"カスタム属性の値1"
],
"name": "カスタム属性名1"
},
{
"values": [
"カスタム属性の値2"
],
"name": "カスタム属性名2"
},
{
"values": [
"カスタム属性の値3"
],
"name": "カスタム属性名3"
},
],
カスタム属性の値が入っていないユーザーは、jsonから該当のカスタム属性の項目ごと省略されます。そのため、全ユーザー分のカスタム属性を取得するために、少々アルゴリズムを工夫することがあります。
3. ISVユーザー情報をCSV出力するPowerShellスクリプト
上の注意点を考慮して作成したスクリプトが以下になります。
実行する際は、ISVテナント名、ISVクライアントID、ISVクライアントシークレットの3つの変数に値を設定してください。
また、customAttribute1,customAttribute2,customAttribute3の箇所に、ISVに設定したカスタム属性の名称をセットし、必要に応じてcustomAttributeの数を増減させてください。
※当記事は、スクリプトの動作を保証するものはありません。
#
# ※※CSVに出力されるユーザー情報※※
# 1. preferred_username:ログインID
# 2. family_name:姓
# 3. given_name:名
# 4. email:メールアドレス
# 5. カスタム属性1
# 6. カスタム属性2
# 7. カスタム属性3
# 8. activate:ユーザー状態(True:有効、False:無効)
# 9. id:ISV内部ID
# 10.created:ユーザー作成日時(ISVにユーザーが登録された日時)
# 11.lastLogin:最終ログイン日時(ISVに最後にログインした日時)
# 12.lastPwdChange:最終パスワード変更日時(ISVで最後にパスワード変更した日時)
#
# ISVテナント名
$tenant_id = "XXXXX.verify.ibm.com"
# ISVクライアントID
$client_id = "XXXXX"
# ISVクライアントシークレット
$client_secret = "XXXXX"
$block = "2022-01-01T00:00:00Z"
#################################################
# アクセストークン取得関数
function getAccessToken{
$headers=@{}
$headers.Add("accept", "application/json")
$headers.Add("content-type", "application/x-www-form-urlencoded")
$get_url = 'https://' + $tenant_id + '/oidc/endpoint/default/token'
$body = 'grant_type=client_credentials&client_id=' + $client_id + `
'&client_secret=' + $client_secret
try {
$response = Invoke-WebRequest -Uri $get_url -Method POST -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body $body
}catch{
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
exit
}
$response_json = ConvertFrom-Json $response
return $response_json.access_token
}
#################################################
# URLエンコーディング関数
function UrlEncode {
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$Text
)
$UrlEncodedText = [System.Web.HttpUtility]::UrlEncode($Text)
Write-Output $UrlEncodedText
}
# アクセストークン取得
$access_token = getAccessToken
$masterlist = @()
$flag = $true
while ($flag) {
# ユーザリスト取得APIのパラメータ
$headers=@{}
$headers.Add("accept", "application/scim+json")
$headers.Add("Authorization", "Bearer " + $access_token)
$encodedblock = UrlEncode -Text ('"'+$block+'"')
$get_url = 'https://' + $tenant_id + '/v2.0/Users?filter=meta.created%20ge%20' + $encodedblock + '&sortBy=meta.created&sortOrder=ascending&count=2000'
# ユーザリスト取得API実行
try {
$response = Invoke-WebRequest -Uri $get_url -Method GET -Headers $headers
}catch{
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
exit
}
# PowerShellのInvoke-WebRequestでISVデータを取得すると、日本語文字列が???になっていたのでUtf8エンコード
$response_utf8 = [System.Text.Encoding]::Utf8.GetString($response.RawContentStream.GetBuffer())
# その際、後ろにNUL(文字コード0000)が埋め込まれてjson変換できなかったので、NUL字を削除
$res = $response_utf8 -replace "\u0000",""
# json構造に変換
$output = ConvertFrom-Json $res
if ($output.totalResults -lt 2000) {
$output = $output.Resources
$masterlist += $output
Write-Output $masterlist.Length
$flag = $false
}
else {
$output = $output.Resources
# 配列の最後の2つのmeta.created が等しい場合は、最後の配列を削除
while ($output[-1].meta.created -eq $output[-2].meta.created) {
$output = $output[0..($output.Length - 2)]
}
# 末尾の配列のmeta.createdを変数に指定して削除
$block = $output[-1].meta.created
$output = $output[0..($output.Length - 2)]
Write-Output $block
$masterlist += $output
Write-Output $masterlist.Length
}
}
# ディレクトリパスを取得し、YYYYMMDD.csvファイルを生成
$scriptPath = $MyInvocation.MyCommand.Path
$scriptDirectory = Split-Path $scriptPath -Parent
$now = Get-Date
$strYM = $now.ToString("yyyyMMdd")
$csvPath = "$scriptDirectory\$strYM.csv"
# CSVファイルにヘッダ行を書き込む。
$header = "preferred_username,family_name,given_name,email,customAttribute1,customAttribute2,customAttribute3,activate,id,created,lastLogin,lastPwdChange"
$header | Out-File -FilePath $csvPath -Encoding UTF8 -Append
# ユーザー情報リストをCSVに出力
foreach ($i in $masterlist) {
# カスタム属性の初期値 (booleanカスタム属性の場合はfalseをセットする)
$customAttribute1 = ""
$customAttribute2 = ""
$customAttribute3 = ""
#(カスタム属性を追加する場合は、ここに追加)
# カスタム属性の属性名を一覧で取得しリスト化
$custom_names = $i."urn:ietf:params:scim:schemas:extension:ibm:2.0:User".customAttributes.name
$custom_names_list = $custom_names -split " "
# カスタム属性の値を一覧で取得しリスト化
$custom_values = $i."urn:ietf:params:scim:schemas:extension:ibm:2.0:User".customAttributes.values
$custom_values_list = $custom_values -split " "
# カスタム属性リストに属性名が存在する場合、それに対応する値をセットする
if ($custom_names_list.Count -gt 0) {
for ($k=0; $k -lt $custom_names_list.Count; $k++) {
switch($custom_names_list[$k]){
"customAttribute1" {$customAttribute1 = $custom_values_list[$k]; break}
"customAttribute2" {$customAttribute2 = $custom_values_list[$k]; break}
"customAttribute3" {$customAttribute3 = $custom_values_list[$k]; break}
#(カスタム属性を追加する場合は、ここに追加)
}
}
}
# CSVにユーザー情報を出力
$row = $i.userName + "," + $i.name.familyName + "," + $i.name.givenName + "," + $i.emails.value + "," + $customAttribute1 + "," + $customAttribute2 + "," + $customAttribute3 + "," + $i.active + "," + $i.id + "," + $i.meta.created + "," + $i."urn:ietf:params:scim:schemas:extension:ibm:2.0:User".lastLogin + "," + $i."urn:ietf:params:scim:schemas:extension:ibm:2.0:User".pwdChangedTime
$row | Out-File -FilePath $csvPath -Encoding UTF8 -Append
}
exit
4. 参考
本記事を書くにあたり、@fitz さんの以下qiita記事を参考にしました。
IBM Security Verify API + Pythonでユーザー情報一覧を取得する
IBM公式ドキュメント
https://docs.verify.ibm.com/verify/reference/getusers
https://docs.verify.ibm.com/verify/docs/looking-up-users