今回はAzureに関する記事です。
Azure のKey Vaultへ格納した変数を、インターネット経由でLogic Appsへアクセスし、
自宅や会社等、特定の場所から安全に参照する構成を解説していきます。
最初に、本記事で扱う用語は公式やAzureポータル上などで表記揺れがあるため
以下の太字部分で統一します。
- Azure Key Vault:初出は正式名称、以降は「Key Vault」
- Azure Logic Apps:初出は正式名称、以降は「Logic Apps」
- キー コンテナー:Azure Portalの操作手順で、画面上の項目を指す場合だけ使用
- ロジック アプリ:同じく画面上の項目を指す場合だけ使用
【Azure】まだWindows BATにパスワードを埋め込んでるの? Azure Logic Apps+Key Vaultで固定変数を外部化する方法
本記事のターゲット
以下に該当する方へおすすめするべく、本記事を執筆しています⇩
- 使用しているツールにパスワード直書きなどしているものを見直したい
- 複数のツールで毎回同じ固定変数を利用しており一元管理したい
- 複数PCなどに同じツールを展開して、変数管理も一元化したい
- 格納した変数を取り出す際に、Azure CLIなど専用のツールを利用したくない
- 指定したネットワークからのみ取得できる固定変数置き場を作成したい
- 専用ソフトやDBを導入せず、上記をフラットな感覚で実現したい
本構成は、送信元のグローバルIPアドレスを特定できることが前提です。
IPアドレスが変更された場合は、Logic Apps側の許可設定も更新する必要があります。なお筆者の利用しているSoftBank光では、
グローバルIPが数年単位で変わらないこともあるため、今回は手動管理としています。また本記事では、パスワードやAPIキー、各種設定値など、
プログラムから参照する比較的変更頻度の低い値を便宜上「固定変数」と表現しています。
全体概要図
自宅PCからLogicAppsを参照すると、引数で与えた文字列をキーにして、
LogicAppsがKeyVaultへ問い合わせをします。
戻り値としてKeyVaultへ格納されているSecretsが応答されます。

