Merge pull request #297 from Shabirmean/master

Modifications to incorporate token-refresh for Virtual Firealarm
revert-dabc3590
Ruwan 9 years ago
commit 71f972d027

@ -173,6 +173,13 @@
<artifactId>json</artifactId> <artifactId>json</artifactId>
</dependency> </dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
</dependencies> </dependencies>

@ -23,12 +23,12 @@ import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http.HTTPTransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http.HTTPTransportHandler;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -191,21 +191,19 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
private void executeDataPush(String pushDataPayload) { private void executeDataPush(String pushDataPayload) {
AgentManager agentManager = AgentManager.getInstance(); AgentManager agentManager = AgentManager.getInstance();
int responseCode = -1;
String pushDataEndPointURL = agentManager.getPushDataAPIEP(); String pushDataEndPointURL = agentManager.getPushDataAPIEP();
HttpURLConnection httpConnection = null; HttpURLConnection httpConnection;
int responseCode = -1;
try { try {
httpConnection = TransportUtils.getHttpConnection(agentManager.getPushDataAPIEP()); httpConnection = TransportUtils.getHttpConnection(agentManager.getPushDataAPIEP());
httpConnection.setRequestMethod(AgentConstants.HTTP_POST); httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty("Authorization", "Bearer " + httpConnection.setRequestProperty("Authorization",
agentManager.getAgentConfigs().getAuthToken()); "Bearer " + agentManager.getAgentConfigs().getAuthToken());
httpConnection.setRequestProperty("Content-Type", httpConnection.setRequestProperty("Content-Type", AgentConstants.APPLICATION_JSON);
AgentConstants.APPLICATION_JSON_TYPE);
httpConnection.setDoOutput(true); httpConnection.setDoOutput(true);
DataOutputStream dataOutPutWriter = new DataOutputStream( DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
httpConnection.getOutputStream());
dataOutPutWriter.writeBytes(pushDataPayload); dataOutPutWriter.writeBytes(pushDataPayload);
dataOutPutWriter.flush(); dataOutPutWriter.flush();
dataOutPutWriter.close(); dataOutPutWriter.close();
@ -225,39 +223,34 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
} catch (IOException exception) { } catch (IOException exception) {
String errorMsg = String errorMsg =
"An IO error occurred whilst trying to get the response code from: " + "An IO error occurred whilst trying to get the response code from: " +
pushDataEndPointURL + " for a " + AgentConstants.HTTP_POST + pushDataEndPointURL + " for a " + AgentConstants.HTTP_POST + " method.";
" " + "method.";
log.error(AgentConstants.LOG_APPENDER + errorMsg); log.error(AgentConstants.LOG_APPENDER + errorMsg);
} catch (TransportHandlerException exception) { } catch (TransportHandlerException exception) {
log.error(AgentConstants.LOG_APPENDER + log.error(AgentConstants.LOG_APPENDER +
"Error encountered whilst trying to create HTTP-Connection " + "Error encountered whilst trying to create HTTP-Connection to IoT-Server EP at: " +
"to IoT-Server EP at: " +
pushDataEndPointURL); pushDataEndPointURL);
} }
if (responseCode == HttpStatus.CONFLICT_409 || if (responseCode == HttpStatus.CONFLICT_409 ||
responseCode == HttpStatus.PRECONDITION_FAILED_412) { responseCode == HttpStatus.PRECONDITION_FAILED_412) {
log.warn(AgentConstants.LOG_APPENDER + log.warn(AgentConstants.LOG_APPENDER +
"DeviceIP is being Re-Registered due to Push-Data failure " + "DeviceIP is being Re-Registered due to Push-Data failure with response code: " +
"with response code: " +
responseCode); responseCode);
registerThisDevice(); registerThisDevice();
} else if (responseCode != HttpStatus.NO_CONTENT_204) { } else if (responseCode != HttpStatus.NO_CONTENT_204) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.error(AgentConstants.LOG_APPENDER + "Status Code: " + responseCode + log.error(AgentConstants.LOG_APPENDER + "Status Code: " + responseCode +
" encountered whilst trying to Push-Device-Data to IoT " + " encountered whilst trying to Push-Device-Data to IoT Server at: " +
"Server at: " +
agentManager.getPushDataAPIEP()); agentManager.getPushDataAPIEP());
} }
agentManager.updateAgentStatus(AgentConstants.SERVER_NOT_RESPONDING); agentManager.updateAgentStatus(AgentConstants.SERVER_NOT_RESPONDING);
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug(AgentConstants.LOG_APPENDER + "Push-Data call with payload - " + log.debug(AgentConstants.LOG_APPENDER + "Push-Data call with payload - " + pushDataPayload +
pushDataPayload + ", to IoT Server returned status " + ", to IoT Server returned status " + responseCode);
responseCode);
} }
} }
@ -272,16 +265,14 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
closeConnection(); closeConnection();
} catch (Exception e) { } catch (Exception e) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.warn(AgentConstants.LOG_APPENDER + log.warn(AgentConstants.LOG_APPENDER + "Unable to 'STOP' HTTP server at port: " + port);
"Unable to 'STOP' HTTP server at port: " + port);
} }
try { try {
Thread.sleep(timeoutInterval); Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
log.error(AgentConstants.LOG_APPENDER + log.error(
"HTTP-Termination: Thread Sleep Interrupt " + AgentConstants.LOG_APPENDER + "HTTP-Termination: Thread Sleep Interrupt Exception");
"Exception");
} }
} }
} }
@ -398,8 +389,7 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
String errorMsg = String errorMsg =
"Protocol specific error occurred when trying to fetch an HTTPConnection to:" + "Protocol specific error occurred when trying to fetch an HTTPConnection to:" +
" " + " " + registerEndpointURLString;
registerEndpointURLString;
log.error(AgentConstants.LOG_APPENDER + errorMsg); log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(); throw new AgentCoreOperationException();
} }
@ -419,8 +409,7 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
} catch (IOException exception) { } catch (IOException exception) {
String errorMsg = "An IO error occurred whilst trying to get the response code from:" + String errorMsg = "An IO error occurred whilst trying to get the response code from:" +
" " + " " + registerEndpointURLString + " for a " + AgentConstants.HTTP_POST + " method.";
registerEndpointURLString + " for a " + AgentConstants.HTTP_POST + " method.";
log.error(AgentConstants.LOG_APPENDER + errorMsg); log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, exception); throw new AgentCoreOperationException(errorMsg, exception);
} }
@ -436,7 +425,7 @@ public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
/*------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------*/
/* Utility methods relevant to creating and sending HTTP requests to the Iot-Server */ /* Utility methods relevant to creating and sending HTTP requests to the Iot-Server */
/*------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------*/
/** /**
* This method is used to get the IP of the device in which the agent is run on. * This method is used to get the IP of the device in which the agent is run on.

@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
@ -35,13 +36,14 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
//TODO:: Lincense heade, comments and SPECIFIC class name since its not generic //TODO:: Lincence header, comments and SPECIFIC class name since its not generic
public class FireAlarmMQTTCommunicator extends MQTTTransportHandler { public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
private static final Log log = LogFactory.getLog(FireAlarmMQTTCommunicator.class); private static final Log log = LogFactory.getLog(FireAlarmMQTTCommunicator.class);
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2); private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
private ScheduledFuture<?> dataPushServiceHandler; private ScheduledFuture<?> dataPushServiceHandler;
private static final String DEFAULT_PASSWORD = "";
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType, public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
String mqttBrokerEndPoint, String subscribeTopic) { String mqttBrokerEndPoint, String subscribeTopic) {
@ -68,18 +70,23 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
public void run() { public void run() {
while (!isConnected()) { while (!isConnected()) {
try { try {
connectToQueue(); connectToQueue(agentManager.getAgentConfigs().getAuthToken(), DEFAULT_PASSWORD);
agentManager.updateAgentStatus("Connected to MQTT Queue"); agentManager.updateAgentStatus("Connected to MQTT Queue");
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Connection to MQTT Broker at: " + mqttBrokerEndPoint + log.warn(AgentConstants.LOG_APPENDER + "Connection to MQTT Broker at: " + mqttBrokerEndPoint +
" failed.\n Will retry in " + timeoutInterval + " milli-seconds."); " failed.\n Will retry in " + timeoutInterval + " milli-seconds.");
}
try{ if (e.getCause() != null && e.getCause() instanceof MqttSecurityException) {
subscribeToQueue(); refreshOAuthToken((MqttSecurityException) e.getCause());
agentManager.updateAgentStatus("Subscribed to MQTT Queue"); }
publishDeviceData(); }
try {
if (isConnected()) {
subscribeToQueue();
agentManager.updateAgentStatus("Subscribed to MQTT Queue");
publishDeviceData();
}
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Subscription to MQTT Broker at: " + log.warn(AgentConstants.LOG_APPENDER + "Subscription to MQTT Broker at: " +
mqttBrokerEndPoint + " failed"); mqttBrokerEndPoint + " failed");
@ -100,6 +107,26 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
connectorThread.start(); connectorThread.start();
} }
private void refreshOAuthToken(final MqttSecurityException exception) {
Runnable tokenRefresher = new Runnable() {
public void run() {
String authenticationMethod = AgentUtilOperations.getAuthenticationMethod();
try {
if (exception.getReasonCode() == MqttSecurityException.REASON_CODE_FAILED_AUTHENTICATION &&
authenticationMethod.equals(AgentConstants.TOKEN_AUTHENTICATION_METHOD)) {
AgentUtilOperations.refreshOAuthToken();
}
} catch (AgentCoreOperationException e1) {
log.error(AgentConstants.LOG_APPENDER + "Token Refresh Attempt Failed. " + e1);
}
}
};
Thread connectorThread = new Thread(tokenRefresher);
connectorThread.setDaemon(true);
connectorThread.start();
}
@Override @Override
public void processIncomingMessage(MqttMessage message, String... messageParams) { public void processIncomingMessage(MqttMessage message, String... messageParams) {

@ -24,150 +24,159 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
* downloading the device agent from the IoT-Server. * downloading the device agent from the IoT-Server.
*/ */
public class AgentConfiguration { public class AgentConfiguration {
private String tenantDomain; private String tenantDomain;
private String deviceOwner; private String deviceOwner;
private String deviceId; private String deviceId;
private String deviceName; private String deviceName;
private String controllerContext; private String controllerContext;
private String scepContext; private String scepContext;
private String HTTPS_ServerEndpoint; private String HTTPS_ServerEndpoint;
private String HTTP_ServerEndpoint; private String HTTP_ServerEndpoint;
private String apimGatewayEndpoint; private String apimGatewayEndpoint;
private String mqttBrokerEndpoint; private String mqttBrokerEndpoint;
private String xmppServerEndpoint; private String xmppServerEndpoint;
private String authMethod; private String apiApplicationKey;
private String authToken; private String authMethod;
private String refreshToken; private String authToken;
private int dataPushInterval; private String refreshToken;
private String xmppServerName; private int dataPushInterval;
private String xmppServerName;
public String getTenantDomain() {
return tenantDomain; public String getTenantDomain() {
} return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain; public void setTenantDomain(String tenantDomain) {
} this.tenantDomain = tenantDomain;
}
public String getDeviceOwner() {
return deviceOwner; public String getDeviceOwner() {
} return deviceOwner;
}
public void setDeviceOwner(String deviceOwner) {
this.deviceOwner = deviceOwner; public void setDeviceOwner(String deviceOwner) {
} this.deviceOwner = deviceOwner;
}
public String getDeviceId() {
return deviceId; public String getDeviceId() {
} return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId; public void setDeviceId(String deviceId) {
} this.deviceId = deviceId;
}
public String getDeviceName() {
return deviceName; public String getDeviceName() {
} return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName; public void setDeviceName(String deviceName) {
} this.deviceName = deviceName;
}
public String getControllerContext() {
return controllerContext; public String getControllerContext() {
} return controllerContext;
}
public void setControllerContext(String controllerContext) {
this.controllerContext = controllerContext; public void setControllerContext(String controllerContext) {
} this.controllerContext = controllerContext;
}
public String getHTTPS_ServerEndpoint() {
return HTTPS_ServerEndpoint; public String getHTTPS_ServerEndpoint() {
} return HTTPS_ServerEndpoint;
}
public void setHTTPS_ServerEndpoint(String HTTPS_ServerEndpoint) {
this.HTTPS_ServerEndpoint = HTTPS_ServerEndpoint; public void setHTTPS_ServerEndpoint(String HTTPS_ServerEndpoint) {
} this.HTTPS_ServerEndpoint = HTTPS_ServerEndpoint;
}
public String getHTTP_ServerEndpoint() {
return HTTP_ServerEndpoint; public String getHTTP_ServerEndpoint() {
} return HTTP_ServerEndpoint;
}
public void setHTTP_ServerEndpoint(String HTTP_ServerEndpoint) {
this.HTTP_ServerEndpoint = HTTP_ServerEndpoint; public void setHTTP_ServerEndpoint(String HTTP_ServerEndpoint) {
} this.HTTP_ServerEndpoint = HTTP_ServerEndpoint;
}
public String getApimGatewayEndpoint() {
return apimGatewayEndpoint; public String getApimGatewayEndpoint() {
} return apimGatewayEndpoint;
}
public void setApimGatewayEndpoint(String apimGatewayEndpoint) {
this.apimGatewayEndpoint = apimGatewayEndpoint; public void setApimGatewayEndpoint(String apimGatewayEndpoint) {
} this.apimGatewayEndpoint = apimGatewayEndpoint;
}
public String getMqttBrokerEndpoint() {
return mqttBrokerEndpoint; public String getMqttBrokerEndpoint() {
} return mqttBrokerEndpoint;
}
public void setMqttBrokerEndpoint(String mqttBrokerEndpoint) {
this.mqttBrokerEndpoint = mqttBrokerEndpoint; public void setMqttBrokerEndpoint(String mqttBrokerEndpoint) {
} this.mqttBrokerEndpoint = mqttBrokerEndpoint;
}
public String getXmppServerEndpoint() {
return xmppServerEndpoint; public String getXmppServerEndpoint() {
} return xmppServerEndpoint;
}
public void setXmppServerEndpoint(String xmppServerEndpoint) {
this.xmppServerEndpoint = xmppServerEndpoint; public void setXmppServerEndpoint(String xmppServerEndpoint) {
} this.xmppServerEndpoint = xmppServerEndpoint;
}
public String getAuthMethod() {
return authMethod; public String getApiApplicationKey() {
} return apiApplicationKey;
}
public void setAuthMethod(String authMethod) {
this.authMethod = authMethod; public void setApiApplicationKey(String apiApplicationKey) {
} this.apiApplicationKey = apiApplicationKey;
}
public String getAuthToken() {
return authToken; public String getAuthMethod() {
} return authMethod;
}
public void setAuthToken(String authToken) {
this.authToken = authToken; public void setAuthMethod(String authMethod) {
} this.authMethod = authMethod;
}
public String getRefreshToken() {
return refreshToken; public String getAuthToken() {
} return authToken;
}
public void setRefreshToken(String refreshToken) { public void setAuthToken(String authToken) {
this.refreshToken = refreshToken; this.authToken = authToken;
} }
public int getDataPushInterval() { public String getRefreshToken() {
return dataPushInterval; return refreshToken;
} }
public void setDataPushInterval(int dataPushInterval) { public void setRefreshToken(String refreshToken) {
this.dataPushInterval = dataPushInterval; this.refreshToken = refreshToken;
} }
public String getScepContext() { public int getDataPushInterval() {
return scepContext; return dataPushInterval;
} }
public void setScepContext(String scepContext) { public void setDataPushInterval(int dataPushInterval) {
this.scepContext = scepContext; this.dataPushInterval = dataPushInterval;
} }
public String getXmppServerName() { public String getScepContext() {
return xmppServerName; return scepContext;
} }
public void setXmppServerName(String xmppServerName) { public void setScepContext(String scepContext) {
this.xmppServerName = xmppServerName; this.scepContext = scepContext;
} }
public String getXmppServerName() {
return xmppServerName;
}
public void setXmppServerName(String xmppServerName) {
this.xmppServerName = xmppServerName;
}
} }

