Chapter 1

Workspace ONE UEM

Статьи по установке, настройке и решению проблем с Workspace ONE UEM (бывший AirWatch).

Subsections of Workspace ONE UEM

AWCM and ECC Troubleshooting

General Rules

  1. Do not install Enterprise Service Connector/AirWatch Cloud Connector (ESC/ACC), until you are absolutely sure AWCM is working
  2. Do not install AWCM or ESC (ACC) in Global tenant
  3. Check there is a Device Root Certificate in the Organization Group, in which work is done. It is located in  \system configuration\system\advanced\device root certificate. If there is nothing, click Generate.

AWCM Installation

  1. When installing AWCM, DO NOT use the self signed SSL certificate, check the box for “custom SSL” which really means the public SSL Cert you put in IIS for Device Services. Notice that in the installation dialog box the two fields for password are NOT the same. One is for the SSL Cert you are importing and one is for the password to the Java Keystore.

  2. Make sure that REST API is enabled in the OG where you are enabling AWCM.

  3. Make sure that AWCM is enabled in the Site URL’s page. Also, put the correct information in the two fields. The External URL should NOT contain http:// or https://. The Internal Service URL should contain https:// instead of http:// and should have the port number after the URL and “/awcm” at the end. It should look like https://{url}:2001/awcm.

  4. Download and run the AWCM Secure Channel Certificate program from the Secure Channel Certificate page ON THE SERVER RUNNING AWCM.

DO NOT download the program onto another computer and copy it to the AWCM server!

Download and run this program “As Administrator”.

There is a possibility that you will receive an error message that the application can’t find the Java Folder, this can be a result of not running the program “As Administrator”.

  1. Browse to the AWCM Status page by going to https://{url}:2001/awcm/status. If this page doesn’t come up or if there is an SSL error stop and fix it before you go on. Check the SSL Certificate common name, it should match the name of the DS URL. If it says “Air Watch “ then you need to uninstall and reinstall AWCM, this time installing the correct SSL Certificate (see #1).

ESC/ACC WILL NOT WORK if you use the self signed certificate!

AWCM Status page MUST BE TRUSTED by AirWatch Console AND by ESC. Test by opening https://{url}:2001/awcm/status status page in browser - there MUST BE NO CERTIFICATE WARNING!

  1. Confirm that the awcm.truststore and the awcm.keystores are not corrupt and contain the correct certificates. Run the keytool application (see next section) and list the contents of both stores.

    • In awcm.keystore there should be 1 certificate and it should contain the SSL certificate for the site.
    • In the awcm.truststore there should be 2 or 3 certificates: one of them is Secure Channel Certificate.

    If the certificates do not exist in the stores then you may need to re-install AWCM. If the password is not accepted then the store may be corrupt and you will need to reinstall AWCM.

Java KeyStore

AWCM is a Java web application and stores its certificates in the Java Keystore as opposed to the Microsoft Certificate store. The Java Keystore and Java Truststore are located in the \airwatch\airwatch {version}\awcm\config folder.

There is a utility in Windows called “keytool”. With this utility you can view, add, and delete certificates from the Java Keystores.

⭐️ Password to awcm.truststore = “password

Password to awcm.keystore = password to the PFX certificate uploaded on installation of AWCM. DO NOT use password less than 6 characters! Or you will not be able to change certificate in awcm.keystore.

Example of keytool commands:

# List the certificates in the store:
keytool -list -v -keystore awcm.truststore

# Import a certificate into a store:
keytool -import -trustcacerts -file {cert file} -alias {common name} -keystore $JAVA_HOME/jre/lib/security/cacerts

Replace database of AWCM

  • Run the following command to replace SSL cert on AWCM servers:
keytool -importkeystore -srckeystore <new-pfx-cert-name>.pfx -srcstoretype pkcs12 -destkeystore awcm.keystore.new -deststoretype JKS
  • Once this has completed successfully, you will now see a new file named awcm.keystore.new in the config directory.
  • Stop the AWCM service.
  • Rename the awcm.keystore to awcm.keystore.old.
  • Rename the awcm.keystore.new to awcm.keystore.
  • Start the AWCM service.

Reinstall of Secure Channel Certificate

If ESC is installed, then uninstall it and delete all its’ folders before reinstall of Secure Channel Certificate.

Before reinstall of Secure Channel Certificate, you must delete the old certificate from the AWCM Java database. Delete a certificate in the store:

keytool -delete -alias "aw secure channel certificate - {url}" -keystore awcm.truststore

AWCM Logs

See General Article on AirWatch Logs.

Verify correct work of AWCM

Verify AWCM is listening on the configured port through netstat:

netstat -ano | findstr LISTENING | findstr {port number} 

Perform the following to make sure that AWCM is functioning accurately:

  • Confirm that there is a device root certificate in the relevant OG by navigating to Settings / System / Advanced / Device Root Certificate.
  • Make sure that REST API is enabled.
  • Make sure that AWCM is enabled in the URL page of the site.
    • The external URL must not contain http:// or https://.
    • Exact format of the URL: https://{url}:2001/awcm.
  • Browse to the AWCM Status page by selecting https://{url}:2001/awcm/status (You should see “OK”) and https://{url}:2001/awcm/statistics

