Přeskočit na hlavní obsah

Azure aplikace pro Power BI

Nastavení řešíme skriptem – místo proklikávání portálu a certifikátu spustíte jeden blok v Azure Cloud Shellu, který:

  1. vytvoří app registration a service principal,
  2. vygeneruje client secret,
  3. založí security group a zařadí do ní aplikaci,
  4. zapne v Power BI tenantu nastavení, které service principalům povoluje volat Fabric API.

Ručně pak zbyde jediný krok – přidat aplikaci do konkrétních pracovních prostorů. To za vás udělat nemůžeme, protože jen vy víte, které prostory to mají být.

K čemu aplikaci potřebujeme: spouštíme přes ni aktualizace sémantických modelů z našeho kódu hned po dokončení ETL, takže data v reportingu jsou dřív a vždycky kompletní.

Kdo to má spustit

Nejjednodušší je pustit skript pod účtem s rolí Global Administrator. Funguje i s nižšími rolemi – jednotlivé kroky potřebují Application Administrator (aplikace), Groups Administrator (skupina) a Fabric Administrator (nastavení tenantu). Na co účet nemá práva, to skript přeskočí a na konci vypíše, co je potřeba doklikat ručně.

Skript je možné pustit opakovaně

Pokud aplikace, skupina nebo nastavení už existují, skript je jen použije a nic nepřepíše. Client secret se podruhé negeneruje – viz Časté dotazy.


1. Otevřete Azure Cloud Shell

  1. Přihlaste se do portal.azure.com.
  2. V horní liště klikněte na ikonu Cloud Shell (>_).
  3. Zvolte Bash. (Při prvním spuštění po vás Azure může chtít vytvořit storage account – potvrďte, jde o pár korun měsíčně, případně zvolte variantu bez úložiště.)

2. Zkopírujte a spusťte skript

Celý následující blok zkopírujte najednou a vložte do Cloud Shellu. První část skript uloží do souboru, druhá ho spustí. Běh trvá zhruba minutu.

cat > setup-powerbi-app.sh <<'SCRIPT'
#!/usr/bin/env bash

APP_NAME="app-powerbi-refresh"
GROUP_NAME="PowerBI-app-group"
GROUP_NICK="powerbi-app-group"

SECRET=""
EXPIRY="-"
GROUP_STATUS="NEPODAŘILO SE"
SETTING_STATUS="NEPODAŘILO SE"
GROUP_ID=""

echo "[1/5] App registration '$APP_NAME'..."
APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv 2>/dev/null)
if [ -n "$APP_ID" ]; then
APP_EXISTED=1
echo " už existuje, používám ji"
else
APP_ID=$(az ad app create \
--display-name "$APP_NAME" \
--sign-in-audience AzureADMyOrg \
--query appId -o tsv 2>/dev/null) || true
if [ -z "$APP_ID" ]; then
echo "CHYBA: aplikaci se nepodařilo vytvořit (chybí role Application Administrator?)"
exit 1
fi
APP_EXISTED=0
echo " vytvořeno"
fi
echo " Client ID: $APP_ID"

echo "[2/5] Service principal..."
SP_OBJECT_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv 2>/dev/null)
if [ -z "$SP_OBJECT_ID" ]; then
az ad sp create --id "$APP_ID" >/dev/null 2>&1 || true
for attempt in 1 2 3 4 5 6; do
SP_OBJECT_ID=$(az ad sp show --id "$APP_ID" --query id -o tsv 2>/dev/null)
[ -n "$SP_OBJECT_ID" ] && break
echo " ještě se nepropsal, čekám 10 s..."
sleep 10
done
fi
if [ -z "$SP_OBJECT_ID" ]; then
echo "CHYBA: service principal se nepodařilo vytvořit"
exit 1
fi

echo "[3/5] Client secret..."
if [ "$APP_EXISTED" = "0" ] || [ "${NEW_SECRET:-0}" = "1" ]; then
SECRET=$(az ad app credential reset \
--id "$APP_ID" \
--display-name "powerbi-refresh" \
--years 2 \
--append \
--query password -o tsv 2>/dev/null) || true
EXPIRY=$(date -u -d '+2 years' +%Y-%m-%d 2>/dev/null)
[ -z "$SECRET" ] && echo " CHYBA: secret se nepodařilo vytvořit"
else
echo " aplikace už existovala, secret negeneruji (viz dokumentace)"
fi

