Android device auto enrollment / self enrollment in WSO2 EMM

WSO2 EMM provides capability to auto enroll a device with the server. This is done through the use of mutual SSL/TSL underneath to authenticate clients. To follow this section basics of mutual SSL is needed[1]. Let's see how the enrollment flow works.

  1. A user with adequate permission to enroll devices access the certificate section of WSO2 EMM.
  2. User generates a certificate signed by a certificate authority, upload this certificate via the certificate section in EMM console. When generating the certificate, user must make sure they provide the serial number of the device as the common name of the certificate. When uploading the certificate to EMM, it is expected to provide the same serial number as well.
  3. User also embed the generated client certificate in the Agent and compiles the Agent. Please note that for each device that needs to enroll with EMM needs to have a certificate embedded.
  4. As described in the basics of mutual SSL article[1], when the user starts the Android agent, it will try to access a protected resource in EMM server and the mutual SSL handshake will happen right down at the transport layer.
  5. If the certificate is valid, EMM will extract the certificate sent by the client and will check it the certificate is available in the database by checking common name of the certificate provided by the client has a matching serial number in the database.

 How do you configure the WSO2 EMM server for mutual SSL authentication?

  1. Open the file [EMM_HOME]/repository/conf/tomcat/catalina-server.xml and search for clientAuth parameter and change the value to clientAuth="want". This mean for all the web apps hosted, mutual SSL is not a must, but may need. Since there are other web apps, other than the web app android agent communicates with, we cannot set this value to true, because that will request client certificate to be present for every request, including calls from the UI.
  2.  If you have not started the server even once, extract the content of [EMM_HOME]/repository/deployment/server/webapps/mdm-android-agent.war to the same folder. If you have at least started the server once, this means the web apps have deployed once, and mdm-android-agent folder is already available inside webapps. Either way, open, [EMM_HOME]/repository/deployment/server/webapps/mdm-android-agent/WEB-INF/web.xml file and uncomment the following,


Let's discuss how we can use a self-signed CA and achieve mutual SSL authentication,
Run the following commands samples,

CA generation

Generate a private key.
  • openssl genrsa -out ca_private.key 4096
 
Generate a certificate signing request(csr).
  • openssl req -new -key ca_private.key -out ca.csr

 Do the self-signing of the csr by signing with our own private key
  • openssl x509 -req -days 365 -in ca.csr -signkey ca_private.key -out ca.crt -extensions v3_ca -extfile ./openssl.cnf

Convert the private key to .pem format for later usage
  • openssl rsa -in ca_private.key -text > ca_private.pem

Convert the CA certificate to .pem format for later usege.
  • openssl x509 -in ca.crt -out ca_cert.pem


Server SSL

Generate a private key.
  • openssl genrsa -out ia.key 4096

 Generate a certificate signing request(csr). Please provide the server IP/hostname as the common name when promted
  • openssl req -new -key ia.key -out ia.csr

Sign the csr with the CA private key to generate the SSL certificate.
  • openssl x509 -req -days 730 -in ia.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial 044324343 -out ia.crt


Client cert

Generate a private key.
  • openssl genrsa -out client.key 4096
When generating the client csr, make sure to give the serial number of the device to be enrolled as the common name.
  • openssl req -new -key client.key -out client.csr

Sign the csr with the CA private key to generate the clien's certificate.
  • openssl x509 -req -days 730 -in client.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial 044324343 -out client.crt


Copy server SLL to wso2carbon jks which is in [EMM_HOME]/repository/resources/security
openssl pkcs12 -export -out KEYSTORE.p12 -inkey ia.key -in ia.crt -CAfile ca_cert.pem -name "wso2carbon"
keytool -importkeystore -srckeystore KEYSTORE.p12 -srcstoretype PKCS12 -destkeystore wso2carbon.jks

Copy CA certificate details to client truststore which is in [EMM_HOME]/repository/resources/security. This is done so that, in the SSL handshake process, server will send the set of trusted CA details and ask from the client to send a matching certificated signed by the servers trusted certificates.
openssl pkcs12 -export -out ca.p12 -inkey ca_private.pem -in ca_cert.pem -name "cacert"
keytool -importkeystore -srckeystore ca.p12 -srcstoretype PKCS12 -destkeystore client-truststore.jks


For the bellow steps, it is possible to use a tool, such as portecle[2] for simplicity

Create a new bks with the name "truststore" and add the CA certificate.

Create a new bks with the name keystore and add clients certificates
openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -CAfile ca_cert.pem -name "wso2carbon"
This client.p12 can be added to the "keystore.bks"

Copy the two bks files to, IDP proxy module of Android agent's res/raw folder.

Please change the following configurations in the Constants class of the IDP proxy module which is under org.wso2.emm.agent.proxy.utils package.
public static final String AUTHENTICATOR_IN_USE = MUTUAL_SSL_AUTHENTICATOR;
public static final String HTTP_CLIENT_IN_USE = MUTUAL_HTTP_CLIENT;
public static final String SERVER_PROTOCOL = "https://";  

If the passwords given when creating the above bks are diffrent from the default wso2carbon, change the following values as well,
public static final String TRUSTSTORE_PASSWORD = "wso2carbon";public static final String KEYSTORE_PASSWORD = "wso2carbon";

Since with agent auto enrollment, the intention is to avoid user interaction in the enrollment process ideally in COPE scenarios, it is a must to set the Owner ship type. This can be done by setting a value to default ownership type which is newly introduced. Possible values are OWNERSHIP_BYOD or OWNERSHIP_COPE

public static final String OWNERSHIP_BYOD = "BYOD";public static final String OWNERSHIP_COPE = "COPE";
public static final String DEFAULT_OWNERSHIP = OWNERSHIP_COPE;


If the anyone needs to skip the initial server url entering screen in production, this can be done by the newly introduced DEFAULT_HOST variable. In mutual SSL make sure to set the https deatils here.

public static final String DEFAULT_HOST = "https://10.10.10.201:9443";

Following special variables can be set in the agent as well,

public static final boolean SKIP_LICENSE = false;public static final boolean HIDE_LOGIN_UI = false;public static final boolean HIDE_UNREGISTER_BUTTON = false;

As the variables suggest, SKIP_LICENSE will skip the showing of end user license to the user. HIDE_LOGIN_UI will hide the login page, which is important for a scenario like auto enrollment. HIDE_UNREGISTER_BUTTON will hide the unregister button and making it hard for the user to unenroll. These are boolean variables, so true or false must be set. These three are not required for mutual SSL authentication.

After making relevant changes, you compile the agent and install it on the target device which matches the serial number in the embedded certificate. Once the user starts using the device, all he will have to do is open the app and the enrollment will happen.

[1]. http://inoshperera.blogspot.com/2016/03/mutual-ssltsl-authentication.html
[2]. https://sourceforge.net/projects/portecle/

Comments

Popular posts from this blog

MDM vendor singing and MDM APNS certificate generation for WSO2 Iot server

Android device owner concepts

[APIM] Send emails to users upon self-sign up aproval