├── .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 |
--------------------------------------------------------------------------------