Mobile Jon's headlines

HEADLINES:

HEADLINES:

Building a Windows 365 Custom Image

Mobile Jon's Blog

A Foray into Working with the VMWare Workspace ONE APIs

VMWare Workspace ONE APIs

Every now and then, I get a little bit bored. After enough years, you run out of stuff to do in your MDM environment. We can optimize and do all sorts of crazy/random things to build a utopia of mobility. My latest optimization adventure is leveraging the REST API to the best of our abilities. Let me take you on an exciting journey using PowerShell/Postman to solve some real-world issues plaguing Workspace ONE customers in a shared environment.

The problems caused by Shared SaaS

Shared SaaS environments are always the most cost-effective solution for customers. You pay a fair price, don’t incur tech debt for the most part, and can deliver maximum value to your organization. With this in mind, you do have certain gaps that you have to deal with. A few of these gaps are:

  • Lack of control over environment updates
  • Limited configuration and customization
  • Essentially sharing an environment with several customers
  • Lack of access to the database and stunted creativity when solving problems

How does the REST API Come Into Play?

The REST API offers a number of different options that let you do some interesting things that are not fully available via the GUI like most products. Some examples are:

  • Creating, Deleting, Updating, and Working with Smart Groups
  • Synchronizing and Querying Devices
  • Reassigning Devices to Different Users
  • Creating Users
  • Generating Enrollment Tokens
  • Sending Notifications

We frequently will run into situations where we need to do something quickly and accurately. A great example that comes to mind is when it comes to synchronizing devices. Let’s discuss the problem and then solution.

The Problem

Most people don’t actually understand the difference between the query and sync command in AirWatch/Workspace ONE.

Query: Querying forces the devices to check-in with the console and provided updated information about the device status

Sync: Synchronization forces the device to check-in for new apps/profiles/updates and applies them once the device is in a state where it can do so (e.g. when an iOS device is unlocked)

One of the major problems we face as engineers with Workspace ONE is how a very limited subset of commands can be done in bulk a.k.a. only certain commands can be performed on multiple devices at a given time. When you go beyond 10 devices, it becomes even more limited.

Shared SaaS compounds this issue even further as it will by default only check for new profiles/apps/etc every 6-8 hours, which as you know isn’t particularly useful when deploying new applications or triaging an issue. This was the use case that lead me to start looking at leveraging the API.

Setting up POSTMAN to use the WS1 API

The setup to run commands in Postman is relatively easy once you understand how it works. We need to setup two parts (the admin account and the API key):

Under Authorization, you set the admin account with basic auth:

Under headers, you set your API key under aw-tenant-code and set the Accept header to use the v2 API (you will just disable this key if you want to use v1).

You will learn quickly that most times you will end up using the v1 API mostly because there’s a number of gaps in v2. I tend to avoid mixing and matching v1 and v2 API commands because sometimes it just doesn’t work. Ideally, you can write each command as its own function if you need to use both v1 and v2 in a function, but I tend to avoid it if possible.

Working with the API and Engineering your Commands

Finding a Result Set to Work With

I start usually by performing some GETs to figure out what I’m trying to do because the API on the whole is poorly documented and not useful most of the time. So, I may start by performing a basic search to see what attributes I can work with:

The base command you start with for searching is: https://asXXX.awmdm.com/api/mdm/devices/search?

You follow this with setting various parameters as seen below. Typically, I use the device type, the org group ID, and page size so I can return the proper count of devices.

The goal when you are building scripts for building utilities and apps is to ensure you are returning the proper values to pipe into commands. Inadequate testing frequently leads to bad mistakes and potential impact. I engineer PowerShell in the same fashion, where we always do a GET before we SET.

Testing your Update Commands

Once you find a result set that works, we will then try the command with a single device to confirm it works.

The command that I use for sync device is: https://asXXX.awmdm.com/api/mdm/devices/{DeviceID}/commands?command=SyncDevice

The GET we did previously, returns an XML formatted result set for each device like this:

We simply, use the ID value and pass that to the DeviceID field. Provided you configured everything correctly, the sync command will return a HTTP OK (200).

