The custom processor and recipes from this repository have been migrated to the AutoPkg organisation, you can find them over here.
Going forward, the recipes in this old repo will no longer be updated.
Please update your settings to use the new repo like so:
autopkg repo-delete https://github.com/codeskipper/WorkSpaceOneImporter
autopkg repo-add https://github.com/autopkg/WorkSpaceOneImporter-recipes
The recipies from this old repo are now deprecated, and the main (.yaml) recipies that were used in production now have a deprecation warning added.
A set of recipes and a custom processor for use with Omnissa Workspace ONE UEM. Formerly known as a VMware business and product. Going back further, Airwatch was the product name for the MDM product.
WorkSpaceOneImporter is a custom AutoPkg Processor for automating import of Mac product installer packages into Workspace ONE UEM. It can also assign them to one or multiple smart groups, and set certain deployment options such as Push Mode. It has support for automated staging to assignment groups. Automated pruning of old versions can also be enabled and configured in detail if needed.
Adapted from jprichards/AirWatchImporter.
You must be running AirWatch Console 9.3.0.0 or higher.
Currently, in order to run AirWatchImporter, you must first install two Python libraries:
- The
requestslibrary - The
requests_toolbeltlibrary
These can be installed by running: (Thanks)
sudo -H /Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/pip3 install requests
sudo -H /Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/pip3 install requests_toolbelt
As of AutoPkg 0.4.0 you can use this processor as a shared processor.
Add the processor repo:
autopkg repo-add https://github.com/codeskipper/WorkSpaceOneImporter.git
Then use this as the processor in your recipes:
com.github.codeskipper.WorkSpaceOneImporter/WorkSpaceOneImporter
The processor currently requires sensitive keys like password and API token to be populated in your recipe (override) Input variables, or by command line keys.
Instead of keeping secrets in plain text recipe override files, they can be added to a macOS keychain. I took a peek at - this and now have a working launcher shell script for a Python wrapper, and I'll share when I can - it's currently in a private repo for GitHub CI as described below. This is useful for testing, in production I use a CI/CD pipeline on a self-hosted GitHub runner.
You can use a CI/CD tool like GitHub actions to wrap credentials securely as secrets and inject to your Autopkg action(script). I'm running an adapted version of the example provided by Gusto in production. Sharing a public version of the adapted code as documentation and/or demo is on the roadmap.
When working to set up GitHub CI with this processor, it became clear consistent naming for input variables will make reading logs etc. much easier.
You'll need to specify credentials for either Oauth or Basic authentication.
ws1_force_import and ws1_import_new_only are intended for troubleshooting (new) recipes.
ws1_console_url is there as a convenience, so you can get a direct link to a newly imported package in the WS1 console.
ws1_smart_group_name and ws1_push_mode let you make simple App Assignments to Assignment Groups, while ws1_app_assignments gives you complete control over the App Assignment settings, but needs more settings in the recipe override.
ws1_app_versions_prune lets you prune old software versions, it is set to dry_run per default. Behaviour can be controlled in detail by setting ws1_app_versions_to_keep and ws1_app_versions_to_keep_default.
ws1_api_urlws1_console_urlws1_oauth_client_idws1_oauth_client_secretws1_oauth_token_urlws1_api_tokenws1_api_usernamews1_api_passwordws1_b64encoded_api_credentialsws1_force_importws1_import_new_onlyws1_groupidws1_smart_group_namews1_push_modews1_app_assignmentsws1_update_assignmentsws1_app_versions_to_keepws1_app_versions_to_keep_defaultws1_app_versions_prune
You can list the custom processor info, including input variables from cli like so:
autopkg processor-info WorkSpaceOneImporter --recipe com.github.codeskipper.WorkSpaceOneImporter
<key>Process</key>
<array>
<dict>
<key>Processor</key>
<string>com.github.codeskipper.WorkSpaceOneImporter/WorkSpaceOneImporter</string>
<key>Arguments</key>
<dict>
<key>ws1_munki_repo_path</key>
<string>MUNKI_REPO_PATH_HERE</string>
<key>ws1_api_token</key>
<string>API_TOKEN_HERE</string>
<key>ws1_api_url</key>
<string>WORKSPACEONE_API_URL_HERE</string>
<key>ws1_console_url</key>
<string>WORKSPACEONE_CONSOLE_URL_HERE</string>
<key>ws1_api_username</key>
<string>API_USERNAME_HERE</string>
<key>ws1_api_password</key>
<string>API_PASSWORD_HERE</string>
<key>ws1_b64encoded_api_credentials</key>
<string>Basic QVBJX1VTRVJOQU1FX0hFUkU6QVBJX1BBU1NXT1JEX0hFUkU=</string>
<key>ws1_groupid</key>
<string>GROUP_ID_HERE</string>
<key>ws1_smart_group_name</key>
<string>SMART_GROUP_NAME</string>
<key>ws1_push_mode</key>
<string>PUSH_MODE, Auto or On-Demand</string>
</dict>
</dict>
</array>
Example recipe below for Suspicious Package.ws1.recipe is from: https://github.com/codeskipper/WorkSpaceOneImporter/blob/main/ws1-plist/SuspiciousPackage.ws1-plist.recipe
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Description</key>
<string>Creates a munki package for Suspicious Package, imports it into WorkSpace ONE.</string>
<key>Identifier</key>
<string>com.github.codeskipper.ws1.SuspiciousPackage</string>
<key>Input</key>
<dict>
<key>WS1_API_TOKEN</key>
<string>API_TOKEN_HERE</string>
<key>WS1_API_USERNAME</key>
<string>API_USERNAME_HERE</string>
<key>WS1_API_PASSWORD</key>
<string>API_PASSWORD_HERE</string>
<key>WS1_MUNKI_REPO_PATH</key>
<string>MUNKI_REPO_PATH_HERE</string>
<key>WS1_API_URL</key>
<string>WORKSPACEONE_API_URL_HERE</string>
<key>WS1_CONSOLE_URL</key>
<string>WORKSPACEONE_CONSOLE_URL_HERE</string>
<key>WS1_GROUPID</key>
<string>GROUP_ID_HERE</string>
<key>WS1_SMART_GROUP_NAME</key>
<string>SMART_GROUP_NAME_HERE</string>
<key>WS1_PUSH_MODE</key>
<string>PUSH_MODE</string>
</dict>
<key>ParentRecipe</key>
<string>com.github.codeskipper.munki.SuspiciousPackage</string>
<key>MinimumVersion</key>
<string>0.4.0</string>
<key>Process</key>
<array>
<dict>
<key>Processor</key>
<string>com.github.codeskipper.WorkSpaceOneImporter/WorkSpaceOneImporter</string>
<key>Arguments</key>
<dict>
<key>ws1_munki_repo_path</key>
<string>%WS1_MUNKI_REPO_PATH%</string>
<key>ws1_api_token</key>
<string>%WS1_API_TOKEN%</string>
<key>ws1_api_username</key>
<string>%WS1_API_USERNAME%</string>
<key>ws1_api_password</key>
<string>%WS1_API_PASSWORD%</string>
<key>ws1_api_url</key>
<string>%WS1_API_URL%</string>
<key>ws1_groupid</key>
<string>%WS1_GROUPID%</string>
<key>ws1_console_url</key>
<string>%WS1_CONSOLE_URL%</string>
<key>ws1_smart_group_name</key>
<string>%WS1_SMART_GROUP_NAME%</string>
<key>ws1_push_mode</key>
<string>%WS1_PUSH_MODE%</string>
</dict>
</dict>
</array>
</dict>
</plist>
My ws1 recipes are in yaml format thanks to the convincing examples from Graham Pugh's recipes. His plist-yaml-plist conversion tool has helped me as well, especially when writing new recipes.
Create a recipe override like this first (if you prefer plist format):
autopkg make-override SuspiciousPackage.ws1.recipe
Again yaml format is easier to deal with, especially if you leave only the input variables you need to override and strip away the rest.
autopkg make-override --format=yaml SuspiciousPackage.ws1.recipe.yaml
Edit it for settings to fit your environment
open -a bbedit SuspiciousPackage.ws1.recipe.yaml
You can run autopkg like this, but be aware: verbose level > 2 will show your password etc. in plaintext on screen
autopkg run -vvvv --key ws1_import_new_only=false --key ws1_update_assignments=true SuspiciousPackage.ws1.recipe.yaml
When testing, you may need to specify an increasing number of settings. You may find it helpful to set these like shell environment variables like so.
export AUTOPKG_verbose=2
export AUTOPKG_ws1_import_new_only=false
export AUTOPKG_ws1_update_assignments=True
autopkg run SuspiciousPackage.ws1.recipe.yaml
During development, I've used a launcher script to store (secret) settings in a dedicated keychain and fetch just before calling autopkg. Sharing this script is on the roadmap.
Uses the same environment as Autopkg.
Install the pre-commit hook like so:
/Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/pre-commit install --install-hooks
isort needed profile = "black" in .isort.cfg and args: ["--profile", "black"] in .pre-commit-config.yaml to avoid conflict with black
line-length was set at 120 in .isort.cfg and in .flake8 just because it was the default I got used to in PyCharm
Found a useful hint to integrate flake8 in PyCharm as external tool here.
Check all the files:
/Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/pre-commit run --all-files