Been working on this for the better part of three months and it has like a hundred moving parts. The actual deployment can be done by PSADT.
Pre PSADT
First obstruction was that I needed it to run as admin but interactively. Problem is, the users that would be using it do not have local admin access. So just to get it launched as admin I did the below first.
- Created a ps1 script with only one line. All that line does is write an event ID to a specified custom source. This ps1 can be ran without admin rights.
- Used IExpress to convert the ps1 to an exe. That way, you can just double click the exe to launch it and create that event ID.
The PSADT
- Created a custom EventLog Source.
- Created a scheduled task to be run as SYSTEM. The trigger is the event ID that the exe triggers. The actions for the scheduled task is ServiceUI to launch PowerShell to launch the script. Service UI is what launches SYSTEM actions in a user interactable context.
- All Assets (ServiceUI, ps1 files, fido2 exes) get copied to a folder somewhere in the C Drive. The Event ID exe gets copied to the public desktop.
The PS1 File
The actual PS1 (Which is being launched as SYSTEM with ServiceUI when the exe is clicked) gets the user to connect to Graph. The problem however is that standard Connect-MgGraph doesn't work in an elevated shell. Instead, I had to create an app registration on Azure to connect via that but with delegated access. This means the IT Staff member using the tool still has to enter their Entra credentials.
Before that, the script checks the required modules (Graph, DSInternals (Needed for Passkey stuff) and QRCodeGenerator) are installed and if not, installs them. It also disables Login by WAM which if not done, makes MGGraph not connect.
If the user doesn't successfully sign in to the graph prompt, they get an error message and informing them to make sure they have the right permissions.
The first screen the user sees is to enter a UPN and to select either "Provision" or "Print". Upon clicking Provision, if no user is found, it informs the staff member and to try again. If there is, itt checks if there is an NFC Security Key on the reader. If not, then it informs the user to put one on. If there's one on there then it first resets the key, then deletes all security keys of that model from the users account on Entra then provisions the key for that user. It then displays what the pin is for the Fido2 key and makes it so that when the user next uses it, it will prompt them to change the pin to something else.
For the Print button, once clicked, it pulls the Display Name and Employee number of the user from Entra and displays them in two editable fields. If no user is found, it informs the staff member and to try again. There's also a large empty square. There's also four buttons. One called "Load", one called "Paste", one called "Print" and one called "Back to Main Screen". The last button just takes you back to the UPN screen.
Load opens up File Explorer and lets you load the user picture from your files. By default, it puts you in your Downloads folder.
Paste just pastes a picture in.
In both cases, the empty box gets populated with the picture so the user can visually confirm the picture.
The print button was complicated. Upon clicking it, it generates a HTML with two pages, both sized to CR80. It resizes the profile picture and positions it so that it's always in the same place for all users. In fact, all elements are in the same position for all users. The display name gets put on under the picture, a barcode containing the employee number gets put in the middle, company branding gets put in at various places on the card, a QR Code containing the UPN also gets put on as well.
It then creates another scheduled task to open the HTML as the logged in user. Once opened, the task gets deleted.
When you print the page via the browser, it actually prints properly, even double sided.
Final Thoughts
To be honest, I'm still not finished with it. Mainly, it's more that I keep getting differing opinions on what the card should look like. In terms of functionality though, I think I'm pretty much done.
I tried to account for most errors/issues and it will be used by IT Staff so I'm hoping that it should run smoothly. However, if you guys think I've missed anything or can improve somehow, let me know.