Configuring Workspace ONE UEM API with PKCS12 Certificates

Overview

A common customer request is to access the Workspace ONE UEM API to enhance their reporting or automated tasks. The APIs require authentication to execute any request against the Workspace ONE UEM instance, those requests can be authenticated using basic credentials (username/password), certificates, and OAuth. During the development of those reports or automated tasks, the basic credentials are used as a method of authentication. However, when moved into production, this is no longer the best practice to access the APIs because you have to share those with other team members.

The alternative methods that follow security best practices are to leverage certificates or OAuth for authentication. This guide will instruct you in one way of doing this in a secure manner using certificate-based authentication.

Purpose of This Tutorial

In this tutorial, we’ll walk you through creating a certificate in your Workspace ONE UEM console, downloading it in a secure manner, and using it in a Python script to make authenticated API calls. Additionally, we’ll show how to generate signed data and use it in Postman for API testing.

Audience

This tutorial is intended for IT professionals and Administrators who utilize Workspace ONE UEM.

Requirements

This tutorial uses Python as the language to demonstrate the features. Some great guides are online if you do not have Python installed already, below are a couple of recommendations, but these are not set in stone.

For Mac

We recommend the use of a common developer tool called Brew to handle installation on a Mac and a Brew package called pyenv to set you up to install any version of Python you like on your Mac. Open a terminal on your Mac and execute the following commands.

# Install pyenv
brew install pyenv

# This will install Python 3.10.xx ( the latest version ) as well as pip3.
pyenv install 3.10

# The local command configures your current terminal session to run this version of python.
pyenv local 3.10

# If you like this version and want to use it by default, run this command:
pyenv global 3.10

# Next you need pip to be set to default ( because tutorials don’t use pip3 ).
pip3 install –upgrade pip

# Finally, you need to install the requirements for our script, which needs the following packages: python-dotenv, cryptography, and requests.
pip install python-dotenv cryptography requests

For Windows

To make things simple, we recommend using the Microsoft Store and installing Python from there. The 3.10 version is stable and used in this tutorial, but you can use whichever version you like.

A screenshot of a computer

Description automatically generated

Once Python is installed you can install the packages in the same way:

pip install python-dotenv cryptography requests

Configuring Enhanced Secure Access with Workspace ONE UEM APIs

In this section, follow the steps to create your certificate in Workspace ONE and execute the Python script using an ENV file.

Step 1: Create Your Certificate in Workspace ONE Console

From the Workspace ONE UEM console, perform the following steps to create the certificate that will be used to authenticate the API calls against Workspace ONE UEM.

A screenshot of a computer

Description automatically generated

  1. Go to Accounts > Administrators > List View.
  2. Click Add > Add Admin > Basic.
    1. For this example, the Basic account has been used.
  3. Enter the Username, Password, Confirm Password, First Name, Last Name, and Email.
    1. Make sure to set a strong password for the certificate.
  4. Click Next.

    You can choose the appropriate role based on your requirements; the selected role must have access to perform API calls. For this example, Console Administrator was used, however, for production environments, use a limited role that is authorized to perform only the necessary API calls.
    A screenshot of a computer

Description automatically generated 
  5. Give your admin user a Role appropriate for your needs. In this example, Console Administrator has been used.
  6. Click Next.
  7. The Details screen information is optional; fill in any other details you like and click Next.

The Settings screen is a key step when creating the account–this is the step where the certificate for this account will be generated and downloaded for use later.

Perform the following steps to generate the account certificate:

  1. At the bottom of the Settings screen select the Certificates check box as the Authentication Method.
  2. On the Certificate Password field, enter a password to use as your certificate password.
  3. Click Save and Continue on the dialog that will pop up.
    A screenshot of a computer

Description automatically generated 

With the account created, the next step is to download the account certificate.

  1. Click the account you just created, and return to the Settings screen.
    A screenshot of a computer

Description automatically generated 
  2. Fill in the certificate password again and then click EXPORT CERTIFICATE. A file with a p12 extension will be downloaded.
  3. Save the certificate to your computer in a secure location such as ~/.ssh.
  4. Click Save.

Step 2: Create an ENV File in a Secure Folder