I’m sure you are now wondering, why is this helpful? I can do a sync in the console! You can ONLY do a sync device per device and there is no bulk command supported. This is a major issue because people think “Query” does the job and it absolutely does not. Let’s walk through a simple PowerShell script that will help you solve this use case.

Putting the Power in Powershell

To achieve what we just did in Postman inside of PowerShell, we borrow a bit of code from Chris Halstead’s great session at VMWorld 2019 to build a foundation.

First we set the credentials and API key like we did in Postman via some basic read-host:

$Username = Read-Host -Prompt 'Enter the Username'
$Password = Read-Host -Prompt 'Enter the Password' -AsSecureString
$apikey = Read-Host -Prompt 'Enter the API Key'

Then we store it appropriately:

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

#Base64 Encode AW Username and Password
$combined = $Username + ":" + $UnsecurePassword
$encoding = [System.Text.Encoding]::ASCII.GetBytes($combined)
$cred = [Convert]::ToBase64String($encoding)

Then we build the header like we did in Postman. Notice that I commented out the v2 header:

$script:header = @{
"Authorization" = "Basic $cred";
"aw-tenant-code" = $apikey;

## "Accept" = "application/json;version=2";
"Content-Type" = "application/json";}

Now we build our array of devices that we want to sync below. A few nice things to keep in mind. I built separate functions for iPads and iPhones as the use cases may vary. I also write in a filter to filter out any devices that aren’t enrolled so the sync command doesn’t fail:

$devicetype = 'iPad'

$devices = Invoke-RestMethod -Method Get -Uri "https://asXXX.awmdm.com/api/mdm/devices/search?lgid=11111&PageSize=5000" -ContentType "application/json" -Header $header

$ipads = $devices.devices.id.value

$devicelist = $devices.devices | where-object -filterscript {$_.enrollmentstatus -eq "Enrolled"}

$ipads = $devicelist.id.value

Now that I have that array to work with, I can use it however I want to do some fun things. The two commands that I focus on are doing a device sync and then a device query. The brilliance of the array is you can now pass it to any list of commands depending on what you are trying to achieve:

foreach ($ipad in $ipads) { invoke-restmethod -Method Post -Uri "https://asXXX.awmdm.com/api/mdm/devices/$ipad/commands?command=SyncDevice" -ContentType "application/json" -Header $header | Out-Null }

foreach ($ipad in $ipads) { invoke-restmethod -Method Post -Uri "https://asXXX.awmdm.com/api/mdm/devices/$ipad/commands?command=DeviceQuery" -ContentType "application/json" -Header $header | Out-Null }

Bringing it all Together

Now that you understand how to use it, its entirely up to you how its used. There are a few good uses for leveraging the API commands via PowerShell:

  • Running certain API commands via windows scheduler
  • Building Utilities/Apps for various teams without needing to give them additional roles/controls
  • Leveraging the API inside of your ITSM or Mobile Flows

The main lesson to learn here is that we can always evolve and continue to do bigger and better things. We don’t need to restrict ourselves to what is available in the GUI. Scripting is an essential skill that will take you places in your career. PowerShell opens so many doors and gives you some great foundational skills.

I strongly recommend playing around and testing the REST API. If you do need help, reach out as I’ve learned a bunch about how to use the REST API for both Workspace ONE Access and Workspace ONE UEM. I cannot stress enough the usefulness of the API and how good it makes you look. Being able to tell teams that you created a new tool or utility makes you look great and solves business problems that cannot be easily solved otherwise.

Facebook
Twitter
LinkedIn