Cloud Shellで構築するための準備
今回はAzure Cloud Shellの Bash を使用します。対象サブスクリプションに「所有者」相当の権限があるユーザーで、Azureポータルへログインしてください。
リソース名はGUI版と同じものを使用します。
| 項目 | 設定値 |
|---|---|
| リソースグループ | Addache-Test |
| リージョン | japaneast(Japan East) |
| Key Vault | key-testsecrets |
| Logic Apps | Lap-TestSecrets |
| Logic Appsのプラン | Consumption(従量課金) |
| Key Vaultの価格レベル | Standard(標準) |
| 実行履歴の保存期間 | 7日 |
同じサブスクリプション・リソースグループに同名のリソースがある場合は、
そのリソースを更新します。
なお、Key VaultのStandardとLogic AppsのStandardは別の設定です。
今回は、Logic Appsを Consumption(従量課金) で作成します。
構築用ファイルを取得する
Cloud Shellを開き、Bashへ切り替えてから以下を実行します。
mkdir -p ~/azure-logicapps-keyvault-02
cd ~/azure-logicapps-keyvault-02
umask 077
BASE_URL='https://raw.githubusercontent.com/addache/addache-blog-assets/main/azure-logicapps-keyvault-02'
curl -fSLo setup.sh "$BASE_URL/setup.sh"
curl -fSLo settings.example.sh "$BASE_URL/settings.example.sh"
curl -fSLo logic-app-resource.template.json "$BASE_URL/logic-app-resource.template.json"
if [[ ! -f settings.local.sh ]]; then
cp settings.example.sh settings.local.sh
fi
chmod 600 settings.local.sh
code settings.local.sh
取得するファイルは以下の3つです。
| ファイル | 用途 |
|---|---|
setup.sh | リソース作成・権限設定などを行うスクリプト |
settings.example.sh | 設定値のサンプル |
logic-app-resource.template.json | Logic Apps作成用のJSONテンプレート |
設定値を編集する
Cloud Shellのエディターで開いた settings.local.sh を編集します。
- Ctrl+S で保存
- Ctrl+Q でエディターを閉じる
赤文字の部分は、筆者側で用意しかねますので、編集して頂く必要があります。
順番に説明していきます。
SUBSCRIPTION_ID='REPLACE_WITH_SUBSCRIPTION_ID'
LOCATION='japaneast'
RG_NAME='Addache-Test'
KV_NAME='key-testsecrets'
LOGICAPP_NAME='Lap-TestSecrets'
ALLOWED_IP_CIDR='REPLACE_WITH_HOME_PUBLIC_IPV4/32'
RETENTION_DAYS=7
RDP_HOST='localhost'
RDP_USER='REPLACE_WITH_WINDOWS_USER'
RDP_PASS='REPLACE_WITH_WINDOWS_PASSWORD'
APP_ENABLED='ON'
COPY_FROM='FromFolder'
COPY_TO='ToFolder'
(1)SUBSCRIPTION_ID
構築先のサブスクリプションIDです。
Azureポータルの「サブスクリプション」で確認するか、
次のコマンドで一覧を表示し、出力されたSubscriptionIdのみ転記してください。
(サブスクリプション名は不要)
az account list \
--query '[].{subscriptionName:name,subscriptionId:id}' \
--output table
(2)ALLOWED_IP_CIDR
完成後にBATを実行する、Windows PC側のグローバルIPv4アドレスを指定します。末尾には /32 を付けます。
(書式の例)
203.0.113.10/32
そのまま使わず、ご自身のIPアドレスへ置き換えてください。
自宅のグローバルIPアドレスが分からない場合は以下のサイトで確認してください⇩
(3)RDP_USER/RDP_PASS
接続先Windowsのユーザー名とパスワードです。
Azureへログインしているユーザーのパスワードではありません。
今回は手軽に試せるよう、シークレット値も設定ファイルへまとめています。settings.local.sh にはパスワードが平文で残るため、
GitHubへの登録や画面の公開は避けてください。
値は単一引用符で囲みます。
値自体に単一引用符が含まれる場合は、'ab'\''cd' のようにBashの記法でエスケープしてください。
構築スクリプトを実行する
一発自動生成するスクリプト
コレを実行するとテストBATの章まで手順をスキップできます。
非常にシンプルな代わり、以下の要素に抵抗がない方だけ実行ください。
- 構築している感が薄い
- 筆者の提供するスクリプトを利用することに抵抗がある
※ネット上に転がっている長文コードは信用しないのが普通
(実行する場合)同じ作業フォルダで以下を実行します。
bash setup.sh
リソースの作成や権限反映に、数分かかる場合があります。
ひとつずつ、順番に作成していく場合
まずは設定した変数を読み込みします。
source ./settings.local.sh
(1)Key Vaultを作成する
対象サブスクリプションを選択し、必要なリソースプロバイダーを登録してから、
リソースグループとKey Vaultを作成します。
Key Vault作成部分のコマンドは以下です。
az keyvault create \
--name "$KV_NAME" \
--resource-group "$RG_NAME" \
--location "$LOCATION" \
--sku standard \
--enable-rbac-authorization true \
--public-network-access Enabled \
--default-action Allow \
--output none
GUI版と同じく、Key Vaultは標準プランを使用します。
アクセス許可モデルはAzure RBACを明示しています。
本記事ではVNetやプライベートエンドポイントを構成せず、パブリックネットワークへのアクセスを許可したうえで、RBACによって利用者を制御します。
(2)自分へKey Vault Administrator権限を付与する
GUI版で設定した「キー コンテナー管理者」を、Cloud Shellで操作している自分自身へ割り当てます。Azureリソースの「所有者」であっても、Key Vaultのシークレットを操作する権限は別途必要です。
まずは、先に作成したKeyVaultのリソースIDと、自身のユーザーIDを取得します。
KV_ID="$(az keyvault show \
--name "$KV_NAME" \
--resource-group "$RG_NAME" \
--query id \
--output tsv)"
USER_ID="$(az ad signed-in-user show \
--query id \
--output tsv)"
取得した値を確認します。USER_ID はログイン中のユーザー、KV_ID は今回のKey VaultのリソースIDです。
printf 'KV_ID=%s\nUSER_ID=%s\n' "$KV_ID" "$USER_ID"
上記が正常に取得できているなら、権限の設定を行います。
az role assignment create \
--assignee-object-id "$USER_ID" \
--assignee-principal-type User \
--role '00482a5a-887f-4fb3-b363-3b7fe8e74483' \
--scope "$KV_ID" \
--output none
※日本語の表示名と英語名の違いに影響されないよう、コマンドではロールIDを使っています。
| 日本語の表示名 | 英語名 |
|---|---|
| キー コンテナー管理者 | Key Vault Administrator |
| キー コンテナー シークレット ユーザー | Key Vault Secrets User |
Microsoft Learn:Key Vault関連のロール
権限付与の直後は、まだシークレットを操作できない場合があります。
(3)テスト用シークレットを登録する
GUI版と同じ6個のシークレットを登録します。
| シークレット名 | 設定する変数 |
|---|---|
RDP-HOST | RDP_HOST |
RDP-USER | RDP_USER |
RDP-PASS | RDP_PASS |
APP-ENABLED | APP_ENABLED |
COPY-FROM | COPY_FROM |
COPY-TO | COPY_TO |
For文を利用し、一気に登録します。
for SECRET_NAME in \
RDP-HOST RDP-USER RDP-PASS APP-ENABLED COPY-FROM COPY-TO
do
VARIABLE_NAME="${SECRET_NAME//-/_}"
if az keyvault secret set \
--vault-name "$KV_NAME" \
--name "$SECRET_NAME" \
--value="${!VARIABLE_NAME}" \
--output none
then
echo "登録完了: $SECRET_NAME"
else
echo "登録失敗: $SECRET_NAME"
break
fi
done
登録結果にシークレット値を表示しないよう、--output none を指定しています。
最後に、登録されたシークレットの名前だけを一覧表示します。
同じシークレットへ再登録すると、新しいバージョンが作成されます。
(4)JSONテンプレートの設定値を置き換える
ダウンロードしたJSONテンプレートには、ワークフローと周辺設定をまとめています。
以下を実行し、設定済みの変数を使って
リージョン/Key Vault名/許可する送信元IP/実行履歴の保存日数
を置き換えます。
mkdir -p .generated
sed \
-e "s|__LOCATION__|$LOCATION|g" \
-e "s|__KEY_VAULT_NAME__|$KV_NAME|g" \
-e "s|__ALLOWED_IP_CIDR__|$ALLOWED_IP_CIDR|g" \
-e "s|__RETENTION_DAYS__|$RETENTION_DAYS|g" \
logic-app-resource.template.json \
| jq '.properties.runtimeConfiguration.lifetime.count |= tonumber' \
> .generated/logic-app-resource.json
元のテンプレートは残し、置換結果を .generated/logic-app-resource.json へ保存します。
最後の jq は、履歴日数をJSONの数値型へ変換する処理です。
続けて、JSONの構文を確認します。
jq empty .generated/logic-app-resource.json \
&& echo 'JSONの構文チェックが完了しました。'
エラーが出た場合は、設定値や置換コマンドを確認してから次へ進んでください。
(5)Logic AppsをConsumptionで作成する
作成先のリソースIDと管理APIのURLを変数へ設定します。
WORKFLOW_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RG_NAME/providers/Microsoft.Logic/workflows/$LOGICAPP_NAME"
WORKFLOW_API="https://management.azure.com${WORKFLOW_ID}?api-version=2019-05-01"
次のコマンドで、置換済みJSONを投入します。
az rest \
--method put \
--url "$WORKFLOW_API" \
--headers 'Content-Type=application/json' \
--body @.generated/logic-app-resource.json \
--output none
Consumptionのリソースである Microsoft.Logic/workflows を作成します。Standard用のApp Serviceプランは作成しません。
WORKFLOW_ID と WORKFLOW_API は、
後続の権限設定やHTTP URL取得でも使用するため、同じCloud Shellで続けて操作してください。
(6)Logic AppsへKey Vault Secrets User権限を付与する
作成したLogic AppsのマネージドIDを取得します。
PRINCIPAL_ID="$(az rest \
--method get \
--url "$WORKFLOW_API" \
--query identity.principalId \
--output tsv)"
取得結果を確認します。
printf 'PRINCIPAL_ID=%s\n' "$PRINCIPAL_ID"
ハイフンを含むIDが表示されたら、次のコマンドでKey Vaultの読み取り権限を付与します。
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role '4633458b-17de-408a-b874-0445c86b69e6' \
--scope "$KV_ID" \
--output none
GUI版で「キー コンテナー シークレット ユーザー」を選び、
Logic Appsをメンバーに追加する操作に対応します。
IDが空、または None・null の場合は権限付与へ進まず、
- Logic Appsの作成が成功していること
- マネージドIDが有効であること
を確認してください。作成直後なら、少し待ってID取得コマンドを再実行します。
権限付与後も反映に時間がかかる場合があるため、接続テストで権限エラーが出た場合は
数分待って再度試してください。
(7)IP制限と実行履歴を設定する
GUI版で設定していた以下の項目も、今回はJSONへ含めています。
| 項目 | 設定内容 |
|---|---|
| HTTPトリガーの送信元IP制限 | ALLOWED_IP_CIDR |
| 実行履歴の保存期間 | RETENTION_DAYS(初期値7日) |
| HTTPアクションのSecure outputs | ON |
| Response-MyHomeのSecure inputs | ON |
送信元IP制限と、秘密値を扱う処理の履歴非表示を組み合わせています。
HTTP URLを取得する
GUI版では画面からコピーしていた署名付きURLも、コマンドで取得します。
TRIGGER_NAME='When_an_HTTP_request_is_received'
CALLBACK_URL="$(az rest \
--method post \
--url "https://management.azure.com${WORKFLOW_ID}/triggers/${TRIGGER_NAME}/listCallbackUrl?api-version=2016-06-01" \
--query value \
--output tsv)"
取得したURLをTXTへ保存し、sed で % を %% に置き換えます。
umask 077
mkdir -p .generated
if [[ "$CALLBACK_URL" == https://* && "$CALLBACK_URL" == *sig=* ]]; then
printf '%s\n' "$CALLBACK_URL" > .generated/callback-url.txt
sed -i 's/%/%%/g' .generated/callback-url.txt
chmod 600 .generated/callback-url.txt
echo 'BAT貼り付け用のHTTP URLを保存しました。'
else
echo 'HTTP URLを取得できていません。取得時のエラーを確認してください。'
fi
保存できたら、以下で表示します。
cat .generated/callback-url.txt
表示内容を、そのままBAT冒頭の URI へ貼り付けてください。変換済みなので、手動でさらに % を増やす必要はありません。
sedの行だけを繰り返すと二重変換になるため、
やり直す場合はURL取得⇨TXT保存から実行してください。
また、このTXTはBATソース用です。ブラウザーやcurlで直接呼び出す場合は、
未変換のURLを使用します。
URLには認証用の署名が含まれるため、ファイルや表示画面は公開しないでください。
「BAT貼り付け用のHTTP URLを保存しました。」と表示されたら、以下で表示して控えてください。
cat .generated/callback-url.txt
このURLには認証用の署名が含まれています。
URLを含む画面や、設定済みBATを公開しないでください。
構築結果を確認する
スクリプトの最後に、以下の設定を表示します。
| 表示項目 | 確認する内容 |
|---|---|
resourceType | Microsoft.Logic/workflows |
state | Enabled |
identity | SystemAssigned |
allowedIPs | 設定したWindows PC側のIPアドレス |
retention | 7(初期値の場合) |
シークレット値や署名付きURLは、この確認結果には表示しません。
接続テストは、許可した送信元IPのWindows PCから行ってください。Cloud ShellからHTTP URLへアクセスすると、送信元IPが異なるため拒否される場合があります。
Windows BATを使った接続テスト
Key Vaultに登録した値を、WindowsのBATから取得して使ってみましょう。
用途別に3本のサンプルを用意しました。それぞれ単独で実行可能です。
(1)下準備
デスクトップへ以下のフォルダを作成してください。
[FromFolder]

ココに、サンプルBATを配置します。
このPATHじゃないと動かない、というものではありませんが、
以下の意図により指定いたします。
- サンプル③(ファイルコピー)で実行結果の確認が出来るようにする
- BATの置き場を記事内で統一する
フォルダを作成したら、以下をDLして格納してください。
サンプル②:ON/OFF制御(02-app-enabled.bat)
サンプル③:ファイルコピー(03-file-copy.bat)
各コードページの Download raw file から、.bat 形式で保存してください。
(そのままDLすれば即利用可能です)
DL後はBAT冒頭の
set "URI=REPLACE_WITH_LOGIC_APPS_SIGNED_URL"
を、先に控えたHTTP URLへ置き換えれば実行できます。
以下はHTTP URLを表示するCloudShellです。(少し前に記載したもの)
cat .generated/callback-url.txt
URL中の % は、BAT内では %% と記述してください。
共通的に以下部分へ含まれています。
なおブラウザ版と異なり、CLI版では最初から%→%%へ変換済みです。(例)
変更前: sp=%2Ftriggers%2FWhen_an_HTTP_request_is_received%2F
変更後: sp=%%2Ftriggers%%2FWhen_an_HTTP_request_is_received%%2F
実際の署名付きURLを設定したBATは、GitHubなどへ公開しないでください。
必要なシークレットや設定上の注意点は、サンプルのREADMEにまとめています。
なお、筆者の作成したBATに警戒心があるときは
ChatGPTなどにコードを渡して、リスク監査を実施してもらってください。・バックドアやウィルスなどの仕込みがないか
・不明な場所へのデータ送信が設定されていないか
それぞれのコードについて、簡単に解説します。
① RDP接続
シークレット:RDP-USER、RDP-PASS、RDP-HOST
に記述されている接続先/ユーザー名/パスワードをそれぞれ取得し、
リモートデスクトップを起動します。
画面には接続先とユーザー名を表示し、パスワードはマスクします。
※登録した資格情報は10秒後に削除されます
ただしWindows HomeはRDPの接続先になれず、自分自身への接続にも制約があります。
接続できない場合は、利用可能な別PCを指定してください。※テスト可能なマシンをお持ちでない場合は、本検証はスキップしてください
② 処理のON/OFF制御
シークレット:APP-ENABLED を取得し、ON のときだけPC名を表示する hostname を実行します。
OFF の場合は実行をスキップします。
Key Vaultの値を変更して再実行すると、BATを書き換えずに動作を切り替えられます。
この設定は、ほかのBATには影響しません。
③ ファイルコピー
シークレット:COPY-FROM と COPY-TO を取得し、
デスクトップ上のフォルダ間でファイルをコピーします。
実行前にデスクトップへ FromFolder を手動で作成し、テスト用ファイルを置いてください。
記事の手順通りに進んでいれば、作成済のはずです。
コピー先の ToFolder は、存在しなければBATが作成し、存在していればそのまま使います。
同名ファイルは上書きされるため、テスト用のファイルで試しましょう。
本手順ではBATをFromFolderへまとめて配置してます。
ToFolderへBATがコピーされていれば成功です。
最後に
今回は変数をKeyVaultへ保存し、インターネット経由で取得し利用する手順を執筆しました。
10年前であれば
「PC内の特定の場所にスクリプトを固めて配置し、iniファイルなどへ変数をまとめる」
「Windows標準の環境変数設定をメンテナンスして、環境にあった動作をさせる」
あたりが定石だったと思いますが、モダンなパブリッククラウドを利用すれば
- 「自宅で利用する変数までクラウドで管理できる」
- 「BATだけ配布すれば自宅内にある、どのPCからでも即利用できる」
- 「BATのファイルコピーとあわせてiniファイルなどのコピーや配置も不要、PC内でもBATの格納場所を選ばない」
- 「Windowsの環境設定変数を、環境にあわせてメンテナンスする必要がない」
- 「インターネット参照にも関わらず、グローバルIPによる最低限のセキュリティが担保できる(他の場所から利用できない)」
というメリットがあります。
Windowsの環境変数設定などの機能は、
よりセキュアな設定を行いたい場合は選択肢に入ってきます。セキュリティと運用(操作性)はトレードオフなので、
「その環境でどこまでの安全確保をするか?」を検討し、
双方バランスの取れた機能を採用してください。
余談
AWSで実現する場合は
「Lambda + SSMパラメータストア or Secret Manager」のような構成になると思います。
コチラも機会があれば記事化したいと思います。
AzureのLogicAppsと直接対応するサービスは現時点(2026年11月現在)では存在しません。
M365 Power Automate が類似するサービスとなっており、完全にMicrosoftな世界観です。
また、LogicAppsへアクセスするためのHTTP URLに限って、
本記事内では各コードに埋め込むしかありませんが、こちらも
LogicAppsに依存せず、変数のようにインターネットから取得する
方法がありますので、そちらも機会を見て記事化します。
なお、本記事ではWindows BATをテストコードとして利用しています。
本当はPowerShellで提供したかったのですが、以下の理由でBATを採用しています。
Windows標準ではPowerShellをそのまま実行できないので、少々環境依存になる
本記事が皆さまのご参考になれば幸いです。
関連記事



コメント