mirror of
https://repository.entgra.net/community/device-mgt-plugins.git
synced 2025-09-16 23:42:15 +00:00
Modifications to the Token Refresh Flow & the Enrolment flow in the VFAlarm
This commit is contained in:
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.");
|
||||
|
||||
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 {
|
||||
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,7 +83,9 @@ public class AgentUtilOperations {
|
||||
try {
|
||||
ClassLoader loader = AgentUtilOperations.class.getClassLoader();
|
||||
URL path = loader.getResource(propertiesFileName);
|
||||
System.out.println(path);
|
||||
|
||||
if (path != null) {
|
||||
log.info(AgentConstants.LOG_APPENDER + path);
|
||||
rootPath = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
|
||||
.replace("jar:", "").replace("file:", "");
|
||||
|
||||
@ -157,7 +164,10 @@ 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: " + 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,16 +349,18 @@ public class AgentUtilOperations {
|
||||
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.");
|
||||
|
||||
refreshStatus = updateExistingTokens(responseMessage.toString());
|
||||
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.");
|
||||
}
|
||||
|
||||
} catch (TransportHandlerException e) {
|
||||
throw new AgentCoreOperationException(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,13 +241,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);
|
||||
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…
Reference in New Issue
Block a user