com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_link3' is unknown.

Auto Enrolling an Android Device

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 SSL in WSO2 IoT Server, see Mutual SSL Authentication.

If you are running WSO2 IoT Server using an IP and not localhost, make sure to Configure WSO2 IoT Server with the IP.

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:

  1. Configure the web.xml file that is in the <IOTS_HOME>/repository/deployment/server/webapps/api#device-mgt#android#v1.0/WEB-INF directory by adding the content given below.

    • 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.
    <!--For Mutual SSL enabling, please uncomment login-config and security-constraint tags-->
    <login-config>
       <auth-method>CLIENT-CERT</auth-method>
    </login-config>
  2. 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
  3. 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.


    1. Generate the private key.

      openssl genrsa -out <CA PRIVATE KEY> 4096

      Example:

      openssl genrsa -out ca_private.key 4096
    2. Generate a certificate signing request (CSR).

      Provide the server IP/hostname as the common name when prompted.

      openssl req -new -key <CA PRIVATE KEY> -out <CA CSR> 

      Example:

      openssl req -new -key ca_private.key -out ca.csr
    3. 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
    4. 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
    5. 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
  4. Generate the SSL certificate (version 3) based on your domain/IP address:
    1. Generate a private key.

      openssl genrsa -out <RSA_key>.key 4096 

      Example:

      openssl genrsa -out ia.key 4096
    2. 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
    3. 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
  5. Generate the client-side SSL certificate (version 3):
    1. Generate a private key.

      openssl genrsa -out <CLIENT_key>.key 4096 

      Example:

      openssl genrsa -out client.key 4096
    2. 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
    3. 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
    4. 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
  6. Copy the 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 
  7. 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.

  8. Export the wso2carbon certificate that is in the <IoT_HOME>/core/repository/resources/security directory to the .pem format suing the command given below.

    keytool -exportcert -alias wso2carbon -keystore wso2carbon.jks -rfc -file cert_pem.pem -deststorepass wso2carbon -srcstorepass wso2carbon -noprompt
  9. Copying the command given below the content between BEGIN CERTIFICATE and END CERTIFICATE tags of the cert_pem.pem file you just generated and paste it within the <Certificate> tag of the <IOTS_HOME>/conf/identity/identity-providers/iot_default.xml file.

  10. Enable Mutual SSL in the WSO2 IoT Server API Gateway by configuring the <IOTS_HOME>/conf/axis2/axis2.xml file. Make sure to configure the property that is under the HTTPS transport receiver as shown below.

    <parameter name="SSLVerifyClient">optional</parameter>
  11. Restart the server and upload the generated certificate in step 5.d above, to the certificate section of the device management console or add the certificate to the database via the REST API.

  12. 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'
  13. 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'

  14. 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.

  15. Navigate to the Constants.java file, which is under the org.wso2.iot.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 for AUTHENTICATOR_IN_USE.

      public static final String AUTHENTICATOR_IN_USE = MUTUAL_SSL_AUTHENTICATOR;
    • Assign MUTUAL_HTTP_CLIENT as the value for HTTP_CLIENT_IN_USE.

      public static final String HTTP_CLIENT_IN_USE = MUTUAL_HTTP_CLIENT;
    • Assign https as the value for SERVER_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 and KEYSTORE_PASSWORD fields with the password that was used and if the certificates are stored in the device storage, configure TRUSTSTORE_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>";
  16. Navigate to the <ANDROID_AGENT_SOURCE_CODE>/client/client/src/main/java/org/wso2/iot/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 and OWNERSHIP_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 to true.

      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.

       Click here to view the screen where you have to enter the server URL

      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:8243";
    • 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 workdata 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;
  17. 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:

  1. Tap the WSO2 agent application and open it.

  2. 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.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.