@ -19,94 +19,109 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
public class AgentConstants { public class AgentConstants {
public static final String DEVICE_TYPE = "virtual_firealarm"; public static final String DEVICE_TYPE = "virtual_firealarm";
public static final String LOG_APPENDER = "AGENT_LOG:: "; public static final String LOG_APPENDER = "AGENT_LOG:: ";
public static final String PROPERTIES_FILE_PATH = ""; public static final String PROPERTIES_FILE_PATH = "";
public static final int DEFAULT_RETRY_THREAD_INTERVAL = 5000; // time in millis public static final int DEFAULT_RETRY_THREAD_INTERVAL = 5000; // time in millis
/* --------------------------------------------------------------------------------------- public static final String TOKEN_AUTHENTICATION_METHOD = "token";
IoT-Server specific information /* ---------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------- */ IoT-Server specific information
public static final String DEVICE_CONTROLLER_API_EP = "/virtual_firealarm/controller"; --------------------------------------------------------------------------------------- */
public static final String DEVICE_ENROLLMENT_API_EP = "/scep"; public static final String DEVICE_ENROLLMENT_API_EP = "/scep";
public static final String DEVICE_REGISTER_API_EP = "/register"; public static final String DEVICE_REGISTER_API_EP = "/register";
public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/temperature"; public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/temperature";
public static final String PUSH_DATA_PAYLOAD = public static final String PUSH_DATA_PAYLOAD =
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\"}"; "{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\"}";
public static final String PUSH_SIMULATION_DATA_PAYLOAD = public static final String PUSH_SIMULATION_DATA_PAYLOAD =
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\",\"isSimulated\":\"%s\",\"duration\":\"%s\",\"frequency\":\"%s\"}"; "{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\",\"isSimulated\":\"%s\"," +
"\"duration\":\"%s\",\"frequency\":\"%s\"}";
public static final String AGENT_CONTROL_APP_EP = "/devicemgt/device/%s?id=%s"; public static final String DEVICE_DETAILS_PAGE_EP = "/devicemgt/device/%s?id=%s";
public static final String DEVICE_DETAILS_PAGE_EP = "/devicemgt/device/%s?id=%s"; public static final String DEVICE_ANALYTICS_PAGE_URL =
public static final String DEVICE_ANALYTICS_PAGE_URL = "/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s"; "/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s";
/* --------------------------------------------------------------------------------------- /* ---------------------------------------------------------------------------------------
HTTP Connection specific information for communicating with IoT-Server HTTP Connection specific information for communicating with IoT-Server
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
public static final String HTTP_POST = "POST"; public static final String HTTP_POST = "POST";
public static final String HTTP_GET = "GET"; public static final String HTTP_GET = "GET";
public static final String APPLICATION_JSON_TYPE = "application/json"; public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String REGISTERED = "Registered"; public static final String CONTENT_TYPE_HEADER = "Content-Type";
public static final String NOT_REGISTERED = "Not-Registered"; public static final String APPLICATION_JSON = "application/json";
public static final String REGISTRATION_FAILED = "Registration Failed"; public static final String X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
public static final String RETRYING_TO_REGISTER = "Registration Failed. Re-trying.."; public static final String REGISTERED = "Registered";
public static final String SERVER_NOT_RESPONDING = "Server not responding.."; public static final String NOT_REGISTERED = "Not-Registered";
public static final String REGISTRATION_FAILED = "Registration Failed";
public static final String RETRYING_TO_REGISTER = "Registration Failed. Re-trying..";
public static final String SERVER_NOT_RESPONDING = "Server not responding..";
/* --------------------------------------------------------------------------------------- /* ---------------------------------------------------------------------------------------
MQTT Connection specific information MQTT Connection specific information
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s"; public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/publisher"; public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/publisher";
/* ---------------------------------------------------------------------------------------
XMPP Connection specific information /* ---------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------- */ Device/Agent specific properties to be read from the 'deviceConfig.properties' file
public static final String XMPP_ADMIN_ACCOUNT_UNAME = "admin"; --------------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------------- public static final String AGENT_PROPERTIES_FILE_NAME = "deviceConfig.properties";
Device/Agent specific properties to be read from the 'deviceConfig.properties' file public static final String TENANT_DOMAIN = "tenantDomain";
--------------------------------------------------------------------------------------- */ public static final String DEVICE_OWNER_PROPERTY = "owner";
public static final String AGENT_PROPERTIES_FILE_NAME = "deviceConfig.properties"; public static final String DEVICE_ID_PROPERTY = "deviceId";
public static final String TENANT_DOMAIN = "tenantDomain"; public static final String DEVICE_NAME_PROPERTY = "device-name";
public static final String DEVICE_OWNER_PROPERTY = "owner"; public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context";
public static final String DEVICE_ID_PROPERTY = "deviceId"; public static final String DEVICE_SCEP_CONTEXT_PROPERTY = "scep-context";
public static final String DEVICE_NAME_PROPERTY = "device-name"; public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep";
public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context"; public static final String SERVER_HTTP_EP_PROPERTY = "http-ep";
public static final String DEVICE_SCEP_CONTEXT_PROPERTY = "scep-context"; public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep";
public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep"; public static final String MQTT_BROKER_EP_PROPERTY = "mqtt-ep";
public static final String SERVER_HTTP_EP_PROPERTY = "http-ep"; public static final String XMPP_SERVER_EP_PROPERTY = "xmpp-ep";
public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep"; public static final String XMPP_SERVER_NAME_PROPERTY = "xmpp-server-name";
public static final String MQTT_BROKER_EP_PROPERTY = "mqtt-ep"; public static final String API_APPLICATION_KEY = "application-key";
public static final String XMPP_SERVER_EP_PROPERTY = "xmpp-ep"; public static final String AUTH_METHOD_PROPERTY = "auth-method";
public static final String XMPP_SERVER_NAME_PROPERTY = "xmpp-server-name"; public static final String AUTH_TOKEN_PROPERTY = "auth-token";
public static final String AUTH_METHOD_PROPERTY = "auth-method"; public static final String REFRESH_TOKEN_PROPERTY = "refresh-token";
public static final String AUTH_TOKEN_PROPERTY = "auth-token"; public static final String NETWORK_INTERFACE_PROPERTY = "network-interface";
public static final String REFRESH_TOKEN_PROPERTY = "refresh-token"; public static final String PUSH_INTERVAL_PROPERTY = "push-interval";
public static final String NETWORK_INTERFACE_PROPERTY = "network-interface"; /* ---------------------------------------------------------------------------------------
public static final String PUSH_INTERVAL_PROPERTY = "push-interval"; Default values for the Device/Agent specific configurations listed above
/* --------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------- */
Default values for the Device/Agent specific configurations listed above public static final String DEFAULT_NETWORK_INTERFACE = "en0";
--------------------------------------------------------------------------------------- */ public static final int DEFAULT_DATA_PUBLISH_INTERVAL = 15; // seconds
public static final String DEFAULT_NETWORK_INTERFACE = "en0"; public static final String DEFAULT_PROTOCOL = "MQTT";
public static final int DEFAULT_DATA_PUBLISH_INTERVAL = 15; // seconds /* ---------------------------------------------------------------------------------------
public static final String DEFAULT_PROTOCOL = "MQTT"; Control Signal specific constants to match the request context
/* --------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------- */
Control Signal specific constants to match the request context public static final String BULB_CONTROL = "BULB";
--------------------------------------------------------------------------------------- */ public static final String TEMPERATURE_CONTROL = "TEMPERATURE";
public static final String BULB_CONTROL = "BULB"; public static final String POLICY_SIGNAL = "POLICY";
public static final String TEMPERATURE_CONTROL = "TEMPERATURE"; public static final String HUMIDITY_CONTROL = "HUMIDITY";
public static final String POLICY_SIGNAL = "POLICY"; public static final String CONTROL_ON = "ON";
public static final String HUMIDITY_CONTROL = "HUMIDITY"; public static final String CONTROL_OFF = "OFF";
public static final String CONTROL_ON = "ON"; public static final String AUDIO_FILE_NAME = "fireAlarmSound.mid";
public static final String CONTROL_OFF = "OFF"; /* ---------------------------------------------------------------------------------------
public static final String AUDIO_FILE_NAME = "fireAlarmSound.mid"; Communication protocol specific Strings
/* --------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------- */
Communication protocol specific Strings public static final String TCP_PREFIX = "tcp://";
--------------------------------------------------------------------------------------- */ public static final String HTTP_PREFIX = "http://";
public static final String TCP_PREFIX = "tcp://"; public static final String HTTPS_PREFIX = "https://";
public static final String HTTP_PREFIX = "http://"; public static final String HTTP_PROTOCOL = "HTTP";
public static final String HTTPS_PREFIX = "https://"; public static final String MQTT_PROTOCOL = "MQTT";
public static final String HTTP_PROTOCOL = "HTTP"; public static final String XMPP_PROTOCOL = "XMPP";
public static final String MQTT_PROTOCOL = "MQTT"; public static final String PROTOCOL_PROPERTY = "Protocol";
public static final String XMPP_PROTOCOL = "XMPP"; public static final String HOST_PROPERTY = "Host";
public static final String PORT_PROPERTY = "Port";
/* ---------------------------------------------------------------------------------------
Keystore specific strings for the device trustStore
--------------------------------------------------------------------------------------- */
public static final String DEVICE_KEYSTORE_TYPE = "JKS";
public static final String DEVICE_KEYSTORE = "virtual_firealarm.jks";
public static final String DEVICE_KEYSTORE_PASSWORD = "wso2@virtual_firealarm";
public static final String DEVICE_PRIVATE_KEY_ALIAS = "virtual_firealarm_key";
public static final String DEVICE_CERT_ALIAS = "virtual_firealarm_cert";
public static final String SERVER_CA_CERT_ALIAS = "ca_iotServer";
} }