❗️For clustering infrastructure on SaaS, browse over port 443 instead of 2001 (https://awcm118.awmdm.com/awcm/statistics) while testing the status page.

❗️For lor load balanced deployments:

  • Ensure that clients who are required to connect to AWCM are pointed to and are able to reach the endpoint on the load balancer. This means that if installation of AWCM is on the DS servers, then ensure that the requests for AWCM from the DS services are still accessing the load balancer so that they are subject to the set rules;
  • As per the Installation Guide, the preferred deployment for a customer using ESC/ACC with AWCM is to deploy multiple AWCM nodes in an active-passive configuration. This makes everything easier since persistence of connections doesn’t matter. There are no specific advantages with having two active nodes as the network load is not much while using only ESC/ACC.

Load Balancing AWCM - Persistence Rules with F5 LTM

See KB for details: https://kb.vmware.com/s/article/2960904

To deploy AWCM with multiple nodes behind a load balancer without clustering, you must account for persisting the connections to the AWCM servers. In the HTTP request that is sent to AWCM (from a device, the Device Services server, the Console Server, ACC, and so on), there is a cookie value called awcmsessionid, which is used to establish request level affinity to an AWCM node from a pool of nodes. You must configure your load balancer or proxy to parse the HTTP request for this value and use it for persistence. The persistence settings are only necessary for AWCM servers that are load-balanced in an active-active manner. The persistence settings will ensure that established connections are not dropped when the F5 switches from one AWCM server to the other to balance the load.

The iRule might vary based on a client’s existing configuration or best-practices, but the basics are straight forward:

  • Parse the HTTP request for the awcmsessionid cookie’s value
  • Set persistence with this value via the “persist carp” command.

For more background on this methodology, see the following F5 solution page for Overview of the CARP hash algorithm.

  • In Local Traffic → iRules : iRule List create an iRule to inspect the HTTP request for the value of the “awcmsessionid” cookie:
    when HTTP_REQUEST {

        if { [HTTP::cookie exists "awcmsessionid"] }{

            set awcm_session_id [string tolower [HTTP::cookie "awcmsessionid"]]

            persist carp $awcm_session_id

        }

    }
  • In Local Traffic → Profiles: Persistence create a persistence profile based on the default “hash” profile. All items should be default except the following:

    • Algorithm: “CARP”
    • iRule: created in Step 1.
  • Configure the Virtual server with the following settings:

    • Select an HTTP profile from the “HTTP Profile” drop-down list;
    • Select OneConnect profile = oneconnect (for HTTP request balancing, not just connection);
    • Apply the persistence profile under the Resources tab

Load Balancing AWCM - Persistence Rules with Citrix NetScaler

See details in an archived article - http://web.archive.org/web/20190506104002/https://www.citrix.com/blogs/2010/06/01/configuring-verifying-and-monitoring-persistence-on-netscaler/

Check the Persistence Rule

Check for persistence by hitting the URL [https://awcm url:port/awcm/statistics?awcmsessionid=abc123](https://awcm urlport) on ACC server and on machine from outside network. If the servers are different then customer needs to change the persistence rule on load balancer on their end.

Common Errors

AWCM Status Error - DNS name

AWCM not working - page https://<DS_URL>:2001/awcm/status unavailable. Error log seen:

2017-08-15 12:02:44,229 ERROR (nioEventLoopGroup-3-3) [com.airwatch.awcm.event.AWCMChannelConnectedEventHandler] - java.nio.channels.ClosedChannelException
java.util.concurrent.ExecutionException: java.nio.channels.ClosedChannelException
<...>
at io.netty.handler.ssl.SslHandler.channelInactive(...)(Unknown Source) [netty-all-4.0.43.Final.jar:4.0.43.Final]

Solution: DNS name of Device Services is registered on external proxy and not known to servers. Go to C:\Windows\System32\drivers\etc\hosts file on AirWatch Admin Console, and also on server with Enterprise Connector Service and add the EXTERNAL public DNS name (listed in public certificate) of AWCM binded to its’ internal IP.

AWCM Status Error - Cryptography

AWCM not working - page https://<DS_URL>:2001/awcm/status unavailable. Error log seen:

2017-08-15 14:49:41,044 ERROR (nioEventLoopGroup-3-7) [com.airwatch.awcm.event.AWCMChannelConnectedEventHandler] - javax.net.ssl.SSLHandshakeException: no cipher suites in common
java.util.concurrent.ExecutionException: javax.net.ssl.SSLHandshakeException: no cipher suites in common

Solution: AWCM was installed AFTER crypto algorithms were disabled in IIS hardening, and it cannot launch normally. Reinstall of AWCM needed.

AWCM SSL Certificate Error

Certificate error while browsing the AWCM status page

  1. Login to the AWCM server.

  2. Open a command prompt, navigate to the following directory (E:\airwatch\airwatch\AWCM\config) and run the following: keytool -list -v -keystore awcm.keystore

  3. Enter the password when prompted

  4. Export a new SSL certificate from a machine.

❗️Make sure that the full signing chain is exported (settings that you select when exporting the certificate) and that the password used to export is same as the one used for the current awcm.keystore.

If the passwords are not same, the import happens but an error message appears when AWCM starts and the status page does not load (as the pre-configured password will be incorrect and the AWCM app will not be able to open the keystore).

  • AWCM_BRIDGE_FILE_TRANSFER_TIMEOUT_IN_MINUTES : 15 2013-09-23 10:46:22,036
  • Error (main) [com.airwatch.awcm.ssl.AWCMSSLContext]:
java.security.UnrecoverableKeyException: Cannot recover key java.security.UnrecoverableKeyException: Cannot recover key
<...>
2013-09-23 10:46:22,036 ERROR (main) [com.airwatch.awcm.server.AWCMServer] - Error initializing server environment, exiting
  1. When the certificate is on the AWCM server (copy into the C:\airwatch\airwatch\AWCM\config directory), run the following command to replace SSL certificate:

keytool -importkeystore -srckeystore <new-pfx-cert-name>.pfx -srcstoretype pkcs12 -destkeystore awcm.keystore.new -deststoretype JKS

  1. Once this has completed successfully, you will now see a new file named awcm.keystore.new in the config directory. Stop the AWCM service.

  2. Rename the awcm.keystore to awcm.keystore.old.

  3. Rename the awcm.keystore.new to awcm.keystore.

  4. Start the AWCM service.

  5. Using a valid AWCM URL, try to access the page (https://{url}:2001/awcm/status) and if the status page loads, then check the certificate details. It should display the values for the newly uploaded certificate.

  • If the status page does not load, check the log files.
  • If rollback is required, rename the awcm.keystore to awcm.keystore.new.
  • Then rename awcm.keystore.old to awcm.keystore. Restart AWCM to restore the old settings.

AWCM and Admin Console trust error

ESC/ACC starts and generates no errors in log, also no errors in AWCM. But error in console while performing Test connection for ESC/ACC: Undefined Error; Please check server logs.

Reason: there is no trust between AWCM and AirWatch Admin Console

**Remedy:
**Import Intermediate and Root certificates for public PFX certificate in AWCM server and AirWatch Admin Console Server

ACC Errors

ACC must be able to reach AWCM:

  • Protocol HTTPS
  • Telnet from ACC to AWCM Server on the relevant port (usually 2001 for On-Premise installations and 443 for SaaS environments)
  • Also, verify by opening a browser on the ACC server, entering https://:2001/awcm/status and /awcm/statistics to ensure there is no certificate trust error.
  • For On-Premise installations: if using ACC with AWCM and there are multiple AWCM servers and they required to be load-balanced them, persistence needs to be configured - see the above section.

ACC must be able to reach the Console Server:

  • Protocol: HTTP or HTTPS
  • Telnet from ACC to the Console URL on the relevant port (usually 80 or 443)
  • Also, verify by opening a browser on the ACC server, entering http(s)://
  • If auto-update is enabled, ACC must be able to query AirWatch Console for updates

ACC must be able to reach the API

  • Protocol: HTTPS, port TCP443
  • Verify by navigating to the URL of your API server on the ACC server: https:///API/help
  • When the credentials screen appears, enter the credentials of a console admin and the API Developer page should appear.
  • ACC to API access is required for the proper functioning of the AirWatch Diagnostics service.

Connectivity Errors

  • If you see errors in the ACC logs indicating connections being closed/aborted/terminated, check if there is any network device in between the ACC and AWCM that would close or terminate idle connections. The outbound connection required for use by ACC must remain open at all times. Check the TCP session timeout on this network device in between and see if this can be increased to a value >2 minutes;
  • ACC sends what is known as an IDLE message, by default every 2 minutes. This IDLE message by ACC helps ACC register itself as a listener on AWCM so that AWCM knows that this ACC is ready to take requests;
  • If there are any network devices between ACC and AWCM that closes the connection between these components deeming the connection as an idle connection, it could cause issues with this ACC/AWCM connectivity.

401 Errors on ACC

ACC service does not start:

Error log contains error:

System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
<...>

Reason: ESC/ACC service does not start because there is no trust between ESC/ACC and AWCM.

If this error is present after trying to hit Update/Check URL on the console, check the SSL certificate on the console and do the following: keytool -list -v -keystore "{AWCM install path}/awcm.truststore" > c:\test.txt

In the .txt file, search for the secure channel and it should match with the secure channel certificate in the console.

Remedy:

  • Generate new certificates for ESC/ACC and download the installer. Then, uninstall ACC and install the new ACC with the renewed certificates. Restart the AWCM service, if required.
  • Reinstall AWCM and download the installer from the console.

Globalization settings

WS1 UEM .NET Globalization settings

Issue

Usually, on-prem installation of WS1 UEM is doing with localized Windows servers (French, Russian, as an examples). With that, default settings in IIS can be set up incorrectly. This issue may prevent enrolling Windows devices (iOS or Android devices enroll well at the same time).

Solution

To fix this isseu you need to change .NET Globalization settings for Default Website level for all DS servers in your environment:

Parameter Value
Culture
Culture English (United States) (en-US)
UI Culture English (United States) (en-US)
Encoding
File Windows-1252

.NET-Globalization-Settings

Important Tools

General Tools

Verification Tool Description...
  • The pre-installation verification tool is an exe file that can be loaded onto the AirWatch app servers and will perform standard checks on the local machine, to the DB, and to the internet to ensure that the environment meets the VMware AirWatch Pre-Reqs.
  • Once installed, certain information is required, such as DB server and username/PW, and once entered takes you through the checks and presents the results in the application. Should it need to be shared there is an export option that creates an Excel file.
  • There is also additional functionality tests related LDAP, SMTP, Exchange, SSRS, and PKI

OS Specific Tools

iOS

MacOS

Android

  1. https://awagent.com/mobileenrollment/airwatchagent.apk
  2. https://discovery.awmdm.com/mobileenrollment/airwatchagent.apk

Description of tool…

Windows 10/11

Windows Phone (support deprecated)

Other Tools

SSL Checkers

EAS Troubleshooting Tools

Integration - EMail

Linked Articles

EMail Integration Schema

Subsections of Integration - EMail

Boxer and SCL Restrictions

What needs to be checked to restrict transfer of mail attachments and files transmission between Boxer and SCL for iOS and Android:

1.  To restrict transfer of documents in specific controlled apps, on Organization Group level: a. Allow DLP – SCL-step2 functionality

b.  Search for and add Boxer for iOS/Android – SCL-step3

  1. Next step for devices in Organization Group: a.  Create a new profile for all devices of a group – SLC-step4.

b.  Turn off “Allow documents from managed sources in unmanaged destinations”  – SCL-step5

1.  To restrict transfer of files from SCL into Boxer the file share, connected to SCL, has to be configured in the Security tab - SCL-step6:

a.  Allow Open in Email = OFF b.  Allow Opent in Third Party Apps = ON

2.  Check that in the security profile properties, Enable Composing Email = No (SCL-step7).

Boxer and SSL for PoC

Boxer has 2 types of accounts:

  • main – is being added on install, is usually configured with policies. Cannot be deleted.
  • additional – is added by users if this is allowed by policies. Can be configured manually.
Warning

(15.08.2017) For policies which are being distributed centrally for the main account there is no possibility to configure “Ignore SSL errors”. If in a PoC of Boxer you have to connect to a private/test mail server, this may pose a problem.

Variant 1 (recommended): server is signed by a cert, which was given by a inner CA (issued by =/= issued to)

Solution: on all devices in the test, you have to manually deploy the certificate chain in the trusted section:

iOShttp://longwhiteclouds.com/2013/01/03/installing-corporate-ca-certificates-on-iphone-or-ipad-for-use-with-vmware-view/

Androidhttps://support.google.com/nexus/answer/2844832?hl=en

Warning

In Android 7.0+, by default, apps don’t work with CA certificates that you add. But app developers can choose to let their apps work with manually added CA certificates. https://support.google.com/nexus/answer/2844832?hl=en

Variant 2: server is signed by a self-signed cert (issued by == issued to)

Solution: use the first account to distribute policies from any public EMail. For example, Office365 from our VMTestDrive

Note

Account can be only one for all devices - this account will not be used

  1. After Boxer installation connect to the account provided by policies (VMTestDrive)
  2. Choose Add Account (“Добавить аккаунт”) in Boxer left menu (IMG_1455.jpg)
  3. Insert an address (IMG_1456.jpg) and later choose Manual configuration (“Ручная настройка”). Type -> Exchange Server.
  4. See config in IGM_1457.jpg ang IGM_1458.jpg as an example of such a connection. It is important to choose SSL (Accept any certificates / “принимать любые сертификаты”).
Warning

After adding the account first time, Inbox may sync for a long time (>30min)

  1. Choose the default account (IMG_1459.jpg)

Boxer Copy-Paste

Boxer Copy&Paste restrictions in two ways

Unlike all other WS1 SDK-enabled Apps, Boxer has two different approaches to restrict Copy&Paste:


At the Assignment stage in App Policies, there is a Copy Paste setting. As a result, copy&paste functions will be denied in ANY directions

❗️Unrestricted personal mail accounts in Boxer still can be troublmakers in this case. Recommend to disable it

Copy&amp;Paste Total restrict


If you need to do more granular restriction you need to implement this on SDK profile

  • Recommended to set Native Boxer DLP capability to Unrestricted. It can be Restricted for potential more secure way, but SDK settings must be enabled after this settings
  • The Boxer App must be published with SDK-profile enable. We use the Default profile, but it should work with Custom SDK-profile as well
  • Before actual install Apps on devices, you need setup SDK-profile: Authentication Type =/= Disable; SSO must be enabled
  • In DLP section (Security Policies) you may enable Copy&Paste Into to get user possibility to copy from unmanaged messengers/notes/etc into Boxer emails

As a result, copy&paste functions will be denied only in the desired way: into or out from managed Apps Copy&amp;Paste Total unrestrict Enable SDK SSO enable Copy&amp;Paste In and Out

Boxer for Android Fingerprint

  • VMware Boxer v 4.5+ for Android 
  • AirWatch Console 9.0.5+

Following are the steps for fingerprint authentication on the Android Boxer app:

  • In the Apps SDK settings (Groups & Settings > All Settings > Apps > Settings and Polices > Security Polices), enable the Biometric Mode.
  • While deploying the Boxer app, enable the Application to use AirWatch SDK and Select the Global SDK for Android.
  • In the Email settings, enable the Application Configuration and enter “AppForceActivateSSO” (without the quotes) under Configuration Key and Value Type as Boolean and Configuration Type as True.
  • Make sure passcode is set as None 
  • Push the boxer app to the device and download it from the Play Store

ENS Basic Troubleshooting

Warning

Database for ENSv2 must be named “ENS”.

Network

ENSLINKAddress On-Premise, should point to the externally accessible hostname pointed to ENS service. A support ticket has to be made with VMware Airwatch to request API token (internally the support reaches out to Boxer product manager and requests API key).

MS Exchange Server

User agent is configured for ENSv2 on MS Exchange Server CAS role. User agent must have access to receive data from MS Exchange, or ENS will not be able to receive PUSH notifications.

Troubleshooting

ENSLINKAddress for On-Premise installation should point it correctly to the customer’s externally accessible hostname pointed to ENS service.

Autodiscovery errors showing on logs.

  • Make sure that the EWSUrl key is configured in the console with a correct value for the EWS url for their exchange environments.
    Test it out by opening it on the browser and making sure you are prompted for credentials.
    Tip

    Alternatively they can just turn ON autodiscovery on their environment.

Authentication errors (401s)

  • Check what type of authentication is enabled in EWS? Make sure it has parity with whatever they are using for ActiveSync (Basic, OAuth, CBA) as Boxer will be the one to pass whatever type of credentials it has to ENS to use against EWS.
  • Verify the EWSUrl is correct and resolves to Exchange environment and test the credentials used by navigating to the EWS URL and testing them there.
  • Run “Outlook Connectivity Tests” on https://testconnectivity.microsoft.com
    Tip

    Try the Exchange Server or Office 365 tabs accordingly

ENSv2 not sending notifications but no logs found on help portal.

  • Verify the ENSAPIToken key is correct in the console configuration.

  • Verify the ENSLinkAddress key is correct in the console configuration

    Tip

    Try appending the “alive” endpoint for the environment and make sure it responds.

  • Verify the EWSUrl is correctly configured with a valid EWS value.

  • Verify that ENSv2 servers have inbound access to their EWS environment (firewall may be blocking access, they need to open the corresponding IPs)

  • Verify that EWS can send outbound traffic to the corresponding ENSv2 domain (https://.getboxer.com/api/ens)

General FAQ

  • **How are credentials or authentications tokens handled?
    **
    • Although the client does share the credentials/tokens with the ENSv2 environment upon registration, they are not kept (saved anywhere) by AirWatch servers. Rather, the Exchange server passes them back to AirWatch, encrypted, as part of a notification it sends whenever a new email is available. From that notification (Exchange -> ENSv2), ENS decrypts the credentials and uses them to make any requests necessary to the Exchange server. After performing any necessary requests, the credentials are once again discarded.
Warning

Bug in MS Exchange detected: Exchange returns the email information even though the user is not the owner. This results in the notification payload being created for the wrong user and ultimately another user seeing the notification. 

With ENSv2 1.2+, a new service object is created for each EWS request. This will prevent the application from making a request to the EWS endpoint with different credentials.

Patch for Exchange needed from Microsoft on this, since this is unexpected Exchange behavior.

  • If credentials are not persisted, is there any data persistent at all by ENS? How is it secured?
    • There is a secure database that keeps a list of devices and a list of public private key pairs used to unencrypt the credentials when they come from Exchange;
    • Logs are also kept to aide in debugging issues and monitoring the system. These don’t contain any customer’s private information and access to them is also tightly secured via account permissions.
  • What data is transmitted through the ENS server without being persisted? How is it secured?
    • User credentials (encrypted with RSA encryption)
    • Email subject and sender (sent via HTTPS)
    • All communication is done via HTTPS
  • What additional cloud services does ENS depend on?
    • AWS Simple Notification Service (SNS) for push notification handling.
    • Apple Push Notification Service (APNS) as it is the only way to pass notifications to Apple devices.
    • AWS Relational database service (RDS) for data persistence.
  • What is the user agent used by ENSv2 when sending requests to Exchange?
    • MailNotificationService/v2 (ExchangeServicesClient/15.00.0913.015+ (will change as new libraries from Microsoft are released)
  • What email folders does ENSv2 monitor for incoming messages and actions?
    • Currently, ENSv2 only monitors each user’s Inbox folder.

Load Balancing ENSv2

For HA, it is recommended to load balance several ENS web servers as needed following the Hardware Requirements. All web servers should point to the same database server as this will be their shared source of state for each of the clients.

Since the ENS web application itself is stateless there are no requirements to configure any session handling (stickiness) in the loadbalancer so a straightforward configuration should suffice.

Integration - Microsoft IRM-RMS

RMS features in Boxer

According to Boxer User Guide for iOS 4.5.1, Boxer User Guide for Android 4.5.0

Main features

  • Edit
  • Reply
  • Reply All
  • Forward
  • Copy-Paste
  • Modify recipients
  • Extract
  • Print
  • Export
  • Content Expiry Date

Other Features

  • Press and hold an email message to copy and paste it into the application.
  • You cannot copy data from the Boxer application and paste anywhere outside the application. However, you can copy data from outside the application and paste into the Boxer application.
  • If your email message has contact number details, tap hold on the number to immediately dial it.
  • If restricted by your administrator, attachments may open through the VMware Content Locker and other AirWatch approved apps. Hyperlinks may open only through the VMware Browser.
  • If configured by your administrator, you can preview emails and their attachments within Boxer (See Boxer supported files’ types).
  • On the attachment preview screen, the Share icon will be unavailable. When tapped on Share icon, you are presented with a toast message “Disabled by your admin”.
  • After performing an action on an email while viewing it, you can have Boxer either advance to the next message, the previous message, or return to the conversation list. This setting can be configured from Mail settings (navigate to Settings > Mail > More mail settings > Auto Advance).

RMS Attachments

Boxer does not open RMS-restricted attachments - it transmits them to Content Locker. To use Content Locker on iOS device, the following has to be done:

  1. Root certificate must be placed on device

  2. In new iOS version the root Trust has to be ACTIVATED in a special menu option

  3. In order for Content Locker to access RMS attachments, it must be registered on the ADFS server with this command:

Add-AdfsClient -Name "<App name>" -ClientId "<ID name>" -RedirectUri "<RedirectUri>"

Example: Client ID for VMware Content Locker for iOS is e9fcfce0-a20b-4d34-b580-909332723090

Tip

Client ID of application can be found in ADFS logs: every error Content Locker gives while trying to read a RMS-secured attachment is followed by its’ current Client ID.

SEG on Windows Proxy

SEG Guide - VMware AirWatch SEG Guide

Prevent usage of Native EMail on enrolled devices

Problem: Users can gain access to Exchange ActiveSync from uncontrolled devices and mail clients on them. Usage of SEG solves the problem of uncontrolled devices access.

You can enforce using Boxer/Inbox by creating an email compliance policy from the AirWatch console:

Email> Compliance Polices > General Email Policies > Mail Client

SEG as MS Exchange OWA Proxy

Warning

Article is for OLD separate SEG. NOT about SEG on UAG.

You can restrict mobile traffic to seg.company.com by installing IP and Domain restrictions on the IIS on the Exchange server, and then enable IP filtering to deny everyone but the SEG on the ActiveSync endpoint on IIS. This will ensure all enrolled mobile devices will access email through SEG. You can also implement email policies to ensure that unmanaged devices do not access the SEG.

AirWatch cannot block access to OWA for unenrolled mobile devices since SEG does not manage OWA. The only way to do so would be checking through the AD for unenrolled users and preventing them from webmail access from there.

Note

OWA traffic can be routed through the SEG however it will act as a simple pass through.

Warning

The OWA through SEG & proxying Webmail through SEG is not a supported setup as it could lead to a single point of failure for email access.

SEG Java Keystore

Warning

Article is for OLD separate SEG. NOT about SEG on UAG.

Default password for SEG Java Key store = changeit

SEG on Windows Java Memory

Warning

Article is for OLD separate SEG. NOT about SEG on UAG.

Zulu is the new Java Corporate middleware.

Resolution

  • Upgrade to latest version of SEG (2.18+);
  • Set the max heap size to 5Gb;
  • Use Shenandoah as the garbage collection method.

Follow these steps to apply the settings:

  1. Stop SEG service;
  2. Go to SEG install directory and edit file SecureEmailGateway-2.18/service/conf/segServiceWrapper.conf
  3. Update max heap to 5Gb, look for “Xmx” and update the property to: 

wrapper.java.additional.3=-Xmx5120m

  1. Use Shenandoah GC, look for “#wrapper.java.additional.38” and in the next line add: 

wrapper.java.additional.39=-XX:+UseShenandoahGC
wrapper.java.additional.40=-Xlog:gc=debug:file=tmp/gc-%p-%t.log:time,level,tags:filecount=10,filesize=50m*

  1. Save file and start the SEG service. 
  • Observe the system resources once this change is placed + enable GC logs in the above settings.

If no issue is seen, then remove the GC logging setting by following these steps: 

  1. Stop SEG service. 
  2. Go to SEG install directory and edit file SecureEmailGateway-2.18/service/conf/segServiceWrapper.conf
  3. Remove line: 

wrapper.java.additional.40=-Xlog:gc=debug:file=tmp/gc-%p-%t.log:time,level,tags:filecount=10,filesize=50m*

  1. Save and start SEG service.

SEG Clustering

If multiple SEG servers are load balanced, single policy broadcast messages apply to only one SEG. This includes the messages sent from the AirWatch Console to SEG upon enrollment, compliance violation, or correction. Use Delta Sync with a refresh interval of ten minutes to facilitate newly enrolled or compliant devices. These devices experience a waiting period of maximum ten minutes before email begins to sync. Benefits of this approach include:

  •  Updated policies from the same API source for all SEG servers. 
  • Smaller performance impact on API server.  
  • Reduced implementation or maintenance complexity compared to the SEG clustering model.   
  • Fewer failure points as each SEG is responsible for its own policy sets.
  •  Improved user experience. 
     

 SEG Clustering is also available to facilitate the sharing of single policy updates to all nodes of a SEG cluster.

SEG TLSv1

Please go through the following instructions in order to enable TLSv1.0 on SEG V2:

  • Go to SEG installation directory -> {SEG_DIRECTORTY}/service/conf
  • Edit file conf
  • Look for following properties:

Property 1

wrapper.java.additional.9=-Djdk.tls.disabledAlgorithms=MD5\, RC4\, TLSv1\, SSLv2Hello\, SSLv3\, DSA\, DESede\, DES\, 3DES\, DES40_CBC\, RC4_40\, MD5withRSA\, DH\, 3DES_EDE_CBC\, DHE\, DH keySize < 1024\, EC keySize < 224

set this property as: (Removing TLSv1 from the disabled list):

wrapper.java.additional.9=-Djdk.tls.disabledAlgorithms=MD5\, RC4\, SSLv2Hello\, SSLv3\, DSA\, DESede\, DES\, 3DES\, DES40_CBC\, RC4_40\, MD5withRSA\, DH\, 3DES_EDE_CBC\, DHE\, DH keySize < 1024\, EC keySize < 224

Property 2

wrapper.java.additional.12=-Dhttps.protocols=TLSv1.1\,TLSv1.2

set this property as:

wrapper.java.additional.12=-Dhttps.protocols= TLSv1\,TLSv1.1\,TLSv1.2

  • Restart SEG Service.

Integration - LDAP

Linked Articles

List of LDAP Queries used in Directory Searches (Active Directory and NON-Active Directory)

Search Group

(&(objectClass=group)(|(CN=*{inputName}*)(distinguishedName={inputName})))  

Sync Group

(&(objectClass=group)(|(objectGUID={ExternalID1})(objectGUID={ExternalID2}))) {ExternalID}
  • Hex Value if the object identifier has GUID value - String Value if the object identifier has string value

Search User

(&(objectCategory=person)(sAMAccountName={InputUserName}))  

Sync User

(&(objectCategory=person)(sAMAccountName=*)(|(objectGUID={ExternalID1})(objectGUID={ExternalID2}))  

Search Group member

(&(objectCategory=person)(sAMAccountName=*)(memberOf={GroupDN})) (&(objectClass=Group)(memberOf={GroupDN})) -- For recursive member search {GroupDN} - Group's distinguishedName value  

Add Missing Users

(&(objectCategory=person)(sAMAccountName=*)(|(distinguishedName={UserDN1})(distinguishedName={UserDN2})))

A sample how LDAP query works on the customer envirionment.

–sample—

ldapsearch -h gvx0lsami01q.company.com -p 389 -b O=COMPANY cn=EU_MDM_AirwatchEnabled,ou=groups,O=COMPANY member

Output:

C:\tools>ldapsearch -h gvx0lsami01q.company.com -p 389 -b O=COMPANY cn=EU_MDM_AirwatchEnabled member  
cn=EU_MDM_AirwatchEnabled,ou=groups,O=COMPANY  
member=secAuthority=Default  
member=cn=emmatest01,ou=eu,O=COMPANY  
member=cn=emmatest02,ou=eu,O=COMPANY  
member=cn=emmatest03,ou=eu,O=COMPANY  
member=cn=emmatest04,ou=eu,O=COMPANY
ldapsearch -h gvx0lsami01q.company.com -p 389 -b cn=emmatest01,ou=eu,O=COMPANY objectclass=* cn sn mail uid uniqueidentifier  
Alternatief evt: ldapsearch -h gvx0lsami01q.company.com -p 389 -b cn=emmatest01,ou=eu,O=COMPANY uid=* cn sn mail uid uniqueidentifier

Output:

C:\tools>ldapsearch -h gvx0lsami01q.company.com -p 389 -b cn=emmatest01,ou=eu,O=COMPANY objectclass=* cn sn mail uid uniqueidentifier  
cn=emmatest01,ou=eu,O=COMPANY  
cn=emmatest01  
cn=John Doe  
sn=emmatest01  
uid=emmatest01  
uniqueidentifier=5510012309  
mail=rr@company.com
C:\tools>ldapsearch -h gvx0lsami01q.company.com -p 389 -b cn=emmatest02,ou=eu,O=COMPANY objectclass=* cn sn mail uid uniqueidentifier  
cn=emmatest02,ou=eu,O=COMPANY  
cn=emmatest02  
cn=Adam Smith  
sn=emmatest02  
uid=emmatest02  
uniqueidentifier=5510012319  
mail=ph@company.com

Subsections of Integration - LDAP

IBM ISAM

Notes on integration:

  • Change the attribute where Distinguished Name in the AW Console is ‘distinguishedName’ to ’entryDN’ (see attached screenshot)
  • This is Accessible from the AW Console from Groups & Settings > All Settings > System > Enterprise Integration > Directory Services

Microsoft Active Directory

Note

VMware vSphere & Microsoft LDAP Channel Binding & Signing patch

Due to CVE-2017-8563 potential exploit, Microsoft is changing behavior of AD to accept connections only using TLS.

See external links:

Test if LDAP server listens to ports TCP636 and TCP3269:

nc -v LDAP-SERVER-IP 636
nc -v LDAP-SERVER-IP 3269

Integration

Go to Configuration > System Configuration > System > Enterprise Integration  > Directory Services

  • Directory Type: Directory platform being utilized
  • Server: Address of the directory services server
  • Port: TCP Port for communication with directory services
  • Protocol Version: Version of LDAP being used
  • Bind Authentication Type: Protocol used to authenticate the LDAP session (GSS-NEGOTIATE recommended, gives auto-choice of Kerberos/NTLM)

Advanced config

  • Search Subdomains: Search subdomains by LDAP chase referrals
  • Connection/Request Timeout: Timeout setting per connection/request in seconds
  • Search without Base DN: Enable to search without sending a base DN
  • Use Recursive OID at Enrollment/Group Sync : Only supported by AD; used to obtain group membership during enrollment and not rely on the scheduler to run
  • Object Identifier Data Type: Set the object ID type to string or binary. AD is binary by default while most other LDAPs are strings.
    Note

    In AirWatch 7.3+, the AD group structure itself is stored in the sync table, and if the user is shown to be a member of a nested group whose External ID is already stored in the table, the group membership will be reflected. The only flow unaccounted for is the group structure itself changes between scheduler iterations, in which at most there will be up to a 12 hour delay from when the user enrolls and is associated with the group after the group structure has changed.

Directory users mapping

  • From Directory Services, navigate to User

  • Specify the Base DN AirWatch uses to find users in the directory

  • For User Search Filter, enter the parameters used to associate AirWatch user accounts with AD/LDAP accounts (&(objectCategory=person)(sAMAccountName={EnrollmentUser}))

  • Select Show Advanced to display additional options

  • Enable Auto Merge to consolidate changes made in the directory with AirWatch automatically

  • Use Attributes to assign directory services information to the correct AirWatch fields

  • Click Save

    Note

    All members of the Group or Organizational Unit from the directory are first synced into the dbo.UserGroupEnrollmentUserMapSync table by running the below LDAP query (for AD).

  • Another query is run for all of the DN’s in the sync table to pull the actual user information from the directory: (&(objectCategory=person)(sAMAccountName=*)(|(distinguishedName={UserDN1})(distinguishedName={UserDN2})))

  • When we sync User attributes, we query the directory for the users based on their ExternalID:
    (&(objectCategory=person)(sAMAccountName=*)(|(objectGUID={ExternalID1})(objectGUID={ExternalID2})))

  • The User Group Membership Sync is the process by which we sync up the group membership for users from the directory. This will happen during a scheduler iteration if the Auto Sync option is enabled on the User Group and can be performed manually by clicking the Sync button on the User Group in the List View: (&(objectClass=group)(|(objectGUID={ExternalID1}) (objectGUID={ExternalID2}))

Sync interval

There are three primary scheduler jobs that sync up the group membership and user attributes:

  1. LDAP Sync – the LDAP Sync job will sync the User Group membership.
  2. Sync Directory Users – this job will sync up user attributes.
  3. Sync Admin Users – this job will sync up admin attributes.
Note

member vs. memberOf

Every object in AD has certain attributes like phone number, name, etc. In AD, membership to a group is determined by both the member and memberOf attribute, which is not the case in other directory types. Some directories only have member or only memberOf. The difference is key, memberOf is the attribute on the actual “member” or “user” object that says “I am a member of XYZ group”, this value is usually the Distinguished Name (DN) of the group the object is a member of. The Member attribute is on the “container” or “group”, and says “I have XYZ as a member”, which is also usually the DN of their members. Directories that use the Member relation will have groups with a list of Member attributes of all the users that are members of that group. Directories that use the MemberOf attribute will have users that list the groups they are members of on the actual user object.

Auto sync

In production all LDAP based scheduler jobs are set to fire every 12 hours. It is not recommended to lower these values for On-Premise or Dedicated SaaS customers as setting the scheduler interval too low may cause performance issues in versions older than 7.1. If a customer requires a lower interval, it is recommended to run at least one sync, and pull the LastSyncTimeInMinutes column from the dbo.LDAPDefinition table to determine how long it takes to sync the Organization Group.

Note

All issues that arise during a scheduler iteration will appear in the scheduler logs

Manual sync

The Add Missing Users, User Group Membership Sync, and Sync User Attributes processes can all be triggered manually by clicking a button in the console.

Note

Manual user attribute sync will only sync enrollment users, not administrator attributes

Warning

If any issues arise during one of these processes when they are triggered manually, the BulkProcessingServiceLogFile.txt in the Services folder will contain the backend information. If it appears there is a UI issue with the buttons, the WebLogFile.txt file in the WebConsole folder will contain the information needed to troubleshoot.

User enrollment

The mobileManagement.EnrollmentUser table contains information on all of the enrollment users in the environment:

select ExternalID, SecurityTypeID, * from mobileManagement.EnrollmentUser EU
join dbo.LocationGroup LG
on LG.LocationGroupID = EU.LocationGroupID
where LG.Name = 'ams'
  • ExternalID – the ExternalID column contains a hashed value of the attribute configured for Object Identifier. This value is used to match the AirWatch user with the customer’s directory user. If for whatever reason this value is null or incorrect, the AirWatch user will not sync.
  • SecurityTypeID – this column determines the type of user. 1 denotes a directory user, 2 denotes a basic user, and 3 denotes an authentication proxy user.
  • LocationGroupID – the Organization Group ID where the user is imported. Note that all directory users will always reside at the same level Directory Services is configured, even if imported or added at a child.
  • LDAPDefinitionID – the ID of the LDAP Definition the user is associated with.

dbo.LDAPDefinition table contains all of the configuration information from the Directory Services for an Organization Group

select LD.UserSearchFilter, LD. * from dbo.LDAPDefinition LD
join dbo.LocationGroup LG
on LG.LocationGroupID = EU.LocationGroupID
where LG.Name = 'ams'
  • LastSyncDurationInMinutes – this column contains the time it took to sync the entire Organization Group in minutes.
  • LastSyncedOn – last date the Organization Group synced with the directory.
  • MemberPageSize – the MemberPageSize value can be configured, but should not exceed 5000 if the customer is using EIS. This value determines the chunk size of information being sent back and forth between ACC\EIS
  • IsSortControlSupported – determines if the directory type supports sorting results at the directory server before the response is sent.

The dbo.UserGroupEnrollmentUserMapSync table will contain only the ExternalIDs of both the users and the groups that are members of the AirWatch group that was added

select MAP. * from dbo.UserGroupEnrollment(Core)UserMapSync MAP
join dbo.UserGroup UG
on UG.UserGroupSyncID = MAP.UserGroupSyncID
where UG.FriendlyName = 'ams'

The dbo.UserGroup table contains information about the configured User Groups in AirWatch.

select UG. * from dbo.UserGroup UG
join dbo.LocationGroup LG
on UG.RootLocationGroupID = LG.LocationGroupID
where LG.Name = 'ams'

The dbo.UserGroupSync table contains syncing information for directory User and Admin groups. It provides a few more columns of information that contain the settings you have configured per group in the console.

select UGS. * from dbo.UserGroupSync UGS
join dbo.LocationGroup LG
on UGS.RootLocationGroupID = LG.LocationGroupID
where LG.Name = 'ams'
Note

A user’s primary group in Active Directory cannot be added to AirWatch, as the primary group has no memberOf attribute on the user object. This is an AD limitation.

Query Troubleshooting

Tip

LDAP Admin is the LDAP browser most commonly used internally. An LDAP browser is an excellent way to troubleshoot certain queries and determine which attributes should be configured in Directory Services. The tool can be download at http://www.ldapadmin.org/

With some issues, AirWatch is not able to find certain users and/or groups. This is often due to an incorrect filter or lack of permissions in the directory. If we are unable to find the user and group objects with the LDAP Admin tool using the same settings from the console, we will be unable to find them using AirWatch. It will be necessary to test queries during troubleshooting. To run a custom query, click the magnifying glass icon in the toolbar, select the Custom tab in the window that appears, type the Base DN in the Path field, and type the query in the Filter field.

Connection Troubleshooting

Test connection failures are usually due to one of two error codes, either 49 or 81. An 81 error code indicates the console cannot find the directory server, which can happen if the hostname was entered incorrectly, ACC\EIS is not functioning properly, the directory server is firewalled, or there is no route to the directory server from the console server.

When an administrator encounters a 49 error it is important to note that this error is generated by the directory server, not AirWatch. In 99% of cases this is because the bind authentication type is not supported, or the account and passwords are incorrect. To verify that the console is not sending a bad username or password, SSL must be turned off and the authentication type must be set to basic so the bind request can be sniffed off the network in plaintext. Use Wireshark!

Warning

“System.DirectoryServices.Protocols.LdapException: Error code:81”

Tip
  • LDAP error 81 = The LDAP library can’t contact the LDAP server
  • AirWatch is not able to communicate with the LDAP server. Verify that Airwatch services are enabled in AirWatch Cloud Connector. If not, the AirWatch Cloud Connector may require re-installation after enabling.

Optimization

Warning

Optimization of slow enrollment into AD

Groups & Settings > All Settings > Enterprise Integration > Directory Services, Advanced section

Use Recursive OID At Enrollment = Disable

Common LDAP Queries

Search Group: (&(objectClass=group)(|(CN={inputName})(distinguishedName={inputName})))

Sync Group: (&(objectClass=group)(|(objectGUID={ExternalID1})(objectGUID={ExternalID2})))

Search User: (&(objectCategory=person)(sAMAccountName={InputUserName}))

Sync User: (&(objectCategory=person)(sAMAccountName=*)(|(objectGUID={ExternalID1})(objectGUID={ExternalID2})))

Add Missing Users: (&(objectCategory=person)(sAMAccountName=*)(|(distinguishedName={UserDN1})(distinguishedName={UserDN2})))

Novell eDirectory

Server Settings

User Settings

Advanced User Settings

Group Settings

Advanced Group Settings

Integration - Microsoft CA

DCOM preferred architecture for PoC

  • Windows Server for Certificate Authority role should be Datacenter/Enterprise Edition
  • The Certificate Authority should be in Enterprise Mode (AD integration)
  • The ACC/ESC connector should be in the same Active Directory Domain with appropriate CA
  • Check network ports! They are different for DCOM and SCEP

WS1 UEM Integration with MS CA Schema

Network Requirements

  • TCP Port 135: Microsoft DCOM Service Control Manager.
  • TCP Ports 1025 - 5000: Default ports DCOM processes.
  • TCP Ports 49152 - 65535: Dynamic Ports.

Configuration

Step 1 - Install Microsoft CA

Installation of MS CA Role...

Step 2a - Configure Microsoft CA, Basic

Warning

The following steps are applicable only if the Security Department allows a service account to have access to their CA

Add a Service Account on the CA

  1. Launch the Certification Authority Console from the Administrative Tools in Windows.
  2. In the left pane, select (+) to expand the CA directory.
  3. Right-click the name of the CA and select Properties. The CA Properties dialog box displays.
  4. Click the Security tab.
  5. Click Add. The Select Users, Computers, Service Accounts, or Groups dialog box displays.
  6. Click within the Enter the object names to select field and type the name of the service account (e.g., Ima Service).
  7. Click OK. The CA Properties dialog box displays.
  8. Select the service account you added in the previous step (e.g., Ima Service) from the Group or user names list.
  9. Select the Read, the Issue and Manage Certificates, and the Request Certificates checkboxes to assign permissions to the service account. Click OK.
Info

If Security Department does not allow the above, propose to use a separate child CA, and do the above configuration on it. Separate CA can be turned off in case of problems.

Warning

CA server must be in Enterprise Mode of operation. To install CA in Enterprise mode, Enterprise Admin account is needed. CA in Enterprise Mode is installed on forest level! This means Domain Controllers will have links to this CA, even if it is installed in a subdomain.

Step 2b - Configure Microsoft CA, Enroll On Behalf Of (EOBO)

Tip

Security Advantage!

  • The following steps are applicable if the Security Department DOES NOT allow a service account to have access to their CA;
  • As result of EOBO configuration, users will request certificates by themselves. If service account gets disabled, users will still be able to request certificates.

CA Step 0: Enable LDAP Referrals

Info

This action is only needed in multi-domain environment!

Run the following commands on the CA. This configuration is needed on ADCS CA since we are requesting certificates on behalf of some other user using service account.
This feature is only supported on Windows 2008 R2 Enterprise and later. See the link below for context and details: https://technet.microsoft.com/en-us/library/ff955842(v=ws.10).aspx

Use CMD to restart certificate services and enable cross-forest LDAP Referrals:

net stop certsvc
certutil -setreg policy\EditFlags +EDITF_ENABLELDAPREFERRALS
net start certsvc

CA Step 1: Create the Restricted Enrollment Agent Certificate Template

  1. Open the Certificate Authority (CA).
  2. Expand the CA Name, Right click Certificate Templates, and select Manage.
  3. Right click the Enrollment Agent (Computer) template and select Duplicate Template (Do not choose Enrollment Agent user cert!). Name it per your preference.
  4. Select Windows Server 2008+ Enterprise.
  5. On the Request Handling tab, select Allow Private Key to be Exported.
  6. In the Subject Name tab, make sure Build from this Active Directory Information is activated and Subject Name format is set to Fully distinguished name. Click OK.
  7. Navigate back to the CA, right click Certificate Templates, select New, and select Certificate Template to Issue.
  8. Select the duplicate copy of the template created in the previous step. Click OK.

CA Step 2 - Enroll a computer for the Signer Certificate

Substep A: Generate a new Restricted Enrollment Agent Signer Certificate
Tip

The following actions in this step can be done on any server that can connects to the Certificate Authority. Hint: do it on the server with ESC/ACC connector.

  1. Open MMC.
    Warning

    Use the same service user account to open MMC and import certificate, as the one used later for transmitting EOBO certificates. Using other user account, including admin accounts, will break the certificate request schema!

  2. Click File and select Add/Remove Snap in.
  3. Select Certificates.
  4. Select Computer Account.
  5. Select Local Computer and select Finish. Click OK.
  6. Expand Certificates (Local Computer), double click Personal, right click Certificates, select All Tasks, and select Request New Certificate. Click Next.
  7. Select Active Directory Enrollment Policy and select Next.
  8. Check the duplicate template created in earlier steps and select Enroll.
  9. Once completed, select Finish.
    Warning

    Service user account, which is used by AirWatch to create a certificate request, must be a domain account and have enough permissions to access Windows certificate store. Standard user will not work. Local admin rights on the computer is a simple solution.

Troubleshooting ESC service rights...
Substep B: Configure the issued certificate
  1. Once the certificate has been issued, right click it and select All Tasks followed by Manage Private Keys.
  2. Click Add.
  3. Type Network Service and select Check Names. Once added, select OK twice.
Substep C: Export the Certificate

Note

If the certificate needs to be installed on multiple Device Services servers or AirWatch Cloud Connector servers, export with the private key. If not, skip to exporting just the public key.

Export the public key to .cer file Only the public key needs to be exported for upload to the console:

  1. Right click the issued certificate, select All Tasks followed by Export.
  2. Select No, do not export the private key, select Next.
  3. Select DER encoded binary X.509 (.CER), select Next.
  4. Select a destination for the exported certificate and select Next. Click Finish.
Substep D: Import the certificate for Device Services and ESC/ACC servers
  1. Open MMC.
  2. Click File and select Add/Remove Snap in.
  3. Select Certificates.
  4. Select Computer Account and select Next.
  5. Select Local Computer and select Finish. Click OK.
  6. Expand Certificates (Local Computer) and select Personal. Right click Certificates, select All Tasks and select Import
  7. Select the .cer file exported in previous steps and select Next.
  8. Ensure Place all certificate in the following store is set to Personal and select Next. Click Finish.

CA Step 3: Add a User Certificate Template on the CA

  1. Open the CA (certsrv) window.
  2. In the left pane, select (+) to expand the CA directory.
  3. Right-click the Certificate Template folder and select Manage. The Certificate Templates Console window displays.
  4. Select the desired template (User) under Template Display Name, and right-click Duplicate Template. The Duplicate Template dialog box displays. AirWatch will use the duplicate certificate template. The template you choose depends on the function being configured in AirWatch.
    Tip

    For Wi-Fi, VPN, or Exchange Active Sync (EAS) client authentication select User template.

  5. Select the Windows Server that represents the oldest enterprise version being used within the domain to ensure backward compatibility of the certificate that was issued.
  6. Click OK. The Properties of New Template dialog box displays.

CA Step 4: Configure Certificate Template Properties

  1. Click the General tab.
  2. Type the name of the template displayed to users in the Template display name field. The Template name field auto-fills with the template display name without spaces.

You may use this default value or enter a new template name if desired. The template name may not contain spaces. Make note of the template name. You will need to enter this information in AirWatch. You will enter the Template name you just configured with no spaces in the AirWatch Console in the Issuing Template field within the Configuring the Certificate Template screen.

  1. Select the desired length of time for the certificate to be active from the Validity period entry field/drop-down menu.
  2. Click Apply.
  3. Click the Request Handling tab.
  4. Select the appropriate client authentication method from the Purpose: drop-down menu. This selection might be based on the application of the certificate being issued, although for general purpose client authentication, select Signature and Encryption.
  5. Select the Allow private key to be exported checkbox. For a certificate to be installed on an iOS device, this checkbox MUST be selected.
  6. Click Apply.
  7. Select the Subject Name tab.
  8. Select Supply in the request or Build from this Active Directory
Note

Selecting Supply in the request means the certificate fields will be generated by AirWatch console. Doing this will give AirWatch admin control over the text in certificate request.

Selecting Build from this Active Directory allows to write something simple in the AirWatch console Request Template fields (DN). CA admin will control over the text in certificate request. Do this if multiple fields are required for customer to configure EMail etc., and add these:

  • Include e-mail name in subject name
  • Include this information in alternate subjject name: E-Mail name, User principal name (UPN), etc.

11 (optional). If Enrollment agent template is used, select the Issuance Requirements tab and select This number of authorized signatures = 1. Under the Application policy drop-down field, select Certificate Request Agent and select Apply.

Enable the Template for Certificate Authentication
  1. Click the Extensions tab.
  2. Select Application Policies from the Extensions included in this template: field. This allows you to add client authentication.
  3. Click Edit. The Edit Application Policies Extension dialog box displays.
  4. Click Add. The Add Application Policy dialog box displays.
  5. Select Client Authentication from the Application policies: field.
  6. Click OK. The Properties of New Template dialog box displays.
Provide the AD Service Account Permissions to Request a Certificate
  1. Click the Security tab.
  2. Click Add. The Select Users, Computers, Service Accounts or Groups dialog box displays. This allows you to add the service account configured in Active Directory to request a certificate.
  3. Enter the name of the AirWatch service account in the Enter the object names to select field.
  4. Click OK. The Properties of New Template dialog box displays.
  5. Select the service account you created previously - for AirWatch on the CA, from the Group or user names: field.
  6. Select the Enroll checkbox under Permissions for CertTemplate ServiceAccount. Click OK.
Enable the Certificate Template on the CA
  1. Navigate to the Certificate Authority Console.
  2. Click (+) to expand the CA directory.
  3. Click Certificate Templates folder.
  4. Right-click and select New > Certificate Template to Issue. The Enable Certificates Templates dialog box displays.
  5. Select the name of the certificate template (e.g., Mobile User) that you previously created in Creating a Name for the Certificate Template.
  6. Click OK.
  1. Open the Certificate Authority (CA).
  2. Expand the CA Name, Right click Certificate Templates, and select Manage.
  3. Choose the new Enrollment Agent (Computer) template created for AirWatch
  4. Open the Superseded Templates tab.
  5. Click Add..
  6. Choose the created User Template, and add it to the list. Click OK.

Step 3 - Configure the AirWatch console

Configure the CA

  1. Login to the AirWatch Console as a user with AirWatch Administrator privileges, at minimum.
  2. Navigate to System > Enterprise Integration > Certificate Authorities.
  3. Click Add.
  4. Select Microsoft ADCS from the Authority Type drop-down menu. You need to select this option prior to populating other fields in the dialog so applicable fields and options display.
  5. Enter the following details about the CA in the remaining fields:
    • Enter a name for the CA in the Certificate Authority field. This is how the CA will be displayed within the AirWatch Console.
    • Enter a brief Description for the new CA.
    • Select ADCS radio button in the Protocol section.
      Note

      If you select SCEP, note that there are different fields and selections available not covered in this guide

    • Enter the host name of the CA server in the Server Hostname field (FQDN or IP)
    • Enter the actual CA Name in the Authority Name field. This is the name of the CA to which the ADCS endpoint is connected
      Tip

      Authority Name can be found by launching the Certification Authority application on the CA server - the inner name of the CA.

    • Select the radio button that reflects the type of service account in the Authentication section. Service Account causes the device user to enter credentials. Self-Service Portal authenticates the device without the user having to enter their credentials.
    • Enter the service account Domain\Username and Password. This is the username and password of the ADCS service account which has sufficient access to allow AirWatch to request and issue certificates.

Note

If Enrollment Agent is used:

  • In Additional Options list choose Restricted Enrollment Agent.
  • Upload the public key file (.cer) exported in previous steps.
6. Click Save.

Configure the Certificate Template

For Enrollment Agent, data supplied by AD (in CA config)
  1. Select the Request Templates tab. Click Add.
  2. Complete the certificate template information:. + Name: a friendly name for the new Request Template. This name is used by the AirWatch Console + Description (optional): a brief Description for the new certificate template + Certificate Authority: choose the just created one from the certificate authority drop-down menu + Issuing Template: the name that you configured in CA in Configuring Certificate Template Properties in the Template name field. Make sure you enter the name with no spaces. AirWatch automatically places “certificatetemplate:” prefix afterwards. This is normal. Do not enter the word “certificatetemplate:” yourself! + Requester Name: put something simple here, since request attribs are handled at the CA level. Example: {EmailDomain} or {EnrollmentUser}
  3. Click Save.
For direct User template, data supplied in request
  1. Select the Request Templates tab. Click Add.
  2. Complete the certificate template information. + Name: a friendly name for the new Request Template. This name is used by the AirWatch Console + Description (optional): a brief Description for the new certificate template + Certificate Authority: choose the just created one from the certificate authority drop-down menu + Issuing Template: the name that you configured in CA in Configuring Certificate Template Properties in the Template name field. Make sure you enter the name with no spaces. AirWatch automatically places “certificatetemplate:” prefix afterwards. This is normal. Do not enter the word “certificatetemplate:” yourself! + Subject Name: put specific fields, which will be in the certificate. Example syntax for multi-line Subject Name field:
CN={EnrollmentUser},E={EmailAddress},OU={UserDistinguishedName}

Private Key Length: choose a value (This is typically 2048 and should match the setting on the certificate template that is being used by DCOM) + Private Key Type: +Signing, +Encryption (This should match the setting on the certificate template that is being used by DCOM) + San Type: enter fields for Subject Alternative Name. Email AddressUser Principal Name, and DNS Name are supported by ADCS Templates by default, and AirWatch recommends that you use them.

Example of fields to match CA config: User Principal Name = {UserPrincipalName} Email Address = {EmailAddress}

- Select the **Automatic Certificate Renewal** checkbox to have certificates using this template automatically renewed prior to their expiration date. If enabled, specify the Auto Renewal Period in days.

- Select the **Enable Certificate Revocation** checkbox to have certificates automatically revoked when applicable devices are unenrolled or deleted, or if the applicable profile is removed.
Note

If you are making use of the Enable Certificate Revocation feature, go to Devices & Users > General > Advanced and set the number of hours in the Certificate Revocation Grace Period field. This is the amount of time in hours after the discovery that a required certificate is missing from a device that the system will wait before actually revoking the certificate.This will help to NOT identify certificate missing on device because of big Wi-Fi latency or network issues.

- Select the **Force Key Generation on Device** checkbox to generate public and private key pair on the device which improves CA performance and security.
  1. Click Save.

Test the certificates

  • Create a new device profile

Profile screen 1

  • Configure EMail settings in profile to use the Certificate (automatically named “certificate #1”)

Profile screen 2

  • Configure Wi-Fi settings in profile to use Certificate (automatically named “certificate #1”)

Profile screen 3

Check the profile on iPhone/Android: you should see the Certificate profile applied, then certificate gets issued. Check the customized fields: Subject Name and Subject Alternative Name.

Internal Apps

Articles in section

Apps Upload

Automatic application upload can be made using the following CURL command via blob file:

curl -k -v -X POST -H 'Authorization: Basic ***' -H 'aw-tenant-code: ***'
-H 'Content-Type: application/octet-stream' -H 'Accept: application/json;version=1'
-H 'Expect: 100-continue' --data-binary '@./TestApp2.ipa'
'https://airwatch.testserver.ru/API/v1/mam/blobs/uploadblob?fileName=TestApp2.ipa&organizationGroupId=571'

Important moments: -H ‘Expect: 100-continue’ MUST be sent, because else the server answers with code 100, and curl does not know what to do;

-H ‘Content-Type: application/octet-stream’ MUST be specified, because in the original text we have some JSON or similar.

As result we receive the needed:

Value {"uuid":"7182fd4c-7661-4753-b4d3-fd9353ad4c6a","Value":856}

We take this value and do begininstall

curl -k -v -X
POST -H "Authorization: Basic ***" -H "aw-tenant-code: ***"
-H "Accept: application/json" -H "Content-Type: application/json" -d
'{"ApplicationName":"TestApp20", "AutoUpdateVersion":true, "BlobId":856,
"PushMode":"Auto", "DeviceType":"Apple", "LocationGroupId":571,
"SupportedModels":{"Model":[{"ApplicationId":139, "ModelId":2,
"ModelName":"iPad"}]}}' "https://airwatch.testserver.ru/API/v1/mam/apps/internal/begininstall"
Note

What is Blobid? Not fully understood. Tried different numbers..

As an answer we receive:

{"ApplicationName":"TestApp20","BundleId":"ru.testserver.TestApp3",
"AppVersion":"2.54.0","Platform":2,"IsReimbursable":false,"ApplicationSource":0,
"LocationGroupId":571,"OrganizationGroupUuid":"24e7ceee-d233-4697-9fb9-78e32ee25462",
"PushMode":0,"AppRank":0,"AssignedDeviceCount":0,"InstalledDeviceCount":0,
"NotInstalledDeviceCount":0,"AutoUpdateVersion":false,"EnableProvisioning":false,
"IsDependencyFile":false,"ContentGatewayId":0,"Id":{"Value":141},"Uuid":"dde99cc2-228d-4886-8fc8-c28b82683c36"}

Subsections of Internal Apps

Apps Deployment

AirWatch has 2,5 mechanisms to deploy apps:

  1. Apps & Books → Internal. You can only deploy 3 versions of an application called “Alpha”, “Beta”, “Production”;
  2. Devices → Staging & Provisioning →****Product List View → Add Product. Add Manifest → Install Application. Difference between this method and the one below is not clear, except slightly easier config;
  3. Devices → Staging & Provisioning → Components → Files/Actions. Add Files/Actions → Add Manifest → Install Unmanaged Application.

I recommend the 3rd method as the most descriptive and stable if several versions of an application are needed in one Organization Group.

Things to check in application deployment

Application ID

Check if there is a modification of the Application ID while uploading the application in the Console via Staging & Provisioning → Components → Applications or check while uploading the Application, is it fetching the Application ID and populating the same name in the Application ID field.

Application Metadata

Once the app gets uploaded, AirWatch SQL writes down its’ metadata to SQL. Parsing the data:

SELECT a.name, a.versionhash, * FROM INTERROGATOR.APPLICATIONLIST AL
JOIN interrogator.Application A ON AL.ApplicationID=A.ApplicationID
WHERE DEVICEID in (1473) and isinstalled=1

See more on SQL querying apps

Warning

On AirWatch 9.2.3 version and lower, metadata provided by some build systems like Gradle 3 is incorrectly processed. Specifically a VersionHash is needed in the correct place for the app to see it.

Application Deployment Logs

  • Device receives command to install application
  • Device is directed to app destination for download via Manifest.plist file - so search for “manifest” in the logs:

  • Device is redirected to Manifest.plist URL
  • Device locates Blobhandler.pblob URL:

  • Device is redirected Blobhandler.pblob URL
  • Application download begins
Tip

You can copy the blob link (see picture) manually in the browser to check that download starts.

macOS Apps Deployment

External link:

You are able to deploy apps on Mac OSX devices either from Apps & Books or from Product & Provisioning method. If you have a pkg or dmg file, then you could simply use Apps & Books. However, if you have multiple files to be executed or scripts to run then you could use Product & Provisioning. In AirWatch 9.3+, all macOS application file types (.dmg, .pkg, .mpkg, .app) can be managed through the Internal Applications section. This new framework leverages the popular Mac Admin community tool, Munki.

Provisioning with Munki

Enabling Software Management

  • Navigate to Settings > Devices & Users > Apple > Apple macOS > Software Management
  • Enable Software Management , there is a check in place to verify if File Storage is enabled at this page. If there is no File Storage, the admin will be requested to enable File Storage.
  • On-Prem deployments will need to enable CDN.

Before uploading macOS File to AirWatch

All primary macOS software file types will now be uploaded through Internal Applications (.pkg, .dmg, .mpkg). A .pkg file can be a Bootstrap Package or can be managed through full lifecycle management (this feature). In order to configure Advanced Management options for macOS software and for effective desired state management, which is achieved through the integrated Open-Source Munki library in the AirWatch Agent, a metadata file must be generated for the file separately before uploading it to the AirWatch Console. Munki’s deployment logic is built on the concept of pkginfo files, which are xml/plist files that contain metadata, configuration information, and more for a given application file. AirWatch requires this pkginfo file along with the application file to manage the deployment in the Console.

The pkginfo file is genetrated with VMware AirWatch Admin Assistant (see tools page for download). This is a GUI wrapper for a Munki command-line utility and is used to generate the pkginfo metadata file for a given application file.

Generating a pkginfo metadata file using VMware AirWatch Admin Assistant

  1. Download and install the Admin Assistant tool to a macOS device or VM.

  2. Open the Assistant. The Assistant dialog will ask for the application installer files to parse.

  3. Upload an application installer file by dragging & dropping a .pkg, .dmg, .mpkg, .app file into the labeled field, or browse the local files on the machine in order to find an installer file.

    Note

    If the file is .app, it will be converted into a .dmg for deployment

  4. Once the file is selected and uploaded, the Assistant will automatically start parsing process the process. Additional files can be added during this time if needed.

  5. Once the parsing is complete, the tool will prompt to reveal the parsed metadata files in Finder. Store the metadata files in a local folder where they can be easily retrieved during the Software Distribution procedure.

Generating a pkginfo metadata file using Autopkg

There are multiple ways to obtain the metadata/pkginfo file aside from using the Admin Assistant. One of them is to use Autopkg and its’ GUI tool Autopkgr.

Uploading a macOS Application to the AW Console:

  1. Navigate to Apps & Books > Applications > Native > Internal
  2. Click Add Application
  3. Upload app/software file (.pkg, .mpkg, .dmg)
  4. Continue to the next screen and Upload the pkginfo .plist file
  5. Continue to customize the app deployment. The proceeding screens will display any available configurations present in the pkginfo file (for example, a pkginfo from AutoPkg may contain an install_check script). Additional deployment configurations can be defined, and will be merged with the existing configurations
    • If the pkginfo file has one or more key and configuration that are not exposed in the UI, they will not be affected. This feature is important as it allows administrators to upload pkginfo files with keys that would be supported by the Munki client but would not be configurable in the UI. Any changes in the UI will be merged with the existing keys.

Pre/Post Install Scripts

A common reason to repackage software is to perform additional configuration tasks or to install additional items. A technique to avoid repackaging is to add pre-install scripts and/or post-install scripts to the configuration of an item. These scripts can take care of some of the tasks which previously may have required repackaging to implement.

An Exit Code of 0 will define the script as successfully executed in order to allow Munki to continue.

Note

Failure of the pre-install script will abort the installation attempt. Failure of the post-install script will log errors, but the installation will be considered complete.

Note

SCRIPT LOG echo statements will be logged to /Library/Application Support/AirWatch/Data/Munki/Managed Installs/Logs/ManagedSoftwareUpdate.log

Uninstall Methods

There are multiple options available for uninstallation of software. The appropriate option will be selected by default by the VMware Admin Assistant tool based on the software’s file type. If needed options to override the default values are available in the AirWatch Console.

Remove Copied Items
Used primarily for software installed from a .dmg

  • Pulls from items_to_copy array[dicts] in the pkginfo file
    • All file paths in this array will be deleted
  • Future Console release will show the paths in the items_to_copy array in the UI

Remove App

  • Pulls from installs array[dicts] in the pkginfo file
    • All file paths in this array will be deleted
  • Future Console release will show the paths in the installs array in the UI

Remove Packages 
Used primarily for software installed from a .pkg

  • Uses receipts and analyzes the packages to remove
    • Tries to determine what files were installed via the Bom file
    • Deletes receipt
  • Will only remove if package is not associated with any other files or programs
  • Future Console releases will show the receipts that Munki check for in the UI

Uninstall Script 
Can be used for any installer type

  • Written in shell script
  • Used to perform custom uninstall operations if needed
    • If the Admin has a customized deployment of an app, they will need to also write a corresponding uninstall script to remove their custom configurations

Install or Uninstall Verification

With some software, the Admin needs to configure what exactly defines a Successful Install or Uninstall. Munki allows this through setting an Install or Uninstall Check Script

Install Check Script - If present, this script is executed to determine if an item needs to be installed. A return code of 0 means install is needed; any other return code causes install to be skipped.

Uninstall Check Script - If present, this script is executed to determine if an item needs to be uninstalled. A return code of 0 means uninstall is needed; any other return code causes uninstall to be skipped.

Conditions

Conditions can defined on a per-application level so that they are evaluated prior to the download and installation of a software.

Warning

Custom conditions will be created in a later version of AirWatch.

Built-in Conditions Currently available built-in attributes for conditional comparison:

AttributeTypeDescriptionExample Comparison
hostnamestringHostnamehostname == "Lobby iMac"
archstringProcessor architecture. e.g. 'powerpc', 'i386', 'x86_64'.arch == "x86_64"
os_versstringFull OS Version e.g. "10.7.2"os_vers BEGINSWITH "10.7"
os_vers_majorintegerMajor OS Version e.g. '10'os_vers_major == 10
os_vers_minorintegerMinor OS Version e.g. '7'os_vers_minor == 7
os_vers_patchintegerPoint release version e.g. '2'os_vers_patch >= 2
machine_modelstring'Macmini1,1', 'iMac4,1', 'MacBookPro8,2'machine_model == "iMac4,1"
machine_typestring'laptop' or 'desktop'machine_type == "laptop"
ipv4_addressarray of stringsThis contains current IPv4 addresses for all interfaces.ANY ipv4_address CONTAINS '192.168.161.'
munki_versionstringFull version of the installed munkitoolsmunki_version LIKE '*0.8.3*'
serial_numberstringMachine serial numberserial_number == "W9999999U2P"
dateUTC date stringDate and time. Note the special syntax required to cast a string into an NSDate object.date > CAST("2013-01-02T00:00:00Z", "NSDate")

Example:

machine_type == “laptop” AND os_vers BEGINSWITH “10.7”

date > CAST(“2016-03-02T00:00:00Z”, “NSDate”)

Dates in conditions:

The date string must be written in UTC format, this format is interpreted as a local date/time. The condition date > CAST("2013-01-02T00:00:00Z", "NSDate") is True if the local time is after midnight local time on 02 Jan 2013.

Literal types in comparisons

  • Strings are delimited by either single or double-quotes: os_vers BEGINSWITH "10.7"

  • Integers have no quotes: os_vers_major == 10

  • Booleans are indicated as TRUE or FALSE (and have no quotes, or they’d be strings!): some_custom_condition == TRUE

  • Dates are possible, but they must be cast from ISO 8601 strings: date > CAST("2013-01-02T00:00:00Z", "NSDate")

Updates

Updates can be managed similarly to the other platforms in the AirWatch Console. If a new version of the file needs to be added, perform the following:

  1. Navigate to Apps & Books > Native
  2. Click on the App that requires an update. Clicking the app will navigate to the Details View page.
  3. In the top right side, click “Add Version
  4. Upload the new installer for the new app version
  5. Upload the new pkginfo file for the new version
  6. Make any additional changes and then save the configuration

Troubleshooting

The AirWatch Console will show report macOS app installation data from a device in several  locations:

  • Apps & Books > Applications > Native > Internal. Click onto the Application to drill into Application Details > Devices Tab. The grid in this tab will display installation statuses for each device.
  • Devices & Users > Devices > List View. Click on a device to drill into Device Details > Troubleshooting Tab. The grid on this tab will show activity on the device and provides filtering options to show information relating to Software Distribution.

Munki Logs can also be directly accessed on the device: /Library/Application\ Support/AirWatch/Data/Munki/Managed\ Installs/Logs/ManagedSoftwareUpdate.log

tail -n 20 -F /Library/Application\ Support/AirWatch/Data/Munki/Managed\ Installs/Logs/ManagedSoftwareUpdate.log

Munki Known Issues

  • Once software has been published and installed on a few devices, if any of the configuration options such as “install script”, “uninstall script” etc.. are changed, devices which already have the application installed successfully will not receive the updated options as these can only be updated when an “InstallApplication” command. This is the only command that can update the locally cached PKGInfo files on the device. In order to update the scripts, administrators will have to manually select all of the devices which have the software installed and repush the command. Repushing the command will update the respective cached PKGinfo file with the latest information.
    Note: Repushing the command will NOT reinstall the application unless there is a change in the software version. Munki is has mechanisms in place to not reinstall software when the application is already installed.
  • If a package has a dependency on another package or software then an administrator will have to manually provide a required key in the pkginfo of the package with a dependency. Providing the key in the pkginfo is the only way for Munki to recognize if there are any dependencies, and determine the sequence of installation steps for such dependent packages. Unless otherwise specified, packages are installed in random order. Such package installation will fail if a package dependency is not met during the installation. 
    ExampleNetbeans requires that Java be present and installed on the machine. Netbeans will not implicitly install Java while installing the Netbeans software package. Even if administrators attempt to install Netbeans without utilizing M****unki or using standalone Munki, the installation will fail and will prompt the administrator to first install Java before installing Netbeans.
  • For packages which have the same receipts array with same version even on an upgraded package, Munki will not be able to detect that a new package is an upgraded package. The reason is that the receipt array has the same version as the previous package. The impact of duplicated receipts arrays is that the packages will not be installed on User machines as Munki cannot determine that a new version needs to be installed.
    Note: The best solution for packages with duplicate versions in the Receipts Array is to use an Autopkg Recipe, which adds an installs array in the pkginfo. This method allows Munki to detect upgraded packages; alternatively an administrator can manually add an installs array into the pkginfo.

Example: Wireshark is an example of a package which has identical receipts which contain the same version, thus Munki cannot detect the when upgraded packages are deployed.

Legacy methods (AirWatch 9.2 & older)

Apps & Books

  • Go to Groups & Settings > All Settings > Devices and Users > Apple > MAC OS > Software Distribution.
  • Enable Software distribution.
  • Now go to Apps and Books > Native > Internal > Add Application.
  • Upload the .pkg or .dmg file.
  • Once uploaded, click on Continue. You will get an option to download VMware AirWatch Admin Assistance tool.
  • Download the tool.
  • Upload the .pkg or .dmg file there.
  • You will see that it will open the package into .dmg file, .plist file and .png file.
  • Go back to the Console and upload the .plist file for metadata.
  • Click on upload and you will see the application description.
  • You will get an option to upload the image. Upload .png file there.
  • Now assign the application to the required Smart Group.
  • Click on Save and Publish.

Product provisioning

It allows you to create, through AirWatch, products containing profiles, applications, and files/actions (depending on the platform you use). These products follow a set of rules, schedules, and dependencies as guidelines for ensuring your devices remain up to date with the content they need.

  • Navigate to Devices > Staging & Provisioning > Components > Files/Actions
  • Click on Add > General
  • Navigate to Files > Add Files and enter the specific path
  • Navigate to Manifest. Under Install Manifest, click Add Action. Choose the action type Install and provide the specific path. 
  • Under Uninstall Manifest, click Add Action and set the action type as Install, again providing the specific path. 
  • Under Uninstall Manifest, click on Add Action and choose the action type Uninstall, and provide the exact application name with the extension as ‘.app’.
  • Select Save
  • Navigate to Staging & Provisioning > Product List View and select Add Product.
  • Under General, verify the details and assignment group are filled in.
  • Navigate to the Manifest tab and click on Add. Choose the created component after selecting Install/Action.

With this configuration, the application will first be downloaded to the Downloads folder on the Mac. You can then install the application, which will be available in the Applications folder. If you want only to uninstall the application which was previously installed, you may choose the Delete Files option while creating files and actions.

Recipes

Script recipies

TextWrangler Post Install Script Implement a post-install script that copies the command-line tools from the TextWrangler bundle to their intended locations.

After uploading the appropriate files to AirWatch, pre/post install scripts can be configured for the app in the Scripts tab of the Application Details. Simply paste the script into the appropriate field and AirWatch will format it to be used by Munki.

App recipes

Adobe Reader DC...
Apple Enterprise Connect...
McAfee Endpoint Protection...
Microsoft Skype For Business...
Palo Alto GlobalProtect...
RSA SecureID...
Sophos Antivirus...
Symantec Removal Tool...

Manifest recipies

Quick fix for root user login bug (https://techcrunch.com/2017/11/28/astonishing-os-x-bug-lets-anyone-log-into-a-high-sierra-machine/ )

Enable root user with random password

Below are steps to fix the issue via  Product Provisioning -

A. Create a File

  1. Go to Devices > Staging & Provisioning > Components > Files /Actions.
    2.  Add Files / Actions > macOS
  2. Manifest > Install Manifest > Run > Command Line and Arguments to run /usr/bin/dscl . -passwd /Users/root $(/usr/bin/openssl rand -base64 20)
  3. Click Save

B. Create a Product to include above File

  1. Go to Devices > Staging & Provisioning > Products List View  > Add Product > macOS
    2.  Click on Manifest > Add Manifest > Actions to Perform > Install Files / Actions > Files/Actions (Enter the saved file).
  2. Save & Activate the product

Unsigned application launch bypassing Security & Privacy

Use above recipe with command Manifest > Install Manifest > Run > Command Line and Arguments to run:

sudo xattr -rd com.apple.quarantine /Applications/@cursor # where '/Applications/@cursor' is the target app

Large-Scale Performance

Large-Scale Performance Tweaks

For 75000+ devices (iOS, Android & Windows Desktops)

Linked Articles

Attached Documents

SQL

See SQL Database page for base tweaks on MS SQL.

  • Add 1 tempdb file per core (20 tempdb files for 20 core)

Each tempdb data file with below parameters: - Initial Size: 16000 MB - Autogrowth: 512 MB

USE [master];
GO
ALTER DATABASE [tempdb] ADD FILE (NAME = N'Temp1', FILENAME = N'H:\TempDBs\Temp1.ndf', SIZE = 8GB , FILEGROWTH = 512);
ALTER DATABASE [tempdb] ADD FILE (NAME = N'Temp2', FILENAME = N'H:\TempDBs\Temp2.ndf', SIZE = 8GB , FILEGROWTH = 512);
ALTER DATABASE [tempdb] ADD FILE (NAME = N'Temp3', FILENAME = N'H:\TempDBs\Temp3.ndf', SIZE = 8GB , FILEGROWTH = 512);
GO
  • Add below Trace flags in Startup Parameters for “mssqlserver” service as per Microsoft recommendations:
    T174 - https://support.microsoft.com/en-us/help/3026083/fix-sos-cachestorespinlock-contention-on-ad-hoc-sql-server-plan-cache 
    T834 - https://support.microsoft.com/en-us/help/920093/tuning-options-for-sqlserver-when-running-in-high-performance-workloads
    T3247 - https://support.microsoft.com/en-us/help/3216543/workloads-that-utilizemany-frequent-short-transactions-in-sql-server
  • Set “Lock Pages in Memory” privilege for the service account
    Open Windows Local Group Policy Editor
    Open Computer Configuration > Windows Settings > Local Policies > User Rights Assignment, find Lock Pages in Memory
  • Disable “Named Pipes” and Enable “TCP/IP” network protocol
    Open SQL Server Configuration Manager tool
    Open SQL Server Network Configuration > Protocols for MSSQLSERVER, set Named Pipes to Disabled, set TCP/IP to Enabled
  • Increase Maximum Worker threads in server properties to “7500”
    Open Server Properties from SSMS and go to Processors tab, find Maximum Worker threads field
  • Set “Max Degree Of Parallelism” to 2 and “Cost threshold for Parallelism” to 50
    Open Server Properties from SSMS and go to Advanced tab, Parallelism section in the right pane
  • Enable “Received Side scale” setting for Network Adapter on SQL server
    Run DEVMGMT.msc from CMD
    Expand Network adapters, right click on your adapter and select Properties
    Select the Advanced tab and find Receive Side Scaling. Set this to Enabled
  • Set “Delayed Durability” under database properties = “Forced” to reduce WriteLog waits
    Open Database Properties from SSMS and go to Options
  • Update “Minimum and Maximum Server Memory” allocation in Server Properties
    Open Memory from SSMS → Server Memory Options section
    • Minimum Server Memory (in MB): 256000
    • Maximum Server Memory (in MB): 1500000

Performance Tweaks

Example Architecture

  • Update Workspace ONE UEM application server to latest version

In WS1 UEM Console go to Settings > Installation > Performance Tuning:

  • Set Certificate Profile Publish Frequency: 100
  • Set Apple Profile Installation Batch Size: 300
  • Set iOS Device Invites Per Second: 30
  • Set FastLaneMessageRateMultiple: 1.5
  • Run Real-Time Compliance is set to Disabled

Check Windows Sample Frequency (for managing Windows Desktops):

  • Go to Settings > Devices & Users > Windows > Windows Desktop > App Settings
  • Go to Settings > Devices & Users > Windows > Windows Desktop > Windows Sample Schedule
  • Override the default value in Systemcode table for FastLaneMessageRateMultiple to 1.5 by updating Systemcodeoverride table in DB.
  • Add the below config to AW.Send.Messaging.Service.exe.config file in Services folder of all console servers under appSettings:
<add key="WnsMessageProcessingRate" value="10" />
<add key="WnsMessageThrottlingEnabled" value="true" />

Subsections of Large-Scale Performance

Certificate Batching

Note

This logic is only applicable for profiles that contain certificates issues through a defined Certificate Authority (CA) in the AirWatch Console.

Prior to the certificate batching logic, when a defined-CA profile is published to a large number of devices, it can result in significant performance issues on Airwatch Cloud Connectors in the AirWatch environment.  This is due to the extra processing required to issue each device a certificate from the CA, as well as the normal processing required to push the profile to the device.  The performance issues generally lead to CPU spikes and high memory usage on ACC or DS (if no ACC is configured) servers because:

  • Certificate generation is a CPU intensive task. Too many concurrent certificate generation requests spike the CPU usage.
  • Certificates are stored in memory of the process (w3wp - devicesservices) so that they can be reused for the same device.

AirWatch 7.1+ has certificate batch logic to throttle the deployment of all defined-CA profile publish jobs. These profile publish jobs will be broken into multiple batches at the environment level and a next batch will only be executed if the previous batch has been completed. 

Certificate Batching Logic

The deployment of defined-CA certificate profiles will follow the steps outlined below:

  • AirWatch Administrator publishes a profile that contained a defined CA certificate
  • Install profile commands are queued for all assigned devices in the Device Command Queue in the AirWatch Database.  These commands are queued in the Held status.  Commands in the Held status will not be processed by devices.
  • A ProfilePublishBatchJob is created to process these commands.
  • The ProfilePublishJobScheduler selects a batch and batch size, based on the settings configured in the AirWatch Console (under Settings → Installation → Performance Tuning for On-Premises environments).
  • A batch detail entity is inserted into the AirWatch DB; the mobilemanagement.CommandQueueHeldBatch_Update stored procedure is called to “release” a number of the Install Profile commands that are currently in the Held status.  The number released will be equal to or less than the overall batch size.
  • Periodically, more batches of the Install Profile command will be released until all commands are active (or have successfully been issued to devices).  Three scenarios are outlined below that describe this step in more detail.  This time period is defined by the Profile Publish Batch Job in the AirWatch Scheduler (Settings → Admin → Scheduler for On-Premises environments).

In SaaS and on-premise environments, the default Batch Size is set to 50, and the Profile Publish Batch Job interval is set to 3 minutes.

Scenario 1: All devices are consistently active

  • Devices=24000
  • Batch size=200

When a profile is published, all 24000 commands are queued in the Held status (status = 7).  The scheduler released the first 200 commands based on the batch size.  The commands are sent to devices (through APNs/Firebase), and devices consume the commands and install the profile.  At the interval defined by the Profile Publish Batch Job, the system will view how many pending install commands are still active.  As all devices are currently active and check in regularly, all of the previously queued commands will be processed, and another batch of 200 will be released.  This process repeats until all 24,000 install commands are released.

Scenario 2: Devices frequently check in (within 30 minutes)

  • Devices=24,000
  • Batch size=200

During any particular iteration of the Profile Publish Batch Job as outlined above, if {X} number of commands are still in Pending Install state for a period of less than 30 minutes, then only ({batchSize} -{X}) commands will be released in the current iteration.  For example, if the previous batch released 200 commands, but at the time of the next batch only 50 commands have been processed by devices (so that 150 are still active), then only 50 commands will be released at the current batch.  At the time of this iteration, it will ensure that the “active” batch size returns to 200.

Scenario 3:  Devices periodically check in (within 12 hours)

  • Devices=24,000
  • Batch size=200

During any particular iteration of hte Profile Publish Batch Job, if {Y} number of commands are still in Pending Install state for a period of more than 30 minutes, then {batchSize} number of commands will be queued up to maximum limit of *{batchSize}10 commands in queue. This means that at a single point in time, the maximum of *{batchSize}10 Install Profile commands can be queued in Pending Install status.

Following Scenario 2 above, if a new batch iteration is occurring, and all active Pending Install commands are over 30 minutes old, then a full batch size will be released.  If there are {X} pending commands less than 30 minutes and {Y} pending commands greater than 30 minutes, then {batchSize} - {X} commands will be released, up until a total of *{batchSize}10 overall active commands are queued.

Scenario 4:  Devices do not check in for over 12 hours

  • Devices=24,000
  • Batch size=200

After a pending install command has been queued for over 12 hours, it no longer counts toward the *{batchSize}10 limit specified in Scenario 3.  The logic outlined in the first 3 Scenarios will continue, not counting any of these older commands.  These “older” commands remain in the command queue and are active, but no longer affect the batching logic.

Relevant Database Tables

  • dbo.BatchJob - Profile Publish places an entry with “profileVersionID” 
  • dbo.BatchJobDetail - Every Batch Job iteration will place an entry with the number of commands released as “Count”
  • deviceCommandQueue.DeviceQueue - Stores commands (profile install commands in this case) for every device

Large-Scale Performance

WS1 UEM Services/Applications

API Workflow
Batch Processing
Entity Change Queue Monitor
EventLog Processor Service
Integration Service
MEG Service
Messaging Service
Outbound Queue Monitor Service
Smart Group Service
Agent Builder Service
Background Processor Service
Compliance Service
Content Delivery
Device Scheduler
Directory Sync Service
GEM Inventory Service
Policy Engine
SMS Service
Google Play Service
Data Platform Service
Interrogator Queue Service
Provisioning Package Service
MSMQ

PerfMon Object Perfmon Counter
Process “% Privileged Time”, “% Processor Time”, “% User Time”, “Elapsed Time”, “Handle Count”, “IO Read Bytes/sec”, “IO Read Operations/sec”, “IO Write Bytes/sec”, “IO Write Operations/sec”, “Private Bytes”, “Thread Count”, “Virtual Bytes”, “Working Set”, “Working Set - Private”
.NET CLR Exceptions “# of Exceps Thrown”, “# of Exceps Thrown / Sec”, “# of Filters / Sec”, “# of Finallys / Sec”, “Throw to Catch Depth / Sec”
.NET CLR LocksAndThreads “# of current logical Threads”,"# of current physical Threads","# of current recognized threads", “# of total recognized threads”,“Contention Rate / Sec”,“Current Queue Length”,“Queue Length / sec”, “Queue Length Peak”,“rate of recognized threads / sec”,“Total # of Contentions”
.NET CLR Memory “% Time in GC”,"# Bytes in all Heaps","# Gen 0 Collections","# Gen 1 Collections","# Gen 2 Collections", “# Induced GC”,“Allocated Bytes/sec”,“Finalization Survivors”,“Gen 0 heap size”,“Gen 1 heap size”, “Gen 2 heap size”,“Large Object Heap size”,"# of Pinned Objects","# GC Handles","# of Sink Blocks in use", “# Total committed Bytes”,"# Total reserved Bytes",“Finalization Survivors”,“Gen 0 Promoted Bytes/Sec”, “Gen 1 Promoted Bytes/Sec”,“Large Object Heap size”,“Process ID”,“Promoted Finalization-Memory from Gen 0”, “Promoted Memory from Gen 0”,“Promoted Memory from Gen 1”
.NET Data Provider for SqlServer “NumberOfActiveConnections”, “NumberOfFreeConnections”, “NumberOfPooledConnections”, “NumberOfReclaimedConnections”, “SoftConnectsPerSecond”, “SoftDisconnectsPerSecond”
.NET Memory Cache 4.0 “Cache Entries”, “Cache Hit Ratio”, “Cache Hits”, “Cache Misses”, “Cache Trims”, “Cache Turnover Rate”
MSMQ Service “Total bytes in all queues”, “Total messages in all queues”

IIS Web Server Performance Counters

PerfMon Object Perfmon Counter
Web Service “Service Uptime”, “Current Connections”, “Bytes Sent/sec”, “Total Bytes Sent”, “Bytes Received/sec”, “Total Bytes Received”, “Bytes Total/sec”, “Total Bytes Transferred”, “Get Requests/sec”,“Total Get Requests”, “Post Requests/sec”,“Total Post Requests”, “Put Requests/sec”,“Total Put Requests”, “Delete Requests/sec”,“Total Delete Requests”, “Anonymous Users/sec”, “NonAnonymous Users/sec”, “Not Found Errors/sec”, “Locked Errors/sec”, “Total Method Requests”, “Total Method Requests/sec”
Web Service Cache “Current Files Cached”, “Active Flushed Entries”, “Total Files Cached”, “Total Flushed Files”, “File Cache Hits”, “File Cache Misses”, “File Cache Hits %”, “File Cache Flushes”, “Current File Cache Memory Usage”, “Maximum File Cache Memory Usage”, “Current URIs Cached”, “Total URIs Cached”, “Total Flushed URIs”, “URI Cache Hits”, “URI Cache Misses”, “URI Cache Hits %”, “URI Cache Flushes”, “Current Metadata Cached”, “Total Metadata Cached”, “Total Flushed Metadata”, “Metadata Cache Hits”, “Metadata Cache Misses”, “Metadata Cache Hits %”, “Metadata Cache Flushes”, “Kernel: Current URIs Cached”, “Kernel: Total URIs Cached”, “Kernel: Total Flushed URIs”, “Kernel: URI Cache Hits”, “Kernel: Uri Cache Hits/sec”, “Kernel: URI Cache Misses”, “Kernel: URI Cache Hits %”, “Kernel: URI Cache Flushes”
ASP.NET “Application Restarts”, “Requests Queued”, “Requests Rejected”
ASP.NET Applications “Requests/Sec”, “Errors Total”, “Cache Total Entries”, “Cache Total Turnover Rate”, “Cache Total Hits”, “Cache Total Misses”, “Cache Total Hit Ratio”, “Pipeline Instance Count”, “Requests/Sec”, “Requests In Application Queue”, “Request Execution Time”, “Request Wait Time”, “Requests Executing”
HTTP Service Request Queues “ArrivalRate”, “CurrentQueueSize”,“RejectedRequests”

Logs

Linked Articles

Collecting AirWatch Services Logs (On-Premise)

AirWatch Enterprise Systems Connector (ESC) / Cloud Connector (ACC)

To verbose the ACC log, perform the following:

  • Open Windows Explorer on the ACC server, and browse to the C:\AirWatch\CloudConnector\folder
  • Note the presence of two folders: Bank1 and Bank2. Every time the Cloud Connector software is updated, the update is applied to the inactive bank folder. The updated bank folder then becomes the active bank folder.
  • Open each Bank folder and sort the file list by date modified. Compare the most recent date modified in each file. The current bank file has the most recent date modified.
  • Within the current bank folder (C:\AirWatch\CloudConnector\Bank#), open the CloudConnector.exe.config file and change the level value in the from error to verbose and save the file.
  • After reproducing the error, open Windows Explorer on the ACC server and browser to the C:\AirWatch\Logs directory. Copy the appropriate log to a new location for use in support/troubleshooting.
  • Be sure to change the loggingConfiguration level value from verbose to error and save the file to prevent unnecessary impact to the ACC server.

AirWatch API Services (API)

To verbose the API Service Log, perform the following:

  • On the server running API services, open Windows Explorer and browse to C:\AirWatch\AirWatch #.#\Websites\AirWatchApi. Note: You can determine the API server by browsing to Groups & Settings > All Settings > System > Advanced > Site URL’s.
  • Open the web.config file, and look for the loggingConfiguration key.
  • Change the value for level from error to verbose and save the web.config file.
  • Restart IIS services.
  • Reproduce your issue and then copy the log from C:\AirWatch\Logs\AirWatchAPI\webserviceapi.log.
  • Change the value for level from verbose back to error and save the web.config file.
  • Restart IIS Services.

AirWatch Cloud Messaging (AWCM)

To verbose the AWCM logs, please perform the following steps:

  1. Open the logback.xml file. The path to access the file:\AirWatch\AirWatch x.x\AWCM\config\logback.xml.
  2. Search for the following:
  3. Change the state from error to debug.
  4. Save the file and restart the AWCM services.
Note

Once the issue is reproduced, return logging level back to info and restart the AWCM services. Or the AWCM disk may overflow with logs.

Folder = AWCM Log name = Awcm.log Contains information on AWCM such as status, history, properties, and additional sub-services.

Log name = AWCMservice.log Contains log information on AWCM Java service wrapper.

ACC Logs

Use these steps below to verbose ACC logs:

  •  On the ACC server navigate to *\AirWatch\AirWatch #.#\CloudConnector\Bank#*

  •  #.# will be the AirWatch version you are using, if there are multiple choose the most recent.

  •  ACC utilizes two distinct banks: one active and one is used for installation of automatic updates. If you are unsure of which bank is active, make changes to the CloudConnector.exe.config file in each bank. If one bank is empty or does not have the file, it is not the active bank.

  •  Edit the CloudConnector.exe.config lines:

    • level = “Verbose”

    • tracingEnabled = “true”

      <loggingConfiguration filePath="..\..\Logs\CloudConnector\CloudConnector.log" tracingEnabled="true" level="Verbose" logFileRollSize="10240" maxArchivedFiles="20"/>
      
  •  Locate the log by looking at the filePath attribute from the line above. The path is included below as well \AirWatch\Logs\CloudConnector\CloudConnector.log

  • ACC doesn’t need to be restarted to pick up the logging level configuration change.

Console Services (CS)

To enable verbose logging for console and scheduler services, please perform the following steps:

  • Log in to the AirWatch console in question.
  • With the Global organization group selected, browse to Groups & Settings > All Settings > Admin > Diagnostics > Logging.
  • Change the logging level for the services in question to verbose and click Save.
    • Admin Console
    • Self-Service Portal
    • API
    • Scheduled Services (such as Inventory, Workflow, and Monitor services)
    • Reproduce your error, then open Windows Explorer and browser to C:\AirWatch\Logs_Service Folder_ and look for the latest log.
    • Change the Device Services logging level back to Error. This prevents logging from impacting system performance.

Device Services – Targeted

Depending on the version of AirWatch, it is possible to collect verbose logs for an individual device without having to verbose the logs for all devices. This is particularly helpful when troubleshooting a single device in a large production deployment. To do this, perform the following steps:

  • From within the AirWatch console device list view, click on your device to take you to the device details page.
  • Click More > Targeted Logging. If necessary, click the Continue Targeted Logging File Path to ensure the logging path is configured.
  • From the targeted logging page, click Create New Log and select the timeframe you want the logs to collect. Click Start.  At any point, you can click Stop Logging to stop log collection for the device (such as after you have reproduced the issue).
  • Once the tests are completed, go to the appropriate server and look for the TargetedLogging folder.
  • Inside the folder is a zip file with the current date and time. Unzip the file to view the files.

Device Services – General

When you wish to verbose device services logging for all devices, perform the following:

  • Log in to the AirWatch console in question.
  • With the Global organization group selected, browser to Groups & Settings > All Settings > Admin > Diagnostics > Logging.
  • Change the Device Services logging level to verbose and click Save.
  • Reproduce your error, then open Windows Explorer and browser to C:\AirWatch\Logs\DeviceServices\ and look for the latest log.
  • Change the Devices Services logging level back to Error. This prevents logging from impacting system performance.

SEG Console, Setup, and Integration Logs

To verbose the SEG logs for console/setup/integration, please perform the following steps:

  • Open Windows Explorer on the SEG server and browser to C:\AirWatch\Logs
  • Note the following Folders and change the appropriate config log level from error to verbose:
    • Services – Contains the AW.EAS.IntegrationService.log file which details communications between the AirWatch API server and SEG server. Note: This log is verbosed by changing the level value in the key of the AW.ES.IntegrationService.Exe.config file in the C:\AirWatch\AirWatch #.#\AW.Eas.IntegrationService folder.
    • SEG Setup – Contains the AW.EAS.Setup.log file which details activity related to the http://localhost/SEGSetup website. Note: This log is verbosed by changing the level value in the key of the web.config file in the C:\AirWatch\AirWatch #.#\AW.Eas.Setup folder.
    • SEG Console – Contains the AW.EAS.Web.log file which details activity related to the http://localhost/SEGConsole website. Note: This log is verbosed by changing the level value in the key of the web.config file in the C:\AirWatch\AirWatch #.#\AW.Eas.web folder.
    • Before reproducing your issue, making the necessary change to the LoggingConfiguration key for the service in question.
    • After reproducing the error, open Windows Explorer on the SEG server and browse to the appropriate subfolder in the C:\AirWatch\Logs\ directory. Copy the appropriate log to a new location for use in support/troubleshooting.
    • Be sure to change the loggingConfiguration level value (currently verbose) in the appropriate configuration file back to error to prevent unnecessary impact to the SEG server.

SEG Exchange ActiveSync (EAS) Listener Logs

To verbose the SEG EAS Listener logs, please perform the following steps:

  • On the SEG server, open an Internet browser and navigate to http://localhost/SEGSetup
  • In the “Log Level” drop down, select verbose and click Save. Note: This changes the level value in the key of the web.config file in the C:\AirWatch\AirWatch #.#\AW.Eas.Web.Listener folder.
  • Copy the AW.Eas.Web.Listener.log to a new location for use in support/troubleshooting.
  • In your Internet browser, change the “Log Level” drop down back to error and click Save.

FTP Relay Server (Rugged Management)

Logging for the relay server is saved in the following location:

  • Browse to the C:\AirWatch\Logs\Service folder.
  • The logging for the Relay Server is saved in the ContentDeliveryService.log file.

Collecting logs from the Admin Console

If you do not have immediate access to the on-premise servers to access the logs, you can retrieve SEG/ACC logs directly from the console from the following page:

  • Navigate to System > Admin > Diagnostics > System Health. Click on the installed service you wish to pull the logs from.
  • In the pop-up box now displayed, click on the “Acquire Logs,” for the required service, from the four-button menu on the right.
  • Now the “Download” button is activated and you can click on it to download and view logs remotely.

Note: The System Health dashboard will be populated only if you have any of the services (ACC/SEG) already installed and running.

EMail Notification Service (ENS)

ENSv2 is a Windows Service ‘AWSubscription’.  Like other AirWatch services, relevant logs can be found in the path {Installation Path}/Logs, and the logging level can be configured by editing parameters to traceEnabled=“true” Level=“Verbose” in the app config ({Installation Path}\Config\WebSites\Web.config) file located in the installation folder

ENSv2 Errors are in ENS.log and ReSubscriptionMechanism.log

Note

The service must be restarted for logging changes to take effect.

When set to verbose, you will be able to identify log messages pertaining to both new subscriptions being created, as well as any device compliance state-changes being identified.  For example, if a device becomes compromised and is then marked as non-compliant.  In the logs, a message indicating that a device’s access state is True indicates that the device is allowed, whereas False means the device is blocked.

Subsections of Logs

Boxer for Android Logs

Boxer for Android Architecture

Boxer communicates with a few different systems to provide these services.
The flow of the Android Boxer log file looks like this:

  • Boxer reaches out to the console to get the profile information;
  • Boxer reaches out to the console to get any S/MIME certificates and client authentication certificates available from the console;
  • Boxer reaches out to the Exchange ActiveSync(EAS) email endpoint to make the options, provision, foldersync, and ping request;
  • Boxer reaches out to the Email Notification S ervice (ENS) and provides the Exchange Web Services (EWS) credential information that was used for ActiveSync so it can subscrib e to email notifications.
graph TD CS[Console Server] --> Boxer; Boxer --> CS; Exchange --> Boxer; Boxer --> Exchange; Boxer --> ENS; ENS --> Boxer;
  • Boxer logs are in GMT. That means the entries there are 5 hours ahead of EST time. In addition, the logs are in 24 hour time so you will need to subtract 12 if you want am/pm.
  • The very first line in the Boxer logs has the last date of the logs in the file. For example 2019-01-08T21:28:04.539Z - [-] - ###--HEADER--###
  • Boxer logs can persist in the app for up to 3 days, so they can be pulled for review even if the issue hasnt occurred recently, but at least within the 3 day period. This is useful for intermittent types of issues, or where there is a delay in an affected user reporting the issue to their techsupport.

Boxer Communication Logs

Here is an example of what you might see in the logs followed by notes (in bold) that detail what the log entry tracks:

Boxer log sample...

Common Ways to Search Through the Logs

On the console where you configure your Boxer profile, you will have places where you can enter profile information like Account Name, Domain, User, etc… However, in the Boxer logs, when you are looking for the corresponding data there, the wording might be slightly different. You can use the mapping information below to see what this would say in the Boxer logs. The value on the left is what you will see in the console. The value after “=” is what you will see in the Boxer logs.

Account Name = DESCRIPTION  
Exchange ActiveSync Host = SERVER_ADDRESS  
Domain = USER_DOMAIN  
User = USERNAME  
Email Address = EMAIL  
Email Signature = SIGNATURE  
Authentication Type = ACCOUNT_AUTHENTICATION_TYPE | 0 basic, 1 certificate, 2 both Copy Paste = ALLOW_COPY_PASTE  
Screenshots = ALLOW_SCREEN_CAPTURE  
Allow email widget = ALLOW_EMAIL_WIDGET  
Allow calendar widget = ALLOW_CALENDAR_WIDGET  
Hyperlinks = POLICY_ALLOW_OPEN_IN  
Sharing = DOCUMENT_SHARING_RESTRICTION  
Caller ID = ALLOW_CALLER_ID  
Personal Accounts = ALLOW_OTHER_ACCOUNTS  
Personal Contacts = ALLOW_LOCAL_CONTACTS

Boxer reaches out to the console to get the profile information

2019-02-07T15:21:55.345Z I [18459-BoxerWorker-5] - App initialization step complete: 1

2019-02-07T15:21:55.578Z E [18459-main] - FLF.setSelectedAccount(null) called! Destroying existing loader.

2019-02-07T15:21:55.589Z I [18459-BoxerWorker-3] - Waiting for app restrictions

This entry is the best example we have of when Boxer reaches out to the console. You can use Fiddler to further determine when Boxer is reaching out to the console. In the Boxer logs, you can’t directly see this. The other place you can see this is in the ADB device logs. The line here that says “waiting for app restrictions” just indicates that Boxer is waiting to read from the database. Boxer reaches out to the console to get any S/MIME certificates and client authentication certificates available from the console.

2019-02-07T15:21:56.256Z I [18459-IntentService[AirWatchAccountSetupService]] - Fetching S/MIME signing certificate

2019-02-07T15:21:58.021Z I [18459-AsyncTask #2] - Certificate being fetched for : AccountAuthenticationCertificateId
2019-02-07T15:21:59.013Z I [18459-AsyncTask #2] - Certificate fetch successful 
2019-02-07T15:21:59.755Z I [18459-Thread-7] - TrackingKeyManager: requesting a client cert alias for 66.170.96.7 
2019-02-07T15:22:05.776Z I [18459-Thread-9] - Registering socket factory for certificate alias [AW-be6fad91fe2b4291b1d392c9eabf90be] 
2019-02-07T15:22:05.846Z D [18459-Thread-9] - Found cert chain: [ [0] Version: 3
SerialNumber: 468315651040541492877707779630191635557515624
IssuerDN: DC=local,DC=milkyway,CN=milkyway-SUN-CA Start Date: Thu Feb 07 10:11:47 EST 2019  
Final Date: Sat Mar 09 10:11:47 EST 2019  
SubjectDN: CN=lwilcox
Public Key: RSA Public Key
modulus: ccbf28975eafd49dedfcfc43f9d66a309d36c4c636fbece2bf9faa87fe6544c8e025c3da260eb4bc28096f665a231202c5cf53dbb5f1d08ceac4d9af90f0605ee2951e6239576749d39d17e8d411b39c03e6a68e155083866a69de610853ab83d149c0228b6f0b0d67d4e9e1093ce8a3316a563c48d91fcc000bae01c150644113a527d611d83f7303825a58a4382c1818d8fd56b2064ef495c709e4ae4366e7793e29cd3b376e9660028269c8233ba8cd9a42e57dc2f07087d25fc6ce536d3bcbc8fabe2f6c408ddb2fefd8b80fdc029ba16237b48d26072d0f88f9e982ab37720883ff7bfb35bc409637fb314c00cbc1cb262e7406732c45c400ca45d9357b
public exponent: 10001

Boxer reaches out to the Exchange ActiveSync (EAS) email endpoint to make the options, provision, foldersync, and ping request.

Making the Options Request

Boxer Options Request...

Perform a FolderSync

Boxer FolderSync...

Perform a provision request

Boxer provision request...

Perform another FolderSync, this time it works. Start email sync.

Boxer another FolderSync...

Ping example

2019-02-07T15:40:12.911Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - Ping task starting for 1  
2019-02-07T15:40:12.912Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - Exchange ping starting  
2019-02-07T15:43:00.125Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - Changes found in: 8  
2019-02-07T15:43:00.126Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - Ping found changed folders for account 1  
2019-02-07T15:43:00.137Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - requestSync EasOperation requestSyncForMailboxes Account {name=lwilcox@labmail.airwlab.com, type=com.boxer.exchange}, Bundle[{__mailboxCount__=1, force=true, expedited=true, __mailboxId0__=5, PING_ERROR_COUNT=3}] 2019-02-07T15:43:00.139Z I [18459-PingTask-lwilcox@labmail.airwlab.com] - Exchange ping finished with result 2

2019-02-07T15:43:00.200Z I [18459-SyncAdapterThread-8 ] - Email sync for account lwilcox@labmail.airwlab.com, with extras Bundle[{ignore_settings=true, __mailboxCount__=1, force=true, expedited=true, ignore_backoff=true, __mailboxId0__=5, PING_ERROR_COUNT=3}] 2019-02-07T15:43:00.316Z I [18459-SyncAdapterThread-8 ] - Starting sync command

Boxer reaches out to the Email Notification Service (ENS) and provides the Exchange Web Services (EWS) credential information that was used for ActiveSync so it can subscribe to email notifications.

2019-02-07T15:23:08.315Z I [18459-AsyncTask #4 ] - Ens registration for account (id=1) is successful! 
2019-02-07T15:43:30.041Z I [18459-main ] - Sync triggered from distance

You can use Notepad++ to search the logs using the following search terms.

“error” - This is a very general way to look for errors. You will have a lot of false/positives when using this search criteria.

“exception “ - You can use this to search the file for exceptions that are generated when the application runs into an error.

“Current Network” - This will show you what network connection the mobile device was connected to 4g, wi-fi, etc…

“distance” - This shows you each time the ENS server has reached out to the mobile device to wake it up, send a notification, and trigger a sync • “transitioning” - Use this search term to tell when the application is transitioning from background to foreground and vice versa.

“requestPing” - This will show you when the device reaches out to the OS to use the Android SyncAdaptor which it uses to request the ping. The response to this request will be “Email sync for account”.

“Email sync for account” - This will be a response from the OS for a command “requestPing” or “requestSync “. Take note of how long between the request and the reply from the OS. If it’s a long time, it’s likely being throttled by the OS due to battery optimization or a third party product.

“Changes found in: “ - is the response to a ping request. This tells us if the ping found any changes in the inbox. If it did, we will now do a “requestSync " to bring those emails or changes into Boxer.

“requestSync” - This will show you when the device reaches out to the OS to use the Android SyncAdaptor which it uses to request email sync. The response to this request will be “Email sync for account”.

“Q-AppInitialization “ - This shows you when the application is starting up. You will see this when you force close and reopen the application or when you start the application after a crash.

“PingTask “ - shows you all activities related to pings

“SyncAdapterThread “ - shows you all activities related to sync operations.

“Email sync for account “ - The response from the OS after a “requestSync” or “RequestPing” operation.

“ens” - Search the log files for ens errors and settings.

Collecting Boxer Logs When You Can’t Get Into Android Boxer

Depending on what model phone you have, you can follow one of the processes below to collect Boxer logs in the event that you can’t get into Boxer due to an error. You may have a different model device than the ones listed, but the process will be very similar.

Samsung S9+

• Go to “Settings” on the phone followed by “Apps” • Select “Boxer”
• Select “Mobile Data”
• Select “View App settings” • Select “Send logs” • Use one of the other mechanisms to send the logs (either by copying the logs out or another email client).

On Motorola X Pure

• Go to “Settings” on the phone followed by “Apps” • Select “Boxer” • Select “Data Usage”
• Select “App settings”
• Select “Send logs” • Use one of the other mechanisms to send the logs (either by copying the logs out or another email client).

Device-side logs collection

Collecting Device-Side Logs

macOS Devices

With version 2.x of the macOS agent, you can now collect logs via the agent by performing the following steps:

  • Open the agent by right-clicking the agent icon from the menu bar, and then clicking Preferences
  • From the Status screen, click on Diagnostics
  • Click the button to Send Logs to Administrator
    • The agent will gather logs and zip them into an email for you automatically

To manually gather logs on older versions of the AirWatch agent, please perform the following:

  • Enable Debug Logging in the Mac OS X Terminal:
    • $ sudo defaults write /Library/Preferences/com.apple.MCXDebug debugOutput -2
    • $ sudo defaults write /Library/Preferences/com.apple.MCXDebug collateLogs 1
    • $ sudo touch /var/db/MDM_EnableDebug
    • Open the Console application from the Launchpad. Select All Messages and then click Clear Display to clear out old logs.
    • Reproduce the issue on Mac.
    • Click File > Save a Copy As. and save a copy of the logs to be sent to AirWatch.
    • Disable the Debug logging in the Mac OS X Terminal:
      • $ sudo rm –rf /var/db/MDM_EnableDebug
      • $ sudo defaults delete /Library/Preferences/com.apple.MCXDebug debugOutput
      • $ sudo defaults delete /Library/Preferences/com.apple.MCXDebug collateLogs

iOS Devices (iPhone, iPad, Apple TV)

To gather logs from iOS devices (iOS 7.x and below), please perform the following steps:

  • Install iPhone Configuration Utility (iPCU) on your workstation.
  • With iPCU started, connect the iOS device to your computer via the USB cable.
  • On the left-hand side of iPCU, select the iOS device where you wish to collect logs.
  • Click on the Console tab at the top right-hand corner.
  • Reproduce the issue with your iOS devices.
  • Click the Save Console As button to save the text in the console to a file.

To gather logs from iOS devices (iOS 8.0+), please perform the following steps:

  • Install xCode 6 on your OS X Device. Note: You cannot gather iOS 8 logs from a Windows-based computer. You must use a Mac OS X computer.
  • With xCode started, connect the iOS device to your computer via the USB cable.
  • From within xCode, click on the Window menu and click Devices.
  • Select your iOS device from the left hand side, then select the up arrow at the bottom corner of the right hand side.
  • Reproduce the issue with your iOS devices.
  • Save the contents of the activity log to a file.

Android

To gather logs using Console, please see the following documentation.  

To gather logs using ADB, please perform the following steps (see the following page for details):

  • Download and set up the Android SDK per the SDK documentation.
  • Open Windows Explorer and browse to the \platform-tools folder. Ensure you see the adb.exe file.
  • Open a CMD window and navigate to the platform-tools folder. Or, in Windows 7, navigate back to the SDK folder, then Shift + Right-Click on the platform-tools folder, and select Open Command Window Here.
  • Ensure USB Debugging is enabled on your Android device (from the Developer Settings menu). For more information on how to enable the Developer Settings menu, browse to http://www.androidcentral.com/how-enable-developer-settings-android-42
  • In your Notification Center, you may need to make sure the device is not connected in USB Media Device mode.
  • In the CMD window, type adb logcat –v long > androidlog.txt
  • On the Android device, recreate whatever error you are trying to log.
  • When complete, from within the CMD window use CTRL + C to end the logging.
  • Go back to the platform-tools folder and find the log file (androidlog.txt) that you just created.

Windows 7/8/8.1/10/11

To gather logs, please perform the following steps:

  • Click on Start > Run, type eventtvwr.msc and click OK. On Windows 8/8.1, from the start menu you can simply start typing Event and select the View Event Logs item returned from universal search.
  • Expand Event Viewer (Local) > Windows Logs and select the Application log.
  • You can filter logs by Event ID or Source if desired.
  • To export for support, click on either Save All Events As or Save Selected Events to export the log entries as an *.evtx file which can be sent to support.
  • You can also find logs in the following location: \AgentUI\Logs
    • AwclClient.log - AWCM-related Issues
    • AWProcessCommands.log - Issues with sending commands to the device
    • NativeEnrollment.log - Issues with Enrollment
    • TaskScheduler.log - Issues with samples sent to console

Windows Phone 8.1 (deprecated)

To gather logs, please perform the following steps:

  • Ensure you have Visual Studios 2013 Update 3 installed. If not, perform the following:
    • From your Windows Laptop of VM, browse to Windows Phone SDK Archives
    • Download the Visual Studio Express 2013 for Windows and Install it.
    • From within Visual Studios, click on Tools > Windows Phone 8.1 > Developer Unlock. Follow the prompts to unlock your Windows Phone 8.1 device.
    • From within Visual Studios, click on Tools > Windows Phone 8.1 > Developer Power tools.
    • Select Device from the Select Device dropdown, then click Connect. If prompted, click Install to install the Phone Tools Update Pack.
    • Select the Performance Recorder tab, then check the Enterprise Management option under the Extras profile category.
    • Click the Start button in the Developer Power Tools window to start a log.
    • Run your scenarios and re-create the issue you’re experiencing.
    • Click the Stop button in the Developer Power Tools window to stop logging and save the ETW to a local location.
    • You will need to download the Windows Performance Analyzer to view the logs. This can be found in the Windows Performance Toolkit included in the Windows Assessment & Deployment Toolkit (ADK) and Windows Software Development Kit (SDK).

Windows Performance Toolkit

  • Open the Windows Performance Analyzer and Open the ETL file.
  • In the Graph Explorer window, expand System Activity and view the Generic Events window.
  • Double-click the graphic bars in the Generic Events window to display an Analysis window.
  • In the Analysis window, click Open View Editor to show a Generic Events View Editor window.
  • In the Generic Events View Editor window, ensure the Message box is checked and click Apply:
    • The Message field in the analysis window provides the MDM specific log message under various providers.
    • Microsoft-WindowsPhone-Enrollment-API-Provider – ETW logs for MDM Enrollment and MDM Client Cert Renew Process.
    • Microsoft-WindowsPhone-SCEP-Provider – SCEP Cert enrollment logging
    • Microsoft-WindowsPhone-CmCspVpnPlus – VPN Configuration logging

Windows Mobile Devices with Agent 5.x

All log settings are configured in the log_config.cfg file in the \Program Files\AirWatch directory on the device. The file will resemble the following:

[*]trace_level=5

max_file_size_kb=256

files_to_keep=2

log_file_path=\Program Files\AirWatch\Logs

use_local_time=false

[aw_setup]trace_level=5

max_file_size_kb=256

files_to_keep=2

log_file_path=\

use_local_time=false

[awregisterdevice.exe]
trace_level=3

max_file_size_kb=256

files_to_keep=2

log_file_path=\Program Files\AirWatch\Logs

use_local_time=false

[awapplyprofile.exe]trace_level=5

max_file_size_kb=256

files_to_keep=2

log_file_path=\Program Files\AirWatch\Logs

use_local_time=false

[awremotecontrol.exe]trace_level=1

max_file_size_kb=256

files_to_keep=2

log_file_path=\Program Files\AirWatch\Logs

use_local_time=false

In general, the following notes apply to Windows Mobile device logging:

  • The logging level can be modified as a whole, or on an individual basis:
    • The asterisk configuration is the default config for all logs. Trace levels vary from 1 (basic) to 5 (verbose/debug).
    • Each individual section, which can be used to increase logging to override the default setting from the asterisk section.
    • The log files which are available can vary (based on configuration and OEM), but the following are the most common:
      • aw_setup - Provides logging information relating to the AWMasterSetup utility, which is responsible for initiating the agent install and uninstall process on a device. This is the only log file that is not located in the “\Program Files\AirWatch” directory and is instead located in the root of the file system.
      • awacmclient - Provides logging information relating to the AWCM client on the device
      • awapplicationmanager - Provides logging information relating to product provisioning
      • awprocesscommands - Provides logging information relating to the execution of MDM commands and installation of profiles
      • AWService - Provides information about the AWService.exe component, which is responsible for managing beacon and interrogator samples
      • awapplyprofile - Relates to installation of the agent settings xml file which occurs during the enrollment process
      • awregisterdevice - Provides information about the registering of the device that occurs during the enrollment process
      • awapplauncher - Provides information about the Application Launcher executable. This log will only be present if the App Launcher utility is assigned to and being used by a device.
      • fusionwlansetup - Provides information about configuring and setting up the Fusion WiFi driver on Motorola devices.

The general process for configuring log files is as follows:

  • Transfer the log file to your machine. This can be done through the file manager utility in device details or through remote management if a client has that configured.
  • Open the log file via a basic text editor such as notepad.
  • Edit the desired trace level to the needed value.
  • Save the log file.
  • Transfer the log file back down to the “Program Files\AirWatch” directory on the devices. This can be accomplished via file manager, remote manager, or product provisioning. To be safe, you may elect to first delete the old log_config.cfg file.
  • Restart AWService on the device once it has the updated log_config.cfg file. This can be accomplished by directly restarting the AWService through the “Restart AirWatch Agent” or the “Warm Boot” MDM commands that are available in the AirWatch Console.
  • Once the AWService has been restarted, the new logging configuration will take effect. Reproduce your issue and then repeat the steps to turn the logging back down on the device.

Collecting Service/Functionality Specific Logs

Product Provisioning

Review the AirWatch Agent Logs and look for the following items to help you troubleshoot what is occurring:

  • If the device is newly enrolled, you’ll see the following in the logs: A message from [AWProductHandler sendProductResponses] stating “Products: No products with results to be sent!”
  • A message from [AWEnhancedProductsHandler handleCommand:] stating “Got Products New Manifest”
    • Note: In the manifest will be a line entry called ProductID". You’ll want to save this for later on.
    • Depending on the number of products being installed, you may see an entry for each product that is required.
    • Messages from [AWAppDataManager readJobProduct:] looking to see if the product is downloaded to the local cache
    • Messages from [AWOSXUtils deleteFile:] where it attempts to delete any pre-existing plist file for the products.
    • Messages from [AWJob printJob] which show the sequence number assigned to the Product which will be installed.
    • From this point forward you can search the log by the sequence number assigned to the product install job:
      • Messages about the job being queued
      • Messages about the job being started.
        • The line will look like this: airwatchd[PID] : - [AWJobQueue doJob] [Line 98] THREAD: Current Job: where PID is the AirWatch Agent Process ID and the JobID is the Sequence Number assigned to the product.
        • You can get additional information about the product actions occurring by searching from that point forward for entries from the process ID!
  • Messages about any files being downloaded to the product cache
  • Messages about Job Status Change. You’ll want to search for a line ending in Job Status changed ========> :AWJobStatusFailed!" From that point, search up in the log for messages relating to the JobID and/or the ProductID (as found in the manifest). All these messages should be coming from the Process ID of the Airwatch agent that initially started the install.

Screen Recording

Screen Recording

Windows 7/8/8.1/10/11

To document click-through steps on Windows machines, perform the following:

  • Click on Start > Run and type psr.exe to bring up the Problem Steps Recorder (or PSR, a built-in Windows utility).
  • Click on Start Record to begin capturing steps. Note: PSR captures screenshots of ALL monitors; no scoping.
  • Each Mouse-Click you make captures a screenshot. At any time during the session, click on Add Comment to provide more details about the screen, error, etc.
  • When finished, click Stop Record.
  • Choose where to Save the PSR file – it outputs a zip file containing a pre-compiled HTML (*.mhtml) file with all your screenshots and comments.

macOS

To document click-through steps on macOS machines, perform the following:

  • Launch QuickTime Player. You’ll find it in the Other folder within Launchpad.
  • From the QuickTime menu bar, click File > New Screen Recording. Click the red record button.
    • Optionally you may wish to select View > Float on Top before you start recording.
    • Optionally, you can select the upside-down triangle in the record screen to include audio recording during the screen capture for annotation.
    • Click the screen (or Click-Drag to select part of the screen) for recording.
    • When complete, click the Stop button that appears in the menu bar of the screen where you’re recording.
    • Click File > Save (or simply quit QuickTime) to be prompted with a location to save the screen capture. Note: Keep it moving when you record these; they create full-blown movies and the file gets large quickly.

REST API

### URI

Old API URI example: https://host/api/v1/mam/apps/public/{applicationid}/addsmartgroup/{smartgroupid}

New API URI example: https://host/api/mam/apps/public/{applicationid}/smartgroup/{smartgroupid}

Attached Documents

Articles in section

Preparation

You need a user account to run scripts in AirWatch REST API. Create a local account, take its’ credentials: domain\login:password, and go encode it at https://www.base64encode.org/

For example, 'lab\restguy:P@ssw0rd' ==> 'bGFiXHJlc3RndXk6UEBzc3cwcmQ='._

Turn API access ON for this account in the AirWatch console System -> Advanced -> API -> REST, we also should get an API Key for it.

Warning
  • AirWatch requires all requests to be made over SSL.

  • AirWatch limits the number of API requests that can be made during certain time periods. Rate limiting is done per Organization Group (OG) based on the API key used in the request.

    **Server Throttling** - The limit imposed on an Organization Group for a 1 minute interval.  
    **Daily Quota** - The limit imposed on an Organization Groupvfor a 24-hour interval.
    

Local REST API Help

REST API Help is built into the AirWatch API Server host, go to link: https:///api/help/

Examples of using REST API

Let’s take some device from those enrolled in AirWatch and check out the apps list on it.

import requests
consoleURL = 'https://airwatch.example.com'
b64EncodedAuth = 'bGFiXHJlc3RndXk6UEBzc3cwcmQ='
API_Key = 'S390lvIVeFRBSO4InP73MFG3YSFDNKL+BXKW7Wv5Wwo='
basic_headers={"Authorization": "Basic " + b64EncodedAuth, "aw-tenant-code": APItenantCode,"Accept": "application/json"}
 
appsTest = requests.get(consoleURL + "/api/mam/apps/internal/46", headers=basic_headers)
print(appsTest.json())

46 is the device ID inside AirWatch. How do you find the ID of a device? - simplest way to do this is open AirWatch console, device list page, and hover your mouse over any device name: you will see the ID in the browser URL status bar. Now, let’s see where the device has been for the last 2 days:

gps2days = requests.get(consoleURL + "/api/mdm/devices/46/gps?dayrange=2", headers=basic_headers)
print(gps2days.json())

If there are any GPS points recorded for the device, we will get a list of them here. How can we use this? For example, customers say they hate Bing Maps embedded in AirWatch console. So we can build a little portal for searching devices, embed Google Maps into it and use the coordinates list to draw points.

One step deeper: suppose we need to show a customer how GPS coordinates are being collected, but the device enrolled is fresh, did not catch any sattelites yet or has problems with GPS module. Since GPS data is actually stored and taken from the SQL database, we can insert some coordinates there manually and see them right away on the Bing map in the console. See article on inserting false GPS history for a device in SQL section

Last example in this article I got from a cool client. They give out corporate iPhones to their employees, and all of those devices are supposed to be supervized. Only supervized devices are to be enrolled in AirWatch and get corp data, no personal gadgets coming through! AirWatch does have a tag for Apple device status (is it Supervized/DEP/Education?), but uses it only for reporting - there is no Compliance rule or filtering around this currently (a ticket in Jira on the topic is promised to be closed in AirWatch 9.6+). So the client gets a list of all enrolled devices and filters them manually:

import json
devicelist = requests.get(consoleURL + '/api/mdm/devices/search', headers=basic_headers)
for i in devicelist.json()["Devices"]:
    if i["Platform"] == "Apple" and i["IsSupervised"] == False and i["EnrollmentStatus"] == "Enrolled":
        # Tag the toxic devices, or enterprise wipe them

By running this script every half-hour, all unsupervised devices are Enterprise Wiped shortly after they are enrolled.

Subsections of REST API

REST API Example on Python

Several typical functions of working with REST API:

  • Searching for devices in a tenant
  • Filtering devices by OS (Win/Linux)
  • Getting a list of tags for the tenant
  • Scanning a file with list of Notebook/Smartphone/Tablet serial keys, then checking if enrolled devices have such serials, and writing the result in a file
Tip

Default tags have ID 1-8. User-created tags have ID=10000+

  • Assigning devices to a chosen tag

Code is for Python version 3.7+, and is bundled into a dataclass as methods, with error-catching and logging support.

Link to code on GitHub.

'''Version 0.3
Created by Alexei Rybalko aka Aagern.
22.05.2021'''
 
import requests, json, base64, logging, sys
from dataclasses import dataclass
from pprint import pprint
 
logging.basicConfig(filename="DeviceControl.log", level=logging.DEBUG,
                    format="%(asctime)s:%(levelname)s:%(message)s")
 
@dataclass
class DeviceControl:
    API_URL: str = 'https://mdm.example.local'
    API_Key: str = 'oxGI6OORljw/Qsql1OFBycjHvzQzEXVXa/tyEcCfIPI='
    API_User: str = 'defaultDomain\\api_user:VMware1!'
    Serials_File: str = 'S.csv'
    Output_File: str = 'DeviceSerials.csv'   
     
    API_User_B64 = base64.b64encode(API_User.encode('utf-8'))  # convert to Base64
    API_User_UTF8 = API_User_B64.decode('utf-8')
    Platforms = {'Windows':12,'Linux':21}
    Header = {"Authorization": "Basic " + API_User_UTF8, "aw-tenant-code": API_Key, "Accept": "application/json"}
    Devices = {}
    Serials = []
     
    def getMDM(self,request):
        """Get data from MDM Server. Input: API request text. Output: response data in JSON."""
        try:
            dataMDM = requests.get(self.API_URL + request, headers=self.Header)
            dataMDM.raise_for_status()
            data = dict(dataMDM.json())
        except requests.exceptions.RequestException as e:
            logging.error(f'Get request failed with {e}')
            sys.exit(1)
        logging.debug(f'Data received from {self.API_URL}')
        return data
         
    def postMDM(self,request,data):
        """Post data to MDM Server. Input: API request text. Output: HTTP response status and details."""
        try:
            responseMDM = requests.post(self.API_URL + request, headers=self.Header, json=data) # Important to do json= here, rather than prepare data with json.dumps()
        except requests.exceptions.RequestException as e:
            logging.error(f'Post request failed with {e}')
            sys.exit(1)
        logging.debug(f'Data sent to {self.API_URL}')       
        return responseMDM
     
    def scanSerialsFile(self,file=Serials_File):
        """Input file with device serials. Output list of serials from file"""
        try:
            with open(file,encoding='utf-8') as f:
                for serial_line in f:
                    self.Serials.append(serial_line)
                    Serials[0] = Serials[0][1:] # Omitting special symbol at file start
                logging.debug(f'Serials file {file} processed.')
        except OSError as e:
            logging.error(f'File opening error with {e}')
            print('File not opened. Serials list empty')
            self.Serials = []
        return self.Serials
             
    def filterDevices(self,platform='Windows'):
        """
        Method filters out Devices by Platform.
        Inputs: Platform name.
        Outputs: File with serials, Dictionary of Device:[Serial,ID]
        """
        PlatformID = self.Platforms[platform]
        dataDict = self.getMDM('/api/mdm/devices/search')
        for device in dataDict['Devices']:
            if device['PlatformId']['Id']['Value'] == PlatformID:
                self.Devices[device['DeviceFriendlyName']] = [device['SerialNumber'] if device['SerialNumber'] else 'Not set',device['Id']['Value']]
        try:
            with open(self.Output_File,mode="wt",encoding='utf-8') as output_file:
                for device,serial in self.Devices.items():
                    print(f"{device},{serial},",file=output_file)
                    if serial in Serials: print("Registered\n",file=output_file)
                    else: print("NOT Registered\n",file=output_file)
                logging.debug(f'Output file {self.Output_File} written.')
        except OSError as e:
            logging.error(f'File opening error with {e}')
            print('File not written.')
            sys.exit(1)
        return self.Devices
     
    def getMDMTags(self,tenant='570'):
        """Get all tags in tenant. Input: tenant ID. Output: list of tags and their IDs."""
        tagsDict = self.getMDM(f'/api/system/groups/{tenant}/tags')
        for tag in tagsDict['Tags']:
            print(f"Name={tag['TagName']}\t\tID={tag['Id']}")
             
    def setTagDevices(self,tagID='10000',DeviceIDs=['3']):
        """Method assigns devices to tag. Input: tag id, devices ID list. Output: total  of assigned devices"""
        FuncDeviceIDs = { "BulkValues":{"Value":DeviceIDs}}
        response = self.postMDM(f'/api/mdm/tags/{tagID}/adddevices',FuncDeviceIDs)
        print(f'Status code: {response.status_code}, \n {response.text}')
 
# Examples of usage
 
Device = DeviceControl()
data = Device.filterDevices()
Device.getMDMTags()
Device.setTagDevices()

WS1 Launcher and Restrictions

Custom XML Profiles for Android

Custom XML for Workspace ONE Launcher - https://docs.vmware.com/en/VMware-Workspace-ONE-UEM/2209/Launcher_Publication/GUID-CustomXML.html?hWord=N4IghgNiBcIMYFcDOAXA9gWwAQA8MSwAcAnNAMwEsIBTLCMBAOzgAtriQBfIA

When using Ws1 Launcher for Android, it will block Phone app and incoming phone call notifications. In order to allow phone dialer app (example: com.samsung.android.dialer) a custom profile has to be added:

<characteristic type="com.airwatch.android.androidwork.launcher" uuid="568bc89d-1df8-4ce9-a041-e5a24acdb7ec">
<parm name="SkipCosuSetup" value="True"/>

Enable WiFi in Android Kiosk

By default, WiFi is blocked by kiosk mode. To unlock possibility for user to choose WiFi network do this:

  • Check the APP ID of “Settings” application on Android OS;
  • Add Settings app APP ID to AirWatch Launcher as Hidden Apps.

Custom XML Profiles for iOS

Custom Settings profile payload allows admins to enter their own XML into a profile and apply the profile to devices.

(For iOS 11.3+ and macOS 10.13.4+)

  • XML should contain the complete block of code as listed below, from to
  • Administrators should configure each setting from to as desired.
  • If certificates are required, then configure a Certificate payload within the profile and reference the Payload UUID in the Custom Settings payload.

iOS 11.3

Restrictions

<dict>
         <key>allowUSBRestrictedMode</key>
         <true/>
         <key>forceClassroomRequestPermissionToLeaveClasses</key>
         <true/>
         <key>forceDelayedSoftwareUpdates</key>
         <true/>
         <key>enforcedSoftwareUpdateDelay</key>
         <integer>30</integer>
         <key>PayloadDisplayName</key>
         <string>Restrictions</string>
         <key>PayloadDescription</key>
         <string>RestrictionSettings</string>
         <key>PayloadIdentifier</key>
         <string>7480b205-2e1c-40fe-bd59-b53db434652d.Restrictions</string>
         <key>PayloadOrganization</key>
         <string></string>
         <key>PayloadType</key>
         <string>com.apple.applicationaccess</string>
         <key>PayloadUUID</key>
         <string>99b5b40b-5683-4315-9ec2-f9e014a6XXXX</string>
         <key>PayloadVersion</key>
         <integer>1</integer>
 </dict>

Home Screen Layout

Note

Web clips should be configured and deployed using the current web clip payload UI

<dict>
    <key>Dock</key>
    <array>
        <dict>
            <key>Type</key>
            <string>WebClip</string>
            <key>URL</key>
            <string>https://google.com</string>
        </dict>
    </array>
    <key>Pages</key>
    <array>
        <array>
            <dict>
                <key>Type</key>
                <string>WebClip</string>
                <key>URL</key>
                <string>https://yahoo.com</string>
            </dict>
            <dict>
                <key>Type</key>
                <string>Folder</string>
                <key>DisplayName</key>
                <string>My Web Clip</string>
                <key>Pages</key>
                <array>
                    <array>
                        <dict>
                            <key>Type</key>
                            <string>WebClip</string>
                            <key>URL</key>
                            <string>https://www.vmware.com</string>
                        </dict>
                    </array>
                </array>
            </dict>
        </array>
    </array>
    <key>PayloadDisplayName</key>
    <string>Home Screen Layout</string>
    <key>PayloadDescription</key>
    <string>HomeScreenLayout</string>
    <key>PayloadIdentifier</key>
    <string>97213d06-b750-466b-8a89-782d8a406f86.Home Screen Layout</string>
    <key>PayloadOrganization</key>
    <string></string>
    <key>PayloadType</key>
    <string>com.apple.homescreenlayout</string>
    <key>PayloadUUID</key>
    <string>2fa8fe03-30fa-4189-aa00-ba752eabXXXX</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict

Enable Bluetooth Command

Unlike custom profiles, the payload content and UUID are not required for custom commands. This command will not take place if the Allow Bluetooth Settings Modification restriction is enforced.

<dict>
  <key>RequestType</key>
  <string>Settings</string>
  <key>Settings</key>
  <array>
    <dict>
      <key>Item</key>
      <string>Bluetooth</string>
      <key>Enabled</key>
      <true/>
    </dict>
  </array>
</dict>

macOS 10.13.4 Custom XML

Restrictions

<dict>
         <key>forceDelayedSoftwareUpdates</key>
         <true/>
         <key>enforcedSoftwareUpdateDelay</key>
         <integer>30</integer>
         <key>PayloadDisplayName</key>
         <string>Restrictions</string>
         <key>PayloadDescription</key>
         <string>RestrictionSettings</string>
         <key>PayloadIdentifier</key>
         <string>7480b205-2e1c-40fe-bd59-b53db434652d.Restrictions</string>
         <key>PayloadOrganization</key>
         <string></string>
         <key>PayloadType</key>
         <string>com.apple.applicationaccess</string>
         <key>PayloadUUID</key>
         <string>99b5b40b-5683-4315-9ec2-f9e014a6XXXX</string>
         <key>PayloadVersion</key>
         <integer>1</integer>
 </dict>

Autonomous Single App (ASA) Mode

<dict>
    <key>AllowedApplications</key>
    <array>
      <dict>
        <key>BundleIdentifier</key>
        <string>com.sample.app1</string>
        <key>TeamIdentifier</key>
        <string>ABCDEFG1HI</string>
      </dict>
      <dict>
        <key>BundleIdentifier</key>
        <string>com.sample.app2</string>
        <key>TeamIdentifier</key>
        <string>ABCDEFG1HI</string>
      </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>Autonomous Single App Mode</string>
    <key>PayloadDescription</key>
    <string>AutonomousSingleAppMode</string>
    <key>PayloadIdentifier</key>
    <string>7480b205-2e1c-40fe-bd59-b53db434652d.AutonomousSingleAppMode</string>
    <key>PayloadOrganization</key>
    <string></string>
    <key>PayloadType</key>
    <string>com.apple.asam</string>
    <key>PayloadUUID</key>
    <string>91b5e40b-5683-4376-9ec2-f9e214a6XXXX</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict
Warning
  • Can only be installed on User Approved MDM Enrolled devices. Must be installed as Device profile. Only one payload allowed per machine.
  • To be granted access, applications must be signed with the specified Bundle Identifier and Team Identifier using an Apple-issued production developer certificate. Applications must specify the com.apple.developer.assessment entitlement with a value of true.
  • The application’s bundle identifier. BundleIdentifier must be unique. If two dictionaries contain the same BundleIdentifier but different TeamIdentifiers, this will be considered a hard error and the payload will not be installed.

To check if the .app has the correct entitlement noted above:

codesign –d –entitlements - /Applications/Example.app

This will print out XML with the entitlements. It needs to have the com.apple.developer.assessment entitlement with a value of true.

To get the Bundle & Team Identifier for an .app:

codesign –dvvvv /Applications/Example.app

The Bundle Identifier will be in the ‘Identifier’ field. The Team Identifier will be a 10 character string in the ‘TeamIdentifier’ field.

Content Caching

<dict>
    <key>AllowPersonalCaching</key>
    <true/>
    <key>AllowSharedCaching</key>
    <true/>
    <key>AutoActivation</key>
    <true/>
    <key>CacheLimit</key>
    <integer>100000000</integer> <!--100 MB example-->
    <key>DataPath</key>
    <string>/Library/Application Support/Apple/AssetCache/Data</string>
    <key>DenyTetheredCaching</key>
    <false/>
    <key>ListenRanges</key>
    <array>
      <dict>
        <key>type</key>
        <string>IPV4</string>
        <key>first</key>
        <string>0.0.0.0</string>
        <key>last</key>
        <string>255.255.255.255</string>
      </dict>
    </array>
    <key>ListenRangesOnly</key>
    <false/>
    <key>ListenWithPeersAndParents</key>
    <true/>
    <key>LocalSubnetsOnly</key>
    <true/>
    <key>LogClientIdentity</key>
    <false/>
    <key>Parents</key>
    <array>
      <string>1.1.1.1</string>
      <string>2.2.2.2</string>
    </array>
    <key>ParentSelectionPolicy</key>
    
 <string>round-robin</string> <!-- Possible values are
round-robin, first-available, url-path-hash, random, and
sticky-available-->
    <key>PeerFilterRanges</key>
    <array>
      <dict>
        <key>type</key>
        <string>IPV4</string>
        <key>first</key>
        <string>0.0.0.0</string>
        <key>last</key>
        <string>255.255.255.255</string>
      </dict>
    </array>
    <key>PeerListenRanges</key>
    <array>
      <dict>
        <key>type</key>
        <string>IPV4</string>
        <key>first</key>
        <string>0.0.0.0</string>
        <key>last</key>
        <string>255.255.255.255</string>
      </dict>
    </array>
    <key>PeerLocalSubnetsOnly</key>
    <true/>
    <key>Port</key>
    <integer>0</integer>
    <key>PublicRanges</key>
    <array>
      <dict>
        <key>type</key>
        <string>IPV4</string>
        <key>first</key>
        <string>0.0.0.0</string>
        <key>last</key>
        <string>255.255.255.255</string>
      </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>Content Caching</string>
    <key>PayloadDescription</key>
    <string>ContentCaching</string>
    <key>PayloadIdentifier</key>
    <string>7480b205-2e1c-40fe-bd59-b53db434652d.ContentCaching</string>
    <key>PayloadOrganization</key>
    <string></string>
    <key>PayloadType</key>
    <string>com.apple.AssetCache.managed</string>
    <key>PayloadUUID</key>
    <string>98f5b40b-5683-2415-9ec2-f9e014a6XXXX</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>

WS1 SQL Database

Articles in section

SQL Requirements

  • AirWatch 9.1 and later versions are supported on SQL Server 2016, SQL Server 2014, and SQL Server 2012.
  • Both Enterprise and Standard Editions are supported, Express Edition is NOT supported because it does not offer all of the features that are used by AirWatch.
  • It is recommended that the AirWatch databases are operating on 64-bit editions of Windows and using the 64-bit installation of SQL Server.

❗️ SQL Server Collation: AirWatch supports SQL_Latin1_General_CP1_CI_AS as the server AND database collation ONLY.

SQL Connections

MAX database connections are set to 150 per Application Pool and Service. Currently in production on each DS server there are :

4 Application Pools 8 Services
AirWatch Local AW Tunnel Queue Monitor Service
AirWatch API AW Entity Change Queue Monitor
AirWatch DS AW Interrogator Queue Monitor
AirWatch SSP AW Interrogator Server
AW Log Manager Queue Monitor
AW Master Queue Service
AW MEG Queue Service
AW Messaging Service

⭐️ Total = 12 * 150 max connections = 1800 per DS Server.

SQL Recommendations

VMware official recommendations

  • TempDB Configuration: the number of tempDB files must match the number of CPU cores when the core is less than or equal to 8 cores. Beyond 8 cores, the number of files must be the closest multiple of 4 that is less than or equal to the number of cores (e.g. 10 cores will need 8 tempDBs, 12 cores will need 12 tempDBs, 13 cores will need 12 tempDBs, 16 cores will need 16 tempDBs.) File size, growth rate, and the location need to be the same for all tempDB files.

    ⭐️ Microsoft SCCM best practice is to create no more than 8 temp DB files

  • Memory Allocation: Eighty percent of the server memory should be allocated to SQL. The remaining 20% must be freed up to run the OS.

    • Test = 16Gb
    • Production = 128GB In Properties of server in Memory tab set restrictions for memory usage of SQL Server:
    • min = 60%
    • max = 80%
  • Cost Threshold for Parallelism and Maximum Degree of Parallelism: Cost Threshold for Parallelism is the cost needed for a query to be qualified to use more than a single CPU thread. Maximum Degree of Parallelism is the maximum number of threads that can be used per query. The following are recommended values for these parameters:

    • Cost Threshold of Parallelism: 50
    • Max Degree of Parallelism: 2 and reduce to 1 in case of high server utilization.
  • Trace Flag: The following trace flags must be set to 1 at Global. 1117 (https://msdn.microsoft.com/en-us/library/ms188396.aspx) 1118 (https://msdn.microsoft.com/en-us/library/ms188396.aspx) 1236 (https://support.microsoft.com/en-us/kb/2926217) 8048 (https://blogs.msdn.microsoft.com/psssql/2015/03/02/running-sql-server-on-machines-with-more-than-8-cpus-per-numa-node-may-need-trace-flag-8048/) Set flags 1117, 1118, 1236, 8048 = 1

  • Hyperthreading: If the database is running on a physical server, hyperthreading must be disabled on the database to ensure best performance. If it is on a VM, then having hypertherading enabled on the ESX host will not have any performance impact, but hyperthreading must be disabled on the Windows host level;

  • Optimize for Ad hoc Workloads: Enable Optimize for Ad hoc Workloads under SQL server properties. This is recommended in order to free memory from the server. Refer to the following article for more information: https://msdn.microsoft.com/en-us/library/cc645587(v=sql.120).aspx;

  • Lock Escalation: Disable Lock Escalation for “interrogator.scheduler” table by running alter table interrogator.scheduler set (lock_escalation = {Disable}) This is recommended as the scheduler table has very high rate of updates/inserts. There is a high contention on this table with the use of GCM, and disabling lock escalation helps improve performance. However, the drawback is that more memory is consumed. Refer to the following article for more information: https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx.

Additional Microsoft recommendations for SQL DB for large installations

  • SQL Server Agent autostart: In SQL Server Configuration Manager properties of SQL Server Agent component put automatic start;

  • Disable Auto shrink of DB and journals: According to Microsoft Best Practices for SCCM, Auto Shrink of DB and journals should be turned OFF;

  • Journal size edit: According to Microsoft Best Practices for SCCM, initial size of transaction log should be 16Gb, growth by 512Mb;

  • Recovery Model type: Choose recovery model type - Full or Simple See page on SQL Recovery model choice and consequences

    Best practive by Microsoft - to set an SQL Alert on event “log size greater than 18Gb” and a Job to execute Shrink Log File.

Subsections of WS1 SQL Database

Admin Password Reset

Changing an administrator’s password

Changing an administrator’s password requires first getting the CoreUserID for that user, and then updating the password and password salt for that user in the database.

Getting the CoreUserID

Run the following SQL query to get the CoreUserID for the user.  Make sure to replace with the administrator’s username.  If more than one result are returned, make sure you identify the right entry.

Select * from CoreUser where UserName = '<USERNAME>';

Updating the password and password salt

The following query will update the administrator’s password.  Make sure to replace with the proper CoreUserID identified in the first section.  Have updating the password, log in with the account and reset the password to something else.

-- This Updates the password to 'a123b456c789'
UPDATE CoreUser SET Password = 'c2otxl1SURGxVibCX1K9IJvyizYl4ylnIIfXhwNtfe1iCuuVM8LNPK1oWWSwE3C3BB3AYxspGqrfXaVnryxjzw==' ,
PasswordSalt = '6eklCHP5ixaMT9RREfQbmi4Z2jc=' WHERE CoreUserID = <COREUSERID>
 
-- This Updates the password to 'Password123!'
UPDATE dbo.CoreUser SET Password = 'awhash4:IGdeYQ7eaHqyh3g6RelU0zkbHjoRW111/dg2xyqjiK0=:100000:K91XOTYtcw/20ZxDOUm7pe3DVLFA3XrzuUAYtWdl21M=' WHERE UserName = 'Administrator'

Account lock-out

Check IsLockedOut flag - it must be set to 0 for active/unlocked account.

UPDATE dbo.CoreUser SET IsLockedOut = 0 WHERE UserName = 'Administrator'
UPDATE dbo.CoreUser SET LastLoginAttempts = 0 WHERE UserName = 'Administrator'

APNs Troubleshooting

APNs incorrect renewal

  •  First you need to get the GroupID of the organization group that has APNs configured.  In Chrome, you can do this by right-clicking the organization group drop down as shown below and choosing Inspect Element.  In the HTML, search for data-current-lg and note the GroupID.
  • Perform the following SQL query in the database to retrieve information about the APNs certificate:
SELECT DISTINCT DC.CertificateID, DAGS.appleid, DC.SubjectName,
                DC.serialnumber, DC.certificate thumprint,
                DC.notBefore, DC.NotAfter
FROM
      dbo.Certificate (NOLOCK) AS DC
      JOIN
            dbo.ApnsGenerationStatus (NOLOCK) as DAGS
            ON DC.CertificateID = DAGS.IssuedCertID
WHERE
      DAGS.LocationGroupID = 10289
ORDER BY NotBefore ASC
  • Validate the results of this query.  In a correct renewal, both the appleid and SubjectName columns of the results should match between the latest certificate and the previous certificate.  You can tell which certificate is which based on the notBefore and notAfter columns, which match the validity dates of the certificate.
CertificateID appleid SubjectName serialnumber thumprint notBefore NotAfter
378672 userA@yourcompany.com C=US,CN=APSP:06efab8c-1d88-4fed-8c4d-a92f88ea9281,OID.0.9.2342.19200300.100.1.1=com.apple.mgmt.External.06efab8c-1d88-4fed-8c4d-a92f88ea9281 52DEAB4B44A18861 0x30820C9F0… 9/5/2014 9/5/2015
30874966 userA@yourcompany.com C=US, CN=APSP:06efab8c-1d88-4fed-8c4d-a92f88ea9281, OID.0.9.2342.19200300.100.1.1=com.apple.mgmt.External.06efab8c-1d88-4fed-8c4d-a92f88ea9281 0EA275019DF7D704 0x30820C975… 8/28/2015 8/27/2016
  • If the appleid field is different, then the administrator used an incorrect Apple ID when renewing the APNs certificate, and so the SubjectName will not match.  The administrator must use the same Apple ID when renewing APNs, or all devices will lose the ability to communicate.  If appleid matches but SubjectName is different, then the administrator used the correct Apple ID but chose the wrong certificate it Apple’s portal to renew.  They must go back to Apple’s portal and renew the correct certificate.
  • Note: All devices enrolled after the notBefore date of an incorrect APNs certificate must re-enroll when the certificate is corrected.  These devices will lose communication once the certificate is correct.
  • Note: If the administrator previously cleared out the APNs certificate (by selecting the Clear button in the APNs settings page and saving), they will lose communication with all devices.  In this event, a database backup is required to restore the tokens, and this process generally cannot be completed on SaaS environments.

APNs Database Queries

Below are a list of helpful SQL queries specifically when troubleshooting APNs. All of the queries below are SELECT statements, which allows us to view the information but not update it.

  1. This statement will display an overall view of the location group. This allows us to look at certain fields as well as the Location Group ID for the location where the APNs certificate is being uploaded. By inputting the name, you can receive the Group ID.
SELECT * FROM dbo.locationgroup lg (NOLOCK) WHERE lg.Name like '%%'
  1. This statement displays the APNs settings at and above the LG provided. We are looking for these first four fields and which have values that are not NULL. It should only be configured at one level and inherited below. You simply need to input the group ID found in the first query.
SELECT lgf.LGlvl, lg.MDMAppleApplicationID, lg.MDMAppleDeviceProfileID, lg.AppleMDMEnabled, lg.MDMSettingsInheritable,lg.*
FROM dbo.LocationGroup lg (NOLOCK)
 JOIN dbo.LocationGroupFlat lgf (NOLOCK)
  ON lgf.ParentLocationGroupID = lg.LocationGroupID
WHERE lgf.ChildLocationGroupID = ###
ORDER BY lgf.LGlvl DESC
  1. This statement shows the APNs settings at or below the LG provided. You simply need to input the group ID found in the first query. The first four columns after the level should be NULL at every level below the level where the cert was uploaded at. You can also view the levels of the tree in the first column. If you do see multiple levels with values not being NULL, we can look at the different APNs certs and the number of devices associated. This will require some update statements which a DB or T3 Member can assist with.
SELECT lgf.LGlvl, lg.MDMAppleApplicationID, lg.MDMAppleDeviceProfileID, lg.AppleMDMEnabled, lg.MDMSettingsInheritable,lg.*
FROM dbo.LocationGroup lg (NOLOCK)
 JOIN dbo.LocationGroupFlat lgf (NOLOCK)
  ON lgf.ChildLocationGroupID = lg.LocationGroupID
WHERE lgf.ParentLocationGroupID = ###
ORDER BY lgf.LGlvl ASC
  1. This statement will display all the APNs certificates in the environment. You simply need to input the group ID found in the first query. It is important to match this with the previous query so we know which cert is at each level. It is also important to view if the topic is the same for different certs. If it is, we can change the application ID associated to the device without any end user interaction or effect. If the topics are different, devices will need to re-enroll. From this query, you will have the ProductionCertificateID and ApplicationID.
SELECT a.ProductionCertificateID, lg.LocationGroupID, lg.Name, a.*
FROM deviceApplication.Application a (NOLOCK)
 JOIN dbo.LocationGroupFlat lgf (NOLOCK)
  ON a.RootLocationGroupID = lgf.ChildLocationGroupID
 JOIN dbo.LocationGroup lg (NOLOCK)
  ON lgf.ChildLocationGroupID = lg.LocationGroupID
WHERE lgf.ParentLocationGroupID = ###
 AND a.PackageID like '%com.apple.mgmt%'
  1. This statement will confirm if the certificates are alive by viewing the date. You simply need to input the ProductionCertificateID found using the queries previous.
SELECT *
FROM dbo.Certificate c (NOLOCK)
where c.CertificateID IN (###)
  1. This statement will tell the devices that are associated with the Application ID. You simply need to input the ApplicationID found using the queries previous. This will assist if the customer has multiple APNs certificates active in the console and you are trying to determine which to use. Obviously, we will want to choose the cert with the most devices for the least end user impact.
SELECT *
FROM deviceApplication.ApplicationDeviceCredential adc (NOLOCK)
WHERE adc.ApplicationId IN (###)

Condensed query:

SELECT adc.DeviceID, a.ApplicationID, a.PackageID, adc.NotificationID
FROM deviceApplication.ApplicationDeviceCredential adc
LEFT JOIN
deviceApplication.Application a
ON adc.ApplicationID = a.ApplicationIDWHERE DeviceID =
  1. This statement will show the serial number associated with the APNs certificate. This will assist if you need to relay this information to Apple to determine if they have a corrupt certificate where AirWatch is unable to continue troubleshooting. Simply input the name of the Location Group where the APNs Certificate is uploaded.
SELECT lg.Name, c.SerialNumber from dbo.Certificate c
inner join deviceApplication.Application a
on ProductionCertificateID = CertificateID
inner join dbo.LocationGroup lg
on lg.MDMAppleAPplicationID = a.ApplicationID
where lg.Name like '%__%'
  1. This statement will show you all the APNs certificates that have been uploaded to the console at or below the LG provided. You simply need to input the group ID found in the first query.
SELECT c.SerialNumber,c.SubjectName, c.NotBefore, c.NotAfter, ags.*
FROM dbo.ApnsGenerationStatus ags (NOLOCK)
JOIN dbo.Certificate c (NOLOCK)
ON c.CertificateID = ags.IssuedCertID
WHERE ags.LocationGroupID IN (###)
ORDER BY CreatedDate DESC

PushMagic Token

In Database:

SELECT *
FROM dbo.AppleDeviceEx
WHERE DeviceID = ###

APNs in logs

Console (CN) server logs:

  • MessengingServiceLog (C:\AirWatch → Logs → Services) Search for:
  • gateway.push.apple.com
  • APNs token
  • PushMagic token

Device Command Queues

Device operation sequence

A. AirWatch server sends out a PUSH notifications to device:

  • AirWatch prepares command, stores in command queue (SQL)
  • AirWatch sends check-in request to Messaging Service, one of the following:
    1. Google Cloud Messaging: formerly C2DM (Cloud 2 Device Messaging) deprecated 2012 →  Google Cloud Messaging (GCM) deprecated April 2019 → Firebase Cloud Messaging (FCM)
    2. Internal message bus for Android & Windows devices: AirWatch Cloud Messenger (AWCM)
    3. Message bus for iOS: Apple Push Notification Service (APNs)
  • Messaging Service relays check-in request to managed device
  • Managed device checks into MDM server
  • MDM Server delivers commands to device, one-by-one

B. Device performs the commands; C. Device contacts AirWatch server to report the result of the last commands and request new commands, if any.

Command Queue

Every pending command is in SQL database:

SELECT * FROM deviceCommandQueue.DeviceQueue;

Every processed command is in SQL database:

SELECT * FROM deviceCommandQueue.DeviceQueueAudit;

Commands description is in SQL database:

SELECT * FROM deviceCommandQueue.DeviceQueueCommand;

Command statuses in SQL:

SELECT * FROM deviceCommandQueue.DeviceQueueStatus;

Basic command types & statuses…

Device Management commands

  • Lock device
  • Query device
  • Send Message to device

Application commands

  • Install
  • Removal
  • Settings

Profile commands

  • Install
  • Removal

Normal Command Status Flow 1 = Queued 2 = Pending 3 = Processed 7 = Held (if batching is enabled)

Troubleshooting Command Logs

Device Services (DS) server (front-end communication with managed device) logs:

  • DeviceServicesLogs (C:\AirWatch → Logs → DeviceServices)
  • InterrogatorQueueService (C:\AirWatch → Logs → Services)

Console (CN) server (communication with external services: APNs, GCM/FCM, AWCM, ACC etc.) logs:

  • MessengingServiceLog (C:\AirWatch → Logs → Services)
  • BulkProcessingServiceLog (C:\AirWatch → Logs → Services)
  • SchedulerServiceLog (C:\AirWatch → Logs → Services)

Targeted logging: AirWatch console → Device Details → More → Targeted Logging

Device Status

Workspace ONE Registered – Unmanaged WS1 device (MAM Only) ManagedBy column in dbo.Device = 2 EnrollmentCategoryID column in dbo.DeviceExtendedProperties = 1 Query:

select d.ManagedBy, dep.EnrollmentCategoryID, d.DeviceID from dbo.Device d INNER JOIN
dbo.DeviceExtendedProperties dep
ON
d.DeviceID = dep.DeviceID
where d.ManagedBy = 2
AND dep.EnrollmentCategoryID = 1

Workspace ONE Managed – MDM on the device, but did not enroll through agent (Adaptive Mgmt) ManagedBy column in dbo.Device = 1 EnrollmentCategoryID column in dbo.DeviceExtendedProperties = 1 Query:

select d.ManagedBy, dep.EnrollmentCategoryID, d.DeviceID from dbo.Device d INNER JOIN
dbo.DeviceExtendedProperties dep
ON
d.DeviceID = dep.DeviceID
where d.ManagedBy = 1
AND dep.EnrollmentCategoryID = 1

Workspace ONE Managed – MDM on the device, but did not enroll through agent (Direct Enrollment) ManagedBy column in dbo.Device = 1 EnrollmentCategoryID column in dbo.DeviceExtendedProperties = 3 Query:

select d.ManagedBy, dep.EnrollmentCategoryID, d.DeviceID from dbo.Device d INNER JOIN
dbo.DeviceExtendedProperties dep
ON
d.DeviceID = dep.DeviceID
where d.ManagedBy = 1
AND dep.EnrollmentCategoryID = 3

Agent Enrollment with Workspace ONE – Workspace ONE as an app catalog, pushed as a managed app. ManagedBy column in dbo.Device = 1 EnrollmentCategoryID column in dbo.DeviceExtendedProperties = NULL or 0 Query:

select d.ManagedBy, dep.EnrollmentCategoryID, d.DeviceID from dbo.Device d INNER JOIN
dbo.DeviceExtendedProperties dep
ON
d.DeviceID = dep.DeviceID
where d.ManagedBy = 1
AND dep.EnrollmentCategoryID IN (NULL, 0)

EnrollmentCategoryID is mapped to following enum:

public enum EnrollmentCategory
{
    Unknown = 0,
    VmWorkspace = 1,
    Offline = 2,
    WorkSpaceOneDirectEnrollment = 3
}

ManagedBy is mapped to following enum:

public enum DeviceManagedBy
{
    /// <summary>
    /// Unknown value
    /// </summary>
 
    Unknown = 0,
 
    /// <summary>
    /// Managed By MDM
    /// </summary>
 
    MDM = 1,
 
    /// <summary>
    /// Managed by Workspace (newer terminology is 'Container')
    /// </summary>
 
    Workspace = 2,
 
    /// <summary>
    /// Managed by Application Catalog (Web MAM enrollment)
    /// </summary>
 
    AppCatalog = 3,
 
    /// <summary>
    /// Managed by Application
    /// </summary>
 
    AppLevel = 4,
 
    /// <summary>
    /// managed by VmWorkspace
    /// </summary>
 
    VmWorkspace = 5,
 
    /// <summary>
    /// managed by Offline (Enrolled Offline)
    /// </summary>
 
    Offline = 6
}

GPS History Table

  • GPS Poll Time Interval - X mins (configured in AirWatch Console, for example, in Android Agent settings)
  • Data Transmit Interval - Y mins

Privacy settings for “GPS Data” needs to be set to Collect and Display for required device Ownership type.

The samples which are transmitted by the Agent as per the Y interval are all stored in the database in the dbo.GPSLog table. To see if any samples have been reported for your specific device, use the following query:

SELECT * from dbo.LogSample (nolock) ls
inner join dbo.GPSLog (nolock) gl
on ls.logsampleID = gl.logsampleid
WHERE deviceid = ####

Under device details > Location tab on console, not all location data points will be reported:

  • Consecutive duplicate samples will not be reflected
    Note

    Consecutive samples which are not at least 100 ft. apart will not be listed corresponding to the particular time-stamp as can be seen in the DB.

Insert GPS History directly

Copy GPS coordinates from one device to another:

select * from device where Name like '%User01%' --deviceID = 7
select * from device where Name like '%User02%' --deviceID = 52
  
Insert dbo.LogSample ([DeviceUid] ,     [IpAddress] ,[SampleTime],[TransmitTime] ,[DeviceID] )
select      
--[LogSampleID] [int] IDENTITY(1,1) NOT NULL,
             [DeviceUid] ,[IpAddress] ,[SampleTime],[TransmitTime] ,
             52--[DeviceID] ,
       from dbo.LogSample  ls where deviceId = 7 and LogSampleID =8
  
  
select *  from dbo.LogSample  ls where deviceId = 52 --LogSampleID =9
  
Insert dbo.GPSLog ( [LogSampleID] ,[SampleTime],[Latitude] ,[Longitude] ,[Elevation] ,[Speed] ,
[Note] ,[LatitudeInternal] ,[LongitudeInternal] ,[ElevationInternal] ,       [SpeedInternal]
--,    [RowVersion]
                    )
       select 9 ,--[LogSampleID] ,      
             [SampleTime],[Latitude] ,[Longitude] ,  [Elevation] ,[Speed] ,[Note] ,[LatitudeInternal] ,[LongitudeInternal] ,     [ElevationInternal] ,     
[SpeedInternal] --, [RowVersion]
       from dbo.GPSLog  gl where LogSampleID in (select  LogSampleID from dbo.LogSample  ls where deviceId = 7and LogSampleID =8)

Memcached Activation

Activate usage of Memcached

DECLARE @myid uniqueidentifier
DECLARE @GroupOverrideID int
DECLARE @userID int
DECLARE @CacheEndpoint varchar(255)
DECLARE @EnabledOverrideID int
DECLARE @SolutionOverrideID int
DECLARE @EndpointOverrideID int
SET @myid = NEWID()
SET @userID = 52
SET @CacheEndpoint = '[
  {
    "name" : "mc_node1",
    "address" : "192.168.1.1",
    "port" : "11211"
  },
  {
    "name" : "mc_node2",
    "address" : "192.168.1.2",
    "port" : "11211"
  }
]
'
EXEC SystemCodeGroupOverride_Save @GroupOverrideID, 132, 7, NULL, 1, 1, 1, @UserID
IF (@GroupOverrideID IS NULL)
BEGIN
    SELECT TOP (1) @GroupOverrideID =  scgo.SystemCodeGroupOverrideID
    FROM dbo.SystemCodeGroupOverride scgo
    WHERE [SystemCodeGroupID] = 132
    AND LocationGroupID=7
    AND LocationID IS NULL
END
EXEC SystemCodeOverride_Save @EnabledOverrideID, 877, @GroupOverrideID, 'True', @userID
EXEC SystemCodeOverride_Save @SolutionOverrideID, 4147, @GroupOverrideID, '0', @userID
EXEC SystemCodeOverride_Save @EndpointOverrideID, 829, @GroupOverrideID, @CacheEndpoint, @userID
UPDATE dbo.DatabaseVersion set buildkey = CONVERT(varchar(255), @myid)
DELETE from dbo.SystemCodeOverride where SystemCodeid in (829,877,4147)
DELETE from dbo.SystemCodeGroupOverride where SystemCodeGroupID = 132

Check Memcached in SQL

SELECT * from dbo.SystemCodeOverride where SystemCodeID IN (829 , 827, 877, 4147)

Query Internal Apps

Check app versions

Find out the list and version of applications installed on the device by running the following SQL query:

select * from interrogator.applicationlist al
inner join interrogator.application a
on a.applicationid = al.applicationid
where al.deviceid = #affecteddeviceid

How to verify if devices have installed the latest provisioning profile for an internal application?

Search for devices who are reporting the application as installed, but do not have the updated provisioning profile installed

SELECT * FROM interrogator.ApplicationList (NOLOCK)
WHERE DeviceID in (
    SELECT iaa1.DeviceID From deviceApplication.InternalAppAssignment (NOLOCK) iaa1
    WHERE InternalAppID = {INTERNAL_APP_ID}
    AND iaa1.DeviceId NOT IN (
        SELECT iaa.DeviceID FROM deviceApplication.InternalAppAssignment (NOLOCK) iaa
        JOIN deviceProfile.DeviceProfileDevicePool dpdp
        ON iaa.DeviceID = dpdp.DeviceID
        WHERE iaa.InternalAppID = {INTERNAL_APP_ID}
        AND dpdp.DeviceProfileID = {DEVICE_PROFILE_ID}
    )
)
AND ApplicationID = {APPLICATION_ID}
AND IsInstalled = 1

The logic behind this script is:

  • Check for devices reporting the provisioning profile as installed (deviceProfile.DeviceProfileDevicePool)
  • Check against devices that are supposed to be assigned this application (deviceApplication.InternalAppAssignment)
  • Check against devices that are reporting the application as installed (interrogator.ApplicationList)

To find the variables in this query:

  • INTERNAL_APP_ID - This is found in the deviceApplication.Application database table, or in the URL when viewing the summary page for the internal application.
  • DEVICE_PROFILE_ID - This is found in the deviceApplication.Application table as the ProvisioningDeviceProfileID.
  • APPLICATION_ID - This is found in the interrogator.Application table as the ApplicationID.  To find this value you can use the following query:
SELECT ia.* FROM interrogator.Application (NOLOCK) ia
JOIN DeviceApplication.Application daa
    ON ia.Identifier = daa.PackageID
    AND ia.VersionHash = daa.VersionHash
WHERE daa.ApplicationID = {INTERNAL_APP_ID}

Verify if commands are in the command queue to update the provisioning profile

The following query can be used to identify if, for devices that have not yet installed the updated profile, commands have been queued to install it on the next device check in:

SELECT * FROM DeviceCommandQueue.DeviceQueue (nolock) dq
JOIN deviceProfile.DeviceProfileVersion dpv
    ON dq.DeviceProfileVersionID = dpv.DeviceProfileVersionID
WHERE dq.CommandID = 13 --CommandID for InstallProvisioningProfile
AND dpv.DeviceProfileID = {DEVICE_PROFILE_ID}

Search for application upload events

The following query is generated by HUB -> Reports and Analytics -> Events -> Console Events in the console, but the console only searches for Last Month, while manual procedure allows to search further back

exec eventLog.EventLog_Search @LocationGroupID=571,@SeverityID=NULL,@eventGroupTypeID=2,@Module=N'Apps',@StartDateTime='2018-06-01 15:32:34.843',@EndDateTime='2018-07-27 15:33:34.843',
@EventDirectionID=NULL,@EventTypeID=0,@EventActionID=0,@StartRowIndex=50,@MaximumRows=1000,@SortExpression=NULL,@SortAscending=1,@SearchText=NULL

Smart Groups Queries

SQL queries for Smart Groups

List all the smart groups present in that particular environment:

select * from smartgroup.smartGroup

Current version of the smart group being used can be found in the table generated by the query below:

select * from smartgroup.SmartGroupVersion where sgdm.SmartGroupId = ##

Details of devices associated with a smart group:

select * from SmartGroup.SmartGroupDeviceMap sgdm Inner Join smartgroup.SmartGroupVersion sgv on sgdm.smartGroupId = sgv.smartGroupID
and sgdm.SmartGroupVersion = sgv.SmartGroupVersion where sgdm.SmartGroupId = ##

Relationship between smart group and entity can be found from the table generated by the query mentioned below:

select * from smartGroup.AWEntitySmartGroupAssignmentMap where SmartGroupId = ##

The device ID of device to which the entity is assigned can be obtained from the tables generated by the queries mentioned below:

  • Profile
  • InternalApp
  • ExternalApp
select * from deviceProfile.ProfileAssignment where ProfileID = ##
select * from [deviceApplication].[InternalAppAssignment] where InternalAppID = ##
select * from [deviceApplication].[ExternalAppAssignment] where ExternalAppID = ##

Devices associated with a smart group can be seen in the table generated by the query mentioned below:

select batchEvaluateLogic from smartGroup.smartGroupRuleLogic where smartGroupOverrideID = ##
Note

Apps and books are together considered as an app in SQL.

Troubleshooting Smart Groups

Warning

Do not name a Smart Group with the same name as an existing User Group - this leads to Smart Group being “locked” from deletion

Problem 1:

  • After assigning a smart group to the application and selecting Save & Publish , the app assignment in application grid shows 0/0/0 even though the View Device assignment shows all devices in smart group.

Go to Deployment tab and check the deployment time and if possible change it to 12.00 AM same day. If the time is already set at 12.00 AM, check the admin user’s time zone and compare it with OG time zone. Also check if app wrapping is enabled and whether it is still in progress or not completed.

Problem 2:

  • When a smart group is attempted to be deleted, the following error appears: " Deletion is unsuccessful. This smart group is currently being used in assignment. Please remove the smart group from the assignment, and try again."

Check if the smart group is currently assigned to any app, profiles, compliance etc. Check if there is any user group which is having the same name as the smart group which the smart group uses.

Problem 3:

  • Certain apps are not being shown in App Catalog for some users.

Create a new smart group which contains these users. After that edit the app and add this smart group in exclusion list.

SQL Recovery

General

VMware AirWatch Installation Guide (9.2), page 17 recommends Recovery Model = Full.

Also, in AirWatch SQL FAQ we see a comment: When trying to login to the AirWatch console or perform actions within the console you may receive the error message “The transaction log for database ‘AirWatch’ is full.”

This typically means that there is no available space on your SQL server. The common cause for this is backups not being deleted even though newer backups are being done, or lack of transaction log backups. To fix this issue you should first consult your local database admin and make them aware of the issue. The fix that we recommend is to perform a full database backup and then switch the database to simple recovery mode. Your database admin should be familiar with this and know how to perform these actions.

Shrinking the Log File When Disk Space is Full

The log file cannot be shrunk until it is truncated and free space is available. If a log file has grown to the point that it is full or consuming all available disk space, truncate it immediately in order to restore normal database operations. (If the log file has reached the maximum size database property and free disk space is still available, increase the value of maximum size property or set it to ‘unlimited’. A shrink operation should not be required in this case.)

To truncate a log file immediately, set the recovery model to Simple then shrink log file. The following commands are examples of how to do this. They may require editing to tailor them to the customer’s environment.

-- look up the name of the log file
 SELECT name as log_file_name FROM sys.database_files WHERE type_desc='LOG'
ALTER DATABASE [AirWatch] SET RECOVERY SIMPLE; 
DBCC SHRINKFILE ('AirWatch_log',0,TRUNCATEONLY);

-- replace 'log_file_name' with the actual name of the log file
 ALTER DATABASE [AirWatch] MODIFY FILE ( NAME = AirWatch_log, SIZE = 10GB , FILEGROWTH = 128MB );
ALTER DATABASE [AirWatch] SET RECOVERY FULL;

-- Full backup
 BACKUP DATABASE [AirWatch] TO DISK = 'E:\MSSQL\Backup\AirWatch_20160123_full.bak' WITH STATS; 

Setting the recovery model to Simple erases all of the transaction log records. For this reason, it is essential to create a full backup of the database immediately afterward the shrink procedure to ensure full data recoverability in the event of a database failure.

Preventative Measures

Make sure that the regular database and transaction log backups are scheduled for the AirWatch database. There are various methods: SQL scripts, third party tools, or SQL Server maintenance plans, which can be used.

Full Recovery Mode caveats

Generally the reason why DB log file is large is because the required DB maintenance has not been implemented. Typically, the size of the transaction log file stabilizes when it can hold the maximum number of transactions that can occur between transaction log truncations that are triggered by either checkpoints or transaction log backups.

What Scenarios can cause the Log to Keep Growing?
There are many reasons, but usually these reasons are of the following two patterns

Recovery process overview… In SQL Server, there are three recovery models - Full, Bulk-Logged and Simple. We’ll ignore Bulk-Logged hybrid model: most people who are in this model are there for a reason and understand recovery models. The two we care about are Simple and Full.

Before we talk about Recovery Models - Let’s talk about recovery in general.
The transaction log file is there for crash/restart recovery. For the rolling forward and rolling back of work that was either done (rolling forward/redo) before a crash or restart and the work that was started but not finished after a crash or restart (rolling back/undo). It is the job of the transaction log to see that a transaction started but never finished (rolled back or crash/restart happened before the transaction committed). In that situation It is the log’s job to say “hey.. this never really finished, let’s roll it back” during recovery. It is also the log’s job to see that you did finish something and that your client application was told it was finished (even if it hadn’t yet hardened to your data file) and say “Hey.. this really happened, let’s roll it forward, let’s make it like the applications think it was” after a restart. Now there is more but that is the main purpose.

The other purpose for a transaction log file is to be able to give us the ability to recover to a point in time due to an “oops” in a database or to guarantee a recovery point in the event of a hardware failure involving the data and/or log files of a database. If this transaction log contains the records of transactions that have been started and finished for recovery, SQL Server can and does then use this information to get a database to where it was before an issue happened. But that isn’t always an available option for us. For that to work we have to have our database in the right recovery model, and we have to take log backups.

Simple Recovery Model

In this model, you are telling SQL Server - I am fine with you using your transaction log file for crash and restart recovery (You really have no choice there.. Look up ACID properties and that should make sense quickly), but once you no longer need it for that crash/restart recovery purpose, go ahead and reuse the log file.

SQL Server listens to this request in Simple Recovery and it only keeps the information it needs to do crash/restart recovery. Once SQL Server is sure it can recover because data is hardened to the data file (more or less), the data that has been hardened is no longer necessary in the log and is marked for truncation - which means it gets re-used.

Full Recovery Model

With Full Recovery, you are telling SQL Server that you want to be able to recover to a specific point in time, as long as your log file is available, or to a specific point in time that is covered by a log backup. In this case when SQL Server reaches the point where it would be safe to truncate the log file in Simple Recovery Model, it will not do that. Instead It lets the log file continue to grow and will allow it to keep growing, until you take a log backup (or run out of space on your log file drive) under normal circumstances.

If you just switch into Full Recovery mode, but never take an initial Full Backup, SQL Server will not honor your request to be in Full Recovery model. Your transaction log will continue to operate as it has in simple until you switch to Full Recovery Model AND Take your first Full Backup.

So, that’s the most common reason for uncontrolled log growth: Being in Full Recovery mode without having any log backups.

Upgrade Rollback

The rollback process contains two phases.  First, a backup of the database (that was taken prior to the upgrade) is restored and configured.  Next, either backups of any application servers (Console, Device Services, etc) are applied, or the previous version of the AirWatch application is simply reinstalled on those servers after uninstalling the current version.

Restoring a database backup

The following steps can be used to restore a database backup to an existing database server and apply the necessary configuration changes.  This process assumes that a backup has been created prior to any upgrades, when the environment was fully functional.

  • Before working with the database, make sure that, for any AirWatch application servers (Console, Device Services, etc),  all AirWatch services are stopped.  Additionally, stop the World Wide Publishing Service.  Finally, make sure that IIS is stopped as well.
  • Open Microsoft SQL Server Management Studio, right-click on Databases and select Restore Database.
  • Under the General tab on the left and within the Source for restore section, select From device, then select ‘…’ button.
  • From the Specify Backup page, select Add. Locate the backup, select it, and click OK. The database backup will display on the Specify Backup page. Click OK.
  • Select the Restore check box.
  • Under Destination for restore, select the To database drop-down list and select the AirWatch database name. Note: This should be the last database in the list, in the event you have multiple backups all named AirWatch and are unsure of which one to select. Click OK to start the database restoration.

On the old database: Next you need to note the user permissions of the old database’s AirWatch SQL Service Account. To do this:

  • Open Microsoft SQL Server Management Studio
  • Navigate to Security > Logins > to locate your DB User in the Object Explorer, and then right-click and choose Properties.
  • Navigate to the Server Roles tab. Write down the roles listed
  • Select User Mapping. Write down the user mappings listed and the role membership permissions
Warning

Take note of all of the role memberships for AirWatch, master, model, msdb, and tempdb.

On the new database:

  • Delete the AirWatch SQL Service Account, which was created when you restored.
  • Create the new AirWatch SQL Service Account. To do this navigate to Security > Logins,  right-click, and select New Login.
Warning

This procedure is only for the main AirWatch SQL Service Account If you had any other custom-created SQL accounts you will need to perform this procedure for each of them.

  •     Enter the following:

A.   Select whether to use Windows or SQL Server authentication. For SQL Server authentication, enter your user credentials. Note: The username needs to exactly match the username of the old database.

B.   Uncheck Enforce password policy.

C.   Select the AirWatch database as the Default database.

D.   For Server Role, enter the roles you noted previously.

E.   For User Mapping, enter the user mappings and permissions you noted previously. IMPORTANT: This should include all of the permissions that you copied for AirWatch, master, model, msdb, and tempdb.

Next you need to migrate any AirWatch-related jobs.

Warning

The steps below are for the purge job, but any other AirWatch-related jobs need to be similarly migrated using the procedure below

On the old database:

  • Navigate to SQL Server Agent > Jobs, right-click <AirWatch_DB> - Purge Expired Sample Data, and select Script Job as > CREATE To > New Query Editor Window.
  • Save as the query.
  • Transfer the query to your new database.
  • On your new database: Execute the query.
Warning

To reiterate, any other AirWatch-related jobs need to be similarly migrated using the procedure above

On the new database: Perform a test query. For example, one for device count, to ensure proper functioning. To do this:

  • Right-click on the AirWatch database under Databases and select New Query.
  • Enter the query as shown below.

  • Select Execute.

Rename the old database, for example, to AirWatch_OLD. To kill all connections and rename the database, run the following script, replacing ‘AirWatch’ with the name of your old AirWatch DB and AirWatch_OLD with what you would like to rename the old database to.

Restoring a previous version of the application

With the database backup restored, the next step is to restore the proper version of the application.  Ideally, there will be a snapshot or backup of each application server from the same time as the database backup.  In this case, simply restore these backups in order to restore functionality.

However, if there are no available snapshots or backups of the servers, then the previous version of the AirWatch software must be reinstalled.

In these cases, identify which application servers have an updated version of the application (this will likely be all application servers, but may only be a subset of them).  For each of these, ensure that a copy of the AirWatch installer for the correct version has been installed on the server. Uninstall the current version of the software through Computer > Uninstall or change a program by selecting the AirWatch application.  With this uninstalled, open previous version of the AirWatch installer and proceed as normal.  When configuring the database connection, ensure the configurations used match those of the restored database.

Finally, when both the database and application has been restored properly, ensure that IIS and all AirWatch services (as well as the World Wide Web Publishing service) are properly started.

Changing the database connection string

In some cases, it may be necessary to change the database connection string of an application server without fully reinstalling the software.  For example, if a database migration has occurred, the name of the database may have simply changed.  Perform the following steps to update the database connection string on each AirWatch application server.  Note that this must be done on every application server so that they are pointing to the new database.

Note
  • For deployments with dedicated API and AWCM servers: Dedicated API and AWCM servers are considered application servers, similar to the AirWatch Console and Device Services. You should therefore perform the steps below regarding re-pointing app servers on these servers if you have dedicated servers for these components.
  • EIS, SEG, ACC/ESC are considered auxiliary components and you do not need to perform this step for these components.

Steps:

  • Navigate to AirWatch Root Folder on the application server.
  • Navigate to AirWatch X.X\Supplemental Software\Tools\UpdateSQLServerInfo.
  • Launch UpdateSQLServerInfo.exe.
  • Update the Server Hostname, Database Name, Username and Password. If Windows authentication is being used, the password field may be blank.
  • Make sure to restart IIS and all AirWatch services on each server after updating the SQL connection string.

Useful SQL Queries

SQL Database Health

Index Fragmentation Audit

This query provides you with the index fragmentation % for every table in the DB.

/**************************************************************
   You can use the following script to determine index 
   fragmentation by table. This can help to determine 
   that the database is causing performace problems.
**************************************************************/ 

SELECT OBJECT_NAME(object_id), index_id, index_type_desc, index_level, avg_fragmentation_in_percent, avg_Page_space_used_in_percent, page_count 
FROM sys.dm_db_index_physical_stats(DB_ID(N'AirWatch'), null, null, null, 'SAMPLED')
ORDER BY avg_fragmentation_in_percent DESC

Table Size Audit

This query will provide physical sizing information of all the tables in the database.

/**************************************************************
    This query can help you determine what table is taking
    up the most disk space and potentially what tables have
    too many rows.
**************************************************************/ 

--If the temp table exisits drop temp table
IF EXISTS ( SELECT * FROM sys.objects 
     WHERE object_id = OBJECT_ID(N'#Sizes') 
     AND type in (N'U') ) 
     BEGIN 
     DROP TABLE #Sizes; 
     END 

--Create temp table, #Sizes 
CREATE TABLE #Sizes 
( 
--Table name 
     table_name nvarchar(255), 
--Number of rows 
     table_rows char(11),
--Physical space table is using
     table_reserved varchar(18),
--Phyiscal space table data is using
     table_data varchar(18),
--Physical space idexes are using
     table_index_size varchar(18),
--Physical space reserved
     table_unused varchar(18)
)

EXEC sp_MSforeachtable @command1='INSERT #Sizes (table_name, table_rows, table_reserved,
table_data, table_index_size, table_unused) EXEC sp_spaceused ''?'''
--This query orders the results by actual phyisical table size
SELECT * FROM #Sizes ORDER BY CAST ( SUBSTRING (table_data, 0, LEN(table_data) - 2) AS InT) DESC
--This query orders the results by row count
--SELECT * FROM #Sizes ORDER BY CAST (table_rows AS int) DESC

Table Row Count Only

A more efficient script to get table row counts.

/**************************************************************
    This is a more efficient way to get Row Counts
    but will not include any Physical Sizing data
   
**************************************************************/ 

SELECT 
     sc.name +'.'+ ta.name TableName
     , SUM(pa.rows) RowCnt
FROM 
     sys.tables ta
     INNER JOIN sys.partitions pa
          INNER JOIN sys.schemas sc
          ON ta.schema_id = sc.schema_id
WHERE 
     ta.is_ms_shipped = 0 
      AND pa.index_id IN (1,0)
GROUP BY 
     sc.name
     , ta.name
ORDER BY 
     SUM(pa.rows) DESC;

Database IO Stalls

You can use this query to see which queries are causing IO stalls.

/**************************************************************
   The table valued dynamic management function, 
   sys.dm_io_virtual_file_stats provides a breakdown of SQL 
   Server reads, writes, and io_stalls for a particular
   database or transaction log file. IO_stalls is the total 
   cumulative time, in milliseconds, that users waited for
   I/O to be completed on the file since the last restart    of SQL Server. 
**************************************************************/ 

SELECT
     DB_NAME(fs.database_id) AS [DB Name]
     , fs.file_id
     , mf.physical_name
     , io_stall_read_ms
     , num_of_reads
     , CAST(io_stall_read_ms / ( 1.0 + num_of_reads ) AS NUMERIC(10 , 1)) AS 'avg_read_stall_ms'
     , io_stall_write_ms
     , num_of_writes
     , CAST(io_stall_write_ms / ( 1.0 + num_of_writes ) AS NUMERIC(10 , 1)) AS 'avg_write_stall_ms'
     , io_stall_read_ms + io_stall_write_ms AS io_stalls
     , num_of_reads + num_of_writes AS total_io
     , CAST(( io_stall_read_ms + io_stall_write_ms ) / ( 1.0 + num_of_reads
          + num_of_writes ) AS NUMERIC(10 ,
          1)) AS 'avg_io_stall_ms'
FROM
     sys.dm_io_virtual_file_stats(NULL , NULL) AS fs
INNER JOIN sys.master_files AS mf
          ON fs.database_id = mf.database_id
          AND fs.[file_id] = mf.[file_id]
ORDER BY
     avg_io_stall_ms DESC ;
GO

Identify Expensive Operations

/**************************************************************
   This query provides you with operations that are expensive
   from a database standpoint. This query is useful in
   determining what is causing performance problems on a server
**************************************************************/ 

SELECT TOP 25
     DB_NAME(qp.[dbid]) AS dbname
     , qp.[dbid]
     , qp.objectid
     , qp.number 
     --, qp.query_plan 
     --the query plan can be *very* useful; enable if desired 
     , qt.[text]
     , SUBSTRING(qt.[text] , 
          ( qs.statement_start_offset / 2 ) + 1 ,
          ( ( CASE statement_end_offset
          WHEN -1 THEN DATALENGTH(qt.text)
          ELSE qs.statement_end_offset
     END - qs.statement_start_offset ) / 2 ) + 1) 
         AS statement_text
     , qs.creation_time
     , qs.last_execution_time
     , qs.execution_count
     , qs.total_worker_time / qs.execution_count 
         AS avg_worker_time
     , qs.total_physical_reads / qs.execution_count 
         AS avg_physical_reads
     , qs.total_logical_reads / qs.execution_count 
         AS avg_logical_reads
     , qs.total_logical_writes / qs.execution_count 
         AS avg_logical_writes
     , qs.total_elapsed_time / qs.execution_count 
         AS avg_elapsed_time
     , qs.total_clr_time / qs.execution_count
     nbsp;   AS avg_clr_time
     --, qs.total_worker_time 
     --, qs.last_worker_time 
     --, qs.min_worker_time 
     --, qs.max_worker_time 
     , qs.total_physical_reads
     , qs.last_physical_reads
     , qs.min_physical_reads
     , qs.max_physical_reads 
     --, qs.total_logical_reads 
     --, qs.last_logical_reads 
     --, qs.min_logical_reads 
     --, qs.max_logical_reads 
     --, qs.total_logical_writes 
     --, qs.last_logical_writes 
     --, qs.min_logical_writes 
     --, qs.max_logical_writes 
     --, qs.total_elapsed_time 
     --, qs.last_elapsed_time 
     --, qs.min_elapsed_time 
     --, qs.max_elapsed_time
     --, qs.total_clr_time 
     --, qs.last_clr_time 
     --, qs.min_clr_time 
     --, qs.max_clr_time 
     --, qs.[sql_handle] 
     --, qs.statement_start_offset 
     --, qs.statement_end_offset 
     --, qs.plan_generation_num 
     --, qp.encrypted 
FROM
     sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(qs.[sql_handle]) AS qt
     --sample WHERE 
WHERE
     last_execution_time > '20120912 12:15'
     AND creation_time > '20130101'
     AND execution_count > 10
     --AND SUBSTRING(qt.text, (qs.statement_start_offset/2) + 1,
     --((CASE statement_end_offset 
     --WHEN -1 THEN DATALENGTH(qt.text)
     --ELSE qs.statement_end_offset END 
     -- - qs.statement_start_offset)/2) 
     -- + 1)
     -- LIKE '%MyText%'

     --sample ORDER BY
     --ORDER BY qs.execution_count DESC --Frequency
     --ORDER BY qs.total_worker_time DESC --CPU
     --ORDER BY avg_worker_time DESC --CPU
     --ORDER BY qs.total_elapsed_time DESC --Durn
     --ORDER BY qs.total_logical_reads DESC --Reads 
     --ORDER BY qs.total_logical_writes DESC --Writes
     --ORDER BY qs.total_physical_reads DESC --PhysicalReads 
     --ORDER BY avg_worker_time DESC --AvgCPU
     --ORDER BY avg_elapsed_time DESC --AvgDurn 
     --ORDER BY avg_logical_reads DESC --AvgReads
     --ORDER BY avg_logical_writes DESC --AvgWrites
ORDER BY
     avg_physical_reads DESC --AvgPhysicalReads

General SQL Queries

Table search by column name

This query allows you to see what tables / procedures have a specified column name in them.

/**************************************************************
   Example(s) of common column names:
   DeviceId, LocationGroupId, ApplicationId, ProfileId, 
   CoreUserId
**************************************************************/ 

SELECT * FROM sysobjects WHERE id IN 
      (SELECT id FROM syscolumns WHERE name LIKE '%ColumnName%')

SP_WHO2 Advanced Query

This allows you to filter on SP_WHO2, which helps when backing up and restoring the AirWatch database.

/**************************************************************  
   This query may look complex but can really  
   narrow down if something is connected to   
   AirWatch or not. When you are upgrading  
   or restoring a database you need to ensure  
   that nothing is locking the databse. **************************************************************/   
CREATE TABLE #sp_who2(   
     SPID INT,   
     Status VARCHAR(1000) NULL,   
     Login SYSNAME NULL,   
     HostName SYSNAME NULL,   
     BlkBy SYSNAME NULL,   
     DBName SYSNAME NULL,   
     Command VARCHAR(1000) NULL,   
     CPUTime INT NULL,   
     DiskIO INT NULL,   
     LastBatch VARCHAR(1000) NULL,   
     ProgramName VARCHAR(1000) NULL,   
     SPID2 INT   
)   
  
INSERT INTO #sp_who2 EXEC sp_who2   
  
SELECT *   
FROM #sp_who2   
WHERE DBName LIKE '%AirWatch%'  
GO   
  
DROP TABLE #sp_who2   
GO

Get all devices from Location Group

This query can return all devices under one locationgroup tree. This is an especially helpful query when used with other queries.

/**************************************************************
   This script provides all devices residing under
   the parent location group. You can combine this
   query with other queries by using the WHERE column
   IN (SELECT query) filter (this script uses the
   same filter to filter the location groups)
**************************************************************/ 

SELECT *
FROM Device d (nolock)
INNER JOIN Location l (nolock)
ON l.LocationId = d.LocationId
INNER JOIN LocationGroup lg (nolock)
lg.DefaultLocationId = l.LocationId
WHERE lg.LocationGroupID IN 
(
   /*****************************************************
      The below sub query provides all children
      Location Groups under one Parent. This can 
      also be useful with other queries.
     ***************************************************/ 

   SELECT lgf.ChildLocationGroupID
   FROM LocationGroup lg (nolock)
   INNER JOIN LocationGroupFlat lgf (nolock)
   ON lgf.ParentLocationGroupID = lg.LocationGroupID
   WHERE lg.Name LIKE '%Customers LG%'
)

This query allows you to search the event log. This is imperitive since the event log often times out from the console.

/**************************************************************  
   This script provides you with a list of modules in the  
   event log. These can be used to filter the following  
   query.  
**************************************************************/   
SELECT DISTINCT el.Module   
FROM eventLog.EventLog el (nolock)   
  
/**************************************************************  
   This query will select information from the event log   
   and allow you to filter on Modules. Modules provide you  
   with context of the event that occured. The Name is   
   the actual name of the event that occured. This will   
   only show you the last 30 days. You can decrease this   
   number to improve performance.  
     
   You can also filter on the LocationGroupID if you know   
   the location group name. Keep in mind that some modules   
   only report at Global.  
  
   The Username is the Admin user who performed the task.   
   sysadmin is the system user for running stored procedures   
   however some modules (like the device module) show   
   sysadmin even if a user performed the action.  
**************************************************************/  
  
SELECT cu.UserName, el.Module, e.Name, el.*  
FROM eventLog.EventLog el (nolock)  
INNER JOIN eventLog.Event e (nolock)  
ON e.EventId = el.EventId  
INNER JOIN CoreUser cu (nolock)  
ON cu.CoreUserId = el.ActionBy  
WHERE el.CreatedOn > DATEADD(DAY, -30, GETUTCDATE())  
AND el.Module LIKE 'Dashboard'  
--AND LocationGroupID IN (SELECT LocationGroupID   
--FROM LocationGroup WHERE Name LIKE '%AirWatch%')

Role compare script

This script shows you two roles side by side for comparison.

/**************************************************************
   Update the values in @Role1 and @Role2
   to compare two roles. If you need to find
   why a custom role is missing use the next
   script.
**************************************************************/ 

DECLARE @Role1 AS nvarchar(50);
DECLARE @Role2 AS nvarchar(50);
SET @Role1 = 'AirWatch Administrator';
SET @Role2 = 'System Administrator';

SELECT re.ResourceID, c.Name AS 'Module', re.Name, m1.Allow AS 'Role1 Allowed', m2.Allow AS 'Role2 Allowed'
FROM Resource re 
INNER JOIN Category c (nolock)
ON c.CategoryID = re.CategoryID
INNER JOIN Mode m1 (nolock)
ON re.ResourceID = m1.ResourceID
INNER JOIN Role r1 (nolock)
ON r1.RoleId = m1.RoleId
INNER JOIN Mode m2 (nolock)
ON re.ResourceID = m2.ResourceID
INNER JOIN Role r2 (nolock)
ON r2.RoleID = m2.RoleID 
WHERE r1.Name = @Role1 AND r2.Name = @Role2
ORDER BY Module, ResourceID

Missing Custom Role script

This script shows you two roles side by side for comparison.

/**************************************************************
   Update the values in the variables to check
   if resources are missing from the role who is
   supposed to have higher priviledges.
**************************************************************/ 

DECLARE @HigherRole AS nvarchar(50);
DECLARE @LowerRole AS nvarchar(50);
SET @HigherRole = 'Role with higher privileges';
SET @LowerRole = 'Role with less privileges';

SELECT m.ModeID, r.Name, re.Name, m.Allow 
FROM Mode m (nolock)
INNER JOIN Role r (nolock)
ON r.RoleId = m.RoleId
INNER JOIN Resource re 
ON re.ResourceID = m.ResourceID
WHERE r.Name LIKE @LowerRole AND m.Allow = 1 AND
       m.ResourceID IN
       (SELECT ResourceID FROM Mode m 
       INNER JOIN Role r
       ON r.RoleId = m.RoleId
       WHERE r.Name LIKE @HigherRole AND
       m.Allow = 0
       )

### Status of Events stuck in ‘Processing’ or ‘Failed’ to ‘Ready for Processing’

UPDATE adp.AdpExportTracking
    SET [Status] = 2 -- 2 = Completed Event
WHERE [Status] = 1; -- 2 = Pending Event
 
 
-- This script updates the status of Error Exports in adp.ADPExportTracking table
 
SET NOCOUNT ON;
 
BEGIN TRY
    IF  OBJECT_ID(N'adp.ADPExportTracking') IS NOT NULL
    BEGIN
        UPDATE adp.ADPExportTracking
            SET [Status] = 2
        WHERE [Status] = -1 -- -1 = Failed Status
    END
     
END TRY
BEGIN CATCH
    DECLARE    @error_severity        INT,
            @error_state        INT,
            @error_message        NVARCHAR(2048);
 
    SELECT    @error_severity = ERROR_SEVERITY(),
            @error_state = ERROR_STATE(),
            @error_message = ERROR_MESSAGE();
 
    RAISERROR(@error_message, @error_severity, @error_state);
 
END CATCH
GO

VMware Tunnel in SQL

ws1tunnel.TunnelConfiguration

ColumnDescriptionType of Data
UuidUUID based primary Keyuniqueidentifier
NameName of the Tunnel Configurationnvarchar(255)
Enabled

If Tunnel Configuration

is enabled or not

bit
PacFileSupportEnabled

If PAC File Upload support

is enabled or not

bit
OrganizationGroupUuid

UUID based Organization

Group Id

uniqueidentifier
VpnVersionVpn Config versionnvarchar(255)
VpnVersionUtcDateTimeVpnConfigVersionUtcDateTimenvarchar(255)
CreatedByCore user who created this recorduniqueidentifier
CreatedOnCreated on Datedatetime
ModifiedByCore user who modified thisuniqueidentifier
ModifiedOnModified Datedatetime

ws1tunnel.TunnelClientConfiguration

ColumnDescriptionType of Data
UuidUUID based primary Keyuniqueidentifier
TunnelConfigUuidUuid of Tunnel Configurationuniqueidentifier
AuthenticationTypeAuthentication Typeint
CertificateSourceVPN Certificate Sourcenvarchar(255)
CertificateAuthorityUuidVPN  CA Id.uniqueidentifier
CertificateTemplateUuidAirwatch VPN CA Template Id.uniqueidentifier
ScepCertificateTemplateUuidSCEP Certificate Template ID
for Client Certificate for Tunne
uniqueidentifier
ProfileScepCertificateTemplateUuidthe Airwatch CA template id
for SCEP template with key 4096
uniqueidentifier
CreatedByCore user who created this recorduniqueidentifier
CreatedOnCreated on Datedatetime
ModifiedByCore user who modified thisuniqueidentifier
ModifiedOnModified Datedatetime

ws1tunnel.TunnelServerConfiguration

ColumnDescriptionType of Data
UuidUUID based primary Key for the tableuniqueidentifier
TunnelConfigUuidUuid of Tunnel Configurationuniqueidentifier
AwCertificateThumbprintVPN Certificate Thumbprintnvarchar(255)
AwIdentifierUnique string for AWCM to identify an installation of AirWatch for VPNnvarchar(1024)
VpnIdentifierUnique string for AWCM to identify an installation of VPN servernvarchar(1024)
TunnelConfigurationTypeWhether VPN is in a standard or endpoint-relay configuration.int
EndpointHostVPN server endpoint Host namenvarchar(255)
RelayEndpointPortVPN server portint
VpnServerHostNameVPN server Host namenvarchar(255)
VpnServerPortVPN server portint
PublicSslVPNWhether to use a public SSL certificate for vpn.bit
LogLevelVPN logging levelint
ApiViaProxyWhether to enable API and AWCM outbound calls via proxy.bit
AccessLogModeAccessLogMode (rsyslog or file)int
EnableAccessLogVpn EnableAccessLogbit
VpnServerConnectionTypeVPN server connection typeint
SyslogHostSyslog Hostnamenvarchar(255)
SyslogPortSyslog Portint
CreatedByCore user who created this recorduniqueidentifier
CreatedOnCreated on Datedatetime
ModifiedByCore user who modified thisuniqueidentifier
ModifiedOnModified Datedatetime

ws1tunnel.ConfigCertificateMapping

ColumnDescriptionType of Data
UuidUUID based primary Key for the tableuniqueidentifier
TunnelConfigUuidReference Identifier to TunnelConfiguration tableuniqueidentifier
CertificateUuidUUID for Certificateuniqueidentifier
CertificateTypeCertficate typeint
IsActiveActively used certificatebit
CreatedByUser ID that created this recorduniqueidentifier
CreatedOnDateTime when the record was created in the DBdatetime
ModifiedByUser ID that modified this recorduniqueidentifier
ModifiedOnDateTime when the record was last modified in the DBdatetime

ws1tunnel.TunnelTestConnectionStatus

ColumnDescriptionType of Data
UuidUUID based primary Key for the tableuniqueidentifier
TunnelConfigUuidReference Identifier to TunnelConfiguration tableuniqueidentifier
TestConnectionStateCurrent state of Test connectionnvarchar(20)
TestConnectionInitiatedTimeTime at which test connection was initiateddatetime
AWCMReachableAWCM is Reachable or notbit
AWCMConnectionFailureReasonReason for AWCMC not being reachablenvarchar(50)
TestConnectionResultTest connection was successful or notbit
CreatedByCreated by for the Test connection status recorduniqueidentifier
CreatedOnCreated on for the Test connection status recorddatetime
ModifiedByModified by for the Test connection status recorduniqueidentifier
ModifiedOnModified on for the Test connection status recorddatetime

WS1 UEM DB Important Tables

Each application uploaded to AirWatch would have its own row in the deviceApplication.Application table.  Each column contains specific attributes for that object.  For example, an application in the deviceApplication.Application table would have a column for Name, PackageID, LocationGroup, etc.

Device Management Tables

dbo.DeviceOperatingSystem: OS versions supported by AirWatch Console in current version

dbo.DeviceModelInfo: Device models (for Apple) or Android vendors supported by AirWatch Console in current version

User Management Tables

dbo.CoreUser: Admins – UserName, TimeZone, LastLogin, etc.

mobileManagement.EnrollmentUser: End users – UserName, LocationGroupID, DisplayName, UserPrincipleName, etc.

mobileManagement.CurrentDeviceEnrollmentUser: Ties enrolled devices to enrollment users

dbo.UserGroup: FriendlyName,DN,RootLocationGroupID, domain, etc

MAM Tables

deviceApplication.Application: Internal applications

deviceApplication.RecommendedExternalApplication: All things public application

deviceApplication.VPPLicensePool: SmartGroup, Allocated licenses, Redeemed licenses, etc.

deviceApplication.ApplicationGroup: For blacklists/whitelists/required lists of apps

smartGroup.SmartGroup: info about the Smart Group

smartGroup.AWEntitySmartGroupAssignmentMap: Maps a Smart Group to the App/Book that uses it for assignment

MEM Tables

mobileEmailGateway.MEMConfig Contains attributes related to the Email Configuration, including pre-7.1 sets of System Codes

mobileEmailGateway.MEMDevice Contains all the attributes for each device, whether managed or unmanaged

mobileEmailGateway.MEMDeviceActivity Contains the status and activity info for each device

mobileEmailGateway.MEMConfigProfile Contains associations between MEMConfig and EAS device profiles

mobileEmailGateway.MEMDeviceConfig Contains associations between MEMConfig and MEMDevice. When an enrolled device receives an EAS profile, MEMDevice will receive corresponding MEMConfig

mobileEmailGateway.MEMDeviceDiagnostic Contains diagnostics data for devices

mobileEmailGateway.{all the rest}  Email Policy configurations, such as attachment encryption or OS policies

MCM Tables

enterpriseContent.Content All settings pertaining to uploaded content – offlineViewing, allowEmail, Name, etc.

enterpriseContent.ContentRepository Details for repositories – Name, Link, AuthenticationUsername, User/Admin Repository

enterpriseContent.ContentMap Links DeviceID, EnrollmentUserID, and ContentVersionID

enterpriseContent.ContentVersion BlobID, Version, Size, Author, etc

MDM Tables

dbo.Device Device centric information – OS, Friendly Name, Serial Number, Phone Number, Enrollment Date, etc.

Profiles

DeviceProfile.DeviceProfile Settings for profiles – Name, Description, DevicePlatformID, ProfileAssignmentTypeID, etc.

deviceProfile.DeviceProfileVersion Shows historic versions of a profile and their modified dates

deviceProfile.DeviceProfileDevicePool Maps devices to profiles and profileVersions

deviceProfile.deviceProfileSettingValue Maps actual profile settings to profileVersions

Telecom

dbo.Plan Telecom plan details

dbo.PlanAssignmentRule Assignment rule details

dbo.CellCard Cellular details

MobileDataUsage, CellCardUsage Interrogator tables

Compliance

DeviceComplianceStatus Compliance status of devices

Policy List of policies

Device Samples

ManagedAppList,ProfileListSample, SecurityInformationSample Interrogator tables

Reports

dbo.Report Info on all available reports

dbo.ReportSubscription Created subscriptions

Miscellaneous tables

dbo.Certificate Thumbprint, SubjectName, Validity Dates, etc.

dbo.LocationGroup OG info – LocationGroupID, Name, CreatedOn, CreatedBy, MDMSettingsInheritable

deviceCommandQueue.DeviceQueue / deviceQueueAudit Current commands queued / already executed commands for devices

dbo.SystemCode All settings and default values configurable in the AirWatch Console - Groups & Settings

EventLog.EventLog Where console Event Logs pull from

Example of deleting “wipe device” commands from Message Queue

This is needed in case of accidental mass wipe created as result of incorrect compliance policy etc.

SELECT * FROM deviceCommandQueue.DeviceQueue WHERE commandid = 10;
DELETE * FROM deviceCommandQueue.DeviceQueue WHERE commandid = 10;

WS1 UEM DB Monitoring

Recommendations for monitoring on the WS1 UEM database

Monitor Descritpion
Data Files Monitor and alert for resizing when free space in data files drops below 10%.
Transaction Logs Monitor and resize if free space in log drops below 10%.
Waiting Tasks Waiting tasks in the SQL activity monitor must be under 10 on average. Ideally waiting tasks should be between 0 and 2 when compared to 20,000 batch requests per second.
Index Rebuild Monitor for fragmentation between 10% and 29%. Reorganize with an update of statistics. Indexes with fragmentation greater than 29% should be rebuilt.
SQL Server CPU Monitor sustained high CPU utilization (Over 90% for a 15 minute duration).
SQL Server Job History Monitor failed SQL Server Agent Jobs (in particular, AirWatch Jobs).
SQL Server Page Life Expectancy Monitor SQL Server Page Life Expectancy (dropping below 3000).
SQL Server Disk Space Monitor disk space usage on all Data and Log Drives for ‘AirWatch’ and ‘tempdb’ Databases.
SQL Server Disk Queuing Monitor Disk Queuing on all Data and Log Drives for ‘AirWatch’ and ‘tempdb’ Databases. Check Disk Queue Length via Task Manager > Performance > Resource Monitor > Dist Tab > Storage. It should average between 2 and 4. It could increase or decrease, but on average it should be between those values.
Page Life Expectancy Page Life Expectancy is an indication of whether the database server has memory pressure. The expected number is over 1,000 (seconds). If it is low, this is a first indicator of memory pressure. This may not be an issue if:
- The PLE is increasing over time. If it is increasing, but is still less than 1,000, then that is a sign of a memory pressure.
- After an index maintenance job, the PLE can be low. This needs to be monitored for a few hours to see if it goes up.
Index Fragmentation Level A high fragmentation level means data retrieval becomes less efficient and reduces database performance. Run the defragmentation job on a nightly basis. The script below shows the fragmentation level (in percent) against all the tables. The recommended fragmentation level is less than 30% when the page size is more than 1,000.
SELECT OBJECT_NAME(object_id), index_id, index_type_desc, index_level,
avg_fragmentation_in_percent, avg_Page_space_used_in_percent, page_count
 FROM sys.dm_db_index_physical_stats(DB_ID(N'AirWatch'), null, null,
null, 'SAMPLED') ORDER BY avg_fragmentation_in_percent DESC

If the database is highly fragmented, it is recommended that you perform an index reorganize or rebuild.

Health Checks

Synthetic transactions are the strongest indicator of a healthy AirWatch environment. They can mimic end user actions (for example, enrollment) and report if there are issues. Many different use cases could be considered, and high-use scenarios should be tested with synthetic transactions. An example synthetic transaction could be:

  1. Navigate to the AirWatch Console.
  2. Log in using credentials.
  3. Navigate to Hub > Reports & Analytics > Reports > List View.
  4. Run a report.
  5. Log out.

Typically, a tool like Keynote or AlertSite would be used to generate and monitor synthetic transactions.

WS1 UEM Hardening

Linked Articles

Tools to check SSL/TLS certificates and protocol

Subsections of WS1 UEM Hardening

IIS Hardening

Device Services IIS

Disable insecure TLS/SSL protocol support
- Yes, you can disable this and this will not have any impact on AirWatch Applications because we have made the necessary changes in our components as well. 
POODLE attack, SSLv3 etc have been taken care by our developers in console version 8.1 and above.

Remove the default page or stop/disable the IIS server
- Yes, you can remove the default page, but do not disable the IIS server. Recommended not to disable the IIS server.

Disable TLS/SSL support for RC4 ciphers

Disable SSLv2, SSLv3, and TLS 1.0

Regarding Ciphers suites

  •  Be it any kind of Ciphers(Static key cipher, 3DES cipher, Strong cipher) the best solution for this  is to enable TLS. Also, the MicrosoftKB article 245030 as mentioned in the ticket is the best solution for all the Cipher questions.
    https://support.microsoft.com/en-us/kb/245030

The RC4 cipher can be completely disabled on Windows platforms by setting the “Enabled” (REG_DWORD) entry to value 00000000 in the following registry locations:

• HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128
• HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 40/128
• HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 56/128

Disabling SSL and enabling TLS is out of Airwatch’s scope as you have to make registry changes locally on the server:

Disabling SSL 3.0- https://www.digicert.com/ssl-support/iis-disabling-ssl-v3.htm
Enabling TLS - https://support.quovadisglobal.com/KB/a433/how-to-enable-tls-12-on-windows-server-2008-r2.aspx
https://www.hass.de/content/setup-your-iis-ssl-perfect-forward-secrecy-and-tls-12

Disabling RC4 on Java:
http://stackoverflow.com/questions/18589761/restict-cipher-suites-on-jre-level

Example:

jdk.certpath.disabledAlgorithms=MD2
jdk.tls.disabledAlgorithms=MD5, SHA1, RC4, RSA keySize < 1024

We can either do it at a JRE system wide level or at a JVM instance (such as AWCM) level adding RC4 as a disabled algorithm when a choice has to be made as part of SSL handshake.
In the latter case, It will be a config change on AWCM Service parameters (only change being the added restriction option in $AWCM_HOME/service/AWCMService.exe.parameters).

Tip

IIS Crypto Tool can be used to turn off weak ciphers in Windows Server 2008+

Warning

Usage of iiscrypto tool to disable Cipher Suites, as well as registry keys can break communication between AirWatch components.

Use with extreme caution, ONLY AFTER AirWatch was deployed and tested to be working. Disable Cipher Suites one by one and re-test AirWatch functionality after each change!

Security scanner sees IIS vulnerabilities:

  • SWEET32
  • POODLE
  • TLS_FALLBACK_SCSV

Hardening:

  • POODLE - need to disable SSL 3.0 protocol. Open registry: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols and create keys SSL 3.0\Server (if not created previously), create a DWORD value Enabled = 0;

  • SWEET32 - need to disable weak ciphers. Open registry: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\Triple DES 168, create a DWORD value Enabled = 0. Create keys “RC4 56/128”, “RC4 40/128”, “RC4 128/128” create a DWORD value in all keys called Enabled = 0;

Warning

When turning off Triple DES the RDP protocol to server may stop working. Need to patch RDP to use modern ciphers to solve this problem.

  • TLS_FALLBACK_SCSV (only for Windows 2003-2008! see KB from Microsoft: https://support.microsoft.com/kb/980436/en-us) - Open registry: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL and create DWORD called UseScsvForTls with parameters:
    • UseScsvForTls = 0 # Client sends Renegotiation Info extension for TLS protocol
    • UseScsvForTls = 1 # Client sends SCSV for TLS protocol - use this to solve problem
Warning

AirWatch Self-Service portal uses TLS1.0/RC4-type cryptography, and gives Error and blank page after IIS hardening!

iOS 11 & Wi-Fi TLS 1.2 Requirements

With the release of iOS 11, TLS 1.2 will now be the default for EAP-TLS negotiation. This may cause an issue with older clients that still need to connect on TLS 1.0 or 1.1. Apple has allowed for a method to override this default setting with a configuration profile sent down to the device via MDM. In order to ensure your iOS devices maintain Wi-Fi connection when upgrading to iOS 11, please follow the steps below:

Note: If you already have a successfully deployed iOS Wi-Fi with EAP-TLS configured, skip to step 3. 

  1. Create a new profile with a Wi-Fi payload using EAP-TLS and General payload configured.
  2. Ensure that the profile successfully configures Wi-Fi on an iOS device.
  3. From your profile list view, select the Wi-Fi with EAP-TLS created profile and choose to view XML.
  4. Export or copy the XML of the profile.
  5. Edit the XML to remove everything prior to the first and after its corresponding .
  6. Edit the XML again to add the following bolded key/values (accepted values are 1.0, 1.1, and 1.2). These should be a part of the EAPClientConfiguration key
<key>EAPClientConfiguration</key>
<dict>
<key>AcceptEAPTypes</key>
<array>
<integer>13</integer>
</array>
<key>TLSMaximumVersion</key>
<string>1.1</string>
<key>TLSMinimumVersion</key>
<string>1.0</string>
</dict>
  • Edit the XML a final time to create a unique identifier for the payload. Locate the PayloadUUID key and edit the values that correspond to the ‘X’s to random values. Please ensure these values are as random as possible to avoid issues with duplicate identifiers (e.g. 123456, 111111, 101010).
<key>PayloadUUID</key>
      <string>352B3FD9-B875-45C5-AA0E-AAFEE3XXXXXX</string>
  1. Create another new profile and configure the General payload
  2. Paste your edited XML into the Custom Settings payload and publish to devices

IISCrypto config from AirWatch

iOS supports all latest ciphers and encryptions – however there are questions with Android, so Android 4.4 will be the baseline.

Protocols:  SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1 can be turned off as all of the platforms supports newer protocols.

Warning

Test results at client site (AirWatch ver. 9.2.3): disabling TLS 1.0 showed 4 services failing at AirWatch Device Services Server role - proceed with caution!

Cipher Suites, which can be turned off...

VMware Assist

External link: https://stackoverflow.com/questions/52212866/how-can-i-disable-tls-rsa-with-aes-128-cbc-sha-without-disabling-others-as-well

Hardening Assist is basically hardening of Java, disabling TLS_RSA_WITH_AES… in it. Delete RSA Keysize, and add specific protocols.

WS1 UEM Installation

Articles in section

Installation

❗️All Windows systems, which will be used to deploy AirWatch / Workspace One UEM, in localization settings, there should be language = US-EN.

❗️Special attention to Regional Settings on floating point identifier: it must be a dot, not a comma!

❗️All Windows systems, which will be used to deploy AirWatch / Workspace One UEM, should have all current patches applied. For example, early versions of Win2012R2 have broken ASP.NET and break AirWatch installation.

Legend

  • BE - (BackEnd server) WS1 UEM Admin Console
  • FE - (FrontEnd server) WS1 UEM Device Services
  • SQL - Microsoft SQL Database Server
  • UEM - AirWatch / Workspace One UEM

Database Deployment

❗️See first SQL Recommendations page before production or semi-production deployment.

  • Install SQL
  • Login to the SQL server, launch SQL Management Studio;
  • Create a new database. In database settings apply General → Autogrowth / Maximize → File Growth → In Megabytes = 128;
  • Choose collation: Options → Collation → SQL_Latin1_General_CP1_CI_AS;
  • SQL 2008 and MS SQL 2008R2 are not supported anymore. For MS SQL 2016 choose Options → Compatibility Level = 2014

❗️Issues currently detected with installing Workspace ONE UEM up to version 1909 in Microsoft SQL 2017. Services do not start after install, console does not launch. As recommended by Microsoft for SQL 2017, services should use the element to improve startup performance. Using this element can also help avoid delays that can cause a time-out and the cancellation of the service startup. See Microsoft KB article.

  • Create a user in Mixed-mode SQL (non-domain), with sysadmin permissions for server and db_owner for database. Gice the user permissions for msdb: SQLAgentUserRole, SQLAgentReaderRole, db_datareader roles. Do not forget to cancel password expiration for this user;
  • If there is not Internet on DB server - download Microsoft .NET Framework 4.6.2 from Microsoft website for English Windows on separate computer and copy to this server (during setup WorkspaceONE_UEM_DB_XX.YY.Z.K_Setup tries to download the framework itself, with no Internet it may hang the installation process for some time);
  • Copy WorkspaceONE_UEM_DB_XX.YY.Z.K_Setup files to the server, launch it. Copy to **C:\Distr**;

❗️Do NOT launch installer from C:\Users\Documents and Settings\Downloads etc folders - long path may cause unpacking error.

  • Enter “localhost” in install wizard, login and password of the SQL user, and choose the UEM database;
  • ❓️ If the database is created on AlwaysOn Cluster - turn on Using SQL AlwaysON Availability Groups option;
  • Wait for installer to end (10-15min). Install progress can be seen as log file growth in c:\AirWatch\AirWatch 1811\Database\AWDatabaseLog.txt* (the log will grow up to 2.3Mb when the installation will finish);
  • Check the installation, use SQL Management Studio to launch a script:

select * from dbo.DatabaseVersion;

The answer should be the UEM version number.

❓️ For AlwaysOn cluster - do not forget to clone the database Jobs on the other cluster nodes!

Device Services Front-End (FE) Server

  • Enter Windows Server Manager and check the following roles/features (double-check official doc for feature list):
    • Web Server (IIS)
    • Web Server (IIS) → Web Server → Common → Static Content, Default Document, Directory Browsing, HTTP Errors, HTTP Redirection
    • Web Server (IIS) → Web Server → Performance → Dynamic Content Compression
    • Web Server (IIS) → Web Server → ASP
    • Web Server (IIS) → Web Server → ASP.NET 4.5
    • Web Server (IIS) → Web Server → Security → IP & Domain Restrictions
    • Web Server (IIS) → Web Server → Health & Diagnostics → Request Monitor
    • Web Server (IIS) → Web Server → Application Development → Server Side Includes
    • .NET Framework 4.5 → WCF → HTTP Activation
    • Message Queuing
    • Telnet Client

❗️ DON NOT turn on Web Server (IIS) → Web Server → Common → WebDav Publishing - this will lead to multiple bugs in managing iOS devices

  • ❓️ If there is not Internet on FE server - download and install NET Framework 4.6.2 (Microsoft .NET Framework 4.6.2 (Offline Installer) for Windows 7 SP1, Windows 8.1, Windows Server 2008 R2 SP1, Windows Server 2012 and Windows Server 2012 R2). Reboot server;

  • ❓️ If there is not Internet on FE server - download and install URL Rewrite Module 2.0 (https://go.microsoft.com/?linkid=9722532) for IIS. Old version of Rewrite Module 2.0 provided on this page as attachment in case of need;

  • Upload an external certificate in PFX format with private key. Password used to protect the certificate MUST be 6+ characters long. Short password will lead to problems with AWCM Java keystore! Install the certificate into Local Machine account, leaving Automatic Detect option for certificate type. Also install any root and intermediate certificates of the certificate trust chain. Subject Alternative Name of the certificate MUST contain the external DNS name of the server!

  • Check correct start config of IIS - use browser to go to http://127.0.0.1/ (start page of IIS must be present)

  • Go to IIS admin console, bind the certificate: in sites tree choose Default Web Site → Bindings menu → Add.., choose https, in SSL Certificates list choose the certificate from previous step. Enter the external DNS name of the server, which is written in the certificate. 

❗️Port binding is needed ONLY for Device Service and Console Service.

  • Launch installer WorkspaceONE_UEM_Application_X.X.X.X_Full_Install. Choose Continue setup without importing/exporting config file;
  • In modules selection choose only Device Services, select This feature will not be available for Admin Console, continue installation;

❗️For AirWatch 9.2.2+: during installation, AirWatch installer deploys SQL Native Client, which may not have enough time to initialize during the work of the wizard. During SQL check, an error may be generated, that SQL is not found. Press Cancel and reboot the server, then re-launch the setup process.

  • Enter SQL data: in full database name, only enter the server name, do not enter SQL Instance name;
  • Specify the DNS name for reaching the server by HTTPS from outside and inside. Do not choose SSL Offload - it is much easier to make all connections as HTTPS and then edit configuration;

⭐️ Instead of choosing different DNS names and then have issues with AWCM, I recommend to enter the same external name for Device Services and Web Console (check Same as above? option). After this, make an alias on the local DNS server, or use the hosts file on Admin Console/BE server to alias the external name of Directory Services/FE to an internal IP address.

  • Choose Default Web Site as install target;
  • Leave AWCM listening IP as 0.0.0.0 since it is installed locally, and port 2001 for connection. Install the PFX certificate and enter its’ password; 

❗️The PFX certificate MUST be created with Export All Properties option! Or the Java keytool will not be able to import it into awcm.keystore, and it will not give errors in the log! But AWCM will not work!

  • Choose Implicit Clustering (do not cluster AWCM);
  • Wait for install completion. AirWatch Certificate Installation Wizard will open, click Next and choose SQL Authentication. If Internet is accessible, a code must be entered. For offline installation, click Get File and save the *.plist fiel on disk;
  • Go to my.workspaceone.com: My Workspace One menu → My Company → Certificate Signing Portal → Authorize Install → Generate a token (for Internet access); OR
  • My Workspace One menu → My Company → Certificate Signing Portal → Authorize Install → Upload Your File (for offline), and upload *.plist file.
  • Save the certs.plist answer file and upload it in the installation wizard, thus ending the installation.

❗️AirWatch (WOne UEM 1909) services may not start due to timeout error on Windows 2008-2012. Increase Timeout time in Windows registry: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control → ServicesPipeTimeout=180000 External link: https://kb.vmware.com/s/article/50105044?lang=en_US

Admin Console Back-End (BE) Server

  • Enter Windows Server Manager and check the following roles/features (double-check official doc for feature list):
    • Web Server (IIS)
    • Web Server (IIS) → Web Server → Common → Static Content, Default Document, Directory Browsing, HTTP Errors, HTTP Redirection
    • Web Server (IIS) → Web Server → Performance → Dynamic Content Compression
    • Web Server (IIS) → Web Server → ASP
    • Web Server (IIS) → Web Server → ASP.NET 4.5
    • Web Server (IIS) → Web Server → Security → IP & Domain Restrictions
    • Web Server (IIS) → Web Server → Health & Diagnostics → Request Monitor
    • Web Server (IIS) → Web Server → Application Development → Server Side Includes
    • .NET Framework 4.5 → WCF → HTTP Activation
    • Message Queuing
    • Telnet Client

❗️ DON NOT turn on Web Server (IIS) → Web Server → Common → WebDav Publishing - this will lead to multiple bugs in managing iOS devices

  • ❓️ If there is not Internet on FE server - download and install NET Framework 4.6.2 (Microsoft .NET Framework 4.6.2 (Offline Installer) for Windows 7 SP1, Windows 8.1, Windows Server 2008 R2 SP1, Windows Server 2012 and Windows Server 2012 R2). Reboot server;
  • ❓️ If there is not Internet on FE server - download and install URL Rewrite Module 2.0 (https://go.microsoft.com/?linkid=9722532) for IIS. Old version of Rewrite Module 2.0 provided on this page as attachment in case of need;
  • Check correct start config of IIS - use browser to go to http://127.0.0.1/ (start page of IIS must be present)
  • Configure the certificate on IIS - for Admin Console on BE a self-signed certificate may be used:
    • Enter IIS Admin Console, choose Server Certificates, and in the right column menu choose Create Self-Signed Certificate;
    • Enter a name for the certificate, type = Web Hosting, click ОК;
    • Go to IIS admin console, bind the certificate: in sites tree choose Default Web Site → Bindings menu → Add.., choose https, in SSL Certificates list choose the certificate from previous step.

❗️Port binding is needed ONLY for Device Service and Console Service.

  • Launch installer WorkspaceONE_UEM_Application_18.11.0.3_Full_Install. Choose Continue setup without importing/exporting config file;
  • In modules selection choose only the Admin Console, choose This feature will not be available for Device Services, continue the installation;

❗️For AirWatch 9.2.2+: during installation, AirWatch installer deploys SQL Native Client, which may not have enough time to initialize during the work of the wizard. During SQL check, an error may be generated, that SQL is not found. Press Cancel and reboot the server, then re-launch the setup process.

  • Enter SQL data: in full database name, only enter the server name, do not enter SQL Instance name;
  • Specify the FQDN name for HTTPS access on Admin Console from the inside. Do NOT use a short name of DNS alias. Choose an External DNS name for access via HTTPS on Device Services server. Check the absence of space characters before or after the names. An error in this form may be corrected only by re-installing UEM!
  • Choose Default Web Site as the install target;
  • In Company Profile choose the company name and installation type = Production;

❗️AirWatch (WS1 UEM 1909+) services may not start due to timeout error on Windows 2012R2+. Increase Timeout time in Windows registry: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control → New 32-Bit DWORD: ServicesPipeTimeout, Decimal=200000 (Decimal=60000 too small, put more!)

External link: https://support.microsoft.com/en-us/kb/922918

Manually running services: under Supplemental Software → QueueSetup locate and run the InstallQueues.Bat file.

  • Check the installation:
  • Enter the UEM console. Use Login: administrator, Password: airwatch. Choose a new password, choose a PIN-code and secret questions/answers pairs.

⭐️ Hardening of the IIS web-server for AirWatch/UEM Device Services is described in this article.

Subsections of WS1 UEM Installation

WS1 First Time Config

GroupID

  • Switch to tenant - Company
  • Switch to Groups & Settings → Groups → Organization Groups → Organization Groups Detail
  • Set the company name, set GroupID, country and time zone

iOS Agent

  • Switch to Groups & Settings → All Settings → Devices & Users → Apple → Apple iOS → Intelligent Hub Settings, click Override
  • Set Background App Refresh - for the AirWatch Agent works in the background and does not interfere with other apps
  • Turn on Collect Location Data - collection of data from GPS (Location Services)
  • Do not touch SDK profiles, leave settings as is currently

AWCM

  • Launch the Admin Console on the exact server, where AWCM is installed (FE) and go to Groups & Settings > All Settings > Device & Users > Android > Intelligent Hub Settings

  • Switch Use AWCM Instead of C2DM as Push Notification Service - if you have Android devices with no Google Apps/Services, no Google Account, or want to restrict PUSH notifications to MDM-direct

  • Switch AWCM Client Deployment Type to Always Running, click Save

  • Go to Groups & Settings > All Settings > System > Advanced > Secure Channel Certificate

  • Check/configure the Windows environment variable JAVA_HOME - it must point to the last version installed c:\Program Files\jre-<номер версии>

  • Click Download AWCM Secure Channel Certificate Installer and launch the cert installer

  • Check the cert install: open cmd as Administrator and enter command such as:

    c:\Program Files\Java\jre1.8.0_131\bin>keytool.exe -list -v -keystore “C:\AirWatch\AirWatch 1811\AWCM\config\awcm.truststore”

    Enter password as the password for the keystore, and check there are 2 certificates entered, including the secure channel certificate Switch to tenant = Global, go to Groups & Settings > All Settings > System > Advanced > Site URLs, click Enable AWCM Server button at the end of the page

  • Check AWCM settings: internal and external DNS names (they MUST be exactly those used in the corp certificate!) and port number (TCP2001).

Port TCP 2001 MUST be open FROM the outside to server with AWCM (Device Services - FE) in order for direct PUSH to work with Android, and Windows Phone/Desktop devices.

If the external DNS name is published on an external proxy or load balancer, and the inner servers do not know this, use hosts file on Admin Console (BE) server and AirWatch Cloud Connector (ACC) / Enterprise Systems Connector (ESC) to make an alias of external DNS name and internal IP of Device Services (FE) server.

AWCM Troubleshooting - see article.

APNs certificate for Apple and SSL for Apple profiles

  • Launch Admin Console using Firefox, Safari or Chrome (IE not supported!). Go to Groups & Settings → All Settings → Devices & Users → AppleAPNs for MDM
  • Download plist file.
  • Prepare an AppleID account, click Go to Apple
  • On Apple website click Create certificate, accept the terms, upload the plist file, download the corresponding PEM file on local disk
  • Return to the Admin Console - click Next, upload the PEM file and enter the corresponding AppleID click Save. Enter the PIN code of the console administrator
  • Go to Groups & Settings → All Settings → Devices & Users → AppleProfiles
  • Click Upload and choose the PFX file of the corp certificate enter the password of the PFX container

Google Play Registration and Android for Enterprise/Legacy Enrollment

  • Launch Admin Console using Firefox, Safari or Chrome (IE not supported!). Switch to Groups & Settings → All Settings → Devices & Users → Android → Android EMM Registration
  • Click Register with Google
  • Proceed with steps on Google website, entering the GMail Account (each GMail Account may only be used ONCE for 1 ЕММ system (any))

For old AirWatch Console 9.0.1 and earlier, if upgraded to latest version of UEM, the Enable Play Store button should be clicked.

  • Open Enrollment Restrictions tab: choose Define the enrollment method for this organization group. Default is Always use Android, which means to always use Android for Enterprise of type = Device Work Profile (duplication of software into BYOD/Corp containers). If devices with potential AfE support in current group are to be enrolled and managed using Android Legacy ELM/POEM drivers, then choose Always use Android (Legacy) in list, or choose hybrid mode by defining user groups for AfE: Define Assignment Groups that use Android.

After choosing the EMM registration method, DO NOT CHANGE IT with many devices enrolled. Consequences:

  • Profiles can still be installed on the device as they’re being installed directly from Workspace ONE;
  • Communication is maintained between the device and Workspace ONE UEM;
  • You will be unable to leverage any Play store services;
  • No new apps added to Workspace ONE will be visible on the device managed play store;
  • Previously added applications in Workspace ONE will no longer be deployable from the console.

Source - https://blog.eucse.com/things-not-to-do-workspace-one-changing-android-emm-registration/

AirWatch Cloud Connector (ACC) / Enterprise Systems Connector

  • Launch the Admin Console on the exact server, where ACC is to be installed and switch to a non-Global Tenant

You cannot download the ACC distrib on one server, then copy and launch on another!

  • Go to Groups & Settings > All Settings > System > Enterprise Integration > Cloud Connector, turn on Override, switch Enable AirWatch Cloud Connector and Enable Auto Update

It is strongly recommended to configure ACC on non-Global level

  • Switch to Advanced tab, click Generate Certificate button to create the connection certificate to AWCM
  • Choose Use Internal AWCM URL - if the connector is in LAN, and AWCM - in DMZ
  • Use buttons to switch ON services/components, which will talk to the connector (the usual minimum is LDAP, CA, SCEP, Syslog, )
  • Switch back to General tab, choose Download Enterprise Systems Connector Installer link, enter password
  • Install .NET Framework 4.6.2 on server
  • Launch the downloaded installer
  • Enter the password for certificate

Check the installation

  • Go to Groups & Settings > All Settings > System > Enterprise Integration > Cloud Connector
  • Click Test Connection and check that the connector is available

“Error : Reached AWCM but VMware Enterprise Systems Connector is not active” is resolved by server reboot and opening TCP2001 port from Cloud Connector to AWCM.

Active Directory

  • Use Company tenant, go to Groups & Settings > All Settings > System > Enterprise Integration > Directory Services
  • Choose Skip wizard and configure manually (alternative path Accounts > Administrators > Settings > Directory Services)
  • Enter domain data:
    • Directory Type = Active Directory
    • Server - domain controller name
    • Encryption Type = None
    • Bind Authentication Type - connection type = GSS-Negotiate is recommended, which means choose automatically Kerberos or NTLM depending on what is available
    • Bind Username - enter the service account user for reading the domain as <user>
    • Bind Password - enter the domain service account password
    • In Domain - Server fields enter the suffix of the domain and the name of the domain controller
  • Click Test Connection, check there is network access to the domain controller
  • Choose the User tab, DN field - choose the topmost level from the list
  • Choose the Group tab, DN field - choose the topmost level from the list
  • Click Save

Troubleshooting connection to Active Directory - see article.

Self-enrollment of Active Directory Users

  • In Company tenant go to **Groups & Settings > All Settings > Device & Users > General > Enrollment **
  • In Authentication Mode(s) choose Directory checkbox
  • Go to Restrictions, make sure that Restrict Enrollment To Known Users and Restrict Enrollment To Configured Groups are disabled.

Batch Import and Message Templates

To Batch Import users in an AirWatch group, this group needs a Group ID, which allows Enrollment into it.

During user import, a connection token can be distributed via EMail. The template language depends on the localization configuration of the specific Organization Group.

When defining localization on the topmost level, the sub-groups of the lower level may have a strange setting like “Select*”. It is recommended to specify the localization settings on each group and sub-group, so there is no obscurity in the settings.

Configure SDK default profiles

  • Switch to Groups & Settings → All Settings → Apps → Settings & policies → Security Policies, click Override
  • Leave Passcode turned on
  • Activate Single Sign-On
  • Activate Integrated Authentication to auto-enter apps and websites, put Enrollment Credentials and write star symbol ( * ) in mask = all websites

WS1 Installation Problems

Failed to extract custom package message

Console installer needs to be extracted to the *root disk C:*

AirWatch Services are not started before timeout

  1. Click Start, click Run, type regedit, and then click OK.
  2. Locate and then click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  3. In the right pane, locate the ServicesPipeTimeout entry.

Note: If the ServicesPipeTimeout entry does not exist, you must create it. To do this, follow these steps:

 - On the Edit menu, point to New, and then click DWORD Value.

 - Type ServicesPipeTimeout, and then press ENTER.

  1. Right-click ServicesPipeTimeout, and then click Modify.

  2. Click Decimal, type 60000 (default is 30000, use numbers from 60000 to 125000), and then click OK.

 - This value represents the time in milliseconds before a service times out.

  1. Restart the computer.

Database is not getting updated on upgrade of WS1 UEM

Error detected on upgrade to WS1 UEM 2108+

SQL update fails with error:

Only members of sysadmin role are allowed to update or delete jobs owned by a different login.

⭐️ Give account used for WS1 UEM db the MSSQL server role of sysadmin.

AirWatch Self-Service Portal gives error

“HTTP error 503: The service is unavailable”

The Self Service Portal has an associated App Pool in IIS. If the App Pool is not started we see this error.

Ensure that the SSP App Pool is started in IIS.

Log collection

See AirWatch Services and Devices log collection page

App Catalog not seen after successful enroll

Problem: App Catalog does not automatically appear after device enrollment. Solution:

  1. In AirWatch Admin Console go to Groups & Settings > All Settings > Apps > Catalog > General > Publishing > repeat SAVE procedure
  2. Alternative: create separate webclip profile for all devices with URL: https://{DS_URL}/Catalog/ViewCatalog/{SecureDeviceUdid}/{DevicePlatform} External link: https://kb.vmware.com/s/article/50100220?lang=en_US

WS1 Verify Installation

Verify Installation

  • Open AirWatch Console
  • Choose About Airwatch - check the version
  • Check the Site Links: open Groups & Settings > All Settings > System > Advanced > Site URLs and look through the links
  • Check the connection with Device Services server with a defined in the install phase external URL, signed with external certificate (type of link: https://<DS_URL>/DeviceManagement/Enrollment  )
  • Check the AWCM component, using link https://<DS_URL>:2001/awcm/status*
  • Check AirWatch services - launch services.msc in Windows Server and check that AirWatch services are Started
  • Check the GEM Inventory Service: go to the AirWatch Console server, in the folder C:\AirWatch\Logs\Services\ and delete the file AirWatchGemAgent.log; open services.msc and restart GEM Inventory Service. New log will either NOT show up, or show up without errors.