├── .gitattributes ├── .gitignore ├── Administration ├── README.md ├── ReplaceAssetsWhenUserLeavesCompany.ps1 └── removeUnauthorizedEnvironments.ps1 ├── README.md ├── Reporting ├── README.md ├── findFlowsWithCommonDataService1.ps1 ├── findFlowsWithCustomConnectors.ps1 ├── findFlowsWithHttpAction.ps1 ├── findFlowsWithOnPremConnector.ps1 ├── findPowerAppsAsSharePointCustomForms.ps1 ├── findPowerAppsWithCustomConnectors.ps1 ├── findPowerAppsWithOnPremConnectors.ps1 └── findPowerAppsWithPremiumConnectors.ps1 ├── _config.yml └── azure-pipelines.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | .gitignore 14 | _config.yml 15 | .gitattributes 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | bld/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # DNX 48 | project.lock.json 49 | project.fragment.lock.json 50 | artifacts/ 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # NCrunch 118 | _NCrunch_* 119 | .*crunch*.local.xml 120 | nCrunchTemp_* 121 | 122 | # MightyMoose 123 | *.mm.* 124 | AutoTest.Net/ 125 | 126 | # Web workbench (sass) 127 | .sass-cache/ 128 | 129 | # Installshield output folder 130 | [Ee]xpress/ 131 | 132 | # DocProject is a documentation generator add-in 133 | DocProject/buildhelp/ 134 | DocProject/Help/*.HxT 135 | DocProject/Help/*.HxC 136 | DocProject/Help/*.hhc 137 | DocProject/Help/*.hhk 138 | DocProject/Help/*.hhp 139 | DocProject/Help/Html2 140 | DocProject/Help/html 141 | 142 | # Click-Once directory 143 | publish/ 144 | 145 | # Publish Web Output 146 | *.[Pp]ublish.xml 147 | *.azurePubxml 148 | # TODO: Comment the next line if you want to checkin your web deploy settings 149 | # but database connection strings (with potential passwords) will be unencrypted 150 | #*.pubxml 151 | *.publishproj 152 | 153 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 154 | # checkin your Azure Web App publish settings, but sensitive information contained 155 | # in these scripts will be unencrypted 156 | PublishScripts/ 157 | 158 | # NuGet Packages 159 | *.nupkg 160 | # The packages folder can be ignored because of Package Restore 161 | **/packages/* 162 | # except build/, which is used as an MSBuild target. 163 | !**/packages/build/ 164 | # Uncomment if necessary however generally it will be regenerated when needed 165 | #!**/packages/repositories.config 166 | # NuGet v3's project.json files produces more ignoreable files 167 | *.nuget.props 168 | *.nuget.targets 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.jfm 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # Since there are multiple workflows, uncomment next line to ignore bower_components 203 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 204 | #bower_components/ 205 | 206 | # RIA/Silverlight projects 207 | Generated_Code/ 208 | 209 | # Backup & report files from converting an old project file 210 | # to a newer Visual Studio version. Backup files are not needed, 211 | # because we have git ;-) 212 | _UpgradeReport_Files/ 213 | Backup*/ 214 | UpgradeLog*.XML 215 | UpgradeLog*.htm 216 | 217 | # SQL Server files 218 | *.mdf 219 | *.ldf 220 | 221 | # Business Intelligence projects 222 | *.rdl.data 223 | *.bim.layout 224 | *.bim_*.settings 225 | 226 | # Microsoft Fakes 227 | FakesAssemblies/ 228 | 229 | # GhostDoc plugin setting file 230 | *.GhostDoc.xml 231 | 232 | # Node.js Tools for Visual Studio 233 | .ntvs_analysis.dat 234 | 235 | # Visual Studio 6 build log 236 | *.plg 237 | 238 | # Visual Studio 6 workspace options file 239 | *.opt 240 | 241 | # Visual Studio LightSwitch build output 242 | **/*.HTMLClient/GeneratedArtifacts 243 | **/*.DesktopClient/GeneratedArtifacts 244 | **/*.DesktopClient/ModelManifest.xml 245 | **/*.Server/GeneratedArtifacts 246 | **/*.Server/ModelManifest.xml 247 | _Pvt_Extensions 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | paket-files/ 252 | 253 | # FAKE - F# Make 254 | .fake/ 255 | 256 | # JetBrains Rider 257 | .idea/ 258 | *.sln.iml 259 | 260 | # CodeRush 261 | .cr/ 262 | 263 | # Python Tools for Visual Studio (PTVS) 264 | __pycache__/ 265 | *.pyc -------------------------------------------------------------------------------- /Administration/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denise-msft/PowerAppsScripts/b2b8c3b7e641864907797fcae4a23e6f381f8b0a/Administration/README.md -------------------------------------------------------------------------------- /Administration/ReplaceAssetsWhenUserLeavesCompany.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Custom Connectors used in Flows 5 | 6 | PowerApps PowerShell installation instructions and documentation: 7 | https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 8 | 9 | Requirements: 10 | - Azure AD (PS module) (https://www.powershellgallery.com/packages/AzureAD/) 11 | - PowerApps Admin (PS module) (https://www.powershellgallery.com/packages/Microsoft.PowerApps.Administration.PowerShell) 12 | - Global tenant admin account or account with BAP Admin permissions 13 | - PowerApps Plan 2 license 14 | - Configure PS execution policy to remote signed (Set-ExecutionPolicy RemoteSigned) 15 | 16 | Example Input: 17 | .\UserLeftCompany.ps1 -Username "example@contoso.com" -Password "pass" -Leaver "meganb@bappartners.onmicrosoft.com" -Replacement "admin@bappartners.onmicrosoft.com" 18 | #> 19 | 20 | param ( 21 | [string]$Path = './appsAndFlowsWithNewOwners.csv', 22 | [Parameter(Mandatory=$true)] 23 | [string]$Username, 24 | [Parameter(Mandatory=$true)] 25 | [string]$Password, 26 | [Parameter(Mandatory=$true)] 27 | [string]$Leaver, 28 | [Parameter(Mandatory=$true)] 29 | [string]$Replacement 30 | ) 31 | 32 | # check if Azure AD module installed 33 | if (Get-Module -ListAvailable -Name AzureAD) 34 | { 35 | Write-Host 'Azure AD Module is already installed.' 36 | } 37 | else 38 | { 39 | $in = Read-Host -Prompt "Azure AD is not installed and is required to run this script. Install module? `n[Y] Yes [N] No" 40 | 41 | if ( $in -eq 'Y' -or $in -eq 'y' ) 42 | { 43 | Write-Host 'Installing Azure AD module.' 44 | Install-Module -Name AzureAD 45 | } 46 | elseif ( $in -eq 'N' -or $in -eq 'n') 47 | { 48 | Write-Host 'Cancelling operation. Azure AD module is required to run this script.' 49 | return 50 | } 51 | else 52 | { 53 | Write-Host "Command not recognized. Exiting script." 54 | } 55 | } 56 | 57 | # login to AAD and PowerApps 58 | $pass = ConvertTo-SecureString -String $Password -AsPlainText -Force 59 | $AzureAdCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $pass 60 | Connect-AzureAD -Credential $AzureAdCred 61 | Add-PowerAppsAccount -Username $Username -Password $pass 62 | 63 | Write-Progress -activity "Getting AAD User data" -status "Searching for users" -PercentComplete ((0/10) * 100) 64 | 65 | # get leaver and replacement user object 66 | $leaverObject = Get-AzureADUser -SearchString $Leaver 67 | $replacementObject = Get-AzureADUser -SearchString $Replacement 68 | 69 | $OutputObjectArray = @() 70 | $environments = Get-AdminPowerAppEnvironment 71 | 72 | # replace owner of apps currently owned by the leaver 73 | Write-Progress -activity "Discovering and replacing PowerApps owned by leaver ... " -status "Searching for PowerApps." -PercentComplete ((1/10) * 100) 74 | $apps = $environments | Get-AdminPowerApp -Owner $leaverObject.ObjectId 75 | Write-Progress -activity "Discovering and replacing PowerApps owned by leaver ... " -status "Replacing ownership ." -PercentComplete ((2/10) * 100) 76 | 77 | foreach($app in $apps) 78 | { 79 | $appDetails = @{ 80 | ResourceType = "PowerApp" 81 | EnvironmentName = $app.environmentName 82 | Name = $app.appName 83 | DisplayName = $app.displayName 84 | OwnerObjectId = $app.Owner.id 85 | OwnerDisplayName = $app.owner.displayName 86 | CreatedTime = $app.createdTime 87 | LastModifiedTime = $app.lastModifiedTime 88 | } 89 | $OutputObjectArray += $(new-object psobject -Property $appDetails) 90 | 91 | # replace owner 92 | $response = $app | Set-AdminPowerAppOwner -AppOwner $replacementObject.ObjectId 93 | #$response = $app | Set-AdminPowerAppOwner -AppOwner $leaverObject.ObjectId #test, reassign back to leaver 94 | } 95 | 96 | # add replacement user as owner of flows 97 | Write-Progress -activity "Discovering and replacing Flows owned by leaver ... " -status "Searching for Flows." -PercentComplete ((3/10) * 100) 98 | $flows = $environments | Get-AdminFlow -CreatedBy $leaverObject.ObjectId 99 | Write-Progress -activity "Discovering and replacing Flows owned by leaver ... " -status "Adding replacement user as owner to Flows." -PercentComplete ((4/10) * 100) 100 | 101 | foreach ($flow in $flows) 102 | { 103 | # get leaver's owner role record 104 | $ownerRoles = $flow | Get-AdminFlowOwnerRole -Owner $leaverObject.ObjectId 105 | foreach ($ownerRole in $ownerRoles) 106 | { 107 | $flowDetails = @{ 108 | ResourceType = "Flow" 109 | EnvironmentName = $flow.environmentName 110 | Name = $flow.flowName 111 | DisplayName = $flow.displayName 112 | OwnerObjectId = $flow.createdBy.ObjectId 113 | OwnerDisplayName = $leaverObject.displayName 114 | CreatedTime = $flow.createdTime 115 | LastModifiedTime = $flow.lastModifiedTime 116 | } 117 | #Write-Host $(new-object psobject -Property $flowDetails) 118 | $OutputObjectArray += $(new-object psobject -Property $flowDetails) 119 | 120 | # adds the replacement owner to the list of Flow owners 121 | $response = $flow | Set-AdminFlowOwnerRole -RoleName CanEdit -PrincipalType User -PrincipalObjectId $replacementObject.ObjectId 122 | } 123 | } 124 | 125 | 126 | # add replacement user as editor of shared connections 127 | Write-Progress -activity "Discovering and replacing Shared Connections owned by leaver ... " -status "Searching for Connections." -PercentComplete ((5/10) * 100) 128 | $connections = $environments | Get-AdminPowerAppConnection -CreatedBy $leaverObject.ObjectId 129 | Write-Progress -activity "Discovering and replacing Shared Connections owned by leaver ... " -status "Adding replacement user as editor of shared connections." -PercentComplete ((6/10) * 100) 130 | 131 | foreach ($connection in $connections) 132 | { 133 | $connectorDefinition = $connection | Get-PowerAppConnector -ReturnConnectorSwagger 134 | 135 | if ($connectorDefinition.internal.properties.metadata.allowSharing -eq $true) 136 | { 137 | $connectionDetails = @{ 138 | ResourceType = "Connection" 139 | EnvironmentName = $connection.environmentName 140 | Name = $connection.connectionName 141 | DisplayName = "[$($connectorDefinition.displayName)] $($connection.displayName)" 142 | OwnerObjectId = $connection.createdBy.id 143 | OwnerDisplayName = $leaverObject.displayName 144 | CreatedTime = $connection.createdTime 145 | LastModifiedTime = $connection.lastModifiedTime 146 | } 147 | 148 | #Write-Output $(new-object psobject -Property $connectionDetails) 149 | $OutputObjectArray += $(new-object psobject -Property $connectionDetails) 150 | 151 | # add replacement as connection owner 152 | $response = $connection | Set-AdminPowerAppConnectionRoleAssignment -RoleName 'CanEdit' -PrincipalType 'User' -PrincipalObjectId $replacementObject.ObjectId 153 | } 154 | } 155 | 156 | # add replacement user as editor of custom connectors 157 | Write-Progress -activity "Discovering and replacing Custom Connectors owned by leaver ... " -status "Searching for Custom Connectors." -PercentComplete ((7/10) * 100) 158 | $customConnectors = $environments | Get-AdminPowerAppConnector -CreatedBy $leaverObject.ObjectId 159 | Write-Progress -activity "Discovering and replacing Custom Connectors owned by leaver ... " -status "Adding replacement user as editor of Custom Connectors." -PercentComplete ((8/10) * 100) 160 | 161 | foreach ($connector in $customConnectors) 162 | { 163 | $connectorDetails = @{ 164 | ResourceType = "Custom Connector" 165 | EnvironmentName = $connector.environmentName 166 | Name = $connector.connectorName 167 | DisplayName = $connector.displayName 168 | OwnerObjectId = $connector.createdBy.id 169 | OwnerDisplayName = $connector.createdBy.displayName 170 | CreatedTime = $connector.createdTime 171 | LastModifiedTime = $connector.lastModifiedTime 172 | } 173 | #Write-Output $(new-object psobject -Property $connectorDetails) 174 | $OutputObjectArray += $(new-object psobject -Property $connectorDetails) 175 | 176 | $response = $connector | Set-AdminPowerAppConnectorRoleAssignment -RoleName 'CanEdit' -PrincipalType 'User' -PrincipalObjectId $replacementObject.ObjectId 177 | } 178 | 179 | Write-Progress -activity "Exporting data" -status "Generating CSV file and saving to $($OutputFilePath)" -PercentComplete ((9/10) * 100) 180 | 181 | $OutputObjectArray | Export-Csv -Path $Path -------------------------------------------------------------------------------- /Administration/removeUnauthorizedEnvironments.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(DefaultParameterSetName="Report")] 2 | param ( 3 | # Will only report on unauthorised environments 4 | [Parameter(ParameterSetName="Report")] 5 | [switch]$ReportOnly, 6 | # Provide the report path, note: report must end with .csv 7 | [Parameter(ParameterSetName="Report")] 8 | [string]$ReportPath, 9 | # List of approved environments 10 | [Parameter(ParameterSetName="Report")] 11 | [array]$ApprovedEnvironments, 12 | # Will run the script in removal mode 13 | [Parameter(ParameterSetName="Remove")] 14 | [switch]$RemoveUnauthorisedEnvironment, 15 | # You can provide an array of environments, note, this must be the environment GUID ('name' field) 16 | [Parameter(ParameterSetName="Remove")] 17 | [array]$EnvironmentGuid 18 | ) 19 | 20 | Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force 21 | 22 | if ( $ReportOnly ) 23 | { 24 | if ( Test-Path $ReportPath ) 25 | { 26 | Remove-Item $ReportPath 27 | } 28 | 29 | "DisplayName, EnvironmentName, CreatedTime, CreatedBy" | Out-File $ReportPath -Encoding ascii -Append 30 | 31 | $allEnvironments = Get-AdminEnvironment 32 | foreach ( $env in $allEnvironments ) 33 | { 34 | if( $ApprovedEnvironments -notcontains $env.DisplayName ) 35 | { 36 | $env.DisplayName + "," + $env.EnvironmentName + "," + $env.CreatedTime + "," + $env.CreatedBy.email | Out-File $ReportPath -Encoding ascii -Append 37 | } 38 | } 39 | } 40 | 41 | if ( $RemoveUnauthorisedEnvironment ) 42 | { 43 | foreach( $unauthorisedEnvironment in $EnvironmentGuid ) 44 | { 45 | Remove-AdminEnvironment -EnvironmentName $unauthorisedEnvironment 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerApps and Flow PowerShell Scripts 2 | Use PowerShell to automate ALM, Governance, and Administration activities on the Power Platform 3 | 4 | ### Notice 5 | These scripts are experimental and not officialy supported by Microsoft. They are intended to fill certain gaps with the authoring experience of PowerApps and Flow administration. Use them at your own discretion and risk. Please understand of the intended behavior of the script provided in the README (documentation) before running the scripts. 6 | 7 | ## Install the PowerApps modules 8 | See the documentation page [here](https://docs.microsoft.com/en-us/power-platform/admin/powerapps-powershell) for information on installation and requirements. 9 | 10 | ## Run the scripts 11 | Once the modules are installed, follow these instructions to run the scripts provided below. If you receive a security warning, you may need to unblock running the downloaded script, see [this article](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-6#powershell-execution-policies) for more details. 12 | 13 | 1. Download the desired script. 14 | 15 | 2. Run PowerShell as an administrator and make sure you’re in the same directory as the script. 16 | 17 | 3. Run the script by typing out the name 18 | 19 | .\findFlowsWithHttpAction.ps1 20 | 21 | 4. Each of these scripts have optional parameters to specify behavior, such as the Environment (EnvironmentName) or the output file path name (Path). Some of the scripts have mandatory parameters. More details on each parameter is provided in the subfolder's documentation. 22 | 23 | .\findFlowsWithHttpAction.ps1 -EnvironmentName 820d6103-3f73-4107-a1b2-3449a98f5049 -Path ./myFlowsWithHttp.csv 24 | 25 | 26 | ## Sections 27 | Based on the task, there are subfolders that hold multiple scripts to programmatically access the PowerApps and Flow APIs. 28 | 29 | ### [Reporting](./Reporting) 30 | Use the reporting scripts to help discover a filtered list of PowerApps or Flows based on some features they leverage. 31 | 32 | ### [Administration](./Administration) 33 | Automated administrative tasks, such as updating permissions or cleaning up unauthorized resources. 34 | -------------------------------------------------------------------------------- /Reporting/README.md: -------------------------------------------------------------------------------- 1 | # Reporting 2 | Use these scripts to discover PowerApps and Flows based on features, such as the connectors used or if it uses a data gateway. 3 | 4 |
5 | 6 | ## PowerApps 7 | Scripts to find PowerApps 8 | 9 | ### [PowerApps with Custom Connectors](./findPowerAppsWithCustomConnectors.ps1) 10 | 11 | Lists connections to custom connectors being used in a PowerApp. 12 | 13 | Input | Type | Description 14 | ---|---|--- 15 | Environment | string | Optional. The name (GUID) of the Environment. 16 | Path | string | Optional. The path and name for the output csv file. 17 | 18 | ### [PowerApps with Premium Connectors](./findPowerAppsWithCustomConnectors.ps1) 19 | Lists connections to premium connectors being used in a PowerApp. 20 | 21 | Input | Type | Description 22 | ---|---|--- 23 | Environment | string | Optional. The name (GUID) of the Environment. 24 | Path | string | Optional. The path and name for the output csv file. 25 | 26 | ### [PowerApps with on Prem Connectors using Data Gateway](./findPowerAppsWithOnPremConnectors.ps1) 27 | Lists connections to an On Premise gateway being used in a PowerApp. 28 | 29 | Input | Type | Description 30 | ---|---|--- 31 | Environment | string | Optional. The name (GUID) of the Environment. 32 | Path | string | Optional. The path and name for the output csv file. 33 | 34 | 35 | ### [PowerApps used as SharePoint custom forms](./findPowerAppsWithCustomConnectors.ps1) 36 | List PowerApps that are used as custom forms in the SharePoint List experience. 37 | 38 | Input | Type | Description 39 | ---|---|--- 40 | Environment | string | Optional. The name (GUID) of the Environment. 41 | Path | string | Optional. The path and name for the output csv file. 42 | 43 |
44 | 45 | 46 | ## Flows 47 | 48 | ### [Flows with HTTP Actions](./findFlowsWithHttpAction.ps1) 49 | Lists Flows that use the HTTP request action. 50 | 51 | Input | Type | Description 52 | ---|---|--- 53 | Environment | string | Optional. The name (GUID) of the Environment. 54 | Path | string | Optional. The path and name for the output csv file. 55 | 56 | ### [Flows with On Premise Connectors](./findFlowsWithOnPremConnector.ps1) 57 | Lists connections using an on premise gateway being used in a PowerApp. 58 | 59 | Input | Type | Description 60 | ---|---|--- 61 | Environment | string | Optional. The name (GUID) of the Environment. 62 | Path | string | Optional. The path and name for the output csv file. 63 | 64 | ### [Flows with Custom Connectors](./findFlowsWithCustomConnectors.ps1) 65 | Lists connections to custom connectors being used in a Flow. 66 | 67 | Input | Type | Description 68 | ---|---|--- 69 | **Username** | string | Required. The username of the admin account. 70 | **Password** | string | Required. The password of the admin account. 71 | Environment | string | Optional. The name (GUID) of the Environment. 72 | Path | string | Optional. The path and name for the output csv file. 73 | 74 | ### [Flows using the previous version Common Data Service](./findFlowsWithCommonDataService1.ps1) 75 | Lists connections to custom connectors being used in a Flow. 76 | 77 | Input | Type | Description 78 | ---|---|--- 79 | Environment | string | Optional. The name (GUID) of the Environment. 80 | Path | string | Optional. The path and name for the output csv file. 81 | -------------------------------------------------------------------------------- /Reporting/findFlowsWithCommonDataService1.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Flows using the Common Data Service 1.0 (old version) 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './flowsWithCds1.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $flows = Get-AdminFlow -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $flows = Get-AdminFlow 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through flows 26 | foreach ($flow in $flows) 27 | { 28 | $flowDetails = $flow | Get-AdminFlow 29 | 30 | # loop through each connection reference 31 | foreach($conRef in $flowDetails.Internal.properties.connectionReferences) 32 | { 33 | foreach($connection in $conRef) 34 | { 35 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 36 | { 37 | $connDetails = $($connection.$connId) 38 | if ($connDetails.id -eq '/providers/Microsoft.PowerApps/apis/shared_runtimeservice' ) 39 | { 40 | $row = @{ 41 | AffectedResourceType = 'Flow' 42 | DisplayName = $flowDetails.displayName 43 | Name = $flowDetails.flowName 44 | EnvironmentName = $flowDetails.environmentName 45 | ConnectorDisplayName = $connDetails.displayName 46 | ConnectionId = $connDetails.id 47 | ConnectionName = $connDetails.connectionName 48 | CreatedByObjectId = $flowDetails.internal.properties.creator.objectId 49 | } 50 | $premiumFeatures += $(new-object psobject -Property $row) 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | $premiumFeatures | Export-Csv -Path $Path 58 | -------------------------------------------------------------------------------- /Reporting/findFlowsWithCustomConnectors.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Custom Connectors used in Flows 5 | 6 | PowerApps PowerShell installation instructions and documentation: 7 | https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 8 | 9 | Requirements: 10 | - Azure AD (PS module) (https://www.powershellgallery.com/packages/AzureAD/) 11 | - PowerApps Admin (PS module) (https://www.powershellgallery.com/packages/Microsoft.PowerApps.Administration.PowerShell) 12 | - Global tenant admin account or account with BAP Admin permissions 13 | - PowerApps Plan 2 license 14 | - Configure PS execution policy to remote signed (Set-ExecutionPolicy RemoteSigned) 15 | 16 | Example Input: 17 | .\findFlowsWithCustomConnectors 18 | #> 19 | 20 | param( 21 | [string]$EnvironmentName, 22 | [string]$Path = './flowsWithCustomConnectors.csv', 23 | [Parameter(Mandatory=$true)] 24 | [string]$Username, 25 | [Parameter(Mandatory=$true)] 26 | [string]$Password 27 | ) 28 | 29 | # check if Azure AD module installed 30 | if (Get-Module -ListAvailable -Name AzureAD) 31 | { 32 | Write-Host 'Azure AD Module is already installed.' 33 | } 34 | else 35 | { 36 | $in = Read-Host -Prompt "Azure AD is not installed and is required to run this script. Install module? `n[Y] Yes [N] No" 37 | 38 | if ( $in -eq 'Y' -or $in -eq 'y' ) 39 | { 40 | Write-Host 'Installing Azure AD module.' 41 | Install-Module -Name AzureAD 42 | } 43 | elseif ( $in -eq 'N' -or $in -eq 'n') 44 | { 45 | Write-Host 'Cancelling operation. Azure AD module is required to run this script.' 46 | return 47 | } 48 | else 49 | { 50 | Write-Host "Command not recognized. Exiting script." 51 | } 52 | } 53 | 54 | # convert password to secure string and login to AAD 55 | $pass = ConvertTo-SecureString -String $Password -AsPlainText -Force 56 | $AzureAdCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $pass 57 | Connect-AzureAD -Credential $AzureAdCred 58 | 59 | # login to PowerApps 60 | Add-PowerAppsAccount -Username $Username -Password $pass 61 | 62 | # branch to specific environment if provided, else search all environments 63 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 64 | { 65 | $flows = Get-AdminFlow -EnvironmentName $EnvironmentName 66 | } 67 | else 68 | { 69 | $flows = Get-AdminFlow 70 | } 71 | 72 | $premiumFeatures = @() 73 | 74 | # loop through flows 75 | foreach ($flow in $flows) 76 | { 77 | $flowDetails = $flow | Get-AdminFlow 78 | 79 | # loop through each connection reference 80 | foreach($conRef in $flowDetails.Internal.properties.connectionReferences) 81 | { 82 | foreach($connection in $conRef) 83 | { 84 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 85 | { 86 | $connDetails = $($connection.$connId) 87 | if ($connDetails.apiDefinition.properties.isCustomApi) 88 | { 89 | $creator = Get-AzureADUser -ObjectId $flowDetails.internal.properties.creator.objectId 90 | $row = @{ 91 | AffectedResourceType = 'Flow' 92 | DisplayName = $flowDetails.displayName 93 | Name = $flowDetails.flowName 94 | EnvironmentName = $flowDetails.environmentName 95 | ConnectorDisplayName = $connDetails.displayName 96 | ConnectionId = $connDetails.id 97 | ConnectionName = $connDetails.connectionName 98 | CreatedByObjectId = $creator.objectId 99 | CreatedByUserPrincipalName = $creator.UserPrincipalName 100 | IsCustomApiConnection = $connDetails.apiDefinition.properties.isCustomApi 101 | } 102 | $premiumFeatures += $(new-object psobject -Property $row) 103 | } 104 | } 105 | } 106 | } 107 | } 108 | 109 | $premiumFeatures | Export-Csv -Path $Path -------------------------------------------------------------------------------- /Reporting/findFlowsWithHttpAction.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - HTTP Actions used in Flows 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './flowsWithHttpAction.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $flows = Get-AdminFlow -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $flows = Get-AdminFlow 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through flows 26 | foreach ($flow in $flows) 27 | { 28 | $flowDetails = $flow | Get-AdminFlow 29 | 30 | # check if flow uses HTTP action 31 | if ($flowDetails.Internal.properties.definitionSummary.actions -match 'Http') 32 | { 33 | $row = @{ 34 | AffectedResourceType = 'Flow' 35 | DisplayName = $flowDetails.displayName 36 | Name = $flowDetails.flowName 37 | EnvironmentName = $flowDetails.environmentName 38 | ConnectorDisplayName = 'HTTP Action' 39 | CreatedByObjectId = $flowDetails.internal.properties.creator.objectId 40 | IsHttpAction = $true 41 | } 42 | $premiumFeatures += $(new-object psobject -Property $row) 43 | } 44 | } 45 | 46 | $premiumFeatures | Export-Csv -Path $Path 47 | -------------------------------------------------------------------------------- /Reporting/findFlowsWithOnPremConnector.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - HTTP Actions used in Flows 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './flowsWithCustomConnectors.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $flows = Get-AdminFlow -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $flows = Get-AdminFlow 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through flows 26 | foreach ($flow in $flows) 27 | { 28 | $flowDetails = $flow | Get-AdminFlow 29 | 30 | # loop through each connection reference 31 | foreach($conRef in $flowDetails.Internal.properties.connectionReferences) 32 | { 33 | foreach($connection in $conRef) 34 | { 35 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 36 | { 37 | $connDetails = $($connection.$connId) 38 | if ($connDetails.apiDefinition.properties.isCustomApi) 39 | { 40 | $row = @{ 41 | AffectedResourceType = 'Flow' 42 | DisplayName = $flowDetails.displayName 43 | Name = $flowDetails.flowName 44 | EnvironmentName = $flowDetails.environmentName 45 | ConnectorDisplayName = $connDetails.displayName 46 | ConnectionId = $connDetails.id 47 | ConnectionName = $connDetails.connectionName 48 | CreatedByObjectId = $flowDetails.internal.properties.creator.objectId 49 | IsCustomApiConnection = $connDetails.apiDefinition.properties.isCustomApi 50 | } 51 | $premiumFeatures += $(new-object psobject -Property $row) 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | $premiumFeatures | Export-Csv -Path $Path 59 | -------------------------------------------------------------------------------- /Reporting/findPowerAppsAsSharePointCustomForms.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | # Provide the report path, note: report must end with .csv 3 | [string]$Path 4 | ) 5 | 6 | # Decsription: 7 | # PowerShell script to report on PowerApps created from SharePoint. 8 | # Produces a report (.csv) 9 | # This script correlates to Item 21 on the PowerApps O365 DSE work. 10 | # 11 | # Date: 21st January 2019 12 | # Author: Steve Jeffery (stjeffer@microsoft.com) 13 | 14 | #Import-Module .\Microsoft.PowerApps.Administration.PowerShell.psm1 15 | #Import-Module .\Microsoft.PowerApps.PowerShell.psm1 16 | 17 | if (Test-Path $ReportPath) { 18 | Remove-Item $ReportPath 19 | } 20 | "App Name, CreatedTime, App Maker, App Location" | Out-File $ReportPath -Encoding ascii -Append 21 | 22 | $collApps = Get-AdminPowerApp | Where-Object {$_.Internal.tags.primaryFormFactor -eq "Web"} | Select-Object -ExpandProperty 'Internal' | Select-Object -ExpandProperty 'Properties' | Select-Object displayName, createdTime, lastModifiedTime, @{Name="createdBy"; Expression={$_.CreatedBy.email}}, @{Name="listUrl"; Expression={$_.embeddedApp.listUrl}} 23 | 24 | foreach ($app in $collApps) 25 | { 26 | $appName = $app.displayName 27 | $appCreated = $app.createdTime 28 | $appMaker = $app.createdBy 29 | $appLocation = $app.listUrl 30 | 31 | $appName + "," + $appCreated + "," + $appMaker + "," + $appLocation | Out-File $ReportPath -Append -Encoding ascii 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /Reporting/findPowerAppsWithCustomConnectors.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Custom API Connections used in PowerApps 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './powerAppsPremiumConnections.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $apps = Get-AdminPowerApp -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $apps = Get-AdminPowerApp 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through each app 26 | foreach ($app in $apps) 27 | { 28 | # loop through each connection reference 29 | foreach($conRef in $app.Internal.properties.connectionReferences) 30 | { 31 | foreach($connection in $conRef) 32 | { 33 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 34 | { 35 | $connDetails = $($connection.$connId) 36 | 37 | # save connection details if the connector is custom 38 | if ($connDetails.isCustomApiConnection) 39 | { 40 | $row = @{ 41 | ResourceType = 'PowerApp' 42 | DisplayName = $app.displayName 43 | Name = $app.appName 44 | EnvironmentName = $app.environmentName 45 | ConnectorDisplayName = $connDetails.displayName 46 | ConnectionId = $connDetails.id 47 | ConnectionName = $connDetails.connectionName 48 | CreatedByObjectId = $app.owner.id 49 | CreatedByEmail = $app.owner.email 50 | IsCustomApiConnection = $connDetails.isCustomApiConnection 51 | } 52 | $premiumFeatures += $(new-object psobject -Property $row) 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | $premiumFeatures | Export-Csv -Path $Path 60 | -------------------------------------------------------------------------------- /Reporting/findPowerAppsWithOnPremConnectors.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent each premium feature found in PowerApps and Flows 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Connections to On Prem Connectors used in PowerApps 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './powerAppsOnPremConnections.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $apps = Get-AdminPowerApp -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $apps = Get-AdminPowerApp 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through each app 26 | foreach ($app in $apps) 27 | { 28 | # loop through each connection reference 29 | foreach($conRef in $app.Internal.properties.connectionReferences) 30 | { 31 | foreach($connection in $conRef) 32 | { 33 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 34 | { 35 | $connDetails = $($connection.$connId) 36 | 37 | # save connection details if the connector is on prem 38 | if ($connDetails.isOnPremiseConnection) 39 | { 40 | $row = @{ 41 | ResourceType = 'PowerApp' 42 | DisplayName = $app.displayName 43 | Name = $app.appName 44 | EnvironmentName = $app.environmentName 45 | ConnectorDisplayName = $connDetails.displayName 46 | ConnectionId = $connDetails.id 47 | ConnectionName = $connDetails.connectionName 48 | CreatedByObjectId = $app.owner.id 49 | CreatedByEmail = $app.owner.email 50 | IsOnPremiseConnection = $connDetails.isOnPremiseConnection 51 | } 52 | $premiumFeatures += $(new-object psobject -Property $row) 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | # output to file 60 | $premiumFeatures | Export-Csv -Path $Path 61 | -------------------------------------------------------------------------------- /Reporting/findPowerAppsWithPremiumConnectors.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Outputs a .csv file of records that represent a premium feature found in PowerApps and Flow 3 | throughout the tenant it is run in. Result feature records will include: 4 | - Connections to Premium Connectors used in PowerApps 5 | 6 | PowerApps PowerShell installation instructions and documentation: https://docs.microsoft.com/en-us/powerapps/administrator/powerapps-powershell 7 | #> 8 | 9 | param( 10 | [string]$EnvironmentName, 11 | [string]$Path = './powerAppsPremiumConnections.csv' 12 | ) 13 | 14 | if (-not [string]::isNullOrEmpty($EnvironmentName)) 15 | { 16 | $apps = Get-AdminPowerApp -EnvironmentName $EnvironmentName 17 | } 18 | else 19 | { 20 | $apps = Get-AdminPowerApp 21 | } 22 | 23 | $premiumFeatures = @() 24 | 25 | # loop through each app 26 | foreach ($app in $apps) 27 | { 28 | # loop through each connection reference 29 | foreach($conRef in $app.Internal.properties.connectionReferences) 30 | { 31 | foreach($connection in $conRef) 32 | { 33 | foreach ($connId in ($connection | Get-Member -MemberType NoteProperty).Name) 34 | { 35 | $connDetails = $($connection.$connId) 36 | 37 | # save connection details if the connector is premium 38 | if ($connDetails.apiTier -eq 'Premium') 39 | { 40 | $row = @{ 41 | ResourceType = 'PowerApp' 42 | DisplayName = $app.displayName 43 | Name = $app.appName 44 | EnvironmentName = $app.environmentName 45 | ConnectorDisplayName = $connDetails.displayName 46 | ConnectionId = $connDetails.id 47 | ConnectionName = $connDetails.connectionName 48 | CreatedByObjectId = $app.owner.id 49 | CreatedByEmail = $app.owner.email 50 | IsPremiumConnector = $connDetails.apiTier -eq 'Premium' 51 | } 52 | $premiumFeatures += $(new-object psobject -Property $row) 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | # output to file 60 | $premiumFeatures | Export-Csv -Path $Path 61 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | # Start with a minimal pipeline that you can customize to build and deploy your code. 3 | # Add steps that build, run tests, deploy, and more: 4 | # https://aka.ms/yaml 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'Ubuntu-16.04' 11 | 12 | steps: 13 | - script: echo Hello, world! 14 | displayName: 'Run a one-line script' 15 | 16 | - script: | 17 | echo Add other tasks to build, test, and deploy your project. 18 | echo See https://aka.ms/yaml 19 | displayName: 'Run a multi-line script' 20 | --------------------------------------------------------------------------------