Using an .env file helps in managing sensitive information securely and keeping the code clean. Environment variables stored in an .env file can be easily loaded into your application without hardcoding sensitive data directly into the source code. This approach also allows you to manage different configurations for development, testing, and production environments.

Follow these steps to create the .env file:

  1. Create an .env File:
    1. In a safe folder such as your ~/.ssh directory, create a file named .env.
  2. Store Environment Variables:
    1. Open the .env file in a text editor and add the following lines, replacing placeholder values with your actual credentials and file names:
USER=the_username_you_created
HOST=hostname_of_your_workspace_one_api 
 
APIKEY=your_api_key 
CERTNAME=the_filename_of_your_certificate_without the extension 
CERTPASSWORD=your_certificate_password

Step 3: Executing Python Script Using the .env File

The following code is a Python script that uses the requests library to make an authenticated API call to your Workspace ONE UE API. The script reads the certificate file from the specified path, generates signed data using the certificate, and sends the API request with the signed data in the Authorization header.

Copy the following script into a text file and save it as getlistofdevices.py, update the directory folder to where your .env and .p12 files are located.

The script will call a UEM API to get a list of all devices and print the result on the screen.

import base64
from cryptography.hazmat.primitives.serialization import pkcs12, pkcs7
from cryptography.hazmat.primitives import hashes, serialization
import requests
import os
from dotenv import load_dotenv

# Load environment variables from ~/.ssh/.env
load_dotenv('/Users/sampleuser/.ssh/.env')

cert_password = os.getenv('CERTPASSWORD')
# Update with your actual certificate path
CERTNAME = os.getenv('CERTNAME')
cert_path = f"/Users/sampleuser/.ssh/{CERTNAME}.p12"

# Host and signing data for the API call
host = os.getenv('HOST')
signing_data = "/api/mdm/devices/search"
url = f"https://{host}{signing_data}"

# Read the certificate file
with open(cert_path, 'rb') as certfile:
    cert = certfile.read()

# Load the key and certificate
key, certificate, additional_certs = pkcs12.load_key_and_certificates(cert, cert_password.encode())

# Define PKCS#7 signing options
options = [pkcs7.PKCS7Options.DetachedSignature]

# Create the signed data
signed_data = pkcs7.PKCS7SignatureBuilder().set_data(signing_data.encode("UTF-8")).add_signer(certificate, key, hashes.SHA256()).sign(serialization.Encoding.DER, options)

# Encode the signed data in base64
signed_data_b64 = base64.b64encode(signed_data).decode()

# Define headers for the API request
headers = {
    "User-Agent": os.getenv('USER'),
    "aw-tenant-code": os.getenv('APIKEY'),
    "Host": host,
    "Authorization": f"CMSURL'1 {signed_data_b64}",
    'Accept': 'application/json',
    "version": "1",
}

# Make the API request
response = requests.get(url, headers=headers)

# Print the response content
# print the following in a table: DeviceFriendlyName, DeviceId, DeviceModel, DeviceOSVersion, EnrollmentStatus, LastSeen
print(f"""
--------------------------------------------------------------------------------------------------------------------------------
DeviceFriendlyName        | DeviceId  | DeviceModel       | Platform       | EnrollmentStatus      | LastSeen
--------------------------------------------------------------------------------------------------------------------------------
""")
for device in response.json()['Devices']:
    print(
        f"{device['DeviceFriendlyName']} | {device['Id']['Value']} | {device['Model']} | {device['Platform']} | {device['EnrollmentStatus']} | {device['LastSeen']}")
    print(f"--------------------------------------------------------------------------------------------------------------------------------")
# print the total number of devices
print (f"Total number of devices: {len(response.json()['Devices'])}")

A successful script execution will print out a list of devices in a table which you can change as you need.

python3 getlistofdevices.pys

A screenshot of a computer program

Description automatically generated

Extra Credit: Generating Signed Data and Using it in Postman

Postman is a popular API tool that helps to build, test, and modify APIs and it’s heavily used by the Workspace ONE UEM administrator, the following steps demonstrate how to generate the signed data needed for the Authorization header in your API calls through Postman tool.