@ -20,14 +20,14 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http.FireAlarmHTTPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt.FireAlarmMQTTCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.xmpp.FireAlarmXMPPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http.FireAlarmHTTPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt.FireAlarmMQTTCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.xmpp.FireAlarmXMPPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager;
import java.util.ArrayList; import java.util.ArrayList;
@ -74,18 +74,19 @@ public class AgentManager {
public void init() { public void init() {
agentCommunicator = new HashMap<>(); agentCommunicator = new HashMap<>();
// Read IoT-Server specific configurations from the 'deviceConfig.properties' file // Read IoT-Server specific configurations from the 'deviceConfig.properties' file
try { try {
this.agentConfigs = AgentUtilOperations.readIoTServerConfigs(); this.agentConfigs = AgentUtilOperations.readIoTServerConfigs();
} catch (AgentCoreOperationException e) { } catch (AgentCoreOperationException e) {
log.error("Reading device configuration from configd file failed:\n"); log.error("Reading device configuration from configuration file failed:\n");
log.error(e); log.error(e);
System.exit(0); System.exit(0);
} }
// Initialise IoT-Server URL endpoints from the configuration read from file // Initialise IoT-Server URL endpoints from the configuration read from file
AgentUtilOperations.initializeServerEndPoints(); AgentUtilOperations.initializeServerEndPoints();
// Set the hostNameVerifier to the APIM-Server IPAddress to enable HTTPS handshake
AgentUtilOperations.setHTTPSConfigurations();
String analyticsPageContext = String.format(AgentConstants.DEVICE_ANALYTICS_PAGE_URL, String analyticsPageContext = String.format(AgentConstants.DEVICE_ANALYTICS_PAGE_URL,
agentConfigs.getDeviceId(), agentConfigs.getDeviceId(),
@ -153,7 +154,9 @@ public class AgentManager {
} }
try { try {
EnrollmentManager.getInstance().beginEnrollmentFlow(); if (!EnrollmentManager.getInstance().isEnrolled()) {
EnrollmentManager.getInstance().beginEnrollmentFlow();
}
} catch (AgentCoreOperationException e) { } catch (AgentCoreOperationException e) {
log.error("Device Enrollment Failed:\n"); log.error("Device Enrollment Failed:\n");
log.error(e); log.error(e);
@ -217,12 +220,16 @@ public class AgentManager {
/*------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------*/
/* Getter and Setter Methods for the private variables */ /* Getter and Setter Methods for the private variables */
/*------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------*/
public void setRootPath(String rootPath) { public void setRootPath(String rootPath) {
this.rootPath = rootPath; this.rootPath = rootPath;
} }
public String getRootPath() {
return rootPath;
}
public void setDeviceReady(boolean deviceReady) { public void setDeviceReady(boolean deviceReady) {
this.deviceReady = deviceReady; this.deviceReady = deviceReady;
} }
@ -324,6 +331,7 @@ public class AgentManager {
/** /**
* Get temperature reading from device * Get temperature reading from device
*
* @return Temperature * @return Temperature
*/ */
public int getTemperature() { public int getTemperature() {
@ -332,9 +340,10 @@ public class AgentManager {
/** /**
* Get humidity reading from device * Get humidity reading from device
*
* @return Humidity * @return Humidity
*/ */
public int getHumidity(){ public int getHumidity() {
return VirtualHardwareManager.getInstance().getHumidity(); return VirtualHardwareManager.getInstance().getHumidity();
} }

@ -19,19 +19,30 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.json.JSONObject; import org.json.JSONObject;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.CommunicationUtils; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.CommunicationUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import java.io.File; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -67,94 +78,104 @@ public class AgentUtilOperations {
Properties properties = new Properties(); Properties properties = new Properties();
InputStream propertiesInputStream = null; InputStream propertiesInputStream = null;
String propertiesFileName = AgentConstants.AGENT_PROPERTIES_FILE_NAME; String propertiesFileName = AgentConstants.AGENT_PROPERTIES_FILE_NAME;
String rootPath = "";
try { try {
ClassLoader loader = AgentUtilOperations.class.getClassLoader(); ClassLoader loader = AgentUtilOperations.class.getClassLoader();
URL path = loader.getResource(propertiesFileName); URL path = loader.getResource(propertiesFileName);
System.out.println(path);
String root = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
.replace("jar:", "").replace("file:", "");
root = URLDecoder.decode(root, StandardCharsets.UTF_8.toString());
agentManager.setRootPath(root);
String deviceConfigFilePath = root + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
propertiesInputStream = new FileInputStream(deviceConfigFilePath);
//load a properties file from class path, inside static method
properties.load(propertiesInputStream);
iotServerConfigs.setTenantDomain(properties.getProperty(
AgentConstants.TENANT_DOMAIN));
iotServerConfigs.setDeviceOwner(properties.getProperty(
AgentConstants.DEVICE_OWNER_PROPERTY));
iotServerConfigs.setDeviceId(properties.getProperty(
AgentConstants.DEVICE_ID_PROPERTY));
iotServerConfigs.setDeviceName(properties.getProperty(
AgentConstants.DEVICE_NAME_PROPERTY));
iotServerConfigs.setControllerContext(properties.getProperty(
AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY));
iotServerConfigs.setScepContext(properties.getProperty(
AgentConstants.DEVICE_SCEP_CONTEXT_PROPERTY));
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTPS_EP_PROPERTY));
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTP_EP_PROPERTY));
iotServerConfigs.setApimGatewayEndpoint(properties.getProperty(
AgentConstants.APIM_GATEWAY_EP_PROPERTY));
iotServerConfigs.setMqttBrokerEndpoint(properties.getProperty(
AgentConstants.MQTT_BROKER_EP_PROPERTY));
iotServerConfigs.setXmppServerEndpoint(properties.getProperty(
AgentConstants.XMPP_SERVER_EP_PROPERTY));
iotServerConfigs.setXmppServerName(properties.getProperty(
AgentConstants.XMPP_SERVER_NAME_PROPERTY));
iotServerConfigs.setAuthMethod(properties.getProperty(
AgentConstants.AUTH_METHOD_PROPERTY));
iotServerConfigs.setAuthToken(properties.getProperty(
AgentConstants.AUTH_TOKEN_PROPERTY));
iotServerConfigs.setRefreshToken(properties.getProperty(
AgentConstants.REFRESH_TOKEN_PROPERTY));
iotServerConfigs.setDataPushInterval(Integer.parseInt(properties.getProperty(
AgentConstants.PUSH_INTERVAL_PROPERTY)));
log.info(AgentConstants.LOG_APPENDER + "Tenant Domain: " +
iotServerConfigs.getTenantDomain());
log.info(AgentConstants.LOG_APPENDER + "Device Owner: " +
iotServerConfigs.getDeviceOwner());
log.info(AgentConstants.LOG_APPENDER + "Device ID: " + iotServerConfigs.getDeviceId());
log.info(AgentConstants.LOG_APPENDER + "Device Name: " +
iotServerConfigs.getDeviceName());
log.info(AgentConstants.LOG_APPENDER + "Device Controller Context: " +
iotServerConfigs.getControllerContext());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTPS EndPoint: " +
iotServerConfigs.getHTTPS_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTP EndPoint: " +
iotServerConfigs.getHTTP_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "API-Manager Gateway EndPoint: " +
iotServerConfigs.getApimGatewayEndpoint());
log.info(AgentConstants.LOG_APPENDER + "MQTT Broker EndPoint: " +
iotServerConfigs.getMqttBrokerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server EndPoint: " +
iotServerConfigs.getXmppServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "Authentication Method: " +
iotServerConfigs.getAuthMethod());
log.info(AgentConstants.LOG_APPENDER + "Authentication Token: " +
iotServerConfigs.getAuthToken());
log.info(AgentConstants.LOG_APPENDER + "Refresh Token: " +
iotServerConfigs.getRefreshToken());
log.info(AgentConstants.LOG_APPENDER + "Data Push Interval: " +
iotServerConfigs.getDataPushInterval());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server Name: " +
iotServerConfigs.getXmppServerName());
if (path != null) {
log.info(AgentConstants.LOG_APPENDER + path);
rootPath = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
.replace("jar:", "").replace("file:", "");
rootPath = URLDecoder.decode(rootPath, StandardCharsets.UTF_8.toString());
agentManager.setRootPath(rootPath);
String deviceConfigFilePath = rootPath + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
propertiesInputStream = new FileInputStream(deviceConfigFilePath);
//load a properties file from class path, inside static method
properties.load(propertiesInputStream);
iotServerConfigs.setTenantDomain(properties.getProperty(
AgentConstants.TENANT_DOMAIN));
iotServerConfigs.setDeviceOwner(properties.getProperty(
AgentConstants.DEVICE_OWNER_PROPERTY));
iotServerConfigs.setDeviceId(properties.getProperty(
AgentConstants.DEVICE_ID_PROPERTY));
iotServerConfigs.setDeviceName(properties.getProperty(
AgentConstants.DEVICE_NAME_PROPERTY));
iotServerConfigs.setControllerContext(properties.getProperty(
AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY));
iotServerConfigs.setScepContext(properties.getProperty(
AgentConstants.DEVICE_SCEP_CONTEXT_PROPERTY));
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTPS_EP_PROPERTY));
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTP_EP_PROPERTY));
iotServerConfigs.setApimGatewayEndpoint(properties.getProperty(
AgentConstants.APIM_GATEWAY_EP_PROPERTY));
iotServerConfigs.setMqttBrokerEndpoint(properties.getProperty(
AgentConstants.MQTT_BROKER_EP_PROPERTY));
iotServerConfigs.setXmppServerEndpoint(properties.getProperty(
AgentConstants.XMPP_SERVER_EP_PROPERTY));
iotServerConfigs.setXmppServerName(properties.getProperty(
AgentConstants.XMPP_SERVER_NAME_PROPERTY));
iotServerConfigs.setApiApplicationKey(properties.getProperty(
AgentConstants.API_APPLICATION_KEY));
iotServerConfigs.setAuthMethod(properties.getProperty(
AgentConstants.AUTH_METHOD_PROPERTY));
iotServerConfigs.setAuthToken(properties.getProperty(
AgentConstants.AUTH_TOKEN_PROPERTY));
iotServerConfigs.setRefreshToken(properties.getProperty(
AgentConstants.REFRESH_TOKEN_PROPERTY));
iotServerConfigs.setDataPushInterval(Integer.parseInt(properties.getProperty(
AgentConstants.PUSH_INTERVAL_PROPERTY)));
log.info(AgentConstants.LOG_APPENDER + "Tenant Domain: " +
iotServerConfigs.getTenantDomain());
log.info(AgentConstants.LOG_APPENDER + "Device Owner: " +
iotServerConfigs.getDeviceOwner());
log.info(AgentConstants.LOG_APPENDER + "Device ID: " + iotServerConfigs.getDeviceId());
log.info(AgentConstants.LOG_APPENDER + "Device Name: " +
iotServerConfigs.getDeviceName());
log.info(AgentConstants.LOG_APPENDER + "Device Controller Context: " +
iotServerConfigs.getControllerContext());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTPS EndPoint: " +
iotServerConfigs.getHTTPS_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTP EndPoint: " +
iotServerConfigs.getHTTP_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "API-Manager Gateway EndPoint: " +
iotServerConfigs.getApimGatewayEndpoint());
log.info(AgentConstants.LOG_APPENDER + "MQTT Broker EndPoint: " +
iotServerConfigs.getMqttBrokerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server EndPoint: " +
iotServerConfigs.getXmppServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "Authentication Method: " +
iotServerConfigs.getAuthMethod());
log.info(AgentConstants.LOG_APPENDER + "Base64Encoded API Application Key: " +
iotServerConfigs.getApiApplicationKey());
log.info(AgentConstants.LOG_APPENDER + "Authentication Token: " +
iotServerConfigs.getAuthToken());
log.info(AgentConstants.LOG_APPENDER + "Refresh Token: " +
iotServerConfigs.getRefreshToken());
log.info(AgentConstants.LOG_APPENDER + "Data Push Interval: " +
iotServerConfigs.getDataPushInterval());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server Name: " +
iotServerConfigs.getXmppServerName());
} else {
throw new AgentCoreOperationException(
"Failed to load path of resource [" + propertiesFileName + "] from this classpath.");
}
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
String errorMsg = "[" + propertiesFileName + "] file not found at: " + AgentConstants.PROPERTIES_FILE_PATH; String errorMsg = "[" + propertiesFileName + "] file not found at: " + rootPath;
log.error(AgentConstants.LOG_APPENDER + errorMsg); log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} catch (IOException ex) { } catch (IOException ex) {
String errorMsg = "Error occurred whilst trying to fetch [" + propertiesFileName + "] from: " + String errorMsg = "Error occurred whilst trying to fetch [" + propertiesFileName + "] from: " +
AgentConstants.PROPERTIES_FILE_PATH; AgentConstants.PROPERTIES_FILE_PATH;
log.error(AgentConstants.LOG_APPENDER + errorMsg); log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} finally { } finally {
@ -174,10 +195,6 @@ public class AgentUtilOperations {
/** /**
* This method constructs the URLs for each of the API Endpoints called by the device agent * This method constructs the URLs for each of the API Endpoints called by the device agent
* Ex: Register API, Push-Data API * Ex: Register API, Push-Data API
*
* @throws AgentCoreOperationException if any error occurs at socket level whilst trying to
* retrieve the deviceIP of the network-interface read
* from the configs file
*/ */
public static void initializeServerEndPoints() { public static void initializeServerEndPoints() {
AgentManager agentManager = AgentManager.getInstance(); AgentManager agentManager = AgentManager.getInstance();
@ -209,6 +226,26 @@ public class AgentUtilOperations {
log.info(AgentConstants.LOG_APPENDER + "Push-Data API EndPoint: " + pushDataEndPointURL); log.info(AgentConstants.LOG_APPENDER + "Push-Data API EndPoint: " + pushDataEndPointURL);
} }
public static void setHTTPSConfigurations() {
String apimEndpoint = AgentManager.getInstance().getAgentConfigs().getApimGatewayEndpoint();
System.setProperty("javax.net.ssl.trustStore", AgentConstants.DEVICE_KEYSTORE);
System.setProperty("javax.net.ssl.trustStorePassword", AgentConstants.DEVICE_KEYSTORE_PASSWORD);
try {
final String apimHost = TransportUtils.getHostAndPort(apimEndpoint).get(AgentConstants.HOST_PROPERTY);
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return hostname.equals(apimHost);
}
});
} catch (TransportHandlerException e) {
log.error(AgentConstants.LOG_APPENDER +
"Failed to set HTTPS HostNameVerifier to the APIMServer-Host using the APIM-Endpoint " +
"string [" + apimEndpoint + "].");
log.error(AgentConstants.LOG_APPENDER + e);
}
}
public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException { public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException {
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey(); PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
@ -227,7 +264,6 @@ public class AgentUtilOperations {
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload); jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
//below statements are temporary fix. //below statements are temporary fix.
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber()); jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
return jsonPayload.toString(); return jsonPayload.toString();
} }
@ -265,6 +301,138 @@ public class AgentUtilOperations {
return actualMessage; return actualMessage;
} }
public static String getAuthenticationMethod() {
String authMethod = AgentManager.getInstance().getAgentConfigs().getAuthMethod();
switch (authMethod) {
case AgentConstants.TOKEN_AUTHENTICATION_METHOD:
return AgentConstants.TOKEN_AUTHENTICATION_METHOD;
default:
return "";
}
}
public static void refreshOAuthToken() throws AgentCoreOperationException {
AgentManager agentManager = AgentManager.getInstance();
String tokenEndpoint = agentManager.getAgentConfigs().getApimGatewayEndpoint();
tokenEndpoint = tokenEndpoint + APIManagerTokenUtils.TOKEN_ENDPOINT;
HttpURLConnection httpConnection = null;
BufferedReader connectionBuffer = null;
String requestPayload;
String dataFromBuffer;
StringBuilder responseMessage = new StringBuilder();
try {
String refreshToken = agentManager.getAgentConfigs().getRefreshToken();
String applicationScope = "device_type_" + AgentConstants.DEVICE_TYPE +
" device_" + agentManager.getAgentConfigs().getDeviceId();
requestPayload = APIManagerTokenUtils.GRANT_TYPE + "=" + APIManagerTokenUtils.REFRESH_TOKEN + "&" +
APIManagerTokenUtils.REFRESH_TOKEN + "=" + refreshToken + "&" +
APIManagerTokenUtils.SCOPE + "=" + applicationScope;
httpConnection = TransportUtils.getHttpConnection(tokenEndpoint);
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty(AgentConstants.AUTHORIZATION_HEADER,
"Basic " + agentManager.getAgentConfigs().getApiApplicationKey());
httpConnection.setRequestProperty(AgentConstants.CONTENT_TYPE_HEADER, AgentConstants.X_WWW_FORM_URLENCODED);
httpConnection.setDoOutput(true);
DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
dataOutPutWriter.writeBytes(requestPayload);
dataOutPutWriter.flush();
dataOutPutWriter.close();
log.info(AgentConstants.LOG_APPENDER + "Request to refresh OAuth token was sent to [" +
httpConnection.getURL() + "] with payload [" + requestPayload + "].");
log.info(AgentConstants.LOG_APPENDER + "Response [" + httpConnection.getResponseCode() + ":" +
httpConnection.getResponseMessage() + "] was received for token refresh attempt.");
if (httpConnection.getResponseCode() == HttpStatus.OK_200) {
connectionBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
while ((dataFromBuffer = connectionBuffer.readLine()) != null) {
responseMessage.append(dataFromBuffer);
}
log.info(AgentConstants.LOG_APPENDER +
"Response " + responseMessage + " was received for the token refresh call.");
updateExistingTokens(responseMessage.toString());
} else if (httpConnection.getResponseCode() == HttpStatus.BAD_REQUEST_400) {
log.error(AgentConstants.LOG_APPENDER +
"Token refresh call returned with a [400 Bad Request].\nThe refresh-token has " +
"probably expired.\nPlease contact System-Admin to get a valid refresh-token.");
} else {
log.warn(AgentConstants.LOG_APPENDER + "There was an issue with refreshing the Access Token.");
}
} catch (TransportHandlerException e) {
throw new AgentCoreOperationException(e);
} catch (ProtocolException e) {
String errorMsg = "Protocol specific error occurred when trying to set method to " +
AgentConstants.HTTP_POST + " for endpoint at: " + tokenEndpoint;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (IOException e) {
String errorMsg = "An IO error occurred whilst trying to get the response code from: " + tokenEndpoint +
" for a HTTP " + AgentConstants.HTTP_POST + " call.";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} finally {
if (connectionBuffer != null) {
try {
connectionBuffer.close();
} catch (IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"Error encounter whilst attempting to close buffer to connection at: " +
tokenEndpoint);
}
}
if (httpConnection != null) {
httpConnection.disconnect();
}
}
}
private static void updateExistingTokens(String responseFromTokenEP) throws AgentCoreOperationException {
JSONObject jsonTokenObject = new JSONObject(responseFromTokenEP);
String newAccessToken = jsonTokenObject.get(APIManagerTokenUtils.ACCESS_TOKEN).toString();
String newRefreshToken = jsonTokenObject.get(APIManagerTokenUtils.REFRESH_TOKEN).toString();
if (newAccessToken == null || newRefreshToken == null) {
String msg =
"Neither Access-Token nor Refresh-Token was found in the response [" + responseFromTokenEP + "].";
log.error(AgentConstants.LOG_APPENDER + msg);
throw new AgentCoreOperationException(msg);
}
AgentManager.getInstance().getAgentConfigs().setAuthToken(newAccessToken);
AgentManager.getInstance().getAgentConfigs().setRefreshToken(newRefreshToken);
String deviceConfigFilePath =
AgentManager.getInstance().getRootPath() + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
try {
PropertiesConfiguration propertyFileConfiguration = new PropertiesConfiguration(deviceConfigFilePath);
propertyFileConfiguration.setProperty(AgentConstants.AUTH_TOKEN_PROPERTY, newAccessToken);
propertyFileConfiguration.setProperty(AgentConstants.REFRESH_TOKEN_PROPERTY, newRefreshToken);
propertyFileConfiguration.save();
} catch (ConfigurationException e) {
String msg = "Error occurred whilst trying to update the [" + AgentConstants.AGENT_PROPERTIES_FILE_NAME +
"] at: " + deviceConfigFilePath + " will the new tokens.";
log.error(AgentConstants.LOG_APPENDER + msg);
throw new AgentCoreOperationException(msg);
}
}
private class APIManagerTokenUtils {
public static final String TOKEN_ENDPOINT = "/oauth2/token";
public static final String GRANT_TYPE = "grant_type";
public static final String ACCESS_TOKEN = "access_token";
public static final String REFRESH_TOKEN = "refresh_token";
public static final String SCOPE = "scope";
}
} }