echo "[4/5] Security group '$GROUP_NAME'..."
GROUP_ID=$(az ad group list --display-name "$GROUP_NAME" --query "[0].id" -o tsv 2>/dev/null)
if [ -z "$GROUP_ID" ]; then
GROUP_ID=$(az ad group create \
--display-name "$GROUP_NAME" \
--mail-nickname "$GROUP_NICK" \
--query id -o tsv 2>/dev/null) || true
fi
if [ -z "$GROUP_ID" ]; then
echo " NEPODAŘILO SE (chybí role Groups Administrator?)"
GROUP_STATUS="NEPODAŘILO SE – vytvořte skupinu ručně"
else
IS_MEMBER=$(az ad group member check --group "$GROUP_ID" \
--member-id "$SP_OBJECT_ID" --query value -o tsv 2>/dev/null)
if [ "$IS_MEMBER" != "true" ]; then
for attempt in 1 2 3 4; do
if az ad group member add --group "$GROUP_ID" \
--member-id "$SP_OBJECT_ID" >/dev/null 2>&1; then
IS_MEMBER="true"; break
fi
echo " přidání do skupiny: pokus $attempt neúspěšný, čekám 15 s..."
sleep 15
done
fi
if [ "$IS_MEMBER" = "true" ]; then
GROUP_STATUS="$GROUP_NAME"
echo " OK"
else
GROUP_STATUS="skupina existuje, ale aplikaci se do ní nepodařilo přidat"
fi
fi