20 thoughts on “A Foray into Working with the VMWare Workspace ONE APIs”

  1. I could certainly use a little guidance. I am attempting to automate the creation of Org groups and device profiles using REST, MS flow and AirWatch. I can successfully create new orgs using the VM Ware API explorer but when ever I use another tool, IE powershell, I cannot make a successful connection and im also having trouble with trying to take the Curl code provided by API explorer and use it in PS. Can anyone assist? Thanks!! Michael

  2. Jon, thank you for all your posts, but this one hit home with me. Last year I learned PS and how to utilize the AW APIs to do the many things the GUI could not perform for us. My biggest question is how do you personally transform a PS script into a tool that others (who probably don’t have the proper access levels) can use? Do you transform it into an .exe file? I’m not too familiar with how you entered credentials into the script (we do ours via a text file that has the auth code in it, which the scripts read), but is that part of packaging it up for others to use? All of our scripts are either on a server running under Task Scheduler because they are for “clean-up”, or I run manually.

  3. Jon, thank you for all your posts, but this one hit home with me. Last year I learned PS and how to utilize the AW APIs to do the many things the GUI could not perform for us. My biggest question is how do you personally transform a PS script into a tool that others (who probably don�t have the proper access levels) can use? Do you transform it into an .exe file? I�m not too familiar with how you entered credentials into the script (we do ours via a text file that has the auth code in it, which the scripts read), but is that part of packaging it up for others to use? All of our scripts are either on a server running under Task Scheduler because they are for �clean-up�, or I run manually.

    1. Typically I�ve used https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5 to convert it to EXE.

      The most security friendly way of passing credentials are via something like Hashivault which I�ve done in NodeJS historically. Some people will use the built in PS commands to encrypt the credentials. It really depends on your goals. You could just create an API service account in AW to meet your needs.

      Things that are utility-driven, I will use interactivity to prompt the user for the API key and credentials.

  4. Can a user’s Enrollment Organization Group or a device’s Organization Group be changed via AW API? I have a large set of users & devices I need to move from a legacy organizational structure to a new org structure and moving them one at a time through the UI is painful.

  5. Do you have any experience in the use of MS Graph or translating how we currently might use WS1 APIs (via authenticating into WS1, API url’s and PowerShell, exactly as you show above) into using Intune Graph APIs? We perform some automation using the REST APIs available via WS1 and are now tasked with moving to Intune (because we own it already). I’m a little confused with the content available on Microsoft’s site around the use of the MS Graph. It this tool required to use Intune APIs? Will I still be able to script automation using the Intune APIs and Graph via PS?

    1. It�s going to be a bit more complicated because graph is a catch all for office 365. Can you provide an example automation? I know people use a combo or Flow and Graph to do some stuff today

  6. Great article, i’m looking for a way to use the API to add lists of computers to deployment groups in bulk.

  7. Pingback: VMware Forklift: Supersize your Change Management Strategy in Workspace ONE - Mobile Jon's Blog

  8. Looking to use this .ps1 script in Visual Studio Code on macOS and I continue to get the foloiwng error:

    {“errorCode”:1005,”message”:”An error occurred while validating remote service client credentials or user not found : xxx”,”activityId”:”e2dace5c-7d62-49a5-8ea1-3940887f2fb5″}

    the script works great in Windows using power-shell app, Postman.

    The account exists, the password and tenant code are valid.

    Account is not locked.

    ??

    Please direct me to a solution, if any.

    Xavier Vasquez

  9. how do you pull enrollment date of devices using an API? I am making reports for Power Bi but do not see one for this function. I cna do it within workspace one intelligence so I am thinking there is an Api to pull the data into the dataset for PowerBi to read? Do you also know of a source to get what Api call we can use as the API in the workspace one Console is lacking on a lot of items such as event details so I am unable to create an api call for an even like enrollment date per above request? thank you

  10. Bertrand JOZEFIAK

    Jon
    First of all, thank you for your very useful work for the community.
    Then, I seek to automate via the APIs the creation and deployment of application packaged in PSADT.
    I was thinking of creating a PowerShell script that with a configuration Json uses the API/mam/apps/internal/application to create the application.
    How to easily upload the *.zip file from my computer ?
    Should I use mam/apps/internal/uploadchunk or mam/blobs/uploadblob instead?
    Thanks! Bertrand.

    NB : I am currently studying Krati Gupta and Madhushree Nayak M’s Python script, on the VMWare GitHub about this. But I’m not fluent in Python^^

Let me know what you think

Discover more from Mobile Jon's Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading

Scroll to Top