@ -44,18 +44,24 @@ import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.Key;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore; import java.security.cert.CertStore;
import java.security.cert.CertStoreException; import java.security.cert.CertStoreException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
@ -96,6 +102,7 @@ public class EnrollmentManager {
private PublicKey publicKey; private PublicKey publicKey;
private PublicKey serverPublicKey; private PublicKey serverPublicKey;
private X509Certificate SCEPCertificate; private X509Certificate SCEPCertificate;
private boolean isEnrolled = false;
/** /**
@ -104,6 +111,7 @@ public class EnrollmentManager {
*/ */
private EnrollmentManager() { private EnrollmentManager() {
this.SCEPUrl = AgentManager.getInstance().getEnrollmentEP(); this.SCEPUrl = AgentManager.getInstance().getEnrollmentEP();
setEnrollmentStatus();
} }
/** /**
@ -119,6 +127,63 @@ public class EnrollmentManager {
} }
public void setEnrollmentStatus() {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
keyStore.load(new FileInputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
this.isEnrolled = (keyStore.containsAlias(AgentConstants.DEVICE_CERT_ALIAS) &&
keyStore.containsAlias(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS) &&
keyStore.containsAlias(AgentConstants.SERVER_CA_CERT_ALIAS));
} catch (KeyStoreException e) {
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
AgentConstants.DEVICE_KEYSTORE + "' with keystore type [" +
AgentConstants.DEVICE_KEYSTORE_TYPE + "] to ensure enrollment status.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
return;
} catch (CertificateException | NoSuchAlgorithmException e) {
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst trying to [load] the device KeyStore '" +
AgentConstants.DEVICE_KEYSTORE + "'.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
return;
} catch (IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"An error occurred whilst trying to load input stream with the keystore file: " +
AgentConstants.DEVICE_KEYSTORE);
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
return;
}
try {
if (this.isEnrolled) {
this.SCEPCertificate = (X509Certificate) keyStore.getCertificate(AgentConstants.DEVICE_CERT_ALIAS);
this.privateKey = (PrivateKey) keyStore.getKey(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS,
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
this.publicKey = SCEPCertificate.getPublicKey();
X509Certificate serverCACert = (X509Certificate) keyStore.getCertificate(
AgentConstants.SERVER_CA_CERT_ALIAS);
this.serverPublicKey = serverCACert.getPublicKey();
log.info(AgentConstants.LOG_APPENDER +
"Device has already been enrolled. Hence, loaded certificate information from device" +
" trust-store.");
}
} catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
AgentConstants.DEVICE_KEYSTORE + "' to ensure enrollment status.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
this.isEnrolled = false;
}
}
/** /**
* Method to control the entire enrollment flow. This method calls the method to create the Private-Public Key * Method to control the entire enrollment flow. This method calls the method to create the Private-Public Key
* Pair, calls the specific method to generate the Certificate-Sign-Request, creates a one time self signed * Pair, calls the specific method to generate the Certificate-Sign-Request, creates a one time self signed
@ -181,14 +246,66 @@ public class EnrollmentManager {
this.SCEPCertificate = getSignedCertificateFromServer(tmpCert, certSignRequest); this.SCEPCertificate = getSignedCertificateFromServer(tmpCert, certSignRequest);
this.serverPublicKey = initPublicKeyOfServer(); this.serverPublicKey = initPublicKeyOfServer();
storeCertificateToStore(AgentConstants.DEVICE_CERT_ALIAS, SCEPCertificate);
storeKeyToKeyStore(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS, this.privateKey, SCEPCertificate);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.info(AgentConstants.LOG_APPENDER +
"SCEPCertificate, DevicePrivateKey, ServerPublicKey was saved to device keystore [" +
AgentConstants.DEVICE_KEYSTORE + "]");
log.info(AgentConstants.LOG_APPENDER + "TemporaryCertPublicKey:\n[\n" + tmpCert.getPublicKey() + "\n]\n"); log.info(AgentConstants.LOG_APPENDER + "TemporaryCertPublicKey:\n[\n" + tmpCert.getPublicKey() + "\n]\n");
log.info(AgentConstants.LOG_APPENDER + "ServerPublicKey:\n[\n" + serverPublicKey + "\n]\n"); log.info(AgentConstants.LOG_APPENDER + "ServerPublicKey:\n[\n" + serverPublicKey + "\n]\n");
} }
}
private void storeCertificateToStore(String alias, Certificate certificate) {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
keyStore.load(new FileInputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
keyStore.setCertificateEntry(alias, certificate);
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"An error occurred whilst trying to store the Certificate received from the SCEP " +
"Enrollment.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER +
"SCEP Certificate was not stored in the keystore; " +
"Hence the device will be re-enrolled during next restart.");
}
} }
private void storeKeyToKeyStore(String alias, Key cryptoKey, Certificate certInCertChain) {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
keyStore.load(new FileInputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
Certificate[] certChain = new Certificate[1];
certChain[0] = certInCertChain;
keyStore.setKeyEntry(alias, cryptoKey, AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray(), certChain);
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"An error occurred whilst trying to store the key with alias " +
"[" + alias + "] in the device keystore.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER +
"Key [" + alias + "] was not stored in the keystore; " +
"Hence the device will be re-enrolled during next restart.");
}
}
/** /**
* This method creates the Public-Private Key pair for the current client. * This method creates the Public-Private Key pair for the current client.
* *
@ -382,6 +499,7 @@ public class EnrollmentManager {
// This is because the returned keystore may contain many certificates including RAs. // This is because the returned keystore may contain many certificates including RAs.
if (((Boolean) ((X509CertImpl) cert).getBasicConstraintsExtension().get(CERT_IS_CA_EXTENSION))) { if (((Boolean) ((X509CertImpl) cert).getBasicConstraintsExtension().get(CERT_IS_CA_EXTENSION))) {
serverCertPublicKey = cert.getPublicKey(); serverCertPublicKey = cert.getPublicKey();
storeCertificateToStore(AgentConstants.SERVER_CA_CERT_ALIAS, cert);
} }
} }
} }
@ -407,9 +525,9 @@ public class EnrollmentManager {
return serverCertPublicKey; return serverCertPublicKey;
} }
/** /**
* Gets the Public-Key of the client. * Gets the Public-Key of the client.
*
* @return the public key of the client. * @return the public key of the client.
*/ */
public PublicKey getPublicKey() { public PublicKey getPublicKey() {
@ -418,6 +536,7 @@ public class EnrollmentManager {
/** /**
* Gets the Private-Key of the client. * Gets the Private-Key of the client.
*
* @return the private key of the client. * @return the private key of the client.
*/ */
public PrivateKey getPrivateKey() { public PrivateKey getPrivateKey() {
@ -426,6 +545,7 @@ public class EnrollmentManager {
/** /**
* Gets the SCEP-Certificate of the client. * Gets the SCEP-Certificate of the client.
*
* @return the SCEP Certificate of the client. * @return the SCEP Certificate of the client.
*/ */
public X509Certificate getSCEPCertificate() { public X509Certificate getSCEPCertificate() {
@ -434,9 +554,19 @@ public class EnrollmentManager {
/** /**
* Gets the Public-Key of the Server. * Gets the Public-Key of the Server.
*
* @return the pubic key of the server. * @return the pubic key of the server.
*/ */
public PublicKey getServerPublicKey() { public PublicKey getServerPublicKey() {
return serverPublicKey; return serverPublicKey;
} }
/**
* Checks whether the device has already been enrolled with the SCEP Server.
*
* @return the enrollment status; 'TRUE' if already enrolled else 'FALSE'.
*/
public boolean isEnrolled() {
return isEnrolled;
}
} }

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -67,9 +68,9 @@ public class TransportUtils {
throw new TransportHandlerException(errorMsg); throw new TransportHandlerException(errorMsg);
} }
ipPortMap.put("Protocol", ipPortArray[0]); ipPortMap.put(AgentConstants.PROTOCOL_PROPERTY, ipPortArray[0]);
ipPortMap.put("Host", ipPortArray[1].replace("/", "")); ipPortMap.put(AgentConstants.HOST_PROPERTY, ipPortArray[1].replace("/", ""));
ipPortMap.put("Port", ipPortArray[2]); ipPortMap.put(AgentConstants.PORT_PROPERTY, ipPortArray[2]);
return ipPortMap; return ipPortMap;
} }
@ -99,8 +100,7 @@ public class TransportUtils {
return !ipAddress.endsWith("."); return !ipAddress.endsWith(".");
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
log.warn("The IP Address: " + ipAddress + " could not " + log.warn("The IP Address: " + ipAddress + " could not be validated against IPv4-style");
"be validated against IPv4-style");
return false; return false;
} }
} }

@ -52,7 +52,6 @@ import java.nio.charset.StandardCharsets;
public abstract class MQTTTransportHandler public abstract class MQTTTransportHandler
implements MqttCallback, TransportHandler<MqttMessage> { implements MqttCallback, TransportHandler<MqttMessage> {
private static final Log log = LogFactory.getLog(MQTTTransportHandler.class); private static final Log log = LogFactory.getLog(MQTTTransportHandler.class);
private static final String DEFAULT_PASSWORD = "";
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
private MqttClient client; private MqttClient client;
@ -82,8 +81,6 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL; this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
/** /**
@ -108,8 +105,6 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = intervalInMillis; this.timeoutInterval = intervalInMillis;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
public void setTimeoutInterval(int timeoutInterval) { public void setTimeoutInterval(int timeoutInterval) {
@ -156,6 +151,12 @@ public abstract class MQTTTransportHandler
} }
protected void connectToQueue(String username, String password) throws TransportHandlerException {
options.setUserName(username);
options.setPassword(password.toCharArray());
connectToQueue();
}
/** /**
* Connects to the MQTT-Broker and if successfully established connection. * Connects to the MQTT-Broker and if successfully established connection.
* *
@ -248,8 +249,7 @@ public abstract class MQTTTransportHandler
try { try {
client.publish(topic, payLoad.getBytes(StandardCharsets.UTF_8), qos, retained); client.publish(topic, payLoad.getBytes(StandardCharsets.UTF_8), qos, retained);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Message: " + payLoad + " to MQTT topic [" + topic + log.debug("Message: " + payLoad + " to MQTT topic [" + topic + "] published successfully");
"] published successfully");
} }
} catch (MqttException ex) { } catch (MqttException ex) {
String errorMsg = String errorMsg =
@ -267,8 +267,7 @@ public abstract class MQTTTransportHandler
try { try {
client.publish(topic, message); client.publish(topic, message);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Message: " + message.toString() + " to MQTT topic [" + topic + log.debug("Message: " + message.toString() + " to MQTT topic [" + topic + "] published successfully");
"] published successfully");
} }
} catch (MqttException ex) { } catch (MqttException ex) {
//TODO:: Compulsory log of errors and remove formatted error //TODO:: Compulsory log of errors and remove formatted error
@ -291,8 +290,7 @@ public abstract class MQTTTransportHandler
@Override @Override
public void connectionLost(Throwable throwable) { public void connectionLost(Throwable throwable) {
log.warn("Lost Connection for client: " + this.clientId + log.warn("Lost Connection for client: " + this.clientId +
" to " + this.mqttBrokerEndPoint + ".\nThis was due to - " + " to " + this.mqttBrokerEndPoint + ".\nThis was due to - " + throwable.getMessage());
throwable.getMessage());
Thread reconnectThread = new Thread() { Thread reconnectThread = new Thread() {
public void run() { public void run() {
@ -340,8 +338,7 @@ public abstract class MQTTTransportHandler
} catch (MqttException e) { } catch (MqttException e) {
//TODO:: Throw errors //TODO:: Throw errors
log.error( log.error(
"Error occurred whilst trying to read the message from the MQTT delivery " + "Error occurred whilst trying to read the message from the MQTT delivery token.");
"token.");
} }
String topic = iMqttDeliveryToken.getTopics()[0]; String topic = iMqttDeliveryToken.getTopics()[0];
String client = iMqttDeliveryToken.getClient().getClientId(); String client = iMqttDeliveryToken.getClient().getClientId();

@ -1,4 +1,4 @@
# ad#
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. # Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");

@ -54,13 +54,27 @@ import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import javax.ws.rs.*; import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.util.*; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService { public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
@ -136,7 +150,8 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>(); List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE)); deviceIdentifiers.add(new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE));
APIUtil.getDeviceManagementService().addOperation(VirtualFireAlarmConstants.DEVICE_TYPE, commandOp, deviceIdentifiers); APIUtil.getDeviceManagementService().addOperation(VirtualFireAlarmConstants.DEVICE_TYPE, commandOp,
deviceIdentifiers);
break; break;
} }
return Response.ok().build(); return Response.ok().build();
@ -319,14 +334,16 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
scopes); scopes);
String accessToken = accessTokenInfo.getAccessToken(); String accessToken = accessTokenInfo.getAccessToken();
String refreshToken = accessTokenInfo.getRefreshToken(); String refreshToken = accessTokenInfo.getRefreshToken();
//adding registering data
XmppAccount newXmppAccount = new XmppAccount();
newXmppAccount.setAccountName(deviceId);
newXmppAccount.setUsername(deviceId);
newXmppAccount.setPassword(accessToken);
newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
boolean status; boolean status;
if (XmppConfig.getInstance().isEnabled()) { if (XmppConfig.getInstance().isEnabled()) {
XmppAccount newXmppAccount = new XmppAccount();
newXmppAccount.setAccountName(deviceId);
newXmppAccount.setUsername(deviceId);
newXmppAccount.setPassword(accessToken);
newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
status = XmppServerClient.createAccount(newXmppAccount); status = XmppServerClient.createAccount(newXmppAccount);
if (!status) { if (!status) {
String msg = "XMPP Account was not created for device - " + deviceId + " of owner - " + owner + String msg = "XMPP Account was not created for device - " + deviceId + " of owner - " + owner +
@ -335,14 +352,16 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
throw new DeviceManagementException(msg); throw new DeviceManagementException(msg);
} }
} }
status = register(deviceId, deviceName); status = register(deviceId, deviceName);
if (!status) { if (!status) {
String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner; String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner;
throw new DeviceManagementException(msg); throw new DeviceManagementException(msg);
} }
ZipUtil ziputil = new ZipUtil(); ZipUtil ziputil = new ZipUtil();
return ziputil.createZipFile(owner, APIUtil.getTenantDomainOftheUser(), sketchType, deviceId, return ziputil.createZipFile(owner, sketchType, deviceId, deviceName, apiApplicationKey.toString(),
deviceName, accessToken, refreshToken); accessToken, refreshToken);
} }
private static String shortUUID() { private static String shortUUID() {
@ -350,5 +369,4 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong(); long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
return Long.toString(l, Character.MAX_RADIX); return Long.toString(l, Character.MAX_RADIX);
} }
} }

@ -0,0 +1,20 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppConfig;
public class VirtualFireAlarmUtilConstants {
public static final String TENANT_DOMAIN = "TENANT_DOMAIN";
public static final String DEVICE_OWNER = "DEVICE_OWNER";
public static final String DEVICE_ID = "DEVICE_ID";
public static final String DEVICE_NAME = "DEVICE_NAME";
public static final String HTTPS_EP = "HTTPS_EP";
public static final String HTTP_EP = "HTTP_EP";
public static final String APIM_EP = "APIM_EP";
public static final String MQTT_EP = "MQTT_EP";
public static final String XMPP_EP = "XMPP_EP";
public static final String API_APPLICATION_KEY = "API_APPLICATION_KEY";
public static final String DEVICE_TOKEN = "DEVICE_TOKEN";
public static final String DEVICE_REFRESH_TOKEN = "DEVICE_REFRESH_TOKEN";
public static final String SERVER_NAME = "SERVER_NAME";
}

@ -18,6 +18,11 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.application.extension.constants.ApiApplicationConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.util.Utils; import org.wso2.carbon.device.mgt.iot.util.Utils;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive; import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
@ -35,6 +40,7 @@ import java.util.Map;
*/ */
public class ZipUtil { public class ZipUtil {
private static final Log log = LogFactory.getLog(ZipUtil.class);
private static final String HTTPS_PORT_PROPERTY = "httpsPort"; private static final String HTTPS_PORT_PROPERTY = "httpsPort";
private static final String HTTP_PORT_PROPERTY = "httpPort"; private static final String HTTP_PORT_PROPERTY = "httpPort";
@ -42,12 +48,13 @@ public class ZipUtil {
private static final String HTTPS_PROTOCOL_APPENDER = "https://"; private static final String HTTPS_PROTOCOL_APPENDER = "https://";
private static final String HTTP_PROTOCOL_APPENDER = "http://"; private static final String HTTP_PROTOCOL_APPENDER = "http://";
public ZipArchive createZipFile(String owner, String tenantDomain, String deviceType, public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName,
String deviceId, String deviceName, String token, String apiApplicationKey, String token, String refreshToken)
String refreshToken) throws DeviceManagementException { throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches"; String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String archivesPath = CarbonUtils.getCarbonHome() + File.separator + sketchFolder + File.separator + "archives" + String archivesPath =
CarbonUtils.getCarbonHome() + File.separator + sketchFolder + File.separator + "archives" +
File.separator + deviceId; File.separator + deviceId;
String templateSketchPath = sketchFolder + File.separator + deviceType; String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP; String iotServerIP;
@ -63,24 +70,29 @@ public class ZipUtil {
if (mqttEndpoint.contains(LOCALHOST)) { if (mqttEndpoint.contains(LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(LOCALHOST, iotServerIP); mqttEndpoint = mqttEndpoint.replace(LOCALHOST, iotServerIP);
} }
String xmppEndpoint = XmppConfig.getInstance().getXmppServerIP() + ":" + String xmppEndpoint = XmppConfig.getInstance().getXmppServerIP() + ":" +
XmppConfig.getInstance().getXmppServerPort(); XmppConfig.getInstance().getXmppServerPort();
if (xmppEndpoint.contains(LOCALHOST)) { if (xmppEndpoint.contains(LOCALHOST)) {
xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP); xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP);
} }
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey).trim();
Map<String, String> contextParams = new HashMap<>(); Map<String, String> contextParams = new HashMap<>();
contextParams.put("TENANT_DOMAIN", APIUtil.getTenantDomainOftheUser()); contextParams.put(VirtualFireAlarmUtilConstants.TENANT_DOMAIN, APIUtil.getTenantDomainOftheUser());
contextParams.put("DEVICE_OWNER", owner); contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_OWNER, owner);
contextParams.put("DEVICE_ID", deviceId); contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_ID, deviceId);
contextParams.put("DEVICE_NAME", deviceName); contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_NAME, deviceName);
contextParams.put("HTTPS_EP", httpsServerEP); contextParams.put(VirtualFireAlarmUtilConstants.HTTPS_EP, httpsServerEP);
contextParams.put("HTTP_EP", httpServerEP); contextParams.put(VirtualFireAlarmUtilConstants.HTTP_EP, httpServerEP);
contextParams.put("APIM_EP", apimEndpoint); contextParams.put(VirtualFireAlarmUtilConstants.APIM_EP, apimEndpoint);
contextParams.put("MQTT_EP", mqttEndpoint); contextParams.put(VirtualFireAlarmUtilConstants.MQTT_EP, mqttEndpoint);
contextParams.put("XMPP_EP", "XMPP:" + xmppEndpoint); contextParams.put(VirtualFireAlarmUtilConstants.XMPP_EP, "XMPP:" + xmppEndpoint);
contextParams.put("DEVICE_TOKEN", token); contextParams.put(VirtualFireAlarmUtilConstants.API_APPLICATION_KEY, base64EncodedApplicationKey);
contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken); contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_TOKEN, token);
contextParams.put("SERVER_NAME", XmppConfig.getInstance().getXmppServerName()); contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_REFRESH_TOKEN, refreshToken);
contextParams.put(VirtualFireAlarmUtilConstants.SERVER_NAME, XmppConfig.getInstance().getXmppServerName());
ZipArchive zipFile; ZipArchive zipFile;
zipFile = Utils.getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName); zipFile = Utils.getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName);
return zipFile; return zipFile;
@ -88,4 +100,13 @@ public class ZipUtil {
throw new DeviceManagementException("Zip File Creation Failed", e); throw new DeviceManagementException("Zip File Creation Failed", e);
} }
} }
private String getBase64EncodedAPIAppKey(String apiAppCredentialsAsJSONString) {
JSONObject jsonObject = new JSONObject(apiAppCredentialsAsJSONString);
String consumerKey = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_ID).toString();
String consumerSecret = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_SECRET).toString();
String stringToEncode = consumerKey + ":" + consumerSecret;
return Base64.encodeBase64String(stringToEncode.getBytes());
}
} }

