Most Power BI BYOK guides tell you what to click. This lesson explains the three-tier cryptographic key hierarchy behind it, walks you through the complete Azure Key Vault and PowerShell configuration, and gives you the audit evidence, key rotation procedures, and troubleshooting knowledge to operate it in a regulated production environment. If your CISO needs to demonstrate customer-controlled encryption to auditors, this is where you start.

Your healthcare data lives in Power BI Premium. So does your financial services client portfolio, your government contract telemetry, and your EU customer records that GDPR regulations demand you protect with documented, auditable key management. Then one morning your CISO walks into your office and says the words that change your week: "We need to prove we control the encryption keys for all regulated data in Power BI, and we need documentation for the audit next month."
This is not a theoretical scenario. Organizations operating under HIPAA, GDPR, FedRAMP, SOC 2 Type II, PCI-DSS, and financial regulatory frameworks like MiFID II increasingly face requirements that go beyond saying "our cloud provider encrypts data at rest." Regulators want to know who controls the encryption keys, where those keys are stored, how key access is audited, and critically — can the organization revoke key access and render data unreadable if a breach occurs or a vendor relationship changes. Microsoft's default encryption for Power BI handles the encryption itself perfectly well, but the keys are Microsoft-managed, which fails the "customer controls the keys" requirement that many sovereignty frameworks demand.
Power BI's Bring Your Own Key (BYOK) feature, formally called Customer-Managed Keys in the Azure ecosystem, addresses this gap by integrating Power BI Premium capacity encryption with Azure Key Vault. By the end of this lesson, you will have a production-ready BYOK implementation strategy, an understanding of the cryptographic architecture that makes it work, and the operational knowledge to manage it through the full lifecycle — including the audit trails and key rotation procedures your compliance team will need.
What you'll learn:
Before working through this lesson, you should have:
MicrosoftPowerBIMgmt PowerShell module installedIf you're fuzzy on key wrapping cryptography, we'll cover the relevant concepts inline — you don't need a cryptography background, but understanding the model will help you make better architectural decisions.
Most tutorials jump straight to "run this PowerShell command." We're not doing that. If you implement BYOK without understanding the key hierarchy, you will make configuration mistakes that either render datasets inaccessible or, worse, give you a false sense of compliance coverage.
Power BI BYOK uses a three-tier key hierarchy:
Tier 1 — Your RSA Key in Azure Key Vault (Key Encryption Key / KEK) This is the key you own and control. It's an RSA 4096-bit asymmetric key stored in Azure Key Vault. Critically, this key never leaves Key Vault — operations that use it happen inside Key Vault's hardware security module (HSM) boundary. You can generate this key in Key Vault directly, or import it from your own HSM if you're operating under requirements that demand air-gapped key generation.
Tier 2 — The Capacity-Level Symmetric Key (Data Encryption Key / DEK) Power BI generates a symmetric AES-256 key for each Premium capacity. This is the key that actually encrypts your dataset data. Power BI wraps (encrypts) this symmetric key using your RSA public key from Key Vault, and stores the wrapped version alongside the encrypted data. This is the classic envelope encryption pattern used across the cloud industry.
Tier 3 — The Dataset Data Itself Individual dataset content is encrypted at rest using the AES-256 capacity key.
Here's why this architecture matters for compliance: when an auditor asks "who controls the encryption key?", you can truthfully say that without access to your RSA key in your Key Vault, the symmetric key cannot be unwrapped, and therefore the dataset data cannot be decrypted. Microsoft can see encrypted blobs and wrapped keys, but without your RSA key, the data is cryptographically inaccessible. Revoking Key Vault access to the Power BI service principal immediately prevents any future decryption operations.
The practical implication: if you delete or disable your Key Vault key, your datasets become inaccessible. This is by design — it's the "nuclear option" for data protection — but it means key management is not an administrative curiosity. It's an operational dependency.
Critical Warning: BYOK in Power BI applies to data at rest in Premium datasets. It does not encrypt data in transit (that uses TLS), it does not encrypt DirectQuery data that passes through to source systems, and it does not cover Power BI report definitions, dashboards, or workspace metadata. Your compliance scope documentation must be explicit about these boundaries.
When Power BI imports a dataset (Import mode), the data is stored in Azure Blob Storage and Azure SQL databases that back the Premium capacity. BYOK encryption covers this stored data. It applies at the point of write — when a dataset refresh completes and data is committed to storage, it's encrypted with your capacity key.
DirectQuery datasets don't store data in Premium storage at all (the data stays in the source system), so BYOK provides no additional protection for DirectQuery — the source system's encryption controls that data. Composite models sit in a nuanced middle ground: the imported tables in a composite model are covered by BYOK, while the DirectQuery portions are not.
This distinction will come up in your compliance documentation. Be precise about it.
Start by creating a dedicated Key Vault for Power BI encryption keys. Using a dedicated vault — rather than sharing one with application secrets or certificate management — gives you cleaner access policies, cleaner audit logs, and simpler key rotation procedures.
# Connect to Azure
Connect-AzAccount -TenantId "your-tenant-id"
# Create a resource group dedicated to key management
New-AzResourceGroup `
-Name "rg-powerbi-keymanagement-prod" `
-Location "East US 2"
# Create the Key Vault
# Note: Premium SKU enables HSM-backed keys for FIPS 140-2 Level 2 compliance
New-AzKeyVault `
-VaultName "kv-powerbi-byok-prod" `
-ResourceGroupName "rg-powerbi-keymanagement-prod" `
-Location "East US 2" `
-Sku "Premium" `
-EnableSoftDelete `
-SoftDeleteRetentionInDays 90 `
-EnablePurgeProtection
The EnablePurgeProtection flag here is worth discussing. Once enabled, you cannot permanently delete the Key Vault or keys during the soft-delete retention period, even as an owner. This sounds like a limitation, but from a compliance perspective, it's a feature — it prevents accidental or malicious key destruction that would render your datasets permanently inaccessible. Many regulatory frameworks will specifically ask about your protection against accidental key deletion.
The Premium SKU enables HSM-backed keys, which means key operations occur in FIPS 140-2 Level 2 validated hardware. If your regulatory framework requires FIPS 140-3 Level 3, you'll need to look at Azure Dedicated HSM or Azure Managed HSM as the key backing — standard Azure Key Vault Premium doesn't reach Level 3.
Tip: Choose an Azure region for your Key Vault that aligns with your data sovereignty requirements. If your Power BI tenant is in the EU (you can verify this in the Power BI Admin portal under Tenant Settings > About Power BI), the Key Vault should also be in an EU region. This keeps key operations within your regulatory geography.
# Create an HSM-backed RSA 4096-bit key
# Using 4096-bit instead of 2048-bit for stronger key strength
# Key Vault supports RSA and RSA-HSM types; RSA-HSM is backed by hardware
Add-AzKeyVaultKey `
-VaultName "kv-powerbi-byok-prod" `
-Name "powerbi-capacity-key-2024" `
-Destination "HSM" `
-KeyType "RSA" `
-Size 4096 `
-KeyOps @("wrapKey", "unwrapKey") `
-Expires (Get-Date).AddYears(2)
Notice the -KeyOps parameter. By explicitly limiting this key to wrapKey and unwrapKey operations, you're following the principle of least privilege at the cryptographic operation level. This key cannot be used for signing, encrypting arbitrary data, or any other operation — only for wrapping and unwrapping other keys. Some auditors will specifically check that your KEK is operation-restricted.
The -Expires parameter sets a two-year expiration. Before the key expires, you'll need to rotate it. We'll cover the rotation procedure in detail later. Setting an expiration forces regular rotation as an operational discipline, which most compliance frameworks require anyway.
Power BI needs to call Key Vault to perform wrap/unwrap operations. It does this through a Microsoft-managed service principal that represents the Power BI service in your tenant.
# The Power BI service application ID is consistent across all tenants
$powerBIServicePrincipalAppId = "00000009-0000-0000-c000-000000000000"
# Retrieve the service principal object ID from your tenant
$powerBISP = Get-AzADServicePrincipal -ApplicationId $powerBIServicePrincipalAppId
# Grant Key Vault access policy to the Power BI service principal
Set-AzKeyVaultAccessPolicy `
-VaultName "kv-powerbi-byok-prod" `
-ObjectId $powerBISP.Id `
-PermissionsToKeys @("get", "wrapKey", "unwrapKey")
The permissions granted here are deliberately minimal: get (to retrieve the key's public attributes), wrapKey (to encrypt the symmetric key), and unwrapKey (to decrypt the symmetric key during data access). Power BI cannot export your private key, cannot delete your key, and cannot create new keys.
Warning: If your organization uses Azure Key Vault with Azure RBAC authorization mode instead of access policies (the newer model), the permissions assignment is different. You'll use
Set-AzRoleAssignmentto assign the "Key Vault Crypto Service Encryption User" role to the Power BI service principal on the specific key resource. Check which authorization model your vault uses before proceeding.
After key creation, retrieve the full versioned key URI. This URI, which includes the Key Vault name, key name, and specific key version, is what you'll provide to Power BI.
# Get the key and extract the full versioned URI
$key = Get-AzKeyVaultKey -VaultName "kv-powerbi-byok-prod" -Name "powerbi-capacity-key-2024"
$keyUri = $key.Key.Kid
Write-Host "Key URI: $keyUri"
# Output: https://kv-powerbi-byok-prod.vault.azure.net/keys/powerbi-capacity-key-2024/a1b2c3d4e5f6...
Save this URI. You'll need it in the next section. Also document it in your key management runbook — it's a critical operational artifact.
BYOK configuration happens through the Power BI REST API and PowerShell management module. The Admin portal UI does not expose all the required controls, so PowerShell is the correct path here.
# Install the module if you haven't already
Install-Module -Name MicrosoftPowerBIMgmt -Scope CurrentUser
# Connect to Power BI as a tenant administrator
Connect-PowerBIServiceAccount
# Verify your connection and admin access
Get-PowerBICapacity -Scope Organization
If Get-PowerBICapacity returns your capacities, your admin connection is working.
Before you can assign the key to a capacity, you need to register it at the tenant level. This registration validates that Power BI can successfully access the Key Vault key.
# Add the encryption key at the tenant level
# This makes it available for assignment to capacities
Add-PowerBIEncryptionKey `
-Name "PBI-BYOK-ProdCapacityKey-2024" `
-KeyVaultKeyUri "https://kv-powerbi-byok-prod.vault.azure.net/keys/powerbi-capacity-key-2024/a1b2c3d4e5f6..." `
-Activate `
-Default
# Verify the key was registered
Get-PowerBIEncryptionKey
The -Activate switch marks this key as active (as opposed to retired). The -Default switch means this key will be automatically applied to new Premium capacities created in the tenant. For most enterprise environments, you want this behavior — it prevents new capacities from being created without encryption coverage.
If registration fails, the most common causes are: the service principal doesn't have the correct Key Vault permissions, the Key Vault is behind a private endpoint that the Power BI service can't reach, or the key URI is malformed (often because you copied a non-versioned URI). The error messages from Power BI's API in this stage are unfortunately terse, so we'll cover specific troubleshooting later.
Tip: You can register multiple encryption keys at the tenant level and assign different keys to different capacities. This is useful if different business units have different key management requirements, or if you need to segregate keys between environments (development, staging, production).
# Get your Premium capacity ID
$capacities = Get-PowerBICapacity -Scope Organization
$prodCapacity = $capacities | Where-Object { $Name -eq "Contoso-Production-P2" }
$capacityId = $prodCapacity.Id
# Get the registered encryption key
$encKey = Get-PowerBIEncryptionKey | Where-Object { $_.Name -eq "PBI-BYOK-ProdCapacityKey-2024" }
# Assign the encryption key to the capacity
Set-PowerBICapacityEncryptionKey `
-CapacityId $capacityId `
-KeyName "PBI-BYOK-ProdCapacityKey-2024"
# Confirm the assignment
Get-PowerBICapacity -Scope Organization |
Where-Object { $_.Id -eq $capacityId } |
Select-Object Id, DisplayName, EncryptionKeyId
When you assign the key to a capacity, Power BI doesn't immediately re-encrypt all existing datasets on that capacity. It generates the capacity-level symmetric key, wraps it with your RSA key from Key Vault, and begins using it for new data writes. Existing datasets will be re-encrypted on their next refresh cycle.
This has a practical implication: immediately after enabling BYOK, your existing datasets may not be encrypted with your key yet. They will be after their next scheduled refresh, but the transition period is something your compliance documentation should address explicitly.
To immediately bring all existing datasets under BYOK encryption rather than waiting for their scheduled refresh:
# Get all workspaces on the capacity
$workspaces = Get-PowerBIWorkspace -Scope Organization -All |
Where-Object { $_.CapacityId -eq $capacityId }
foreach ($workspace in $workspaces) {
# Get all datasets in the workspace
$datasets = Get-PowerBIDataset -Scope Organization -WorkspaceId $workspace.Id
foreach ($dataset in $datasets) {
# Trigger a refresh to force re-encryption on next data write
# Note: This only applies to Import mode datasets
try {
Invoke-PowerBIRestMethod `
-Url "groups/$($workspace.Id)/datasets/$($dataset.Id)/refreshes" `
-Method Post `
-Body '{"notifyOption": "NoNotification"}'
Write-Host "Triggered refresh for dataset: $($dataset.Name) in workspace: $($workspace.Name)"
}
catch {
Write-Warning "Could not trigger refresh for $($dataset.Name): $_"
}
}
}
This approach triggers refreshes programmatically. For large environments with many datasets, you may want to stagger these refreshes to avoid overwhelming capacity resources. Add a Start-Sleep between iterations if needed.
Knowing that BYOK is configured is one thing. Proving it to an auditor in a documented, repeatable way is another. This section covers both.
# Check encryption status for all datasets across the organization
# This requires executing as a Power BI admin
$workspaces = Get-PowerBIWorkspace -Scope Organization -All
$encryptionReport = foreach ($workspace in $workspaces) {
if ($workspace.CapacityId) {
$datasets = Get-PowerBIDataset -Scope Organization -WorkspaceId $workspace.Id
foreach ($dataset in $datasets) {
$datasetDetails = Invoke-PowerBIRestMethod `
-Url "admin/datasets/$($dataset.Id)" `
-Method Get | ConvertFrom-Json
[PSCustomObject]@{
WorkspaceName = $workspace.Name
WorkspaceId = $workspace.Id
DatasetName = $dataset.Name
DatasetId = $dataset.Id
CapacityId = $workspace.CapacityId
IsEncrypted = $datasetDetails.Encryption.EncryptionStatus -eq "Encrypted"
EncryptionStatus = $datasetDetails.Encryption.EncryptionStatus
LastRefreshed = $dataset.IsRefreshable
}
}
}
}
# Export to CSV for compliance documentation
$encryptionReport | Export-Csv -Path "PowerBI-BYOK-EncryptionStatus-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
# Quick summary
$encryptionReport | Group-Object EncryptionStatus | Select-Object Name, Count
The EncryptionStatus field returns one of three values: Encrypted (BYOK is in effect), EncryptionInProgress (the dataset is mid-refresh and being encrypted), or NotSupported (the dataset type doesn't support BYOK, such as DirectQuery-only datasets). Anything returning NotEncrypted needs investigation — it may indicate a dataset that hasn't been refreshed since BYOK was enabled, or a dataset on a capacity that isn't configured with BYOK.
The Key Vault audit log is your paper trail for every key operation. Enable diagnostic logging immediately — without it, you cannot retrospectively prove that key operations followed your documented procedures.
# Create a Log Analytics workspace for Key Vault audit logs
New-AzOperationalInsightsWorkspace `
-ResourceGroupName "rg-powerbi-keymanagement-prod" `
-Name "law-powerbi-keyvault-audit" `
-Location "East US 2" `
-Sku "PerGB2018"
$logAnalyticsWorkspace = Get-AzOperationalInsightsWorkspace `
-ResourceGroupName "rg-powerbi-keymanagement-prod" `
-Name "law-powerbi-keyvault-audit"
$keyVault = Get-AzKeyVault -VaultName "kv-powerbi-byok-prod"
# Enable diagnostic settings to capture all Key Vault operations
Set-AzDiagnosticSetting `
-ResourceId $keyVault.ResourceId `
-WorkspaceId $logAnalyticsWorkspace.ResourceId `
-Name "KeyVaultAuditLogs" `
-Enabled $true `
-Category "AuditEvent" `
-MetricCategory "AllMetrics"
With this configured, every wrapKey and unwrapKey call that Power BI makes will be logged with timestamp, operation type, caller identity, and result. For a quarterly compliance audit, you can query this log to demonstrate that only the Power BI service principal accessed the key, all operations were successful (or investigate any failures), and the key was not accessed outside of normal operational hours.
A useful KQL query for audit evidence:
// Key Vault audit log query for compliance evidence
AzureDiagnostics
| where ResourceType == "VAULTS"
| where ResourceGroup == "RG-POWERBI-KEYMANAGEMENT-PROD"
| where OperationName in ("KeyWrap", "KeyUnwrap")
| project
TimeGenerated,
OperationName,
CallerIPAddress,
identity_claim_appid_s,
resultType_s,
requestUri_s
| order by TimeGenerated desc
Export this query result as part of your audit package. The identity_claim_appid_s field should consistently show 00000009-0000-0000-c000-000000000000 (the Power BI service application ID) for all legitimate operations.
Having a key is easy. Rotating it correctly without causing a data access outage is the skill that separates professionals who've operated BYOK in production from those who've only configured it in a lab.
Key rotation in the Power BI BYOK context means replacing the RSA key (KEK) used to wrap the capacity's symmetric key. Most compliance frameworks require annual key rotation at minimum; some require quarterly. Before you can rotate, you need to understand what "rotation" means in terms of data access continuity.
The critical insight: when you rotate the KEK in Power BI BYOK, Power BI must perform an unwrap operation with the old key and a wrap operation with the new key for the capacity symmetric key. This transition requires that both the old and new keys are available simultaneously during the rotation operation. If you delete the old key before Power BI completes the transition, you will lose access to your data.
The cleanest rotation pattern in Azure Key Vault is creating a new key version of the same key name, rather than creating an entirely new key:
# Create a new version of the existing key
# This rotates the key material while keeping the same key name
Add-AzKeyVaultKey `
-VaultName "kv-powerbi-byok-prod" `
-Name "powerbi-capacity-key-2024" `
-Destination "HSM" `
-KeyType "RSA" `
-Size 4096 `
-KeyOps @("wrapKey", "unwrapKey") `
-Expires (Get-Date).AddYears(2)
# Get the new key version URI
$newKey = Get-AzKeyVaultKey -VaultName "kv-powerbi-byok-prod" -Name "powerbi-capacity-key-2024"
$newKeyUri = $newKey.Key.Kid
Write-Host "New Key Version URI: $newKeyUri"
Note that if you rotate to an entirely new key name rather than a new version of the same key, you need to re-register the key at the tenant level and re-assign it to the capacity — more steps and more opportunity for error. New key versions under the same name are simpler operationally.
# Register the new key version at the tenant level
# This adds the new version while keeping the old version available for the transition
Add-PowerBIEncryptionKey `
-Name "PBI-BYOK-ProdCapacityKey-2025" `
-KeyVaultKeyUri $newKeyUri `
-Activate
# Update the capacity to use the new key
Set-PowerBICapacityEncryptionKey `
-CapacityId $capacityId `
-KeyName "PBI-BYOK-ProdCapacityKey-2025"
# Verify the capacity is now using the new key
Get-PowerBICapacity -Scope Organization |
Where-Object { $_.Id -eq $capacityId } |
Select-Object Id, DisplayName, EncryptionKeyId
After this operation, Power BI will re-wrap the capacity symmetric key using the new RSA key. New dataset refreshes will use the new wrapping. Existing datasets that were encrypted under the old key will be re-encrypted on their next refresh.
Only retire (disable) the old key after you've confirmed all datasets have been refreshed and re-encrypted under the new key. Check your encryption status report to confirm all datasets show Encrypted under the new key mapping.
# Disable the old key version (not delete — just disable)
# This prevents its use for future operations while preserving it for recovery if needed
$oldKeyVersion = "a1b2c3d4e5f6..." # The version identifier of the old key
Update-AzKeyVaultKey `
-VaultName "kv-powerbi-byok-prod" `
-Name "powerbi-capacity-key-2024" `
-Version $oldKeyVersion `
-Enable $false
Write-Host "Old key version disabled. Monitor for any access issues over the next 24 hours."
Wait 24-48 hours before considering deletion of the old key version. If any datasets fail to refresh during this period and fall back to needing the old key for an unwrap operation, you'll be glad you only disabled rather than deleted it.
Warning: Do not use Azure Key Vault's automatic key rotation feature for Power BI BYOK keys. Azure Key Vault can automatically rotate keys on a schedule, but if a new key version is generated by Key Vault before you update the Power BI capacity configuration, Power BI will continue using the old version URI it has on record. The new version won't be used until you explicitly update Power BI's configuration. Automatic rotation in Key Vault can create a confusing state where you think you've rotated but Power BI hasn't followed.
One of the key compliance arguments for BYOK is the ability to revoke data access. Understanding how this works in practice — and the consequences — is essential before you're in a crisis situation.
Option 1: Disable the Key (Least Destructive) Disabling the key in Key Vault prevents new wrap/unwrap operations. Datasets that are currently loaded in memory may remain accessible briefly (Power BI caches decrypted data in memory for active sessions), but no new data loads or refreshes will succeed.
# Emergency: Disable the encryption key to prevent further decryption
Update-AzKeyVaultKey `
-VaultName "kv-powerbi-byok-prod" `
-Name "powerbi-capacity-key-2024" `
-Enable $false
Re-enabling the key restores access, making this the recoverable option.
Option 2: Remove Power BI Service Principal Access This removes the Power BI service's ability to call Key Vault, without touching the key itself.
# Remove Key Vault access policy for the Power BI service principal
Remove-AzKeyVaultAccessPolicy `
-VaultName "kv-powerbi-byok-prod" `
-ObjectId $powerBISP.Id
This is reversible by re-adding the access policy.
Option 3: Delete the Key (Nuclear Option) With soft-delete and purge protection enabled, deletion moves the key to a soft-deleted state where it's unavailable for operations but can be recovered during the retention period. After the retention period, or if you purge it, the data is cryptographically destroyed — permanently inaccessible.
Document your revocation procedures and test them in a non-production environment. Regulators often want evidence that you've actually tested your revocation capability, not just that it exists on paper.
If you're piloting BYOK using Premium Per User licenses rather than Premium capacities, you need to understand a significant limitation: Premium Per User workspaces do not support BYOK encryption at the same level as Premium capacity.
PPU shares infrastructure differently from dedicated Premium capacities, and the capacity-level key assignment model doesn't map cleanly to the per-user licensing model. For regulatory compliance scenarios, PPU should be considered a development and testing environment for BYOK configuration procedures, not a production compliance solution. Your regulated workloads need P-SKU or EM-SKU Premium capacities with dedicated resources and full BYOK support.
This exercise walks you through the complete BYOK setup for a hypothetical financial services scenario. A regional bank is deploying Power BI Premium to host datasets containing aggregated transaction analytics (not raw PII, but still subject to FFIEC guidance on data protection). They need to demonstrate customer-controlled encryption for their next examination.
Environment Setup (complete before starting):
Step 1: Create the Key Vault
Create a Key Vault named kv-fnb-pbi-byok in resource group rg-fnb-powerbi-security in East US 2. Use the Premium SKU, enable soft-delete with 90-day retention, and enable purge protection. Document the vault URI.
Step 2: Generate the RSA Key
Create an HSM-backed RSA 4096-bit key named fnb-pbi-capacity-master-key with wrapKey and unwrapKey operations only. Set expiry to 365 days from today. Record the full versioned key URI.
Step 3: Grant Service Principal Access
Look up the Power BI service principal in your tenant (AppID: 00000009-0000-0000-c000-000000000000) and grant it get, wrapKey, and unwrapKey permissions on the Key Vault. Verify the access policy is correctly applied.
Step 4: Enable Diagnostic Logging
Create a Log Analytics workspace named law-fnb-keyvault-audit and enable Key Vault diagnostic logging to it, capturing AuditEvent category.
Step 5: Register and Assign the BYOK Key in Power BI
Using MicrosoftPowerBIMgmt, connect to Power BI as admin and register the key with the name FNB-CapacityKey-v1. Assign it to the "FNB-Analytics-Prod" capacity. Set it as the default.
Step 6: Generate Compliance Evidence
Run the encryption status report script against all datasets in workspaces on the capacity. Export to CSV. Run the Key Vault audit query in Log Analytics and export results. These two exports form the basis of your compliance evidence package.
Step 7: Simulate Key Rotation
Create a new version of the key, register it in Power BI as FNB-CapacityKey-v2, update the capacity assignment, verify the capacity shows the new key ID, then disable (not delete) the old key version. Confirm all datasets refresh successfully.
Verification Questions:
Encrypted status?Azure Key Vault provides two forms of key URI: versioned (https://vault.vault.azure.net/keys/keyname/versionhash) and unversioned (https://vault.vault.azure.net/keys/keyname). Power BI requires the versioned URI. Using the unversioned URI will either fail registration or, more confusingly, work initially but then not correctly track which key version Power BI is using after rotation.
Fix: Always retrieve the key after creation and use the .Key.Kid property, which includes the version hash.
If your Key Vault has a firewall enabled (restricting access to specific virtual networks or IP ranges), the Power BI service — which operates from Microsoft's service IPs — will be blocked from calling Key Vault. This manifests as registration succeeding but capacity key assignment failing, or intermittent refresh failures after BYOK is enabled.
Fix: Power BI BYOK requires that the Key Vault allow access from Azure trusted services. In the Key Vault network settings, enable "Allow trusted Microsoft services to bypass this firewall." This allows Power BI's managed service to access Key Vault without putting Power BI's dynamic IP ranges in your allowlist.
If you're using a private endpoint for Key Vault, the setup is more complex — Power BI's service cannot route through your private network, so you'll need to evaluate whether private endpoint + BYOK is architecturally compatible with your setup (in most cases, it's not without additional networking configuration).
This is a compliance documentation problem, not a technical one. BYOK covers Import mode datasets on Premium capacities. It does not cover:
If an auditor asks "is all data in Power BI encrypted with customer-managed keys?", the correct answer is "all Import mode dataset data in our BYOK-enabled Premium capacities is encrypted with our customer-managed key. Here is the scope documentation." Anything broader risks a finding when the auditor discovers DirectQuery workloads.
When you enable BYOK on a capacity with existing datasets, there's a window where those datasets have been imported but not yet re-encrypted with your key (they were encrypted with Microsoft-managed keys before BYOK was enabled). If an auditor looks at your data during this window and you haven't disclosed the transition period, it can look like a control failure.
Fix: Document the BYOK enablement date, the expected completion date (after all datasets have refreshed), and keep a timestamped encryption status report run before and after the transition.
Power BI Dataflows store their data in Azure Data Lake Storage Gen2 (when using ADLS integration) or in internal Power BI storage. BYOK for datasets does not automatically extend to dataflows. If your compliance scope includes dataflows, you need to separately configure encryption for ADLS-backed dataflows through the Azure Storage encryption settings, or use Power BI's separate dataflow encryption configuration.
If Add-PowerBIEncryptionKey returns an error about the key not being found:
00000009-0000-0000-c000-000000000000) exists in your tenant: Get-AzADServicePrincipal -ApplicationId "00000009-0000-0000-c000-000000000000" — in some tenants, this service principal may not be provisioned if Power BI has never been usedGet-AzKeyVaultAccessPolicy to verify)This is almost always the transition period issue. Run the encryption status report:
# Check specific dataset encryption status
$datasetStatus = Invoke-PowerBIRestMethod `
-Url "admin/datasets/{datasetId}" `
-Method Get | ConvertFrom-Json
$datasetStatus.Encryption.EncryptionStatus
If the status is NotEncrypted rather than EncryptionInProgress or Encrypted, trigger a manual refresh of the dataset. If it returns to Encrypted after refresh, BYOK is working correctly and the dataset simply hasn't been through a refresh cycle since BYOK was enabled.
If datasets continue to show NotEncrypted after a successful refresh, verify the capacity is correctly assigned to the BYOK key by checking Get-PowerBICapacity and confirming the EncryptionKeyId field is populated.
Enterprise Power BI deployments often involve multiple Premium capacities — separate capacities for development, testing, and production, or separate capacities for different business units or geographic regions. BYOK adds a key management dimension to this architecture that you need to plan carefully.
One Key Per Capacity vs. One Key Per Environment: You can use the same registered encryption key for multiple capacities, or use different keys for each. Separate keys per capacity provide stronger isolation — a compromise of one key doesn't expose another capacity's data — but increases key management overhead. In regulated industries, separate keys for production versus pre-production is a reasonable default.
Key Management in a Geo-Distributed Setup: If you have Premium capacities in multiple Azure regions (using Power BI's Multi-Geo feature for data residency), each regional capacity should ideally have its Key Vault in the same region. Cross-region Key Vault access works technically, but it introduces latency in key operations (which happen at every dataset refresh) and complicates your data sovereignty argument (your data is in Region A but your key management calls are going to Region B).
Key Governance: For large enterprises, consider Azure Managed HSM or Azure Dedicated HSM rather than standard Key Vault Premium for the highest-sensitivity workloads. These provide FIPS 140-3 Level 3 validated hardware and stronger guarantees about key export prevention. The trade-off is significantly higher cost and more complex management.
You now have a complete picture of Power BI BYOK from cryptographic architecture through operational management. Let's consolidate what we've covered:
The three-tier key hierarchy — your RSA key in Key Vault wrapping a capacity symmetric key that encrypts dataset data — is the foundation everything else builds on. Understanding this hierarchy helps you explain the compliance story accurately and make appropriate architectural decisions about key scope.
Configuration follows a specific sequence that matters: create and configure Key Vault, generate the RSA key with restricted operations, grant the Power BI service principal minimum necessary permissions, register the key at the tenant level, then assign to capacities. Skipping steps or doing them out of order leads to frustrating authentication errors.
BYOK scope is specific: Import mode datasets on Premium capacities. Your compliance documentation must explicitly state what is and is not covered, or you risk audit findings that could have been avoided with clear scoping.
Key rotation is an operational discipline, not a one-time task. Build your rotation procedures into runbooks, test them in non-production environments, and schedule rotation before key expiry dates.
Audit logging is not optional. Enable Key Vault diagnostic logging from day one. The audit log is your compliance evidence, and you cannot retroactively generate it.
Immediate actions:
Deeper exploration:
The regulatory landscape around cloud data sovereignty is continuing to evolve. BYOK is currently one of the strongest controls you can implement within the Power BI platform, but it's part of a broader data protection posture that also includes network security, identity governance, information protection labels, and sensitivity classification. Each of those warrants its own deep exploration.