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>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
</dependencies>

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

@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException;
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.AgentManager;
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.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 {
private static final Log log = LogFactory.getLog(FireAlarmMQTTCommunicator.class);
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
private ScheduledFuture<?> dataPushServiceHandler;
private static final String DEFAULT_PASSWORD = "";
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
String mqttBrokerEndPoint, String subscribeTopic) {
@ -68,18 +70,23 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
public void run() {
while (!isConnected()) {
try {
connectToQueue();
connectToQueue(agentManager.getAgentConfigs().getAuthToken(), DEFAULT_PASSWORD);
agentManager.updateAgentStatus("Connected to MQTT Queue");
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Connection to MQTT Broker at: " + mqttBrokerEndPoint +
" failed.\n Will retry in " + timeoutInterval + " milli-seconds.");
if (e.getCause() != null && e.getCause() instanceof MqttSecurityException) {
refreshOAuthToken((MqttSecurityException) e.getCause());
}
}
try {
if (isConnected()) {
subscribeToQueue();
agentManager.updateAgentStatus("Subscribed to MQTT Queue");
publishDeviceData();
}
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Subscription to MQTT Broker at: " +
mqttBrokerEndPoint + " failed");
@ -100,6 +107,26 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
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
public void processIncomingMessage(MqttMessage message, String... messageParams) {

@ -35,6 +35,7 @@ public class AgentConfiguration {
private String apimGatewayEndpoint;
private String mqttBrokerEndpoint;
private String xmppServerEndpoint;
private String apiApplicationKey;
private String authMethod;
private String authToken;
private String refreshToken;
@ -121,6 +122,14 @@ public class AgentConfiguration {
this.xmppServerEndpoint = xmppServerEndpoint;
}
public String getApiApplicationKey() {
return apiApplicationKey;
}
public void setApiApplicationKey(String apiApplicationKey) {
this.apiApplicationKey = apiApplicationKey;
}
public String getAuthMethod() {
return authMethod;
}

@ -23,10 +23,10 @@ public class AgentConstants {
public static final String LOG_APPENDER = "AGENT_LOG:: ";
public static final String PROPERTIES_FILE_PATH = "";
public static final int DEFAULT_RETRY_THREAD_INTERVAL = 5000; // time in millis
public static final String TOKEN_AUTHENTICATION_METHOD = "token";
/* ---------------------------------------------------------------------------------------
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_REGISTER_API_EP = "/register";
public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/temperature";
@ -34,18 +34,22 @@ public class AgentConstants {
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\"}";
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_ANALYTICS_PAGE_URL = "/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s";
public static final String DEVICE_ANALYTICS_PAGE_URL =
"/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s";
/* ---------------------------------------------------------------------------------------
HTTP Connection specific information for communicating with IoT-Server
--------------------------------------------------------------------------------------- */
public static final String HTTP_POST = "POST";
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 CONTENT_TYPE_HEADER = "Content-Type";
public static final String APPLICATION_JSON = "application/json";
public static final String X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
public static final String REGISTERED = "Registered";
public static final String NOT_REGISTERED = "Not-Registered";
public static final String REGISTRATION_FAILED = "Registration Failed";
@ -59,10 +63,7 @@ public class AgentConstants {
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_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/publisher";
/* ---------------------------------------------------------------------------------------
XMPP Connection specific information
--------------------------------------------------------------------------------------- */
public static final String XMPP_ADMIN_ACCOUNT_UNAME = "admin";
/* ---------------------------------------------------------------------------------------
Device/Agent specific properties to be read from the 'deviceConfig.properties' file
--------------------------------------------------------------------------------------- */
@ -79,6 +80,7 @@ public class AgentConstants {
public static final String MQTT_BROKER_EP_PROPERTY = "mqtt-ep";
public static final String XMPP_SERVER_EP_PROPERTY = "xmpp-ep";
public static final String XMPP_SERVER_NAME_PROPERTY = "xmpp-server-name";
public static final String API_APPLICATION_KEY = "application-key";
public static final String AUTH_METHOD_PROPERTY = "auth-method";
public static final String AUTH_TOKEN_PROPERTY = "auth-token";
public static final String REFRESH_TOKEN_PROPERTY = "refresh-token";
@ -109,4 +111,17 @@ public class AgentConstants {
public static final String HTTP_PROTOCOL = "HTTP";
public static final String MQTT_PROTOCOL = "MQTT";
public static final String XMPP_PROTOCOL = "XMPP";
public static final String PROTOCOL_PROPERTY = "Protocol";
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.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.exception.AgentCoreOperationException;
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.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 java.util.ArrayList;
@ -74,18 +74,19 @@ public class AgentManager {
public void init() {
agentCommunicator = new HashMap<>();
// Read IoT-Server specific configurations from the 'deviceConfig.properties' file
try {
this.agentConfigs = AgentUtilOperations.readIoTServerConfigs();
} 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);
System.exit(0);
}
// Initialise IoT-Server URL endpoints from the configuration read from file
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,
agentConfigs.getDeviceId(),
@ -153,7 +154,9 @@ public class AgentManager {
}
try {
if (!EnrollmentManager.getInstance().isEnrolled()) {
EnrollmentManager.getInstance().beginEnrollmentFlow();
}
} catch (AgentCoreOperationException e) {
log.error("Device Enrollment Failed:\n");
log.error(e);
@ -223,6 +226,10 @@ public class AgentManager {
this.rootPath = rootPath;
}
public String getRootPath() {
return rootPath;
}
public void setDeviceReady(boolean deviceReady) {
this.deviceReady = deviceReady;
}
@ -324,6 +331,7 @@ public class AgentManager {
/**
* Get temperature reading from device
*
* @return Temperature
*/
public int getTemperature() {
@ -332,6 +340,7 @@ public class AgentManager {
/**
* Get humidity reading from device
*
* @return Humidity
*/
public int getHumidity() {

@ -19,19 +19,30 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
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.LogFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.json.JSONObject;
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.transport.CommunicationUtils;
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.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
@ -67,18 +78,21 @@ public class AgentUtilOperations {
Properties properties = new Properties();
InputStream propertiesInputStream = null;
String propertiesFileName = AgentConstants.AGENT_PROPERTIES_FILE_NAME;
String rootPath = "";
try {
ClassLoader loader = AgentUtilOperations.class.getClassLoader();
URL path = loader.getResource(propertiesFileName);
System.out.println(path);
String root = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
if (path != null) {
log.info(AgentConstants.LOG_APPENDER + path);
rootPath = 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);
rootPath = URLDecoder.decode(rootPath, StandardCharsets.UTF_8.toString());
agentManager.setRootPath(rootPath);
String deviceConfigFilePath = root + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
String deviceConfigFilePath = rootPath + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
propertiesInputStream = new FileInputStream(deviceConfigFilePath);
//load a properties file from class path, inside static method
@ -108,6 +122,8 @@ public class AgentUtilOperations {
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(
@ -138,6 +154,8 @@ public class AgentUtilOperations {
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: " +
@ -146,9 +164,12 @@ public class AgentUtilOperations {
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) {
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);
throw new AgentCoreOperationException(errorMsg);
@ -174,10 +195,6 @@ public class AgentUtilOperations {
/**
* This method constructs the URLs for each of the API Endpoints called by the device agent
* 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() {
AgentManager agentManager = AgentManager.getInstance();
@ -209,6 +226,26 @@ public class AgentUtilOperations {
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 {
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
@ -227,7 +264,6 @@ public class AgentUtilOperations {
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
//below statements are temporary fix.
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
return jsonPayload.toString();
}
@ -265,6 +301,138 @@ public class AgentUtilOperations {
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 sun.security.x509.X509CertImpl;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.Certificate;
@ -96,6 +102,7 @@ public class EnrollmentManager {
private PublicKey publicKey;
private PublicKey serverPublicKey;
private X509Certificate SCEPCertificate;
private boolean isEnrolled = false;
/**
@ -104,6 +111,7 @@ public class EnrollmentManager {
*/
private EnrollmentManager() {
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
* 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.serverPublicKey = initPublicKeyOfServer();
storeCertificateToStore(AgentConstants.DEVICE_CERT_ALIAS, SCEPCertificate);
storeKeyToKeyStore(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS, this.privateKey, SCEPCertificate);
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 + "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.
*
@ -382,6 +499,7 @@ public class EnrollmentManager {
// This is because the returned keystore may contain many certificates including RAs.
if (((Boolean) ((X509CertImpl) cert).getBasicConstraintsExtension().get(CERT_IS_CA_EXTENSION))) {
serverCertPublicKey = cert.getPublicKey();
storeCertificateToStore(AgentConstants.SERVER_CA_CERT_ALIAS, cert);
}
}
}
@ -407,9 +525,9 @@ public class EnrollmentManager {
return serverCertPublicKey;
}
/**
* Gets the Public-Key of the client.
*
* @return the public key of the client.
*/
public PublicKey getPublicKey() {
@ -418,6 +536,7 @@ public class EnrollmentManager {
/**
* Gets the Private-Key of the client.
*
* @return the private key of the client.
*/
public PrivateKey getPrivateKey() {
@ -426,6 +545,7 @@ public class EnrollmentManager {
/**
* Gets the SCEP-Certificate of the client.
*
* @return the SCEP Certificate of the client.
*/
public X509Certificate getSCEPCertificate() {
@ -434,9 +554,19 @@ public class EnrollmentManager {
/**
* Gets the Public-Key of the Server.
*
* @return the pubic key of the server.
*/
public PublicKey getServerPublicKey() {
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.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import java.io.BufferedReader;
@ -67,9 +68,9 @@ public class TransportUtils {
throw new TransportHandlerException(errorMsg);
}
ipPortMap.put("Protocol", ipPortArray[0]);
ipPortMap.put("Host", ipPortArray[1].replace("/", ""));
ipPortMap.put("Port", ipPortArray[2]);
ipPortMap.put(AgentConstants.PROTOCOL_PROPERTY, ipPortArray[0]);
ipPortMap.put(AgentConstants.HOST_PROPERTY, ipPortArray[1].replace("/", ""));
ipPortMap.put(AgentConstants.PORT_PROPERTY, ipPortArray[2]);
return ipPortMap;
}
@ -99,8 +100,7 @@ public class TransportUtils {
return !ipAddress.endsWith(".");
} catch (NumberFormatException nfe) {
log.warn("The IP Address: " + ipAddress + " could not " +
"be validated against IPv4-style");
log.warn("The IP Address: " + ipAddress + " could not be validated against IPv4-style");
return false;
}
}

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

@ -1,4 +1,4 @@
#
ad#
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#
# 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.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 java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
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 {
@ -136,7 +150,8 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
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;
}
return Response.ok().build();
@ -319,14 +334,16 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
scopes);
String accessToken = accessTokenInfo.getAccessToken();
String refreshToken = accessTokenInfo.getRefreshToken();
//adding registering data
boolean status;
if (XmppConfig.getInstance().isEnabled()) {
XmppAccount newXmppAccount = new XmppAccount();
newXmppAccount.setAccountName(deviceId);
newXmppAccount.setUsername(deviceId);
newXmppAccount.setPassword(accessToken);
newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
boolean status;
if (XmppConfig.getInstance().isEnabled()) {
status = XmppServerClient.createAccount(newXmppAccount);
if (!status) {
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);
}
}
status = register(deviceId, deviceName);
if (!status) {
String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner;
throw new DeviceManagementException(msg);
}
ZipUtil ziputil = new ZipUtil();
return ziputil.createZipFile(owner, APIUtil.getTenantDomainOftheUser(), sketchType, deviceId,
deviceName, accessToken, refreshToken);
return ziputil.createZipFile(owner, sketchType, deviceId, deviceName, apiApplicationKey.toString(),
accessToken, refreshToken);
}
private static String shortUUID() {
@ -350,5 +369,4 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
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;
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.iot.util.Utils;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
@ -35,6 +40,7 @@ import java.util.Map;
*/
public class ZipUtil {
private static final Log log = LogFactory.getLog(ZipUtil.class);
private static final String HTTPS_PORT_PROPERTY = "httpsPort";
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 HTTP_PROTOCOL_APPENDER = "http://";
public ZipArchive createZipFile(String owner, String tenantDomain, String deviceType,
String deviceId, String deviceName, String token,
String refreshToken) throws DeviceManagementException {
public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName,
String apiApplicationKey, String token, String refreshToken)
throws DeviceManagementException {
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;
String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP;
@ -63,24 +70,29 @@ public class ZipUtil {
if (mqttEndpoint.contains(LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(LOCALHOST, iotServerIP);
}
String xmppEndpoint = XmppConfig.getInstance().getXmppServerIP() + ":" +
XmppConfig.getInstance().getXmppServerPort();
if (xmppEndpoint.contains(LOCALHOST)) {
xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP);
}
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey).trim();
Map<String, String> contextParams = new HashMap<>();
contextParams.put("TENANT_DOMAIN", APIUtil.getTenantDomainOftheUser());
contextParams.put("DEVICE_OWNER", owner);
contextParams.put("DEVICE_ID", deviceId);
contextParams.put("DEVICE_NAME", deviceName);
contextParams.put("HTTPS_EP", httpsServerEP);
contextParams.put("HTTP_EP", httpServerEP);
contextParams.put("APIM_EP", apimEndpoint);
contextParams.put("MQTT_EP", mqttEndpoint);
contextParams.put("XMPP_EP", "XMPP:" + xmppEndpoint);
contextParams.put("DEVICE_TOKEN", token);
contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken);
contextParams.put("SERVER_NAME", XmppConfig.getInstance().getXmppServerName());
contextParams.put(VirtualFireAlarmUtilConstants.TENANT_DOMAIN, APIUtil.getTenantDomainOftheUser());
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_OWNER, owner);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_ID, deviceId);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_NAME, deviceName);
contextParams.put(VirtualFireAlarmUtilConstants.HTTPS_EP, httpsServerEP);
contextParams.put(VirtualFireAlarmUtilConstants.HTTP_EP, httpServerEP);
contextParams.put(VirtualFireAlarmUtilConstants.APIM_EP, apimEndpoint);
contextParams.put(VirtualFireAlarmUtilConstants.MQTT_EP, mqttEndpoint);
contextParams.put(VirtualFireAlarmUtilConstants.XMPP_EP, "XMPP:" + xmppEndpoint);
contextParams.put(VirtualFireAlarmUtilConstants.API_APPLICATION_KEY, base64EncodedApplicationKey);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_TOKEN, token);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_REFRESH_TOKEN, refreshToken);
contextParams.put(VirtualFireAlarmUtilConstants.SERVER_NAME, XmppConfig.getInstance().getXmppServerName());
ZipArchive zipFile;
zipFile = Utils.getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName);
return zipFile;
@ -88,4 +100,13 @@ public class ZipUtil {
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.exception.VirtualFirealarmDeviceMgtPluginException;
import java.math.BigInteger;
import java.security.PublicKey;
import java.util.Map;
@ -22,7 +23,7 @@ public class VirtualFirealarmMqttContentTransformer implements ContentTransforme
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
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.
// hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmUtils.getDevicePublicKey("" + serialNo);

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

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

Loading…
Cancel
Save