@ -6,6 +6,7 @@ import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import java.math.BigInteger;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Map; import java.util.Map;
@ -22,7 +23,7 @@ public class VirtualFirealarmMqttContentTransformer implements ContentTransforme
PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantDomain(tenantDomain, true); ctx.setTenantDomain(tenantDomain, true);
Long serialNo = (Long) jsonPayload.get(VirtualFireAlarmConstants.JSON_SERIAL_KEY); Integer serialNo = (Integer) jsonPayload.get(VirtualFireAlarmConstants.JSON_SERIAL_KEY);
// the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment. // the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment.
// hence, the same is used here to fetch the device-specific-certificate from the key store. // hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmUtils.getDevicePublicKey("" + serialNo); PublicKey clientPublicKey = VirtualFireAlarmUtils.getDevicePublicKey("" + serialNo);

@ -28,6 +28,7 @@ apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP} mqtt-ep=${MQTT_EP}
xmpp-ep=${XMPP_EP} xmpp-ep=${XMPP_EP}
auth-method=token auth-method=token
application-key=${API_APPLICATION_KEY}
auth-token=${DEVICE_TOKEN} auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN} refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15 push-interval=15

@ -28,6 +28,7 @@ apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP} mqtt-ep=${MQTT_EP}
xmpp-ep=${XMPP_EP} xmpp-ep=${XMPP_EP}
auth-method=token auth-method=token
application-key=${API_APPLICATION_KEY}
auth-token=${DEVICE_TOKEN} auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN} refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15 push-interval=15

Loading…
Cancel
Save