- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2020-08-07T03:35:11+00:00","","")
#author("2020-08-07T06:54:46+00:00","","")
#mynavi(Azureメモ)
#setlinebreak(on);
* 概要 [#dadf4db4]
#html(<div class="pl10">)
#TODO
#html(</div>)
* 目次 [#g9c9f576]
#contents
- 関連
-- [[Azureメモ]]
- 参考
-- https://grafana.com/docs/grafana/latest/auth/ldap/
-- https://grafana.com/docs/grafana/latest/auth/ldap/#active-directory
-- https://grafana.com/docs/grafana/latest/auth/azuread/
-- https://techexpert.tips/ja/grafana-ja/active-directory%E3%81%A7%E3%81%AEgrafana-ldap%E8%AA%8D%E8%A8%BC/
* Azure に Grafana をデプロイする方法 [#s527b860]
* クライアント(アプリケーション)IDの登録 及び シークレットの作成 [#l24d8307]
#html(<div class="pl10">)
#html(){{
<style>
.images div { vertical-align: top; margin-right: 20px; }
.images img { border: 1px solid #333; }
</style>
}}
#html(<div class="images">)
#html(<div class="ib">)
[Active Directory] を選択
&ref(create_secret1-1.png,nolink);
#html(</div><div class="ib">)
[アプリの登録] を選択
&ref(create_secret1-2.png,nolink);
#html(</div><div class="ib">)
[新規登録] を選択
&ref(create_secret1-3.png,nolink);
#html(</div><div class="ib">)
アプリケーション名を入力して登録
&ref(create_secret1-4.png,nolink);
#html(</div><div class="ib">)
クライアントID(アプリケーションID)を確認しておく
&ref(create_secret1-5.png,nolink);
#html(</div><div class="ib">)
[証明書とシークレット] → [新しいクライアントシークレット] を選択
&ref(create_secret1-6.png,nolink);
#html(</div><div class="ib">)
説明を入力して [追加]
&ref(create_secret1-7.png,nolink);
#html(</div><div class="ib">)
登録したクライアントシークレットを確認しておく。(追加直後しか確認できないので注意)
&ref(create_secret1-8.png,nolink);
#html(</div>)
#html(</div>)
まず、Grafana をどのようにして Azure に配備するかについては、いくつか方法がある。
| 作成方法 | 補足 |h
| 自力で構成を作成 | VM、VNet など全てのリソースを自力で作成。 |
| マーケットプレイスを利用して作成 | ただし ver 6.2.5 の Grafana が構築される( 2020/8 時点 ) |
| App Service で作成 | App Service で Docker コンテナ を利用して作成。( プレビュー版だが、docker-compose も使用できる ) |
#html(</div>)
「全て自力で作成」 する場合と「マーケットプレイスで作成」する場合では、最終的に出来上がる構成はほぼ同じになるが、
マーケットプレイスから作成する場合、Grafana のバージョンは 6.2.5 となる。( 2020/8 時点 )
この記事では、「自力で構成を作成」 「App Service で作成」 で以下の構成を作成する。
* リソースの作成 [#p10153b6]
#html(<div class="pl10">)
#TODO
** シェル作成 [#r711498e]
#html(<div class="pl10">)
#html(){{
<div id="tabs1">
<ul>
<li><a href="#tabs1-0">0_env.sh</a></li>
<li><a href="#tabs1-1">1_resources.sh</a></li>
<li><a href="#tabs1-2">2_vm_setup.tmpl</a></li>
</ul>
}}
// START tabs1-0
#html(<div id="tabs1-0">)
0_env.sh
#mycode2(){{
#!/bin/bash
PREFIX="各リソース名に付ける接頭文字"
subscriptionId="サブスクリプションID"
region=japanwest
resourceGroup=${PREFIX}ResourceGroup
vnetName=${PREFIX}VNet
vnetPrefix=10.1.0.0/16
nsgName=${vnetName}SecGrp
nsgPubRuleName=${nsgName}PubRule
nsgPubInboundPort="3000"
vmSubnetName=${PREFIX}VmSubnet
vmSubnetPrefix=10.1.1.0/24
vmName=${PREFIX}Vm
vmImage=UbuntuLTS
vmIpAddress=10.1.1.5
vmUser=sample
# 登録したアプリケーションのクライアントID、シークレット
clientId="確認したクライアントID"
clientSecret="確認したクライアントシークレット"
# テナントIDの取得
tenantId=`az account show -s $subscriptionId -o table | tail -1 | awk '{print $NF}'`
}}
#html(</div>)
// END tabs1-0
* App Service で作成 [#c3d0621a]
#html(<div class="pl10">)
// START tabs1-1
#html(<div id="tabs1-1">)
App Service で Docker コンテナーを利用して Grafana 環境を作成する。(2020/8 時点でプレビュー版だが docker-compose も使用できる)
また、今回のように仮想プライベートネットワークへのアクセスが必要な場合、「VNet統合」 を利用する事になるが、この場合 App Service のプランとして Standard または Premium を選ぶ必要がある。
#mycode2(){{
#!/bin/bash
** 実装 [#hf9bff3e]
#html(<div class="pl10">)
# 設定の読み込み
source 0_env.sh
docker-compose.yml
# リソース作成
if [ "$1" == "--create" ]; then
# リソースグループの作成
echo az group create
az group create --name $resourceGroup --location $region
# NSG(ネットワークセキュリティグループの)作成
echo az network nsg create
az network nsg create --resource-group $resourceGroup --name $nsgName
# NSGルール(Public)
echo az network nsg rule create
az network nsg rule create \
--resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}1\
--access Allow --protocol Tcp --direction Inbound --priority 100 \
--source-address-prefix Internet --source-port-range "*" --destination-port-range $nsgPubInboundPort
# NSGルール(Public) SSH
echo "az network nsg rule create(ssh)"
az network nsg rule create \
--resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}2 \
--access Allow --protocol Tcp --direction Inbound --priority 101 \
--source-address-prefix Internet --source-port-range "*" --destination-port-range "22"
# 仮想ネットワーク 及び サブネット作成
echo az network vnet create
az network vnet create \
--name $vnetName --resource-group $resourceGroup \
--address-prefixes $vnetPrefix --network-security-group $nsgName \
--subnet-name $vmSubnetName --subnet-prefixes $vmSubnetPrefix
# VM用の初期化シェルに含まれているシークレットID等を置換する
cat 2_vm_setup.tmpl | sed "s/\$clientId/$clientId/g" \
| sed "s/\$clientSecret/$clientSecret/g" \
| sed "s/\$tenantId/$tenantId/g">2_vm_setup.sh
# 仮想マシンの作成
rm -rf ~/.ssh/id_rsa
rm -rf ~/.ssh/id_rsa.pub
echo az vm create
az vm create \
--resource-group $resourceGroup --name $vmName --image $vmImage --generate-ssh-keys \
--vnet-name $vnetName --subnet $vmSubnetName \
--private-ip-address $vmIpAddress --admin-username $vmUser \
--public-ip-address-dns-name `echo $vmName | tr '[A-Z]' '[a-z]'` \
--custom-data 2_vm_setup.sh
# Grafana用のポート開放
az vm open-port --resource-group $resourceGroup --name $vmName --port 3000
# 生成されたSSH鍵を移動( --ssh-dest-key-path が効かない為 )
mkdir -p pem
if [ -e ~/.ssh/id_rsa ]; then
mv ~/.ssh/id_rsa ./pem/id_rsa_${vmName}
mv ~/.ssh/id_rsa.pub ./pem/id_rsa_${vmName}.pub
fi
fi
# リソース削除
if [ "$1" == "--delete" ]; then
echo az group delete
az group delete --name $resourceGroup
fi
}}
#html(</div>)
// END tabs1-1
// START tabs1-2
#html(<div id="tabs1-2">)
#mycode2(){{
#!/bin/bash
apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
mkdir /tmp/grafana_docker && cd /tmp/grafana_docker
mkdir -p data/grafana && chmod 777 data/grafana
cat <<_EOYML_>docker-compose.yml
version: "3"
services:
grafana:
image: grafana/grafana:7.1.1
hostname: grafana_sample
container_name: grafana_sample
ports:
- "3000:3000"
volumes:
- ./grafana.ini:/etc/grafana/grafana.ini
environment:
- GF_SERVER_ROOT_URL=http://localhost:3000
- GF_SECURITY_ADMIN_PASSWORD=admin
_EOYML_
# get grafana.ini template
docker run -d --name grafana_tmp --rm grafana/grafana:7.1.1
while [ true ]; do
docker cp grafana_tmp:/etc/grafana/grafana.ini grafana.ini.tmpl
if [ "$?" == "0" ]; then
docker stop grafana_tmp
break
fi
sleep 2
done
# replace [auth.azuread] config
cat grafana.ini.tmpl | awk -v client_id="$clientId" -v client_secret="$clientSecret" -v tenant_id="$tenantId" '
BEGIN{
target=0
}
{
if ($1=="[auth.azuread]") {
target=1
print $1
}
if (target>1){
target=target+1
if (substr($1, 1, 1) == "[") {
target=0
} else {
print
}
}
if (target==1){
print "name = Azure AD"
print "enabled = true"
print "client_id = "client_id
print "client_secret = "client_secret
print "auth_url = https://login.microsoftonline.com/"tenant_id"/oauth2/v2.0/authorize"
print "token_url = https://login.microsoftonline.com/"tenant_id"/oauth2/v2.0/token"
print "role_attribute_path = contains(groups[*], 'admin') && 'Admin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'"
print ""
target=target+1
}
if (target==0) {
print
}
}' > grafana.ini
# start grafana
docker-compose up -d
}}
#html(</div>)
// END tabs1-2
#html(</div>)
// END tabs1
#html(<script>$(function() { $("#tabs1").tabs(); });</script>)
#html(</div>)
** リソース作成 [#w558c42c]
#html(<div class="pl10">)
#myterm2(){{
./1_resources.sh --create
}}
#html(</div>)
#html(</div>)
* XXXXXXXXXX [#v8d82db4]
#html(<div class="pl10">)
grafana.ini (抜粋)
#mycode2(){{
[auth.azuread]
name = Azure AD
enabled = true
client_id = クライアントID
client_secret = クライアントシークレット
;scopes = openid email profile
auth_url = https://login.microsoftonline.com/テナントID/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/テナントID/oauth2/v2.0/token
;allowed_domains =
;allowed_groups =
; 正常に動作しない (常に Viewer になってしまう )
;role_attribute_path = contains(info.groups[*], 'admin') && 'Admin' || contains(info.groups[*], 'editor') && 'Editor' || 'Viewer'
role_attribute_path = contains(groups[*], 'admin') && 'Admin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'
}}
イメージをビルド
#myterm2(){{
#TODO
}}
#html(</div>)
** デプロイ [#z96616f6]
#html(<div class="pl10">)
#myterm2(){{
az webapp up --sku B1 -n アプリ名 -l リージョン -g リソースグループ
}}
#html(</div>)
#html(</div>)
// App Service で作成
* 自力で作成 [#kfb4523d]
#html(<div class="pl10">)
自力作成は [[Azure FunctionsからVMにアクセスする]] でも実施済み。
#html(</div>)
* Azure AD認証を設定する [#n828409e]
#html(<div class="pl10">)
Azure AD OAuth2 authentication
https://grafana.com/docs/grafana/latest/auth/azuread/
#html(</div>)
Microsoft ID プラットフォームと暗黙的な許可のフロー (暗黙的な許可フローの有効有効化)
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#send-the-sign-in-request
#mycode3(){{
ID トークンおよびアクセス トークンを正しく要求するには、Azure portal の [アプリの登録] ページのアプリ登録で、
[暗黙の付与] セクションの [ID トークン] および [アクセス トークン] を選択して、対応する暗黙的な許可フローを有効にする必要があります。
それが有効でない場合は、unsupported_response エラーが返されます
}}