Modifications to the Token Refresh Flow & the Enrolment flow in the VFAlarm

revert-dabc3590
Shabirmean 9 years ago
parent 75914aee4e
commit a117ae37c7

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

@ -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;
@ -42,6 +43,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
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.");
}
try{
subscribeToQueue();
agentManager.updateAgentStatus("Subscribed to MQTT Queue");
publishDeviceData();
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) {

@ -27,7 +27,6 @@ public class AgentConstants {
/* ---------------------------------------------------------------------------------------
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";
@ -38,7 +37,6 @@ public class AgentConstants {
"{\"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";
@ -51,7 +49,7 @@ public class AgentConstants {
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 = "x-www-form-urlencoded";
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";
@ -113,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_PUBLIC_KEY_ALIAS = "iotServer_key";
}

@ -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 {
EnrollmentManager.getInstance().beginEnrollmentFlow();
if (!EnrollmentManager.getInstance().isEnrolled()) {
EnrollmentManager.getInstance().beginEnrollmentFlow();
}
} catch (AgentCoreOperationException e) {
log.error("Device Enrollment Failed:\n");
log.error(e);

@ -19,8 +19,11 @@
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;
@ -28,11 +31,13 @@ import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.Communica
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
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.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -78,86 +83,91 @@ public class AgentUtilOperations {
try {
ClassLoader loader = AgentUtilOperations.class.getClassLoader();
URL path = loader.getResource(propertiesFileName);
System.out.println(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());
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) {
String errorMsg = "[" + propertiesFileName + "] file not found at: " + rootPath;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
@ -216,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();
@ -234,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();
}
@ -282,26 +311,19 @@ public class AgentUtilOperations {
}
}
public static boolean refreshOAuthToken() throws AgentCoreOperationException {
public static void refreshOAuthToken() throws AgentCoreOperationException {
AgentManager agentManager = AgentManager.getInstance();
String tokenEndpoint = agentManager.getAgentConfigs().getApimGatewayEndpoint() + "/token";
String tokenEndpoint = agentManager.getAgentConfigs().getApimGatewayEndpoint();
tokenEndpoint = tokenEndpoint + APIManagerTokenUtils.TOKEN_ENDPOINT;
HttpURLConnection httpConnection = null;
BufferedReader connectionBuffer = null;
String requestPayload;
String dataFromBuffer;
StringBuilder responseMessage = new StringBuilder();
boolean refreshStatus = false;
try {
httpConnection = TransportUtils.getHttpConnection(tokenEndpoint);
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty(AgentConstants.AUTHORIZATION_HEADER,
"Bearer " + agentManager.getAgentConfigs().getApiApplicationKey());
httpConnection.setRequestProperty(AgentConstants.CONTENT_TYPE_HEADER, AgentConstants.X_WWW_FORM_URLENCODED);
httpConnection.setDoOutput(true);
String refreshToken = agentManager.getAgentConfigs().getRefreshToken();
String applicationScope = "device_type_" + AgentConstants.DEVICE_TYPE +
" device_" + agentManager.getAgentConfigs().getDeviceId();
@ -310,6 +332,13 @@ public class AgentUtilOperations {
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();
@ -320,17 +349,19 @@ public class AgentUtilOperations {
log.info(AgentConstants.LOG_APPENDER + "Response [" + httpConnection.getResponseCode() + ":" +
httpConnection.getResponseMessage() + "] was received for token refresh attempt.");
connectionBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
if (httpConnection.getResponseCode() == HttpStatus.OK_200) {
connectionBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
while ((dataFromBuffer = connectionBuffer.readLine()) != null) {
responseMessage.append(dataFromBuffer);
}
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 {
log.info(AgentConstants.LOG_APPENDER + "There was an issue with refreshing the Access Token.");
}
log.info(AgentConstants.LOG_APPENDER + "Response [" + responseMessage +
"] was received for the token refresh call.");
refreshStatus = updateExistingTokens(responseMessage.toString());
} catch (TransportHandlerException e) {
throw new AgentCoreOperationException(e);
} catch (ProtocolException e) {
@ -359,20 +390,18 @@ public class AgentUtilOperations {
httpConnection.disconnect();
}
}
return refreshStatus;
}
private static boolean updateExistingTokens(String responseFromTokenEP) {
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) {
log.error(
AgentConstants.LOG_APPENDER + "Neither Access-Token nor Refresh-Token was found in the response [" +
responseFromTokenEP + "].");
return false;
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);
@ -380,42 +409,21 @@ public class AgentUtilOperations {
String deviceConfigFilePath =
AgentManager.getInstance().getRootPath() + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
Properties deviceProperties = new Properties();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(deviceConfigFilePath);
deviceProperties.setProperty(AgentConstants.AUTH_TOKEN_PROPERTY, newAccessToken);
deviceProperties.setProperty(AgentConstants.REFRESH_TOKEN_PROPERTY, newRefreshToken);
deviceProperties.store(fileOutputStream, null);
} catch (FileNotFoundException ex) {
String errorMsg =
"[" + AgentConstants.AGENT_PROPERTIES_FILE_NAME + "] file not found at: " + deviceConfigFilePath;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
return false;
} catch (IOException ex) {
String errorMsg = "Error occurred whilst trying to write to [" + AgentConstants.AGENT_PROPERTIES_FILE_NAME +
"] at: " + deviceConfigFilePath;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
return false;
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"Error occurred whilst trying to close InputStream resource used to read the '" +
AgentConstants.AGENT_PROPERTIES_FILE_NAME + "' file");
}
}
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);
}
return true;
}
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";

@ -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,58 @@ 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));
} 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.serverPublicKey = (PublicKey) keyStore.getKey(AgentConstants.SERVER_PUBLIC_KEY_ALIAS,
AgentConstants.DEVICE_KEYSTORE_PASSWORD
.toCharArray());
this.publicKey = SCEPCertificate.getPublicKey();
}
} 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 +241,67 @@ 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);
storeKeyToKeyStore(AgentConstants.SERVER_PUBLIC_KEY_ALIAS, this.serverPublicKey, 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.
*
@ -407,9 +520,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 +531,7 @@ public class EnrollmentManager {
/**
* Gets the Private-Key of the client.
*
* @return the private key of the client.
*/
public PrivateKey getPrivateKey() {
@ -426,6 +540,7 @@ public class EnrollmentManager {
/**
* Gets the SCEP-Certificate of the client.
*
* @return the SCEP Certificate of the client.
*/
public X509Certificate getSCEPCertificate() {
@ -434,9 +549,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();

@ -77,7 +77,7 @@ public class ZipUtil {
xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP);
}
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey);
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey).trim();
Map<String, String> contextParams = new HashMap<>();
contextParams.put(VirtualFireAlarmUtilConstants.TENANT_DOMAIN, APIUtil.getTenantDomainOftheUser());

@ -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