You can enroll your device automatically with WSO2 IoT Server via mutual SSL. For a better understanding of how auto-enrollment is achieved via mutual SS, in WSO2 IoT Server, see Mutual SSL Authentication.
Configure WSO2 IoT Server for mutual SSL authentication
Before you begin
Download and install OpenSSL. For more information, see the guide on how to download and install OpenSSL.
Follow the steps given below to configure WSO2 IoT Server for mutual SSL authentication:
Open the
<IoT_HOME>/core/conf/tomcat/catalina-server.xml
file and configure theclientAuth
field that is underConnector protocol="org.apache.coyote.http11.Http11NioProtocol"
as shown below:clientAuth="want"
- The
catalina-server.xml
file has two connectors with the nameConnector protocol="org.apache.coyote.http11.Http11NioProtocol"
. Make sure to configure the connector that has the property,scheme="https
in it. - The values that can be assigned for clientAuth is
true
,want
orfalse
, wherefalse
is the default value that is assigned. - When you assign the value as
want
it indicates that mutual SSL is not a must for all the hosted web apps.There are many web apps in WSO2 IoT Server other than the web app the android agent communicates with. Therefore, it is advisable not to assign true as the value because it will then request the client certificate to be present for every request, including calls made from the UI.
- The
Configure the
web.xml
file that is in the<IoT_HOME>/core/repository/deployment/server/webapps/api#device-mgt#android#v1.0/WEB-INF
directory by uncommenting the content given below:<!--Below configuration is used to redirect http requests to https--> <security-constraint> <web-resource-collection> <web-resource-name>MDM-Admin</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> <!--For Mutual SSL enabling, please uncomment login-config and security-constraint tags--> <login-config> <auth-method>CLIENT-CERT</auth-method> </login-config>
- If you have not started WSO2 IoT Server previously, you need to extract the content that is in the
<IoT_HOME>/core/repository/deployment/server/webapps/api#device-mgt#android#v1.0.war
file. - If you have started WSO2 IoT Server previously it means that the
api#device-mgt#android#v1.0
folder is already available in the<IoT_HOME>/repository/deployment/server/webapps
directory.
- If you have not started WSO2 IoT Server previously, you need to extract the content that is in the
- Make a copy of the
openssl.cnf
file, move it to another location, and configure the file to generate version 3 certificates as shown below:[ v3_req ] # Extensions to add to a certificate request basicConstraints=CA:TRUE keyUsage = digitalSignature, keyEncipherment [ v3_ca ] # Extensions for a typical CA # PKIX recommendation. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer # This is what PKIX recommends but some broken software chokes on critical # extensions. basicConstraints = critical,CA:true # So we do this instead. #basicConstraints = CA:true # Key usage: this is typical for a CA certificate. However since it will # prevent it being used as an test self-signed certificate it is best # left out by default. keyUsage = digitalSignature, keyCertSign, cRLSign
- Generate a self-signed Certificate Authority (CA) certificate (version 3) and convert the certificate to the
.pem
format:If you have already configured iOS with the self-sign certificates, you can skip steps 3, 4 and 6 by and use the same certificates.
Generate the private key.
openssl genrsa -out <CA PRIVATE KEY> 4096
Example:
openssl genrsa -out ca_private.key 4096
Generate a certificate signing request (CSR).
openssl req -new -key <CA PRIVATE KEY> -out <CA CSR>
Example:
openssl req -new -key ca_private.key -out ca.csr
Self-sign the CSR by signing it with the private key.
openssl x509 -req -days <DAYS> -in <CA CSR> -signkey <CA PRIVATE KEY> -out <CA CRT> -extensions v3_ca -extfile <PATH-TO-MODIFIED-openssl.cnf-FILE>
Example:
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 the
.pem
format.openssl rsa -in <CA PRIVATE KEY> -text > <CA PRIVATE PEM>
Example:
openssl rsa -in ca_private.key -text > ca_private.pem
Convert the CA certificate to the
.pem
format.openssl x509 -in <CA CRT> -out <CA CERT PEM>
Example:
openssl x509 -in ca.crt -out ca_cert.pem
- Generate the SSL certificate (version 3) based on your domain/IP address:
Generate a private key.
openssl genrsa -out <RSA_key>.key 4096
Example:
openssl genrsa -out ia.key 4096
Generate a certificate signing request (CSR).
Provide the server IP/hostname as the common name when prompted
openssl req -new -key <RSA_key>.key -out <CSR>.csr
Example:
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 <CSR>.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial <serial number> -out ia.crt
Example:
openssl x509 -req -days 730 -in ia.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial 044324343 -out ia.crt
- Generate the client-side SSL certificate (version 3):
Generate a private key.
openssl genrsa -out <CLIENT_key>.key 4096
Example:
openssl genrsa -out client.key 4096
Generate a certificate signing request (CSR). When generating the client CSR, make sure to give the serial number of the device that is being enrolled as the common name.
openssl req -new -key <CLIENT_key>.key -out <CSR>.csr
Example:
openssl req -new -key client.key -out client.csr
Sign the CSR file with the CA private key to generate the client certificate.
openssl x509 -req -days 730 -in <CSR>.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial <serial number> -out ia.crt
Example:
openssl x509 -req -days 730 -in client.csr -CA ca_cert.pem -CAkey ca_private.pem -set_serial 12438035315552875930 -out client.crt
Convert the client certificate to the
.pem
format for future use.openssl x509 -in <CLIENT CRT> -out <CLIENT CERT PEM>
Example:
openssl x509 -in client.crt -out client.pem
Copy server side SSL certificate to the
wso2carbon.jks
file that is in the<IoT_HOME>/core/repository/resources/security
directory using the command given below: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 the CA certificate details to the
client-truststore.jks
file that is in the<IoT_HOME>/core/repository/resources/security
directory using the command given below: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
Why is this step required?
In the SSL handshake process, the server will send a set of trusted CA details to the client and request the client to send a certificate that matches the certificate signed by the server's trusted certificates.
Restart the server and upload the generated certificate in step 6.d above, to the certificate section of the device management console or add the certificate to the database via the REST API.
Create a new BKS file having the name
truststore
and add the CA certificate.Ensure that you have the
bcprov-jdk16-1.46.jar
file in the same folder where you will be generating the BKS file before you run this command.keytool -noprompt -import -v -trustcacerts -alias `openssl x509 -inform PEM -subject_hash -noout -in ca_cert.pem` -file ca_cert.pem -keystore truststore.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-1.46.jar -storepass 'wso2carbon'
If you are using an SSL certificate by a trusted authority such as GoDaddy, the
cert.crt
defined in the command should be the interim certificate.
Example:keytool -noprompt -import -v -trustcacerts -alias godaddy -file cert.crt -keystore truststore.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-1.46.jar -storepass 'wso2carbon'
Create a new BKS file with the name
keystore
and add the client certificate generated bellow.
Example:openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -CAfile ca_cert.pem -name "wso2carbon"
This client.p12 must be added to the
keystore.bks
file. For example as bellow,keytool -noprompt -importkeystore -v -srckeystore client.p12 -srcstoretype pkcs12 -alias wso2carbon -keystore keystore.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-1.46.jar -storepass 'wso2carbon
'Copy the generated BKS files to the
<ANDROID_AGENT_SOURCE_HOME>/cleint/IDPProxy/src/res/raw
folder.You can download the Android agent source code from here.
- Navigate to the
Constants.java
file, which is under theorg.wso2.emm.agent.proxy.utils
package of the<ANDROID_AGENT_SOURCE_HOME>/cleint/IDPProxy/src/java
directory, and configure the following fields.Assign
MUTUAL_SSL_AUTHENTICATOR
as the value forAUTHENTICATOR_IN_USE
.public static final String AUTHENTICATOR_IN_USE = MUTUAL_SSL_AUTHENTICATOR;
Assign
MUTUAL_HTTP_CLIENT
as the value forHTTP_CLIENT_IN_USE
.public static final String HTTP_CLIENT_IN_USE = MUTUAL_HTTP_CLIENT;
Assign
https
as the value forSERVER_PROTOCOL
.public static final String SERVER_PROTOCOL = "https://";
Optionally, if the passwords given when creating the BKS files was different from the default password used, which is wso2carbon, configure the
TRUSTSTORE_PASSWORD
andKEYSTORE_PASSWORD
fields with the password that were used and if the certificates are stored in the device storage, configureTRUSTSTORE_LOCATION
,KEYSTORE_LOCATION
fields with the full path of the storage location.public static final String TRUSTSTORE_PASSWORD = "<PASSWORD>"; public static final String KEYSTORE_PASSWORD = "<PASSWORD>"; public static final String TRUSTSTORE_LOCATION = "<FULL_PATH_OF_THE_LOCATION>"; public static final String KEYSTORE_LOCATION = "<FULL_PATH_OF_THE_LOCATION>";
- Navigate to the
<ANDROID_AGENT_SOURCE_CODE>/client/client/src/main/java/org/wso2/emm/agent/utils/Constants.java
file of the Android agent and configure the following fields.When enrolling an Android device with WSO2 IoT Server, you have the ability to define if the device belongs to the COPE/BYOD device type. This is defined by the
OWNERSHIP_BYOD
andOWNERSHIP_COPE
fields.
Default configuration:public static final String OWNERSHIP_BYOD = "BYOD"; public static final String OWNERSHIP_COPE = "COPE";
When auto-enrolling an Android device, you must define the default device type of the registered device by assigning the respective value for the
DEFAULT_OWNERSHIP
field.Example: Define that the registered device belongs to the COPE device type by default.
public static final String DEFAULT_OWNERSHIP = OWNERSHIP_COPE;
Optionally, if you wish to perform the enrollment in the background (without any interaction with the user) set the
AUTO_ENROLLMENT_BACKGROUND_SERVICE_ENABLED
field totrue
.This feature is applicable only for COPE devices where the organization has devices that are manufactured specifically for them (OEM scenarios). Further, the Android agent MUST be pre-set by the OS as a Device Administrator. Once this is enabled, the Android agent will automatically trigger this service when the device is connected to the network for the first time.
public static final boolean AUTO_ENROLLMENT_BACKGROUND_SERVICE_ENABLED = true;
Optionally, if you wish to skip initial step of the device registration where you need to enter the server address, you can pre-configure the server address details under the
DEFAULT_HOST
field.Make sure to provide the HTTPS details.
public static final String DEFAULT_HOST = "https://<SERVER_IP>:<PORT>";
Example:
public static final String DEFAULT_HOST = "https://10.10.10.201:9443";
- Optionally, configure the following fields to suit your requirement.
SKIP_LICENSE
- Configure this field so that the end user license agreement is not shown to the user.HIDE_LOGIN_UI
- Configure this fields to hide the login page, which is important for auto enrollment.HIDE_UNREGISTER_BUTTON
- Configure this field to hide the unregister button so that the user can not disenroll the device.SKIP_WORK_PROFILE_CREATION
- Configure this field, by assigning the value as true to skip work-profile creation.For more information on the work profile that separates the personal and work data on Android devices, see Data Containerization for Android Device.
HIDE_ERROR_DIALOG
- Configure this field to hide errors that pop up after the device is enrolled.
Example : The user will not be notified of server configuration issues after the device is enrolled.
public static final boolean SKIP_LICENSE = true; public static final boolean HIDE_LOGIN_UI = true; public static final boolean HIDE_UNREGISTER_BUTTON = true; public static final boolean SKIP_WORK_PROFILE_CREATION = true; public static final boolean HIDE_ERROR_DIALOG = true;
Compile the agent and install it on the device you wish to register.
Before installing the agent make sure to check that the device serial number matches the embedded certificate's common name.
What's next
Once the above configurations are complete, you are able to register the device with WSO2 IoT Server by opening the installed application on the device. Try out the steps given below:
Tap the WSO2 agent application and open it.
- Tap ACTIVATE to enable the device administrator on your device. A confirmation message will appear after enabling the device admin.
Now the Android device is successfully registered with WSO2 IoT Server.