echo "[5/5] Nastavení Power BI tenantu..."
TOKEN=$(az account get-access-token \
--resource https://api.fabric.microsoft.com \
--query accessToken -o tsv 2>/dev/null) || true
if [ -z "$TOKEN" ]; then
SETTING_STATUS="NEPODAŘILO SE – nešel získat token pro Fabric API, nastavte ručně"
echo " $SETTING_STATUS"
elif [ -z "$GROUP_ID" ]; then
SETTING_STATUS="PŘESKOČENO – bez security group to nemá smysl"
echo " $SETTING_STATUS"
else
SETTINGS=$(curl -s -H "Authorization: Bearer $TOKEN" \
"https://api.fabric.microsoft.com/v1/admin/tenantsettings")
CUR=$(echo "$SETTINGS" | jq -c '[.value[]
| select(.title | test("service principal"; "i"))
| select(.title | test("api"; "i"))
| select(.title | test("admin api|global api"; "i") | not)][0] // empty' 2>/dev/null)
SETTING_NAME=$(echo "$CUR" | jq -r '.settingName // empty' 2>/dev/null)
if [ -z "$SETTING_NAME" ]; then
SETTING_STATUS="NEPODAŘILO SE – nastavení se nepodařilo najít (chybí role Fabric Administrator?)"
echo " $SETTING_STATUS"
else
ENABLED=$(echo "$CUR" | jq -r '.enabled')
CANSPEC=$(echo "$CUR" | jq -r '.canSpecifySecurityGroups')
HAS_GROUP=$(echo "$CUR" | jq -r --arg g "$GROUP_ID" \
'[(.enabledSecurityGroups // [])[] | select(.graphId == $g)] | length')
if [ "$ENABLED" = "true" ] && [ "$CANSPEC" = "false" ]; then
SETTING_STATUS="$SETTING_NAME – už zapnuto pro celou organizaci, neměním"
echo " $SETTING_STATUS"
elif [ "$ENABLED" = "true" ] && [ "$HAS_GROUP" != "0" ]; then
SETTING_STATUS="$SETTING_NAME – už zapnuto pro skupinu $GROUP_NAME, neměním"
echo " $SETTING_STATUS"
else
BODY=$(echo "$CUR" | jq -c --arg g "$GROUP_ID" --arg n "$GROUP_NAME" '{
enabled: true,
enabledSecurityGroups: (((.enabledSecurityGroups // [])
+ [{graphId: $g, name: $n}]) | unique_by(.graphId)),
excludedSecurityGroups: (.excludedSecurityGroups // [])
}')
HTTP=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$BODY" \
"https://api.fabric.microsoft.com/v1/admin/tenantsettings/${SETTING_NAME}/update")
if [ "$HTTP" = "200" ]; then
SETTING_STATUS="$SETTING_NAME – zapnuto pro skupinu $GROUP_NAME"
echo " OK"
else
SETTING_STATUS="NEPODAŘILO SE (HTTP $HTTP) – nastavte ručně"
echo " $SETTING_STATUS"
fi
fi
fi
fi

TENANT_ID=$(az account show --query tenantId -o tsv 2>/dev/null)

echo ""
echo "===== ÚDAJE K PŘEDÁNÍ (secret se už nikdy znovu nezobrazí) ====="
echo "App name: $APP_NAME"
echo "Tenant ID: ${TENANT_ID:-<nezjištěno>}"
echo "Client ID: ${APP_ID:-<nevytvořeno>}"
echo "Client secret: ${SECRET:-<nevygenerován – aplikace už existovala>}"
echo "Expirace: $EXPIRY"
echo "Security group: $GROUP_STATUS"
echo "Tenant setting: $SETTING_STATUS"
echo "==============================================================="
echo ""
echo "ZBÝVÁ RUČNĚ: přidat aplikaci '$APP_NAME' do pracovních prostorů"
echo " (workspace -> Manage access -> Add people or groups)"
echo ""
SCRIPT

bash setup-powerbi-app.sh
Nespouštějte skript řádek po řádku

Skript musí běžet jako soubor (bash setup-powerbi-app.sh), ne přes source a ne vkládáním po částech – jinak se proměnné se secretem chovají nepředvídatelně a výsledný výpis nemusí být kompletní.

Skript záměrně nenastavuje žádná API permissions. Power BI se u service principalu oprávněními z Entra ID neřídí – přístup se řeší tenant nastavením a rolí v pracovním prostoru.

3. Přidejte aplikaci do pracovních prostorů

Jediný krok, který skript neudělá. Pro každý pracovní prostor, jehož sémantické modely máme aktualizovat:

  1. Otevřete pracovní prostor → Manage accessAdd people or groups.
  2. Vyhledejte aplikaci app-powerbi-refresh a přiřaďte roli Member, případně Contributor.

4. Pošlete nám výstup

Zkopírujte celý blok ÚDAJE K PŘEDÁNÍ z konce výpisu a připojte seznam pracovních prostorů, do kterých jste aplikaci přidali.

===== ÚDAJE K PŘEDÁNÍ (secret se už nikdy znovu nezobrazí) =====
App name: app-powerbi-refresh
Tenant ID: ...
Client ID: ...
Client secret: ...
Expirace: ...
Security group: PowerBI-app-group
Tenant setting: ... – zapnuto pro skupinu PowerBI-app-group
===============================================================
Client secret je heslo

Client secret se v Azure portálu už nikdy znovu nezobrazí a výpis obsahuje jeho plné znění. Pošlete nám ho bezpečným kanálem – viz Obecné bezpečnostní zásady, např. přes pwpush s platností 1 zobrazení / 1 den.


Když některý krok selže

Na řádcích Security group: a Tenant setting: uvidíte, co se nepovedlo. Aplikace i secret v takovém případě fungují, chybí jen navazující nastavení – doplňte ho ručně.

Security group

  1. Microsoft Entra IDManageGroupsNew group.
  2. Group type nechte na Security, název PowerBI-app-group.
  3. U Members klikněte na No members selected a vyhledejte aplikaci podle Client ID z výpisu. Zaškrtněte ji a potvrďte Select.
  4. Dokončete tlačítkem Create.

Nastavení tenantu

V Power BI klikněte na ozubené kolečko → Admin portalTenant settings → sekce Developer settings. Zapněte:

  • Service principals can call Fabric public APIs – a jako povolenou skupinu vyberte PowerBI-app-group.

Microsoft toto nastavení v čase přejmenoval a rozdělil, takže podle stáří tenantu můžete vidět i starší název Service principals can use Fabric APIs, případně Allow service principals to use Power BI APIs. Jde o totéž nastavení. Sousední volba Service principals can create workspaces, connections, and deployment pipelines je něco jiného a pro aktualizace datasetů ji nepotřebujeme.

Pokud budeme řešit i monitoring nebo inventuru obsahu, povolte stejné skupině navíc Service principals can access read-only admin APIs. Změna nastavení se propisuje řádově minuty.


Časté dotazy

Spustil jsem skript podruhé a secret se nevypsal. Proč? Protože aplikace už existovala. Vygenerovat nový secret by neshodilo ten původní (skript používá --append), ale zbytečně by vznikala další hesla. Když nový secret opravdu chcete, spusťte skript jako NEW_SECRET=1 bash setup-powerbi-app.sh.

Jak dlouho přístup platí? Client secret má platnost 2 roky (datum je na výpisu). Před vypršením se vám ozveme.

Nechceme skript pouštět, jde to i naklikat? Jde, jen to zabere víc času a je u toho víc kroků, kde se dá něco přehlédnout. Ruční postup přes Azure portál s certifikátem najdete na stránce Azure aplikace – ruční postup.

Nastaví skript něco, co bych nečekal? Ne. Tenant setting nejdřív načte, přidá do seznamu povolených skupin tu svoji a zbytek pošle zpátky beze změny – existující povolené ani vyloučené skupiny nepřepisuje. Pokud je nastavení už zapnuté pro celou organizaci, nesahá na něj vůbec.

Jak přístup odeberu? V Microsoft Entra IDApp registrations smažete aplikaci app-powerbi-refresh. Tím náš přístup okamžitě končí, ať už je nastavení v Power BI jakékoliv.