Skip to content
Back to Blog
1 min read

Power Platform Managed Environments: Enterprise Governance at Scale

What Are Managed Environments?

Managed Environments provide a set of premium governance capabilities:

  • Usage insights: Detailed analytics on environment usage
  • Sharing limits: Control who can share apps and flows
  • Solution checker enforcement: Mandatory quality checks
  • Data policies: Enhanced data loss prevention
  • Weekly digest: Automated reports to administrators

Enabling Managed Environments

Enable through the Power Platform Admin Center or PowerShell:

# Install the Power Platform Administration module
Install-Module -Name Microsoft.PowerApps.Administration.PowerShell

# Connect to Power Platform
Add-PowerAppsAccount

# Get the environment
$env = Get-AdminPowerAppEnvironment -EnvironmentName "Production"

# Enable managed environment
Set-AdminPowerAppEnvironmentGovernanceConfiguration `
    -EnvironmentName $env.EnvironmentName `
    -EnableManagedEnvironment $true

Setting Sharing Limits

Control how apps and flows can be shared:

# Configure sharing limits
Set-AdminPowerAppEnvironmentGovernanceConfiguration `
    -EnvironmentName "Production" `
    -EnableManagedEnvironment $true `
    -LimitSharingMode "ExcludeSharingToSecurityGroups" `
    -MaxShareLimit 20

# More restrictive: Only allow sharing with specific security groups
Set-AdminPowerAppEnvironmentGovernanceConfiguration `
    -EnvironmentName "Production" `
    -LimitSharingMode "OnlyShareWithSecurityGroups" `
    -ShareTargetSecurityGroups @(
        "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "b2c3d4e5-f6a7-8901-bcde-f12345678901"
    )

Solution Checker Enforcement

Require all solutions to pass quality checks:

# Enable solution checker
Set-AdminPowerAppEnvironmentGovernanceConfiguration `
    -EnvironmentName "Production" `
    -EnableSolutionChecker $true `
    -SolutionCheckerMode "Block" `
    -SolutionCheckerRuleset "AppSource"

When developing solutions, run the checker locally:

# Check a solution before deployment
$results = Invoke-PowerAppChecker `
    -EnvironmentUrl "https://yourorg.crm.dynamics.com" `
    -SolutionPath "MySolution.zip" `
    -RuleSet "AppSource"

# Review results
$results.IssueSummary | Format-Table

# Critical issues will block deployment in managed environments
$results.Issues | Where-Object { $_.Severity -eq "Critical" }

Data Loss Prevention Policies

Create comprehensive DLP policies:

# Create a new DLP policy
$policy = New-DlpPolicy -DisplayName "Enterprise Data Policy" `
    -EnvironmentType "Production"

# Define connector groups
$businessConnectors = @(
    "shared_office365",
    "shared_sharepointonline",
    "shared_dynamicscrmOnline",
    "shared_sql",
    "shared_azureblob"
)

$blockedConnectors = @(
    "shared_twitter",
    "shared_facebook",
    "shared_dropbox"
)

# Configure the policy
Set-DlpPolicy -PolicyName $policy.Name `
    -BusinessDataGroup $businessConnectors `
    -BlockedGroup $blockedConnectors `
    -DefaultGroup "NonBusiness"

# Apply to specific environments
Add-DlpPolicyEnvironment -PolicyName $policy.Name `
    -EnvironmentName "Production"

Custom Connectors Governance

Control custom connector creation and usage:

# Get existing custom connectors
$connectors = Get-AdminPowerAppConnector -EnvironmentName "Production" `
    | Where-Object { $_.Properties.apiDefinitions.originalSwaggerUrl -ne $null }

# Review connector details
$connectors | ForEach-Object {
    [PSCustomObject]@{
        Name = $_.DisplayName
        Publisher = $_.Properties.publisher
        Tier = $_.Properties.tier
        CreatedBy = $_.Properties.createdBy.email
        CreatedTime = $_.Properties.createdTime
    }
} | Format-Table

# Add custom connector to DLP policy
$customConnectorId = "shared_mycompanyapi"
Add-DlpPolicyConnector -PolicyName "Enterprise Data Policy" `
    -ConnectorId $customConnectorId `
    -Group "Business"

Weekly Digest Configuration

Set up automated governance reports:

