There is no doubt that I am an insanely frugal person when it comes to some things. Why pay for French's Yellow Mustard when Kroger brand is literally the same product? Why buy two-ply toilet paper when single-ply is all you need?! (Just kidding… Ultra-ply for life). The same holds true for my license purchases. If I can make something work without a subscription, or with a cheaper subscription, why would I pay for the more expensive subscription?
Well, there are good reasons. Yet sometimes you just don't have the buy-in from your company for licensing. If this is the case, then this is the post for you! We're going to build a “frugal” version of a Power App that connects with ConfigMgr to avoid needing a premium Power Apps license. What exactly are we saving by going the frugal route?
Base licensing for Power Apps is included with O365 E3/E5 licenses - which is great. Premium licensing for the Power Apps platform is… not cheap. You need to get premium licensing when you get into using features like… custom connectors for REST API endpoints…
The custom connector is a PREMIUM feature? And herein lies my frustration with the Power Platform - I understand that Microsoft needs to make money, but the base license included with O365 is woefully inadequate in my opinion. You can create some cool things in Power Apps alone with the base license, but when you start to bring together other environments (SQL, for example) you better have a good use case to justify the cost to your executive team. There are some free connectors (such as Azure AD and SharePoint) but the list is not really expansive.
How much does it cost? For Power Apps using premium features, you can pay $10/user/month… for two apps and a single portal. You can get unlimited apps and portals for $40/user/month. And that is not the licensing cost for the developer of the application - that is for anyone USING the application with the premium feature.
Needless to say, if you want to empower your end users with an app you created in a 2000 user environment… you're looking at $240,000 PER YEAR (or $960,000 if you're going literally full broke with the unlimited license)… frankly, you may as well pay an outside firm to write a mobile app for you.
I certainly hope Microsoft reconsiders this licensing scheme (*Microsoft laughs while Scrooge McDucking in a giant vault of cash*), but until that time comes let's look at a way we can accomplish some basic ConfigMgr integration using a non-premium connector as our conduit for communication.
Let's talk about scalability first. I wouldn't call this method scalable in any sense of the word. First, working with a large dataset and SharePoint lists via PowerShell isn't exactly quick. It does alright, but I could see this being so incredibly painful if you had like 10,000 users and 1,000. Additionally, there are limitations to the amount of data you can pull into Power Apps - this is the “delegation” problem. You can read more about that in the Understand delegation in a canvas app document. I'm not going to cover it in this post - in a future post we'll talk about some mitigation techniques as we build a more proper ConfigMgr Power App.
So the two things to be aware of here are: our app data is going to be limited to 500 rows per data source and the backend scripts to manage our SharePoint lists are going to be slow. But hey, this is just our “Hello, World!” app - it doesn't have to be perfect. It's more like a proof of concept.
What Are We Building?
So, what exactly are we building here? A common thing I see in many ConfigMgr environments is using collections to manage application deployments - add a device or user to the collection and badda bing badda boom the application deploys. This, however, requires access to the ConfigMgr console (unless you're using a custom PowerShell script or security groups as members of the collection). Also, it generally requires you to be on the network. Wouldn't it be cool if you could add a device or user to the collection from your mobile phone when you get a call while you're on lunch? Here's what that might look like:
Step 1: Create SharePoint Lists
Since we're not creating a direct connection to ConfigMgr through the AdminService (REST API… custom connector) we need something to handle the data that our app needs (users, devices, collections) and something to handle the instructions sent to ConfigMgr (add resource to collection). Since SharePoint lists are a non-premium connector in Power Apps and are accessible externally and internally (firewall and conditional access dependent) they seem like a great conduit for our purpose.
We're going to create three lists here:
CollectionList: a list of the collections (device and user) available in ConfigMgr
ResourceList: a list of the resources (device, user, and group) available in ConfigMgr
ProcessingList: a list of instructions to send to ConfigMgr
This list will contain the following fields:
Collection Name: the name of the collection to display in the Power App
CollectionType: the type of the collection (device or user)
CollectionDescription: the description of the collection to display in the Power App
This list will contain the following fields:
Resource Name: the name of the resource to display in the Power App
ResourceType: the type of the resource (device, user, or group)
ResourceId: the id of the resource which we'll pass to the processing list
This list will contain the following fields:
Collection Name: the name of the collection we're adding a resource to
ResourceId: the id of the resource we're adding
ResourceType: because the command is different for user or device we'll define that here
Completed: a field to track whether ConfigMgr has already executed this instruction
Details: a field to log any errors encountered in the process
The list will need to be accessible to an account that we'll configure for both the PowerShell scripts and the Power App. May I suggest storing the lists in a site accessible only to that account and anyone who might need to see the data?
If you would like a straightforward way to create these three lists, my GitHub repo has scripts to create these using the SharePoint Patterns and Practices PowerShell module. We'll also be using this module to manage the lists and instructions.
Step 2: Create Scripts to Manage Lists and Instructions
The second crucial step to making this function is scripts. We need PowerShell scripts to handle the instructions that ConfigMgr should be processing in addition to scripts for managing the collection list and application list.
Create Script to Manage Collection List
First, we need a script to send the available collections to the list. It should probably remove collections from the list that no longer exist too. Also, we should ignore all the collections with an id beginning with SMS (the built-in collections). None of this is ridiculously hard to do with the ConfigMgr PowerShell module and the SharePoint Patterns and Practices modules. I would love for you to try this on your own first, but if you don't want to put the effort in or get stuck somewhere along the way, “Export-CMCollectionsToSharePointList.ps1” on the GitHub repo above is the script you want to check out.
Create Script to Manage Resources List
Second, we need a script to send the available devices, users, and groups to the list. We definitely want to exclude the “Unknown Computer” objects as well as this thing called “Provisioning Device”. Again, I would love for you to try this yourself, but I went ahead and did the work for you in the “Export-CMResourcesToSharePointList.ps1” in that same GitHub repo.
Create Script to Handle Monitoring of and Execution against Processing List
Finally, we need a script to execute the processing list. We need to get the instructions from the list and then execute them. We should probably exclude anything that we've already done before. Also, if there are errors, we might want to write those back to the list for administrators to review. This script is called “Invoke-ProcessCMActionsFromSharePoint.ps1” in the repo.
Run the Scripts on a Schedule!
Okay, one more step. We should set up these scripts to run on a schedule. I'll let you use whatever tool you want - it's not important. What is important is to make sure you run the processing list script frequently enough to make it worthwhile.
After you run the scripts, check the lists to make sure you're getting the data that you're expecting. If you used my scripts, the lists are hidden so you may need to type in the path to the list manually. You can modify this in the scripts by locating the -Hidden:$true parameter and changing it to -Hidden:$false.
Since this post is already long, we're going to end here. In the next post we'll build our Power App and connect it all together. Until then, I suggest you play around with the Power Apps interface a little bit to familiarize yourself - you can access it from https://create.powerapps.com. If you want a free license for individual use (read: testing) you can get a free Community Plan through this link: https://powerapps.microsoft.com/en-us/communityplan/.
Until the next post, happy admining!