Generate Signed Data with Python

Run the following Python script to generate the signed data. The signed_data_b64 variable will contain the base64-encoded signed data needed for the Authorization header in your API calls.

Copy the script into a text file and save it as getsignedata.py, update the directory folder to where is located your .env and .p12 files.

import base64
from cryptography.hazmat.primitives.serialization import pkcs12, pkcs7
from cryptography.hazmat.primitives import hashes, serialization
import os
from dotenv import load_dotenv

# Load environment variables from ~/.ssh/.env
load_dotenv('/Users/sampleuser/.ssh/.env')

cert_password = os.getenv('CERTPASSWORD')
# Update with your actual certificate path
CERTNAME = os.getenv('CERTNAME')
cert_path = f"/Users/sampleuser/.ssh/{CERTNAME}.p12"

# Host and signing data for the API call
host = os.getenv('HOST')
signing_data = "/api/mdm/devices/search"
url = f"https://{host}{signing_data}"

# Read the certificate file
with open(cert_path, 'rb') as certfile:
    cert = certfile.read()

# Load the key and certificate
key, certificate, additional_certs = pkcs12.load_key_and_certificates(cert, cert_password.encode())

# Define PKCS#7 signing options
options = [pkcs7.PKCS7Options.DetachedSignature]

# Create the signed data
signed_data = pkcs7.PKCS7SignatureBuilder().set_data(signing_data.encode("UTF-8")).add_signer(certificate, key, hashes.SHA256()).sign(serialization.Encoding.DER, options)

# Encode the signed data in base64
signed_data_b64 = base64.b64encode(signed_data).decode()
#

 


print(f"""
------------------------------------
Name           | Value
------------------------------------
User-Agent     | {os.getenv('USER')}
aw-tenant-code | {os.getenv('APIKEY')}
Host           | {host}
Authorization  | CMSURL'1 {signed_data_b64}
Accept         | application/json
version        | 1
""")

The above script will print the signed data encoded in base64, and save the result as it will be required on the headers.

python3 getsignedata.py

A screenshot of a computer

Description automatically generated

Use Signed Data in Postman

Open the Postman tool and perform the following steps to configure your environment to Authenticate through the certificate when calling Workspace ONE UEM APIs.

  1. Set up Environment in Postman:
    1. Go to the Environments tab in Postman.
    2. Click Add to create a new environment.
    3. Add the following variables:
      1. USER
      2. HOST
      3. APIKEY
      4. SIGNED_DATA

Note: Set the values for USER, HOST, and APIKEY based on your .env file. For SIGNED_DATA, use the base64-encoded signed data generated by your Python script.

  1. Create a New Request:
    1. Create a new GET request.
    2. Set the URL to https://{{HOST}}/api/mdm/devices/search.
  2. Add Headers:
    1. Add the following headers:

User-Agent: {{USER}}
aw-tenant-code: {{APIKEY}}
Host: {{HOST}}
Authorization: CMSURL'1 {{SIGNED_DATA}}
Accept: application/json
version: 1

The configuration in Postman should look like this:

A screenshot of a computer

Description automatically generated

  1. Send the Request:
    1. Click Send to make the API call.


A screenshot of a computer

Description automatically generated 

The result is a list of devices available on your UEM environment, you can see the JSON response on the Pretty tab, or in table format using the Visualize tab.

Summary and Additional Resources

 In this tutorial, we have shown you how to create a certificate in your Workspace ONE console, download it in a secure manner, and use it in a Python script to make authenticated API calls and generate signed data to use in Postman. By following these steps, you can access your Workspace ONE API in a secure manner and retrieve data using signed data for authentication.

Additional Resources

 To learn more about Workspace ONE UEM API and the tools used in this article, explore the following resources:

Changelog

The following updates were made to this guide:

Date

Description of Changes

2024/06/28

Guide was published.

About the Author and Contributors

This document was written by:

Feedback

Your feedback is valuable.

To comment on this paper, either use the feedback button or contact us at tech_content_feedback@omnissa.com


Filter Tags

Workspace ONE Workspace ONE UEM Document Operational Tutorial Intermediate Secure Remote Access