# Configure weekly digest recipients
Set-AdminPowerAppEnvironmentGovernanceConfiguration `
    -EnvironmentName "Production" `
    -EnableWeeklyDigest $true `
    -WeeklyDigestRecipients @(
        "admin@company.com",
        "governance-team@company.com"
    )

The digest includes:

  • New apps created
  • Apps shared broadly
  • Flows with errors
  • Connector usage statistics
  • Policy violations

Usage Insights with Power BI

Create custom governance dashboards:

// Power Query to fetch environment analytics
let
    Source = OData.Feed(
        "https://yourorg.api.crm.dynamics.com/api/data/v9.2/",
        null,
        [Implementation = "2.0"]
    ),

    // Get Power Apps usage
    apps = Source{[Name="workflows"]}[Data],

    // Filter and transform
    filteredApps = Table.SelectRows(apps, each [statecode] = 1),

    // Add calculated columns
    enriched = Table.AddColumn(filteredApps, "DaysSinceModified",
        each Duration.Days(DateTime.LocalNow() - [modifiedon]))

in
    enriched

DAX measures for governance metrics:

// Apps not modified in 90 days
Stale Apps =
CALCULATE(
    COUNTROWS(Apps),
    Apps[DaysSinceModified] > 90
)

// Apps shared with everyone
Broadly Shared Apps =
CALCULATE(
    COUNTROWS(Apps),
    Apps[ShareLevel] = "Organization"
)

// Policy violation trend
Violations This Month =
CALCULATE(
    COUNTROWS(PolicyViolations),
    DATESMTD(PolicyViolations[Date])
)

Environment Lifecycle Management

Automate environment provisioning with governance:

# Create a new managed environment
function New-ManagedEnvironment {
    param(
        [string]$DisplayName,
        [string]$Location,
        [string]$Purpose,
        [string[]]$Admins
    )

    # Create the environment
    $env = New-AdminPowerAppEnvironment `
        -DisplayName $DisplayName `
        -LocationName $Location `
        -EnvironmentSku "Production" `
        -ProvisionDatabase $true

    # Wait for provisioning
    do {
        Start-Sleep -Seconds 30
        $env = Get-AdminPowerAppEnvironment -EnvironmentName $env.EnvironmentName
    } while ($env.CommonDataServiceDatabaseProvisioningState -ne "Succeeded")

    # Enable managed environment
    Set-AdminPowerAppEnvironmentGovernanceConfiguration `
        -EnvironmentName $env.EnvironmentName `
        -EnableManagedEnvironment $true `
        -EnableSolutionChecker $true `
        -EnableWeeklyDigest $true

    # Assign administrators
    foreach ($admin in $Admins) {
        Set-AdminPowerAppEnvironmentRoleAssignment `
            -EnvironmentName $env.EnvironmentName `
            -PrincipalType "User" `
            -PrincipalObjectId $admin `
            -RoleName "Environment Admin"
    }

    # Apply DLP policy
    Add-DlpPolicyEnvironment `
        -PolicyName "Enterprise Data Policy" `
        -EnvironmentName $env.EnvironmentName

    return $env
}

# Usage
$newEnv = New-ManagedEnvironment `
    -DisplayName "Sales Department - Production" `
    -Location "unitedstates" `
    -Purpose "Sales team applications" `
    -Admins @("admin1@company.com", "admin2@company.com")

Monitoring with Azure Monitor

Export Power Platform analytics to Azure:

// Bicep template for analytics infrastructure
param location string = resourceGroup().location
param workspaceName string

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
  name: workspaceName
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
    retentionInDays: 90
  }
}

resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'PowerPlatformDiagnostics'
  properties: {
    workspaceId: logAnalytics.id
    logs: [
      {
        category: 'PowerAppsAnalytics'
        enabled: true
      }
      {
        category: 'PowerAutomateAnalytics'
        enabled: true
      }
    ]
  }
}

KQL queries for monitoring:

// Apps with high error rates
PowerAppsAnalytics
| where TimeGenerated > ago(7d)
| where EventType == "AppError"
| summarize ErrorCount = count() by AppName, AppId
| where ErrorCount > 10
| order by ErrorCount desc

// Flow failures by connector
PowerAutomateAnalytics
| where TimeGenerated > ago(24h)
| where Status == "Failed"
| extend ConnectorName = tostring(parse_json(ActionDetails).connectorName)
| summarize Failures = count() by ConnectorName
| order by Failures desc

Managed Environments represent a significant maturation of Power Platform governance. For enterprises that want to enable citizen development while maintaining control, these features are essential.

Resources

Michael John Pena

Michael John Pena

Data & AI Director and Microsoft MVP based in Sydney. Writing about Microsoft Fabric, Azure, data engineering, and AI.