Changes after testing with virtual firealarm and android sense

revert-dabc3590
ayyoob 9 years ago
parent 5f43cc47e8
commit 16fb54d463

@ -140,6 +140,7 @@ public class RegisterActivity extends Activity {
}); });
if (registerStatus.isRegistered()) { if (registerStatus.isRegistered()) {
LocalRegistry.setEnrolled(getApplicationContext(), true);
LocalRegistry.addUsername(getApplicationContext(), username); LocalRegistry.addUsername(getApplicationContext(), username);
LocalRegistry.addDeviceId(getApplicationContext(), deviceId); LocalRegistry.addDeviceId(getApplicationContext(), deviceId);
LocalRegistry.addMqttPort(getApplicationContext(), mqttPortNo); LocalRegistry.addMqttPort(getApplicationContext(), mqttPortNo);

@ -143,7 +143,7 @@ public class DataPublisherService extends Service {
} }
SenseDataHolder.resetWordDataHolder(); SenseDataHolder.resetWordDataHolder();
//publish the data //publish the data
if (events.size() > 0) { if (events.size() > 0 && LocalRegistry.isEnrolled(context)) {
String user = LocalRegistry.getUsername(context); String user = LocalRegistry.getUsername(context);
String deviceId = LocalRegistry.getDeviceId(context); String deviceId = LocalRegistry.getDeviceId(context);
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();

@ -176,7 +176,7 @@ public class ActivitySelectSensor extends AppCompatActivity
Intent activity = new Intent(getApplicationContext(), RegisterActivity.class); Intent activity = new Intent(getApplicationContext(), RegisterActivity.class);
startActivity(activity); startActivity(activity);
} }
LocalRegistry.setEnrolled(getApplicationContext(), false);
LocalRegistry.removeUsername(getApplicationContext()); LocalRegistry.removeUsername(getApplicationContext());
LocalRegistry.removeDeviceId(getApplicationContext()); LocalRegistry.removeDeviceId(getApplicationContext());
LocalRegistry.removeServerURL(getApplicationContext()); LocalRegistry.removeServerURL(getApplicationContext());

@ -35,6 +35,7 @@ public class LocalRegistry {
private static final String ACCESS_TOKEN_KEY = "accessTokenKey"; private static final String ACCESS_TOKEN_KEY = "accessTokenKey";
private static final String REFRESH_TOKEN_KEY = "refreshTokenKey"; private static final String REFRESH_TOKEN_KEY = "refreshTokenKey";
private static final String MQTT_PORT_KEY = "mqttPort"; private static final String MQTT_PORT_KEY = "mqttPort";
private static final String IS_ENROLLED_KEY = "enrolled";
private static boolean exists = false; private static boolean exists = false;
private static String username; private static String username;
private static String deviceId; private static String deviceId;
@ -43,6 +44,7 @@ public class LocalRegistry {
private static String accessToken; private static String accessToken;
private static String refreshToken; private static String refreshToken;
private static int mqttPort; private static int mqttPort;
private static boolean enrolled;
public static boolean isExist(Context context) { public static boolean isExist(Context context) {
if (!exists) { if (!exists) {
@ -209,6 +211,22 @@ public class LocalRegistry {
return LocalRegistry.mqttPort; return LocalRegistry.mqttPort;
} }
public static void setEnrolled(Context context, boolean enrolled) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean(IS_ENROLLED_KEY, enrolled);
editor.commit();
LocalRegistry.enrolled = enrolled;
}
public static boolean isEnrolled(Context context) {
if (!LocalRegistry.enrolled) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
return LocalRegistry.enrolled = sharedpreferences.getBoolean(IS_ENROLLED_KEY, false);
}
return LocalRegistry.enrolled;
}
public static String getServerHost(Context context) { public static String getServerHost(Context context) {
URL url = null; URL url = null;

@ -27,13 +27,13 @@
android:id="@+id/username" android:id="@+id/username"
android:inputType="text" android:inputType="text"
android:maxLines="1" android:singleLine="true" android:maxLines="1" android:singleLine="true"
android:text="admin"/> />
<EditText android:id="@+id/password" android:layout_width="match_parent" <EditText android:id="@+id/password" android:layout_width="match_parent"
android:layout_height="wrap_content" android:hint="@string/prompt_password" android:layout_height="wrap_content" android:hint="@string/prompt_password"
android:inputType="textPassword" android:inputType="textPassword"
android:maxLines="1" android:singleLine="true" android:maxLines="1" android:singleLine="true"
android:text="admin"/> />
<EditText <EditText
android:layout_width="match_parent" android:layout_width="match_parent"

@ -19,13 +19,13 @@
<eventReceiver name="EventReceiver_AndroidSense" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="EventReceiver_AndroidSense" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">wso2/android_sense/#</property> <property name="topic">wso2/android_sense/+/data</property>
<property name="username">admin</property> <property name="username">admin</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property> <property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property>
<property name="contentValidation">default</property> <property name="contentValidation">default</property>
<property name="dcrUrl">https://localhost:9443/dynamic-client-web/register</property> <property name="dcrUrl">https://localhost:9443/dynamic-client-web/register</property>
<property name="url">tcp://localhost:1883</property> <property name="url">tcp://localhost:1883</property>
<property name="cleanSession">false</property> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>
<to streamName="org.wso2.iot.android.sense" version="1.0.0"/> <to streamName="org.wso2.iot.android.sense" version="1.0.0"/>

@ -46,9 +46,8 @@ public interface AndroidSenseControllerService {
*/ */
@Path("device/{deviceId}/words") @Path("device/{deviceId}/words")
@POST @POST
@Feature(code = "keywords", name = "Add Keywords", description = "Send keywords to the device", @Feature(code = "keywords", name = "Add Keywords", description = "Send keywords to the device", type = "operation")
type = "operation") Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords);
Response sendKeyWords(@PathParam("deviceId") String deviceId, @FormParam("keywords") String keywords);
/** /**
* End point to send the key words to the device * End point to send the key words to the device
@ -60,7 +59,7 @@ public interface AndroidSenseControllerService {
@POST @POST
@Feature(code = "threshold", name = "Add a Threshold", description = "Set a threshold for word in the device", @Feature(code = "threshold", name = "Add a Threshold", description = "Set a threshold for word in the device",
type = "operation") type = "operation")
Response sendThreshold(@PathParam("deviceId") String deviceId, @FormParam("threshold") String threshold); Response sendThreshold(@PathParam("deviceId") String deviceId, @QueryParam("threshold") String threshold);
@Path("device/{deviceId}/words") @Path("device/{deviceId}/words")
@DELETE @DELETE
@ -71,7 +70,6 @@ public interface AndroidSenseControllerService {
/** /**
* Retrieve Sensor data for the device type * Retrieve Sensor data for the device type
*/ */
@Path("stats/{deviceId}/sensors/{sensorName}") @Path("stats/{deviceId}/sensors/{sensorName}")
@GET @GET
@Consumes("application/json") @Consumes("application/json")

@ -24,6 +24,8 @@ import org.wso2.carbon.analytics.dataservice.commons.SORT;
import org.wso2.carbon.analytics.dataservice.commons.SortByField; import org.wso2.carbon.analytics.dataservice.commons.SortByField;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException; import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport.AndroidSenseMQTTConnector; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport.AndroidSenseMQTTConnector;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorRecord; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorRecord;
@ -57,9 +59,17 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
@POST @POST
public Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords) { public Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords) {
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
AndroidSenseConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "add", keywords); androidSenseMQTTConnector.publishDeviceData(deviceId, "add", keywords);
return Response.ok().build(); return Response.ok().build();
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@ -68,9 +78,16 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
@POST @POST
public Response sendThreshold(@PathParam("deviceId") String deviceId, @QueryParam("threshold") String threshold) { public Response sendThreshold(@PathParam("deviceId") String deviceId, @QueryParam("threshold") String threshold) {
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
AndroidSenseConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "threshold", threshold); androidSenseMQTTConnector.publishDeviceData(deviceId, "threshold", threshold);
return Response.ok().build(); return Response.ok().build();
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@ -79,9 +96,17 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
@DELETE @DELETE
public Response removeKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("words") String words) { public Response removeKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("words") String words) {
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
AndroidSenseConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
androidSenseMQTTConnector.publishDeviceData(deviceId, "remove", words); androidSenseMQTTConnector.publishDeviceData(deviceId, "remove", words);
return Response.ok().build(); return Response.ok().build();
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@ -101,8 +126,13 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
query = "owner:" + user + " AND deviceId:" + deviceId; query = "owner:" + user + " AND deviceId:" + deviceId;
} }
String sensorTableName = getSensorEventTableName(sensor); String sensorTableName = getSensorEventTableName(sensor);
List<SensorRecord> sensorDatas;
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
AndroidSenseConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
List<SensorRecord> sensorDatas;
if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) { if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) {
List<SortByField> sortByFields = new ArrayList<>(); List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SORT.ASC, false); SortByField sortByField = new SortByField("time", SORT.ASC, false);
@ -116,6 +146,9 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query; String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg); log.error(errorMsg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }

@ -31,7 +31,6 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@Path("enrollment") @Path("enrollment")
@DeviceType(value = "android_sense")
@API(name = "android_sense_mgt", version = "1.0.0", context = "/android_sense_mgt", tags = {"android_sense"}) @API(name = "android_sense_mgt", version = "1.0.0", context = "/android_sense_mgt", tags = {"android_sense"})
public interface AndroidSenseManagerService { public interface AndroidSenseManagerService {
@ -53,10 +52,5 @@ public interface AndroidSenseManagerService {
@Produces("application/json") @Produces("application/json")
Response getDevice(@PathParam("device_id") String deviceId); Response getDevice(@PathParam("device_id") String deviceId);
@Path("/devices/download")
@GET
@Produces("application/octet-stream")
Response downloadSketch();
} }

@ -24,9 +24,9 @@ import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants; import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.utils.CarbonUtils;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
@ -38,7 +38,6 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.File;
import java.util.Date; import java.util.Date;
@Path("enrollment") @Path("enrollment")
@ -56,7 +55,6 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) { if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) {
return Response.status(Response.Status.CONFLICT.getStatusCode()).build(); return Response.status(Response.Status.CONFLICT.getStatusCode()).build();
} }
Device device = new Device(); Device device = new Device();
device.setDeviceIdentifier(deviceId); device.setDeviceIdentifier(deviceId);
EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); EnrolmentInfo enrolmentInfo = new EnrolmentInfo();
@ -76,6 +74,7 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).entity(false).build(); return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).entity(false).build();
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(false).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(false).build();
} }
} }
@ -87,6 +86,9 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE); deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
boolean removed = APIUtil.getDeviceManagementService().disenrollDevice(deviceIdentifier); boolean removed = APIUtil.getDeviceManagementService().disenrollDevice(deviceIdentifier);
if (removed) { if (removed) {
return Response.ok().build(); return Response.ok().build();
@ -94,6 +96,10 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build(); return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build();
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@ -105,6 +111,9 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE); deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
device.setDeviceIdentifier(deviceId); device.setDeviceIdentifier(deviceId);
device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime()); device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime());
@ -117,6 +126,10 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build(); return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build();
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@ -130,26 +143,17 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE); deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
return Response.ok().entity(device).build(); return Response.ok().entity(device).build();
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
@Path("/devices/download")
@GET
@Produces("application/octet-stream")
public Response downloadSketch() {
try {
String sep = File.separator;
String sketchFolder = "repository" + sep + "resources" + sep + "sketches" + sep + "android_sense" + sep;
String archivesPath = CarbonUtils.getCarbonHome() + sep + sketchFolder;
Response.ResponseBuilder rb = Response.ok(new File(archivesPath + sep + "androidsense.apk"));
rb.header("Content-Disposition", "attachment; filename=\"" + "androidsense.apk" + "\"");
return rb.build();
} catch (IllegalArgumentException ex) {
return Response.status(Response.Status.BAD_REQUEST).entity(ex.getMessage()).build();
} }
} }

@ -45,7 +45,7 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
private static String subscribeTopic = AndroidSenseConstants.MQTT_SUBSCRIBE_WORDS_TOPIC; private static String subscribeTopic = AndroidSenseConstants.MQTT_SUBSCRIBE_WORDS_TOPIC;
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5); private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private static final String KEY_TYPE = "PRODUCTION"; private static final String KEY_TYPE = "PRODUCTION";
private static final String EMPTY_STRING = ""; private static final String DEFAULT_PASSWORD = "";
private AndroidSenseMQTTConnector() { private AndroidSenseMQTTConnector() {
super(iotServerSubscriber, AndroidSenseConstants.DEVICE_TYPE, super(iotServerSubscriber, AndroidSenseConstants.DEVICE_TYPE,
@ -75,9 +75,8 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes); apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
//create token //create token
String accessToken = accessTokenInfo.getAccessToken(); String accessToken = accessTokenInfo.getAccessToken();
setUsernameAndPassword(accessToken, EMPTY_STRING); setUsernameAndPassword(accessToken, DEFAULT_PASSWORD);
connectToQueue(); connectToQueue();
subscribeToQueue();
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
log.warn("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed"); log.warn("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed");
try { try {

@ -13,8 +13,14 @@ import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException;
import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionUtils;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
@ -30,7 +36,6 @@ import java.util.Map;
public class APIUtil { public class APIUtil {
private static Log log = LogFactory.getLog(APIUtil.class); private static Log log = LogFactory.getLog(APIUtil.class);
private static Object lock = new Object();
public static String getAuthenticatedUser() { public static String getAuthenticatedUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
@ -66,7 +71,8 @@ public class APIUtil {
return analyticsDataAPI; return analyticsDataAPI;
} }
public static List<SensorRecord> getAllEventsForDevice(String tableName, String query, List<SortByField> sortByFields) throws AnalyticsException { public static List<SensorRecord> getAllEventsForDevice(String tableName, String query,
List<SortByField> sortByFields) throws AnalyticsException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI(); AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query); int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
@ -158,37 +164,52 @@ public class APIUtil {
return jwtClientManagerService; return jwtClientManagerService;
} }
public static DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceAccessAuthorizationService deviceAccessAuthorizationService =
(DeviceAccessAuthorizationService) ctx.getOSGiService(DeviceAccessAuthorizationService.class, null);
if (deviceAccessAuthorizationService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceAccessAuthorizationService;
}
public static void registerApiAccessRoles(String user) { public static void registerApiAccessRoles(String user) {
UserStoreManager userStoreManager = null; UserStoreManager userStoreManager = null;
try { try {
userStoreManager = getUserStoreManager(); userStoreManager = getUserStoreManager();
if (userStoreManager != null) { if (userStoreManager != null) {
synchronized (lock) {
String[] userList = new String[]{user}; String[] userList = new String[]{user};
if (!userStoreManager.isExistingRole(Constants.DEFAULT_ROLE_NAME)) { if (!userStoreManager.isExistingRole(Constants.DEFAULT_ROLE_NAME)) {
userStoreManager.addRole(Constants.DEFAULT_ROLE_NAME, userList, Constants.DEFAULT_PERMISSION); userStoreManager.addRole(Constants.DEFAULT_ROLE_NAME, userList, Constants.DEFAULT_PERMISSION);
} }
} }
}
} catch (UserStoreException e) { } catch (UserStoreException e) {
log.error("error on wso2 user component"); log.error("Error while creating a role and adding a user for android_sense.", e);
} }
} }
private static UserStoreManager getUserStoreManager() throws UserStoreException { public static UserStoreManager getUserStoreManager() {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); RealmService realmService;
return getRealmService().getTenantUserRealm(tenantId).getUserStoreManager(); UserStoreManager userStoreManager;
} try {
public static RealmService getRealmService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RealmService realmService = realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
(RealmService) ctx.getOSGiService(RealmService.class, null);
if (realmService == null) { if (realmService == null) {
String msg = "JWT Client manager service has not initialized."; String msg = "Realm service has not initialized.";
log.error(msg); log.error(msg);
throw new IllegalStateException(msg); throw new IllegalStateException(msg);
} }
return realmService; int tenantId = ctx.getTenantId();
userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
} catch (UserStoreException e) {
String msg = "Error occurred while retrieving current user store manager";
log.error(msg, e);
throw new IllegalStateException(msg);
}
return userStoreManager;
} }
} }

@ -19,15 +19,14 @@
package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util; package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.wso2.carbon.user.core.Permission; import org.wso2.carbon.user.core.Permission;
import org.wso2.carbon.user.core.authorization.TreeNode;
/** /**
* This hold the constants related to android sense. * This hold the constants related to the device type.
*/ */
public class Constants { public class Constants {
private static final String DEFAULT_PERMISSION_RESOURCE = "/_system/governance/permission/admin/device-mgt/android_sense/user"; public static final String DEFAULT_PERMISSION_RESOURCE = "/permission/admin/device-mgt/android_sense/user";
public static final String DEFAULT_ROLE_NAME = "android_sense_user"; public static final String DEFAULT_ROLE_NAME = "android_sense_user";
public static final Permission DEFAULT_PERMISSION[] = new Permission[]{new Permission(Constants.DEFAULT_PERMISSION_RESOURCE, public static final Permission DEFAULT_PERMISSION[] = new Permission[]{new Permission(Constants.DEFAULT_PERMISSION_RESOURCE,
TreeNode.Permission.UI_EXECUTE.toString())}; "ui.execute")};
} }

@ -77,13 +77,6 @@
<method>DELETE</method> <method>DELETE</method>
<scope>android_sense_user</scope> <scope>android_sense_user</scope>
</Permission> </Permission>
<Permission>
<name>Download device</name>
<path>/device-mgt/android_sense/user</path>
<url>/enrollment/devices/download</url>
<method>GET</method>
<scope>android_sense_user</scope>
</Permission>
<Permission> <Permission>
<name>Update device</name> <name>Update device</name>
<path>/device-mgt/android_sense/user</path> <path>/device-mgt/android_sense/user</path>

@ -1,68 +1,230 @@
<div class="col-lg-12 margin-top-double"> <div class="col-lg-12 margin-top-double">
<h1 class="grey ">Android Mobile</h1> <h1 class="grey ">Android Sense</h1>
<hr> <hr>
</div> </div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 padding-top"> <div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 padding-top">
<img src="{{@unit.publicUri}}/images/android-icon.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/android-sense-icon.png" class="img-responsive">
</div> </div>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top"> <div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top">
<h4 class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS100/Android" <h4 class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS100/Android+Sense"
target="_blank">[ here ]</a> for latest instructions and troubleshooting.</h4> target="_blank">[ here ]</a> for latest instructions and
troubleshooting.</h4>
</div> </div>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top"> <div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top">
<h3 class="uppercase">What it Does</h3> <h3 class="uppercase">What it Does</h3>
<hr> <hr>
<p class="grey margin-top">Connect and manage your Android device with WSO2 IoT Server.</p> <p class="grey margin-top">Connect an Android device to WSO2 IoT Server and visualize sensor
data.</p>
<br> <br>
<h3 class="uppercase">What You Need</h3> <h3 class="uppercase">What You Need</h3>
<hr> <hr>
<p class="grey margin-top">You should have an Android Device to get started.</p>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li class="padding-top-double"><span class="circle">STEP 01</span>&nbsp;&nbsp;&nbsp;Android <li class="padding-top-double">
Mobile. <span class="circle">STEP 01</span>
&nbsp;&nbsp;&nbsp;Go ahead and click [Enroll Device].
</li> </li>
<li class="padding-top-double"><span class="circle">STEP 02</span>&nbsp;&nbsp;&nbsp;Go ahead <li class="padding-top-double">
and click [Enroll Device]. <span class="circle">STEP 02</span>
&nbsp;&nbsp;&nbsp;You can either scan the QR code or directly download Android agent.
</li> </li>
<li class="padding-top-double"><span class="circle">STEP 03</span>&nbsp;&nbsp;&nbsp;Proceed <li class="padding-top-double">
to the [Prepare] section. <span class="circle">STEP 03</span>
&nbsp;&nbsp;&nbsp;Install Android agent into your Android Device.
</li> </li>
<li class="padding-top-double"><span class="circle">STEP 04</span>
&nbsp;&nbsp;&nbsp;Proceed to [Prepare] section.
</ul> </ul>
<br> <br>
<a href="#" class="download-link btn-operations">
<i class="fw fw-mobile fw-inverse fw-lg"></i> Enroll Device</a>
<br/><br/>
<div id="download-device-modal-content-links" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Please download the file from following link(Press CTRL+C).</h3>
<br/>
<div>
<input id="download-device-url" style="color:#3f3f3f;padding:5px"
type="text" value="" placeholder="Type here" size="60">
</div>
</div>
</div>
</div>
</div>
<a href="#" class="download-link btn-operations"><i class="fw fw-mobile fw-inverse fw-lg"></i> Enroll Device</a> <div id="device-400-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Exception at backend. Try Later.</h3>
<div class="buttons">
<a href="#" id="device-400-link" class="btn-operations">
OK
</a>
</div>
</div>
</div>
</div>
</div>
<div id="device-401-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>You have to log in first.</h3><br/>
<div class="buttons">
<a href="#" id="device-401-link" class="blue-button">
Goto Login Page
</a>&nbsp;&nbsp;
<a href="#" onclick="hidePopup();" class="btn-operations">
Cancel
</a>
</div>
</div>
</div>
</div>
</div>
<div id="device-403-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Action not permitted.</h3><br/>
<div class="buttons">
<a href="#" id="device-403-link" class="btn-operations">
OK
</a>
</div>
</div>
</div>
</div>
</div>
<div id="device-409-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Device Sketch does not exist.</h3><br/>
<div class="buttons">
<a href="#" id="device-409-link" class="btn-operations">
OK
</a>
</div>
</div>
</div>
</div>
</div>
<div id="device-unexpected-error-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Unexpected error.</h3><br/>
<div class="buttons">
<a href="#" id="device-unexpected-error-link" class="btn-operations">
OK
</a>
</div>
</div>
</div>
</div>
</div>
<br/><br/> <br/><br/>
</div> </div>
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-12 padding-double grey-bg"> <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 padding-double grey-bg">
<h3 class="uppercase">Prepare</h3><hr> <h3 class="uppercase">Prepare</h3>
<hr>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li class="padding-top-double"><span class="circle">01</span> Download Device Agent into your Android Mobile.</li> <li class="padding-top-double">
<li class="padding-top-double"><span class="circle">02</span> Install Agent APK file.</li> <span class="circle">01</span>
<li class="padding-top-double"><span class="circle">03</span> Configure Agent App</li> &nbsp;&nbsp;&nbsp;Connect Android device to network.
</li>
<li class="padding-top-double">
<span class="circle">02</span>
&nbsp;&nbsp;&nbsp;Start Android Sense app in your device.
</li>
<li class="padding-top-double">
<span class="circle">03</span>
&nbsp;&nbsp;&nbsp;Fill login form with the credentials.
<i>(Use server URL as [&nbsp;https://&lt;WSO2_IoT_SERVER_HOST&gt;:&lt;
HTTPS_SERVER_PORT&gt;&nbsp;] and click on
<strong>Register Device</strong> button.)</i>
</li>
<li>
<a href="{{@unit.publicUri}}/images/registerView.png" target="_blank"
class="padding-top-double">
<img src="{{@unit.publicUri}}/images/registerView.png" class="img-responsive">
</a>
</li>
<li class="padding-top-double">
<span class="circle">04</span>
&nbsp;&nbsp;&nbsp;Once the device is enrolled, click on <strong>[+]</strong> button to
select the sensors.
<a href="{{@unit.publicUri}}/images/selectSensorView.png" target="_blank"
class="padding-top-double">
<img src="{{@unit.publicUri}}/images/selectSensorView.png" class="img-responsive">
</a>
</li>
<li class="padding-top-double">
<span class="circle">05</span>
&nbsp;&nbsp;&nbsp;Click on <i>[Publish data]</i> button to publish sensor readings to
IoT server.
<a href="{{@unit.publicUri}}/images/publishDataView.png" target="_blank"
class="padding-top-double">
<img src="{{@unit.publicUri}}/images/publishDataView.png" class="img-responsive">
</a>
</li>
</ul> </ul>
<br> <br>
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 padding-double"> <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 padding-double">
<h3 class="uppercase">Try Out</h3>
<hr>
<ul class="list-unstyled">
<li class="padding-top-double">
<span class="fw-stack fw-lg margin-right">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-right-arrow fw-stack-1x"></i>
</span>
&nbsp;&nbsp;&nbsp;You can view all your connected devices
<a href="{{@app.context}}/devices">[Device Management]</a> page.
</li>
<li class="padding-top-double">
<span class="fw-stack fw-lg margin-right">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-right-arrow fw-stack-1x"></i>
</span>
&nbsp;&nbsp;&nbsp;You can select any one of your connected devices for available
operations and Real-Time data monitoring.
</li>
<li class="padding-top-double">
<span class="fw-stack fw-lg margin-right">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-right-arrow fw-stack-1x"></i>
</span>&nbsp;&nbsp;&nbsp;For historical analytics of sensor data navigate to device
analytics page.
</li>
</ul>
<br/>
<p class="grey margin-top">Click on the image to zoom</p> <p class="grey margin-top">Click on the image to zoom</p>
<center> <center>
<a href="{{@unit.publicUri}}/images/android_device.png" target="_blank"> <a href="{{@unit.publicUri}}/images/myDevices_analytics.png" target="_blank">
<img src="{{@unit.publicUri}}/images/android_device.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/myDevices_analytics.png" class="img-responsive">
</a> </a>
</center> </center>
</div> </div>
<br/> <div id="qr-code-modal" data-enrollment-url="{{hostName}}{{@unit.publicUri}}/asset/androidsense.apk" class="hidden">
<div id="qr-code-modal"
data-enrollment-url="{{hostName}}{{@unit.publicUri}}/asset/android-agent.apk" class="hidden">
<div class="content"> <div class="content">
<div class="row"> <div class="row">
<div class="col-lg-5 col-md-6 col-centered"> <div class="col-lg-5 col-md-6 col-centered">
@ -73,13 +235,27 @@
<div class="qr-code"></div> <div class="qr-code"></div>
</div> </div>
</div> </div>
<form id="downloadForm" method="GET"
action="{{hostName}}{{@unit.publicUri}}/asset/androidsense.apk">
<div class="buttons" style="padding-bottom: 0px">
<input class="btn btn-operations" type="submit" value="Download Now">
</div>
</form>
</div>
</div>
</div>
<div id="device-agent-downloading-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Device Agent will downloading shortly.</h3>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{{#zone "topCss"}} <style type="text/css">
<style type="text/css">
.circle { .circle {
background: none repeat scroll 0 0 #191919; background: none repeat scroll 0 0 #191919;
border-radius: 50px; border-radius: 50px;
@ -88,15 +264,19 @@
width: 50px; width: 50px;
color: #fff; color: #fff;
} }
.padding-top-double { .padding-top-double {
padding-top: 20px; padding-top: 20px;
} }
.padding-double { .padding-double {
padding: 20px; padding: 20px;
} }
.grey { .grey {
color: #333; color: #333;
} }
hr { hr {
display: block; display: block;
height: 1px; height: 1px;
@ -106,12 +286,15 @@
padding: 0; padding: 0;
opacity: 0.2; opacity: 0.2;
} }
.light-grey { .light-grey {
color: #7c7c7c; color: #7c7c7c;
} }
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
.grey-bg { .grey-bg {
background-color: #f6f4f4; background-color: #f6f4f4;
} }
@ -126,21 +309,20 @@
.doc-link a { .doc-link a {
color: white; color: white;
} }
</style> </style>
{{/zone}}
{{#zone "bottomJs"}} {{#zone "bottomJs"}}
{{js "/js/download.js"}}
<script type="text/javascript"> <script type="text/javascript">
$(".download-link").click(function () {
$(".download-link").click(function(){
toggleEnrollment(); toggleEnrollment();
}); });
function toggleEnrollment(){ function toggleEnrollment() {
$(".modalpopup-content").html($("#qr-code-modal").html()); $(".modalpopup-content").html($("#qr-code-modal").html());
generateQRCode(".modalpopup-content .qr-code"); generateQRCode(".modalpopup-content .qr-code");
showPopup(); showPopup();
} }
</script> </script>
{{js "/js/jquery.validate.js"}}
{{/zone}} {{/zone}}

@ -69,6 +69,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
public void run() { public void run() {
while (!isConnected()) { while (!isConnected()) {
try { try {
connectToQueue(); connectToQueue();
agentManager.updateAgentStatus("Connected to MQTT Queue"); agentManager.updateAgentStatus("Connected to MQTT Queue");
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
@ -142,8 +143,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'"; String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'";
log.info(AgentConstants.LOG_APPENDER + replyTemperature); log.info(AgentConstants.LOG_APPENDER + replyTemperature);
String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, deviceID);
serverName, deviceOwner, deviceID);
replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature; replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage); securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
@ -157,7 +157,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
log.info(AgentConstants.LOG_APPENDER + replyHumidity); log.info(AgentConstants.LOG_APPENDER + replyHumidity);
String humidPublishTopic = String.format( String humidPublishTopic = String.format(
AgentConstants.MQTT_PUBLISH_TOPIC, serverName, deviceOwner, deviceID); AgentConstants.MQTT_PUBLISH_TOPIC, deviceID);
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity; replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage); securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
@ -202,8 +202,6 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
pushMessage.setRetained(false); pushMessage.setRetained(false);
String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC,
agentManager.getAgentConfigs().getServerName(),
agentManager.getAgentConfigs().getDeviceOwner(),
agentManager.getAgentConfigs().getDeviceId()); agentManager.getAgentConfigs().getDeviceId());
publishToQueue(topic, pushMessage); publishToQueue(topic, pushMessage);

@ -29,6 +29,7 @@ public class AgentConfiguration {
private String deviceId; private String deviceId;
private String deviceName; private String deviceName;
private String controllerContext; private String controllerContext;
private String scepContext;
private String HTTPS_ServerEndpoint; private String HTTPS_ServerEndpoint;
private String HTTP_ServerEndpoint; private String HTTP_ServerEndpoint;
private String apimGatewayEndpoint; private String apimGatewayEndpoint;
@ -150,6 +151,14 @@ public class AgentConfiguration {
public void setDataPushInterval(int dataPushInterval) { public void setDataPushInterval(int dataPushInterval) {
this.dataPushInterval = dataPushInterval; this.dataPushInterval = dataPushInterval;
} }
public String getScepContext() {
return scepContext;
}
public void setScepContext(String scepContext) {
this.scepContext = scepContext;
}
} }

@ -26,7 +26,8 @@ public class AgentConstants {
/* --------------------------------------------------------------------------------------- /* ---------------------------------------------------------------------------------------
IoT-Server specific information IoT-Server specific information
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
public static final String DEVICE_CONTROLLER_API_EP = "/virtual_firealarm/controller"; public static final String DEVICE_CONTROLLER_API_EP = "/virtual_firealarm/device";
public static final String DEVICE_SCEP_API_EP = "/virtual_firealarm_scep";
public static final String DEVICE_ENROLLMENT_API_EP = "/scep"; public static final String DEVICE_ENROLLMENT_API_EP = "/scep";
public static final String DEVICE_REGISTER_API_EP = "/register"; public static final String DEVICE_REGISTER_API_EP = "/register";
public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/push_temperature"; public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/push_temperature";
@ -56,8 +57,8 @@ public class AgentConstants {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/%s/" + DEVICE_TYPE + "/%s"; public static final String MQTT_SUBSCRIBE_TOPIC = "wso2/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "%s/%s/" + DEVICE_TYPE + "/%s/publisher"; public static final String MQTT_PUBLISH_TOPIC = "wso2/" + DEVICE_TYPE + "/%s/publisher";
/* --------------------------------------------------------------------------------------- /* ---------------------------------------------------------------------------------------
XMPP Connection specific information XMPP Connection specific information
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
@ -71,6 +72,7 @@ public class AgentConstants {
public static final String DEVICE_ID_PROPERTY = "deviceId"; public static final String DEVICE_ID_PROPERTY = "deviceId";
public static final String DEVICE_NAME_PROPERTY = "device-name"; public static final String DEVICE_NAME_PROPERTY = "device-name";
public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context"; public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context";
public static final String DEVICE_SCEP_CONTEXT_PROPERTY = "scep-context";
public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep"; public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep";
public static final String SERVER_HTTP_EP_PROPERTY = "http-ep"; public static final String SERVER_HTTP_EP_PROPERTY = "http-ep";
public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep"; public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep";

@ -133,10 +133,7 @@ public class AgentManager {
log.error("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() + log.error("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() +
", provided in the configuration file is invalid."); ", provided in the configuration file is invalid.");
} }
String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, agentConfigs.getDeviceId());
agentConfigs.getServerName(),
agentConfigs.getDeviceOwner(),
agentConfigs.getDeviceId());
// TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator(); // TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator();
TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(), TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(),

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.core; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.core;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONObject; import org.json.JSONObject;
@ -45,6 +46,8 @@ public class AgentUtilOperations {
private static final Log log = LogFactory.getLog(AgentUtilOperations.class); private static final Log log = LogFactory.getLog(AgentUtilOperations.class);
private static final String JSON_MESSAGE_KEY = "Msg"; private static final String JSON_MESSAGE_KEY = "Msg";
private static final String JSON_SIGNATURE_KEY = "Sig"; private static final String JSON_SIGNATURE_KEY = "Sig";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private static final String JSON_TENANT_KEY = "Tenant";
/** /**
* This method reads the agent specific configurations for the device from the * This method reads the agent specific configurations for the device from the
@ -88,6 +91,8 @@ public class AgentUtilOperations {
AgentConstants.DEVICE_NAME_PROPERTY)); AgentConstants.DEVICE_NAME_PROPERTY));
iotServerConfigs.setControllerContext(properties.getProperty( iotServerConfigs.setControllerContext(properties.getProperty(
AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY)); AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY));
iotServerConfigs.setScepContext(properties.getProperty(
AgentConstants.DEVICE_SCEP_CONTEXT_PROPERTY));
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty( iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTPS_EP_PROPERTY)); AgentConstants.SERVER_HTTPS_EP_PROPERTY));
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty( iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
@ -176,6 +181,7 @@ public class AgentUtilOperations {
iotServerConfigs.setDeviceId(AgentConstants.DEFAULT_DEVICE_ID); iotServerConfigs.setDeviceId(AgentConstants.DEFAULT_DEVICE_ID);
iotServerConfigs.setDeviceName(AgentConstants.DEFAULT_DEVICE_NAME); iotServerConfigs.setDeviceName(AgentConstants.DEFAULT_DEVICE_NAME);
iotServerConfigs.setControllerContext(AgentConstants.DEVICE_CONTROLLER_API_EP); iotServerConfigs.setControllerContext(AgentConstants.DEVICE_CONTROLLER_API_EP);
iotServerConfigs.setScepContext(AgentConstants.DEVICE_SCEP_API_EP);
iotServerConfigs.setHTTPS_ServerEndpoint(AgentConstants.DEFAULT_HTTPS_SERVER_EP); iotServerConfigs.setHTTPS_ServerEndpoint(AgentConstants.DEFAULT_HTTPS_SERVER_EP);
iotServerConfigs.setHTTP_ServerEndpoint(AgentConstants.DEFAULT_HTTP_SERVER_EP); iotServerConfigs.setHTTP_ServerEndpoint(AgentConstants.DEFAULT_HTTP_SERVER_EP);
iotServerConfigs.setApimGatewayEndpoint(AgentConstants.DEFAULT_APIM_GATEWAY_EP); iotServerConfigs.setApimGatewayEndpoint(AgentConstants.DEFAULT_APIM_GATEWAY_EP);
@ -203,11 +209,11 @@ public class AgentUtilOperations {
String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint(); String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint();
String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint(); String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint();
String backEndContext = agentManager.getAgentConfigs().getControllerContext(); String backEndContext = agentManager.getAgentConfigs().getControllerContext();
String scepBackEndContext = agentManager.getAgentConfigs().getScepContext();
String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext; String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext;
String deviceEnrollmentEndpoint = String deviceEnrollmentEndpoint =
serverUnSecureEndpoint + backEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP; serverUnSecureEndpoint + scepBackEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP;
agentManager.setEnrollmentEP(deviceEnrollmentEndpoint); agentManager.setEnrollmentEP(deviceEnrollmentEndpoint);
String registerEndpointURL = String registerEndpointURL =
@ -229,21 +235,11 @@ public class AgentUtilOperations {
public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException { public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException {
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey(); PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
String encodedMessage = Base64.encodeBase64String(message.getBytes());
String encryptedMsg;
try {
encryptedMsg = CommunicationUtils.encryptMessage(message, serverPublicKey);
} catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to encryptMessage: [" + message + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
String signedPayload; String signedPayload;
try { try {
signedPayload = CommunicationUtils.signMessage(encryptedMsg, devicePrivateKey); signedPayload = CommunicationUtils.signMessage(encodedMessage, devicePrivateKey);
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]"; String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]";
log.error(errorMsg); log.error(errorMsg);
@ -251,8 +247,11 @@ public class AgentUtilOperations {
} }
JSONObject jsonPayload = new JSONObject(); JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, encryptedMsg); jsonPayload.put(JSON_MESSAGE_KEY, encodedMessage);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload); jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
//below statements are temporary fix.
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
jsonPayload.put(JSON_TENANT_KEY, "carbon.super");
return jsonPayload.toString(); return jsonPayload.toString();
} }
@ -262,17 +261,15 @@ public class AgentUtilOperations {
String actualMessage; String actualMessage;
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey(); PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
JSONObject jsonPayload = new JSONObject(message); JSONObject jsonPayload = new JSONObject(message);
Object encryptedMessage = jsonPayload.get(JSON_MESSAGE_KEY); Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY); Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
boolean verification; boolean verification;
if (encryptedMessage != null && signedPayload != null) { if (encodedMessage != null && signedPayload != null) {
try { try {
verification = CommunicationUtils.verifySignature( verification = CommunicationUtils.verifySignature(
encryptedMessage.toString(), signedPayload.toString(), serverPublicKey); encodedMessage.toString(), signedPayload.toString(), serverPublicKey);
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
String errorMsg = String errorMsg =
"Error occurred whilst trying to verify signature on received message: [" + message + "]"; "Error occurred whilst trying to verify signature on received message: [" + message + "]";
@ -284,21 +281,13 @@ public class AgentUtilOperations {
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}."; "Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} }
try {
if (verification) { if (verification) {
actualMessage = CommunicationUtils.decryptMessage(encryptedMessage.toString(), devicePrivateKey); actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()), StandardCharsets.UTF_8);
} else { } else {
String errorMsg = "Could not verify payload signature. The message was not signed by a valid client"; String errorMsg = "Could not verify payload signature. The message was not signed by a valid client";
log.error(errorMsg); log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} }
} catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to decrypt received message: [" + encryptedMessage + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
return actualMessage; return actualMessage;
} }

@ -27,6 +27,7 @@ import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException; import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.transport.TransportHandler; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.transport.TransportHandlerException;
@ -53,6 +54,7 @@ public abstract class MQTTTransportHandler
private static final Log log = LogFactory.getLog(MQTTTransportHandler.class); private static final Log log = LogFactory.getLog(MQTTTransportHandler.class);
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
private static final String DEFAULT_PASSWORD = "";
private MqttClient client; private MqttClient client;
private String clientId; private String clientId;
@ -81,6 +83,8 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL; this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
/** /**
@ -105,6 +109,8 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = intervalInMillis; this.timeoutInterval = intervalInMillis;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
public void setTimeoutInterval(int timeoutInterval) { public void setTimeoutInterval(int timeoutInterval) {

@ -20,7 +20,8 @@ server-name=WSO2IoTServer
owner=shabirmean owner=shabirmean
deviceId=t4ctwq8qfl11 deviceId=t4ctwq8qfl11
device-name=SMEAN_t4ctwq8qfl11 device-name=SMEAN_t4ctwq8qfl11
controller-context=/virtual_firealarm/controller controller-context=/virtual_firealarm/device
scep-context=/virtual_firealarm_scep
https-ep=https://localhost:9443 https-ep=https://localhost:9443
http-ep=http://localhost:9763 http-ep=http://localhost:9763
apim-ep=http://192.168.67.21:8281 apim-ep=http://192.168.67.21:8281

@ -137,8 +137,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'"; String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'";
log.info(AgentConstants.LOG_APPENDER + replyTemperature); log.info(AgentConstants.LOG_APPENDER + replyTemperature);
String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, deviceID);
serverName, deviceOwner, deviceID);
replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature; replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage); securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
@ -152,7 +151,7 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
log.info(AgentConstants.LOG_APPENDER + replyHumidity); log.info(AgentConstants.LOG_APPENDER + replyHumidity);
String humidPublishTopic = String.format( String humidPublishTopic = String.format(
AgentConstants.MQTT_PUBLISH_TOPIC, serverName, deviceOwner, deviceID); AgentConstants.MQTT_PUBLISH_TOPIC, deviceID);
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity; replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage); securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
@ -193,8 +192,6 @@ public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
pushMessage.setRetained(false); pushMessage.setRetained(false);
String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC,
agentManager.getAgentConfigs().getServerName(),
agentManager.getAgentConfigs().getDeviceOwner(),
agentManager.getAgentConfigs().getDeviceId()); agentManager.getAgentConfigs().getDeviceId());
publishToQueue(topic, pushMessage); publishToQueue(topic, pushMessage);

@ -29,6 +29,7 @@ public class AgentConfiguration {
private String deviceId; private String deviceId;
private String deviceName; private String deviceName;
private String controllerContext; private String controllerContext;
private String scepContext;
private String HTTPS_ServerEndpoint; private String HTTPS_ServerEndpoint;
private String HTTP_ServerEndpoint; private String HTTP_ServerEndpoint;
private String apimGatewayEndpoint; private String apimGatewayEndpoint;
@ -150,6 +151,14 @@ public class AgentConfiguration {
public void setDataPushInterval(int dataPushInterval) { public void setDataPushInterval(int dataPushInterval) {
this.dataPushInterval = dataPushInterval; this.dataPushInterval = dataPushInterval;
} }
public String getScepContext() {
return scepContext;
}
public void setScepContext(String scepContext) {
this.scepContext = scepContext;
}
} }

@ -56,8 +56,8 @@ public class AgentConstants {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/%s/" + DEVICE_TYPE + "/%s"; public static final String MQTT_SUBSCRIBE_TOPIC = "wso2/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "%s/%s/" + DEVICE_TYPE + "/%s/publisher"; public static final String MQTT_PUBLISH_TOPIC = "wso2/" + DEVICE_TYPE + "/%s/publisher";
/* --------------------------------------------------------------------------------------- /* ---------------------------------------------------------------------------------------
XMPP Connection specific information XMPP Connection specific information
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
@ -71,6 +71,7 @@ public class AgentConstants {
public static final String DEVICE_ID_PROPERTY = "deviceId"; public static final String DEVICE_ID_PROPERTY = "deviceId";
public static final String DEVICE_NAME_PROPERTY = "device-name"; public static final String DEVICE_NAME_PROPERTY = "device-name";
public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context"; public static final String DEVICE_CONTROLLER_CONTEXT_PROPERTY = "controller-context";
public static final String DEVICE_SCEP_CONTEXT_PROPERTY = "scep-context";
public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep"; public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep";
public static final String SERVER_HTTP_EP_PROPERTY = "http-ep"; public static final String SERVER_HTTP_EP_PROPERTY = "http-ep";
public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep"; public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep";

@ -121,10 +121,7 @@ public class AgentManager {
log.error("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() + log.error("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() +
", provided in the configuration file is invalid."); ", provided in the configuration file is invalid.");
} }
String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, agentConfigs.getDeviceId());
agentConfigs.getServerName(),
agentConfigs.getDeviceOwner(),
agentConfigs.getDeviceId());
// TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator(); // TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator();
TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(), TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(),

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONObject; import org.json.JSONObject;
@ -49,6 +50,8 @@ public class AgentUtilOperations {
private static final Log log = LogFactory.getLog(AgentUtilOperations.class); private static final Log log = LogFactory.getLog(AgentUtilOperations.class);
private static final String JSON_MESSAGE_KEY = "Msg"; private static final String JSON_MESSAGE_KEY = "Msg";
private static final String JSON_SIGNATURE_KEY = "Sig"; private static final String JSON_SIGNATURE_KEY = "Sig";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private static final String JSON_TENANT_KEY = "Tenant";
/** /**
* This method reads the agent specific configurations for the device from the * This method reads the agent specific configurations for the device from the
@ -92,6 +95,8 @@ public class AgentUtilOperations {
AgentConstants.DEVICE_NAME_PROPERTY)); AgentConstants.DEVICE_NAME_PROPERTY));
iotServerConfigs.setControllerContext(properties.getProperty( iotServerConfigs.setControllerContext(properties.getProperty(
AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY)); AgentConstants.DEVICE_CONTROLLER_CONTEXT_PROPERTY));
iotServerConfigs.setScepContext(properties.getProperty(
AgentConstants.DEVICE_SCEP_CONTEXT_PROPERTY));
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty( iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTPS_EP_PROPERTY)); AgentConstants.SERVER_HTTPS_EP_PROPERTY));
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty( iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
@ -176,11 +181,12 @@ public class AgentUtilOperations {
String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint(); String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint();
String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint(); String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint();
String backEndContext = agentManager.getAgentConfigs().getControllerContext(); String backEndContext = agentManager.getAgentConfigs().getControllerContext();
String scepBackEndContext = agentManager.getAgentConfigs().getScepContext();
String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext; String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext;
String deviceEnrollmentEndpoint = String deviceEnrollmentEndpoint =
serverUnSecureEndpoint + backEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP; serverUnSecureEndpoint + scepBackEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP;
agentManager.setEnrollmentEP(deviceEnrollmentEndpoint); agentManager.setEnrollmentEP(deviceEnrollmentEndpoint);
String registerEndpointURL = String registerEndpointURL =
@ -202,21 +208,11 @@ public class AgentUtilOperations {
public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException { public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException {
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey(); PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
String encodedMessage = Base64.encodeBase64String(message.getBytes());
String encryptedMsg;
try {
encryptedMsg = CommunicationUtils.encryptMessage(message, serverPublicKey);
} catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to encryptMessage: [" + message + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
String signedPayload; String signedPayload;
try { try {
signedPayload = CommunicationUtils.signMessage(encryptedMsg, devicePrivateKey); signedPayload = CommunicationUtils.signMessage(encodedMessage, devicePrivateKey);
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]"; String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]";
log.error(errorMsg); log.error(errorMsg);
@ -224,28 +220,28 @@ public class AgentUtilOperations {
} }
JSONObject jsonPayload = new JSONObject(); JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, encryptedMsg); jsonPayload.put(JSON_MESSAGE_KEY, encodedMessage);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload); jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
//below statements are temporary fix.
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
jsonPayload.put(JSON_TENANT_KEY, "carbon.super");
return jsonPayload.toString(); return jsonPayload.toString();
} }
public static String extractMessageFromPayload(String message) throws AgentCoreOperationException { public static String extractMessageFromPayload(String message) throws AgentCoreOperationException {
String actualMessage; String actualMessage;
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey(); PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
JSONObject jsonPayload = new JSONObject(message); JSONObject jsonPayload = new JSONObject(message);
Object encryptedMessage = jsonPayload.get(JSON_MESSAGE_KEY); Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY); Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
boolean verification; boolean verification;
if (encryptedMessage != null && signedPayload != null) { if (encodedMessage != null && signedPayload != null) {
try { try {
verification = CommunicationUtils.verifySignature( verification = CommunicationUtils.verifySignature(
encryptedMessage.toString(), signedPayload.toString(), serverPublicKey); encodedMessage.toString(), signedPayload.toString(), serverPublicKey);
} catch (TransportHandlerException e) { } catch (TransportHandlerException e) {
String errorMsg = String errorMsg =
"Error occurred whilst trying to verify signature on received message: [" + message + "]"; "Error occurred whilst trying to verify signature on received message: [" + message + "]";
@ -257,21 +253,13 @@ public class AgentUtilOperations {
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}."; "Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} }
try {
if (verification) { if (verification) {
actualMessage = CommunicationUtils.decryptMessage(encryptedMessage.toString(), devicePrivateKey); actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()), StandardCharsets.UTF_8);
} else { } else {
String errorMsg = "Could not verify payload signature. The message was not signed by a valid client"; String errorMsg = "Could not verify payload signature. The message was not signed by a valid client";
log.error(errorMsg); log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg); throw new AgentCoreOperationException(errorMsg);
} }
} catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to decrypt received message: [" + encryptedMessage + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
return actualMessage; return actualMessage;
} }

@ -27,6 +27,7 @@ import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException; import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
@ -51,7 +52,7 @@ import java.nio.charset.StandardCharsets;
public abstract class MQTTTransportHandler public abstract class MQTTTransportHandler
implements MqttCallback, TransportHandler<MqttMessage> { implements MqttCallback, TransportHandler<MqttMessage> {
private static final Log log = LogFactory.getLog(MQTTTransportHandler.class); private static final Log log = LogFactory.getLog(MQTTTransportHandler.class);
private static final String DEFAULT_PASSWORD = "";
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0; public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
private MqttClient client; private MqttClient client;
@ -81,6 +82,8 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL; this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
/** /**
@ -105,6 +108,8 @@ public abstract class MQTTTransportHandler
this.mqttBrokerEndPoint = mqttBrokerEndPoint; this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = intervalInMillis; this.timeoutInterval = intervalInMillis;
this.initSubscriber(); this.initSubscriber();
options.setUserName(AgentManager.getInstance().getAgentConfigs().getAuthToken());
options.setPassword(DEFAULT_PASSWORD.toCharArray());
} }
public void setTimeoutInterval(int timeoutInterval) { public void setTimeoutInterval(int timeoutInterval) {

@ -20,7 +20,8 @@ server-name=WSO2IoTServer
owner=shabirmean owner=shabirmean
deviceId=t4ctwq8qfl11 deviceId=t4ctwq8qfl11
device-name=SMEAN_t4ctwq8qfl11 device-name=SMEAN_t4ctwq8qfl11
controller-context=/virtual_firealarm/controller controller-context=/virtual_firealarm/device
scep-context=/virtual_firealarm_scep
https-ep=https://localhost:9443 https-ep=https://localhost:9443
http-ep=http://localhost:9763 http-ep=http://localhost:9763
apim-ep=http://192.168.67.21:8281 apim-ep=http://192.168.67.21:8281

@ -37,6 +37,13 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.InputStream; import java.io.InputStream;
/**
* This class consists the functions/APIs specific to the "actions" of the VirtualFirealarm device-type. These APIs
* include the ones that are used by the [Device] to contact the server (i.e: Enrollment & Publishing Data) and the
* ones used by the [Server/Owner] to contact the [Device] (i.e: sending control signals). This class also initializes
* the transport 'Connectors' [XMPP & MQTT] specific to the VirtualFirealarm device-type in order to communicate with
* such devices and to receive messages form it.
*/
@API(name = "virtual_firealarm", version = "1.0.0", context = "/virtual_firealarm", tags = "virtual_firealarm") @API(name = "virtual_firealarm", version = "1.0.0", context = "/virtual_firealarm", tags = "virtual_firealarm")
@DeviceType(value = "virtual_firealarm") @DeviceType(value = "virtual_firealarm")
public interface VirtualFireAlarmControllerService { public interface VirtualFireAlarmControllerService {
@ -90,39 +97,6 @@ public interface VirtualFireAlarmControllerService {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
Response pushTemperatureData(final DeviceData dataMsg); Response pushTemperatureData(final DeviceData dataMsg);
/**
* This is an API called/used by the SCEP Client of the VirtualFirealarm device in its SCEP enrollment process.
* This acts as the endpoint exposed as part of the SCEP-Server for use by a SCEP Client. This is one of the two
* method-signatures that takes different parameters according to the SCEP-Operation executed by the SCEP-Client
* of the enrolling device. The API supports 2 SCEP Operations [GetCACert] and [GetCACaps].
* <p/>
* Operation [GetCACert] returns the CA cert of the SCEP-Server for the device to verify its authenticity.
* Operation [GetCACaps] returns the CA Capabilities of the SCEP-Server.
*
* @param operation the SCEP operation requested by the client. [GetCACert] or [GetCACaps]
* @param message any messages pertaining to the requested SCEP Operation.
* @return an HTTP Response object with either the CA-Cert or the CA-Capabilities according to the operation.
*/
@GET
@Path("device/scep")
Response scepRequest(@QueryParam("operation") String operation, @QueryParam("message") String message);
/**
* This is an API called/used by the SCEP Client of the VirtualFirealarm device in its SCEP enrollment process.
* This acts as the endpoint exposed as part of the SCEP-Server for use by a SCEP Client. This is one of the two
* method-signatures that takes different parameters according to the SCEP-Operation executed by the SCEP-Client
* of the enrolling device. This API supports the SCEP Operation [PKIOperation].
* <p/>
* Operation [PKIOperation] returns a certificate generated by the SCEP-Server for the enrolling device.
*
* @param operation the final SCEP operation executed in the enrollment process - which is [PKIOperation]
* @param inputStream an input stream consisting of the Certificate-Signing-Request (CSR) from the device.
* @return an HTTP Response object with the signed certificate for the device by the CA of the SCEP Server.
*/
@POST
@Path("device/scep")
Response scepRequestPost(@QueryParam("operation") String operation, InputStream inputStream);
/** /**
* Retrieve Sensor data for the device type * Retrieve Sensor data for the device type

@ -26,21 +26,23 @@ import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException
import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse; import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig; import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener; import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.DeviceData; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.DeviceData;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmXMPPConnector;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.scep.ContentType;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.scep.SCEPOperation;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmMQTTConnector; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmMQTTConnector;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmXMPPConnector;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.scep.ContentType;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.scep.SCEPOperation;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -60,13 +62,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/**
* This class consists the functions/APIs specific to the "actions" of the VirtualFirealarm device-type. These APIs
* include the ones that are used by the [Device] to contact the server (i.e: Enrollment & Publishing Data) and the
* ones used by the [Server/Owner] to contact the [Device] (i.e: sending control signals). This class also initializes
* the transport 'Connectors' [XMPP & MQTT] specific to the VirtualFirealarm device-type in order to communicate with
* such devices and to receive messages form it.
*/
@SuppressWarnings("Non-Annoted WebService") @SuppressWarnings("Non-Annoted WebService")
public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmControllerService { public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmControllerService {
@ -75,7 +70,7 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
private static final String MQTT_PROTOCOL = "MQTT"; private static final String MQTT_PROTOCOL = "MQTT";
private static Log log = LogFactory.getLog(VirtualFireAlarmControllerServiceImpl.class); private static Log log = LogFactory.getLog(VirtualFireAlarmControllerServiceImpl.class);
// consists of utility methods related to encrypting and decrypting messages // consists of utility methods related to encrypting and decrypting messages
private SecurityManager securityManager; private org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager securityManager;
// connects to the given MQTT broker and handles MQTT communication // connects to the given MQTT broker and handles MQTT communication
private VirtualFireAlarmMQTTConnector virtualFireAlarmMQTTConnector; private VirtualFireAlarmMQTTConnector virtualFireAlarmMQTTConnector;
// connects to the given XMPP server and handles XMPP communication // connects to the given XMPP server and handles XMPP communication
@ -117,6 +112,10 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
protocolString); protocolString);
} }
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
switch (protocolString) { switch (protocolString) {
case HTTP_PROTOCOL: case HTTP_PROTOCOL:
String deviceHTTPEndpoint = deviceToIpMap.get(deviceId); String deviceHTTPEndpoint = deviceToIpMap.get(deviceId);
@ -138,6 +137,9 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
} catch (DeviceManagementException | TransportHandlerException e) { } catch (DeviceManagementException | TransportHandlerException e) {
log.error("Failed to send switch-bulb request to device [" + deviceId + "] via " + protocolString); log.error("Failed to send switch-bulb request to device [" + deviceId + "] via " + protocolString);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} }
} }
@ -147,7 +149,6 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
public Response pushTemperatureData(final DeviceData dataMsg) { public Response pushTemperatureData(final DeviceData dataMsg) {
String deviceId = dataMsg.deviceId; String deviceId = dataMsg.deviceId;
String deviceIp = dataMsg.reply; String deviceIp = dataMsg.reply;
float temperature = dataMsg.value;
String registeredIp = deviceToIpMap.get(deviceId); String registeredIp = deviceToIpMap.get(deviceId);
if (registeredIp == null) { if (registeredIp == null) {
log.warn("Unregistered IP: Temperature Data Received from an un-registered IP " + log.warn("Unregistered IP: Temperature Data Received from an un-registered IP " +
@ -158,102 +159,19 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
" is already registered under some other IP. Re-registration required"); " is already registered under some other IP. Re-registration required");
return Response.status(Response.Status.CONFLICT).build(); return Response.status(Response.Status.CONFLICT).build();
} }
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
if (!VirtualFireAlarmServiceUtils.publishToDAS(dataMsg.deviceId, dataMsg.value)) { if (!VirtualFireAlarmServiceUtils.publishToDAS(dataMsg.deviceId, dataMsg.value)) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} }
return Response.ok().build(); return Response.ok().build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} }
@GET
@Path("device/scep")
public Response scepRequest(@QueryParam("operation") String operation, @QueryParam("message") String message) {
if (log.isDebugEnabled()) {
log.debug("Invoking SCEP operation " + operation);
}
if (SCEPOperation.GET_CA_CERT.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking GetCACert");
}
try {
CertificateManagementService certificateManagementService =
VirtualFireAlarmServiceUtils.getCertificateManagementService();
SCEPResponse scepResponse = certificateManagementService.getCACertSCEP();
Response.ResponseBuilder responseBuilder;
switch (scepResponse.getResultCriteria()) {
case CA_CERT_FAILED:
log.error("CA cert failed");
responseBuilder = Response.serverError();
break;
case CA_CERT_RECEIVED:
if (log.isDebugEnabled()) {
log.debug("CA certificate received in GetCACert");
}
responseBuilder = Response.ok(scepResponse.getEncodedResponse(),
ContentType.X_X509_CA_CERT);
break;
case CA_RA_CERT_RECEIVED:
if (log.isDebugEnabled()) {
log.debug("CA and RA certificates received in GetCACert");
}
responseBuilder = Response.ok(scepResponse.getEncodedResponse(),
ContentType.X_X509_CA_RA_CERT);
break;
default:
log.error("Invalid SCEP request");
responseBuilder = Response.serverError();
break;
}
return responseBuilder.build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the VirtualFireAlarm device", e);
} catch (KeystoreException e) {
log.error("Keystore error occurred while enrolling the VirtualFireAlarm device", e);
}
} else if (SCEPOperation.GET_CA_CAPS.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking GetCACaps");
}
try {
CertificateManagementService certificateManagementService = VirtualFireAlarmServiceUtils.
getCertificateManagementService();
byte caCaps[] = certificateManagementService.getCACapsSCEP();
return Response.ok(caCaps, MediaType.TEXT_PLAIN).build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the device", e);
}
} else {
log.error("Invalid SCEP operation " + operation);
}
return Response.serverError().build();
}
@POST
@Path("device/scep")
public Response scepRequestPost(@QueryParam("operation") String operation, InputStream inputStream) {
if (log.isDebugEnabled()) {
log.debug("Invoking SCEP operation " + operation);
}
if (SCEPOperation.PKI_OPERATION.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking PKIOperation");
}
try {
CertificateManagementService certificateManagementService = VirtualFireAlarmServiceUtils.
getCertificateManagementService();
byte pkiMessage[] = certificateManagementService.getPKIMessageSCEP(inputStream);
return Response.ok(pkiMessage, ContentType.X_PKI_MESSAGE).build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the device", e);
} catch (KeystoreException e) {
log.error("Keystore error occurred while enrolling the device", e);
}
}
return Response.serverError().build();
} }
@Path("device/stats/{deviceId}/sensors/{sensorName}") @Path("device/stats/{deviceId}/sensors/{sensorName}")
@ -270,6 +188,10 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
VirtualFireAlarmConstants.DEVICE_TYPE + " AND time : [" + fromDate + " TO " + toDate + "]"; VirtualFireAlarmConstants.DEVICE_TYPE + " AND time : [" + fromDate + " TO " + toDate + "]";
String sensorTableName = getSensorEventTableName(sensor); String sensorTableName = getSensorEventTableName(sensor);
try { try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE))) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
if (sensorTableName != null) { if (sensorTableName != null) {
List<SortByField> sortByFields = new ArrayList<>(); List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SORT.ASC, false); SortByField sortByField = new SortByField("time", SORT.ASC, false);
@ -281,6 +203,9 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query; String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg); log.error(errorMsg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} }
return Response.status(Response.Status.BAD_REQUEST).build(); return Response.status(Response.Status.BAD_REQUEST).build();
} }

@ -34,39 +34,32 @@ import javax.ws.rs.core.Response;
@Path("enrollment") @Path("enrollment")
@API(name = "virtual_firealarm_mgt", version = "1.0.0", context = "/virtual_firealarm_mgt", tags = "virtual_firealarm") @API(name = "virtual_firealarm_mgt", version = "1.0.0", context = "/virtual_firealarm_mgt", tags = "virtual_firealarm")
@DeviceType(value = "virtual_firealarm")
public interface VirtualFireAlarmManagerService { public interface VirtualFireAlarmManagerService {
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@DELETE @DELETE
Response removeDevice(@PathParam("device_id") String deviceId); Response removeDevice(@PathParam("device_id") String deviceId);
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@PUT @PUT
Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name); Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name);
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@GET @GET
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
Response getDevice(@PathParam("device_id") String deviceId); Response getDevice(@PathParam("device_id") String deviceId);
@Path("devices") @Path("/devices")
@GET @GET
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
Response getFirealarmDevices(); Response getFirealarmDevices();
@Path("devices/download") @Path("/devices/download")
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces("application/zip")
Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType); Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType);
@Path("devices/generate_link")
@GET
Response generateSketchLink(@QueryParam("deviceName") String deviceName,
@QueryParam("sketchType") String sketchType);
} }

@ -19,6 +19,8 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
@ -27,6 +29,7 @@ import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient;
@ -63,14 +66,18 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
private static final String KEY_TYPE = "PRODUCTION"; private static final String KEY_TYPE = "PRODUCTION";
private static ApiApplicationKey apiApplicationKey; private static ApiApplicationKey apiApplicationKey;
private static Log log = LogFactory.getLog(VirtualFireAlarmManagerServiceImpl.class);
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@DELETE @DELETE
public Response removeDevice(@PathParam("device_id") String deviceId) { public Response removeDevice(@PathParam("device_id") String deviceId) {
try { try {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE); deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
boolean removed = APIUtil.getDeviceManagementService().disenrollDevice( boolean removed = APIUtil.getDeviceManagementService().disenrollDevice(
deviceIdentifier); deviceIdentifier);
if (removed) { if (removed) {
@ -79,17 +86,24 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build(); return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build();
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@PUT @PUT
public Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name) { public Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name) {
try { try {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE); deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
device.setDeviceIdentifier(deviceId); device.setDeviceIdentifier(deviceId);
device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime()); device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime());
@ -102,11 +116,15 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build(); return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build();
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@Path("devices/{device_id}") @Path("/devices/{device_id}")
@GET @GET
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ -115,14 +133,21 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId); deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE); deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier); Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
return Response.ok().entity(device).build(); return Response.ok().entity(device).build();
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@Path("devices") @Path("/devices")
@GET @GET
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ -140,57 +165,44 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
Device[] devices = userDevicesforFirealarm.toArray(new Device[]{}); Device[] devices = userDevicesforFirealarm.toArray(new Device[]{});
return Response.ok().entity(devices).build(); return Response.ok().entity(devices).build();
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
} }
} }
@Path("devices/download") @Path("/devices/download")
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces("application/zip")
public Response downloadSketch(@QueryParam("deviceName") String deviceName, public Response downloadSketch(@QueryParam("deviceName") String deviceName,
@QueryParam("sketchType") String sketchType) { @QueryParam("sketchType") String sketchType) {
try { try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType); ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType);
Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile()));
response.status(Response.Status.OK);
response.type("application/zip"); response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
return response.build(); Response resp = response.build();
zipFile.getZipFile().delete();
return resp;
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request return Response.status(400).entity(ex.getMessage()).build();//bad request
} catch (DeviceManagementException ex) { } catch (DeviceManagementException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (JWTClientException ex) { } catch (JWTClientException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (APIManagerException ex) { } catch (APIManagerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (DeviceControllerException ex) { } catch (DeviceControllerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) { } catch (IOException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) { } catch (UserStoreException ex) {
return Response.status(500).entity(ex.getMessage()).build(); log.error(ex.getMessage(), ex);
}
}
@Path("devices/generate_link")
@GET
public Response generateSketchLink(@QueryParam("deviceName") String deviceName,
@QueryParam("sketchType") String sketchType) {
try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType);
Response.ResponseBuilder rb = Response.ok(zipFile.getDeviceId());
return rb.build();
} catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request
} catch (DeviceManagementException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (JWTClientException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (APIManagerException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (DeviceControllerException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) {
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} }
} }
@ -215,8 +227,12 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
enrolmentInfo.setOwner(APIUtil.getAuthenticatedUser()); enrolmentInfo.setOwner(APIUtil.getAuthenticatedUser());
device.setEnrolmentInfo(enrolmentInfo); device.setEnrolmentInfo(enrolmentInfo);
boolean added = APIUtil.getDeviceManagementService().enrollDevice(device); boolean added = APIUtil.getDeviceManagementService().enrollDevice(device);
if (added) {
APIUtil.registerApiAccessRoles(APIUtil.getAuthenticatedUser());
}
return added; return added;
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error(e.getMessage(), e);
return false; return false;
} }
} }

@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
@ -33,9 +34,9 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig; import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler; import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient; import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
@ -47,7 +48,6 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Calendar;
import java.util.UUID; import java.util.UUID;
/** /**
@ -73,6 +73,8 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5); private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private static final String KEY_TYPE = "PRODUCTION"; private static final String KEY_TYPE = "PRODUCTION";
private static final String EMPTY_STRING = ""; private static final String EMPTY_STRING = "";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private static final String JSON_TENANT_KEY = "Tenant";
/** /**
* Default constructor for the VirtualFirealarmMQTTConnector. * Default constructor for the VirtualFirealarmMQTTConnector.
@ -99,7 +101,8 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName(); .getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername); PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); APIManagementProviderService apiManagementProviderService = APIUtil
.getAPIManagementProviderService();
String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE}; String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE};
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true); VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
@ -156,17 +159,34 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Received MQTT message for: [DEVICE.ID-" + deviceId + "]"); log.debug("Received MQTT message for: [DEVICE.ID-" + deviceId + "]");
} }
JSONObject jsonPayload = new JSONObject(mqttMessage.toString());
String actualMessage; String actualMessage;
try { try {
String tenantDomain = (String) jsonPayload.get(JSON_TENANT_KEY);
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class,
null);
ctx.setTenantDomain(tenantDomain, true);
if (deviceManagementProviderService != null) {
DeviceIdentifier identifier = new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE);
Device device = deviceManagementProviderService.getDevice(identifier);
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setUsername(owner);
} else {
return;
}
}
Long serialNo = (Long)jsonPayload.get(JSON_SERIAL_KEY);
// the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment. // the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment.
// hence, the same is used here to fetch the device-specific-certificate from the key store. // hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId); PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey("" + serialNo);
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
// the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, "Sig":<SIGNATURE>} // the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, "Sig":<SIGNATURE>}
actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(mqttMessage.toString(), actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(mqttMessage.toString(),
serverPrivateKey,
clientPublicKey); clientPublicKey);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("MQTT: Received Message [" + actualMessage + "] topic: [" + topic + "]"); log.debug("MQTT: Received Message [" + actualMessage + "] topic: [" + topic + "]");
@ -174,31 +194,9 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
if (actualMessage.contains("PUBLISHER")) { if (actualMessage.contains("PUBLISHER")) {
float temperature = Float.parseFloat(actualMessage.split(":")[2]); float temperature = Float.parseFloat(actualMessage.split(":")[2]);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx
.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService != null) {
DeviceIdentifier identifier = new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE);
Device device = deviceManagementProviderService.getDevice(identifier);
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setTenantDomain(MultitenantUtils.getTenantDomain(owner), true);
ctx.setUsername(owner);
if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) { if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) {
log.error("MQTT Subscriber: Publishing data to DAS failed."); log.error("MQTT Subscriber: Publishing data to DAS failed.");
} }
}
}
} catch (DeviceManagementException e) {
log.error("Failed to retreive the device managment service for device type " +
VirtualFireAlarmConstants.DEVICE_TYPE, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("MQTT Subscriber: Published data to DAS successfully."); log.debug("MQTT Subscriber: Published data to DAS successfully.");
} }
@ -210,6 +208,11 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
String errorMsg = String errorMsg =
"CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful."; "CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful.";
log.error(errorMsg, e); log.error(errorMsg, e);
} catch (DeviceManagementException e) {
log.error("Failed to retreive the device managment service for device type " +
VirtualFireAlarmConstants.DEVICE_TYPE, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
} else { } else {
String errorMsg = String errorMsg =
@ -225,39 +228,30 @@ public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
*/ */
@Override @Override
public void publishDeviceData(String... publishData) throws TransportHandlerException { public void publishDeviceData(String... publishData) throws TransportHandlerException {
if (publishData.length != 4) { if (publishData.length != 3) {
String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " + String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " +
"Need to be [owner, deviceId, resource{BULB/TEMP}, state{ON/OFF or null}]"; "Need to be [owner, deviceId, resource{BULB/TEMP}, state{ON/OFF or null}]";
log.error(errorMsg); log.error(errorMsg);
throw new TransportHandlerException(errorMsg); throw new TransportHandlerException(errorMsg);
} }
String deviceOwner = publishData[0]; String deviceId = publishData[0];
String deviceId = publishData[1]; String resource = publishData[1];
String resource = publishData[2]; String state = publishData[2];
String state = publishData[3];
MqttMessage pushMessage = new MqttMessage(); MqttMessage pushMessage = new MqttMessage();
String publishTopic = "wso2/" + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId; String publishTopic = "wso2/" + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
try { try {
PublicKey devicePublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId);
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey(); PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
String actualMessage = resource + ":" + state; String actualMessage = resource + ":" + state;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey);
devicePublicKey,
serverPrivateKey);
pushMessage.setPayload(encryptedMsg.getBytes(StandardCharsets.UTF_8)); pushMessage.setPayload(encryptedMsg.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE); pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false); pushMessage.setRetained(false);
publishToQueue(publishTopic, pushMessage); publishToQueue(publishTopic, pushMessage);
} catch (VirtualFireAlarmException e) { } catch (VirtualFireAlarmException e) {
String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "] of owner - " + String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "]";
"[" + deviceOwner + "].";
log.error(errorMsg); log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e); throw new TransportHandlerException(errorMsg, e);
} }

@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig; import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
@ -29,15 +30,14 @@ import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException; import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.xmpp.XMPPTransportHandler; import org.wso2.carbon.device.mgt.iot.transport.xmpp.XMPPTransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.File; import java.io.File;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Calendar;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
@ -52,6 +52,7 @@ public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
private static String xmppVFireAlarmAdminAccountJID; private static String xmppVFireAlarmAdminAccountJID;
private static final String V_FIREALARM_XMPP_PASSWORD = "vfirealarm@123"; private static final String V_FIREALARM_XMPP_PASSWORD = "vfirealarm@123";
private static final String DEVICEMGT_CONFIG_FILE = "devicemgt-config.xml"; private static final String DEVICEMGT_CONFIG_FILE = "devicemgt-config.xml";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private ScheduledFuture<?> connectorServiceHandler; private ScheduledFuture<?> connectorServiceHandler;
private ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); private ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
@ -155,9 +156,15 @@ public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
} }
try { try {
PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId); PrivilegedCarbonContext.startTenantFlow();
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey(); String tenantDomain = MultitenantUtils.getTenantDomain(owner);
String actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(message, serverPrivateKey, PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(owner);
JSONObject jsonPayload = new JSONObject(message);
Long serialNo = (Long)jsonPayload.get(JSON_SERIAL_KEY);
PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey("" + serialNo);
String actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(message,
clientPublicKey); clientPublicKey);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("XMPP: Received Message [" + actualMessage + "] from: [" + from + "]"); log.debug("XMPP: Received Message [" + actualMessage + "] from: [" + from + "]");
@ -166,10 +173,6 @@ public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
switch (subject) { switch (subject) {
case "PUBLISHER": case "PUBLISHER":
float temperature = Float.parseFloat(actualMessage.split(":")[1]); float temperature = Float.parseFloat(actualMessage.split(":")[1]);
PrivilegedCarbonContext.startTenantFlow();
String tenantDomain = MultitenantUtils.getTenantDomain(owner);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(owner);
if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) { if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) {
log.error("XMPP Connector: Publishing VirtualFirealarm data to DAS failed."); log.error("XMPP Connector: Publishing VirtualFirealarm data to DAS failed.");
} }
@ -194,6 +197,8 @@ public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
String errorMsg = String errorMsg =
"CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful."; "CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful.";
log.error(errorMsg, e); log.error(errorMsg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
} else { } else {
log.warn("Received XMPP message from client with unexpected JID [" + from + "]."); log.warn("Received XMPP message from client with unexpected JID [" + from + "].");
@ -215,14 +220,9 @@ public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
String state = publishData[3]; String state = publishData[3];
try { try {
PublicKey devicePublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId);
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey(); PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
String actualMessage = resource + ":" + state; String actualMessage = resource + ":" + state;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey);
devicePublicKey,
serverPrivateKey);
String clientToConnect = deviceId + "@" + xmppServerIP + File.separator + deviceOwner; String clientToConnect = deviceId + "@" + xmppServerIP + File.separator + deviceOwner;
sendXMPPMessage(clientToConnect, encryptedMsg, "CONTROL-REQUEST"); sendXMPPMessage(clientToConnect, encryptedMsg, "CONTROL-REQUEST");

@ -13,9 +13,13 @@ import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -63,7 +67,8 @@ public class APIUtil {
return analyticsDataAPI; return analyticsDataAPI;
} }
public static List<SensorRecord> getAllEventsForDevice(String tableName, String query, List<SortByField> sortByFields) throws AnalyticsException { public static List<SensorRecord> getAllEventsForDevice(String tableName, String query,
List<SortByField> sortByFields) throws AnalyticsException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI(); AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query); int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
@ -159,4 +164,52 @@ public class APIUtil {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return threadLocalCarbonContext.getTenantDomain(); return threadLocalCarbonContext.getTenantDomain();
} }
public static UserStoreManager getUserStoreManager() {
RealmService realmService;
UserStoreManager userStoreManager;
try {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
if (realmService == null) {
String msg = "Realm service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
int tenantId = ctx.getTenantId();
userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
} catch (UserStoreException e) {
String msg = "Error occurred while retrieving current user store manager";
log.error(msg, e);
throw new IllegalStateException(msg);
}
return userStoreManager;
}
public static void registerApiAccessRoles(String user) {
UserStoreManager userStoreManager = null;
try {
userStoreManager = getUserStoreManager();
if (userStoreManager != null) {
String[] userList = new String[]{user};
if (!userStoreManager.isExistingRole(Constants.DEFAULT_ROLE_NAME)) {
userStoreManager.addRole(Constants.DEFAULT_ROLE_NAME, userList, Constants.DEFAULT_PERMISSION);
}
}
} catch (UserStoreException e) {
log.error("Error while creating a role and adding a user for virtual_firealarm.", e);
}
}
public static DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceAccessAuthorizationService deviceAccessAuthorizationService =
(DeviceAccessAuthorizationService) ctx.getOSGiService(DeviceAccessAuthorizationService.class, null);
if (deviceAccessAuthorizationService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceAccessAuthorizationService;
}
} }

@ -0,0 +1,32 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.wso2.carbon.user.core.Permission;
/**
* This hold the constants related to the device type.
*/
public class Constants {
public static final String DEFAULT_PERMISSION_RESOURCE = "/permission/admin/device-mgt/virtual_firealarm/user";
public static final String DEFAULT_ROLE_NAME = "virtual_firealarm_user";
public static final Permission DEFAULT_PERMISSION[] = new Permission[]{new Permission(Constants.DEFAULT_PERMISSION_RESOURCE,
"ui.execute")};
}

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -253,8 +254,6 @@ public class VirtualFireAlarmServiceUtils {
payloadData); payloadData);
} catch (DataPublisherConfigurationException e) { } catch (DataPublisherConfigurationException e) {
return false; return false;
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
return true; return true;
} }
@ -264,43 +263,39 @@ public class VirtualFireAlarmServiceUtils {
/** /**
* *
* @param message * @param message
* @param encryptionKey
* @param signatureKey * @param signatureKey
* @return * @return
* @throws VirtualFireAlarmException * @throws VirtualFireAlarmException
*/ */
public static String prepareSecurePayLoad(String message, Key encryptionKey, PrivateKey signatureKey) public static String prepareSecurePayLoad(String message, PrivateKey signatureKey) throws VirtualFireAlarmException {
throws VirtualFireAlarmException { message = Base64.encodeBase64String(message.getBytes());
String encryptedMsg = SecurityManager.encryptMessage(message, encryptionKey); String signedPayload = SecurityManager.signMessage(message, signatureKey);
String signedPayload = SecurityManager.signMessage(encryptedMsg, signatureKey);
JSONObject jsonPayload = new JSONObject(); JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, encryptedMsg); jsonPayload.put(JSON_MESSAGE_KEY, message);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload); jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
return jsonPayload.toString(); return jsonPayload.toString();
} }
/** /**
* *
* @param message * @param message
* @param decryptionKey
* @param verifySignatureKey * @param verifySignatureKey
* @return * @return
* @throws VirtualFireAlarmException * @throws VirtualFireAlarmException
*/ */
public static String extractMessageFromPayload(String message, Key decryptionKey, PublicKey verifySignatureKey) public static String extractMessageFromPayload(String message, PublicKey verifySignatureKey)
throws VirtualFireAlarmException { throws VirtualFireAlarmException {
String actualMessage; String actualMessage;
JSONObject jsonPayload = new JSONObject(message); JSONObject jsonPayload = new JSONObject(message);
Object encryptedMessage = jsonPayload.get(JSON_MESSAGE_KEY); Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY); Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
if (encryptedMessage != null && signedPayload != null) { if (encodedMessage != null && signedPayload != null) {
if (SecurityManager.verifySignature( if (SecurityManager.verifySignature(
encryptedMessage.toString(), signedPayload.toString(), verifySignatureKey)) { encodedMessage.toString(), signedPayload.toString(), verifySignatureKey)) {
actualMessage = SecurityManager.decryptMessage(encryptedMessage.toString(), decryptionKey); actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()));
//SecurityManager.decryptMessage(encryptedMessage.toString(), decryptionKey);
} else { } else {
String errorMsg = "The message was not signed by a valid client. Could not verify signature on payload"; String errorMsg = "The message was not signed by a valid client. Could not verify signature on payload";
throw new VirtualFireAlarmException(errorMsg); throw new VirtualFireAlarmException(errorMsg);
@ -316,17 +311,13 @@ public class VirtualFireAlarmServiceUtils {
/** /**
* *
* @param deviceId * @param alias
* @return * @return
* @throws VirtualFireAlarmException * @throws VirtualFireAlarmException
*/ */
public static PublicKey getDevicePublicKey(String deviceId) throws VirtualFireAlarmException { public static PublicKey getDevicePublicKey(String alias) throws VirtualFireAlarmException {
PublicKey clientPublicKey; PublicKey clientPublicKey;
String alias = "";
try { try {
alias += deviceId.hashCode();
CertificateManagementService certificateManagementService = CertificateManagementService certificateManagementService =
VirtualFireAlarmServiceUtils.getCertificateManagementService(); VirtualFireAlarmServiceUtils.getCertificateManagementService();
X509Certificate clientCertificate = (X509Certificate) certificateManagementService.getCertificateByAlias( X509Certificate clientCertificate = (X509Certificate) certificateManagementService.getCertificateByAlias(
@ -348,7 +339,7 @@ public class VirtualFireAlarmServiceUtils {
} }
throw new VirtualFireAlarmException(errorMsg, e); throw new VirtualFireAlarmException(errorMsg, e);
} else { } else {
errorMsg = "An error occurred whilst trying to retrieve certificate for deviceId [" + deviceId + errorMsg = "An error occurred whilst trying to retrieve certificate for alias [" + alias +
"] with alias: [" + alias + "]"; "] with alias: [" + alias + "]";
if(log.isDebugEnabled()){ if(log.isDebugEnabled()){
log.debug(errorMsg); log.debug(errorMsg);

@ -30,91 +30,64 @@
<!-- Device related APIs --> <!-- Device related APIs -->
<Permission> <Permission>
<name>Get device</name> <name>Get device</name>
<path>/device-mgt/user/devices/list</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/devices/*</url> <url>/enrollment/devices/*</url>
<method>GET</method> <method>GET</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Remove device</name> <name>Remove device</name>
<path>/device-mgt/user/devices/remove</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/devices/*</url> <url>/enrollment/devices/*</url>
<method>DELETE</method> <method>DELETE</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Download device</name> <name>Download device</name>
<path>/device-mgt/user/devices/add</path> <path>/login</path>
<url>/devices/download</url> <url>/enrollment/devices/download</url>
<method>GET</method> <method>GET</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Update device</name> <name>Update device</name>
<path>/device-mgt/user/devices/update</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/devices/*</url> <url>/enrollment/devices/*</url>
<method>POST</method> <method>POST</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Get Devices</name> <name>Get Devices</name>
<path>/device-mgt/user/devices</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/devices</url> <url>/enrollment/devices</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>
</Permission>
<Permission>
<name>Generate Link</name>
<path>/device-mgt/user/devices/generate_link</path>
<url>/devices/generate_link</url>
<method>GET</method> <method>GET</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Register Device</name> <name>Register Device</name>
<path>/device-mgt/user/device/register</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/device/register/*/*/*</url> <url>/device/register/*/*/*</url>
<method>POST</method> <method>POST</method>
<scope>virtual_firealarm_device</scope> <scope>virtual_firealarm_device</scope>
</Permission> </Permission>
<Permission> <Permission>
<name>Control Buzz</name> <name>Control Buzz</name>
<path>/device-mgt/user/device/buzz</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/device/*/buzz</url> <url>/device/*/buzz</url>
<method>POST</method> <method>POST</method>
<scope>virtual_firealarm_user</scope> <scope>virtual_firealarm_user</scope>
</Permission> </Permission>
<Permission>
<name>Get Temperature</name>
<path>/device-mgt/user/device/temperature</path>
<url>/device/*/temperature</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>
</Permission>
<Permission> <Permission>
<name>Push Temperature</name> <name>Push Temperature</name>
<path>/device-mgt/user/device/temperature</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/device/temperature</url> <url>/device/temperature</url>
<method>POST</method> <method>POST</method>
<scope>virtual_firealarm_device</scope> <scope>virtual_firealarm_device</scope>
</Permission> </Permission>
<Permission>
<name>Get SCEP</name>
<path>/device-mgt/user/device/scep</path>
<url>/device/scep</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>
</Permission>
<Permission>
<name>Push SCEP</name>
<path>/device-mgt/user/device/scep</path>
<url>/device/scep</url>
<method>POST</method>
<scope>virtual_firealarm_device</scope>
</Permission>
<Permission> <Permission>
<name>Get Stats</name> <name>Get Stats</name>
<path>/device-mgt/user/device/stats</path> <path>/device-mgt/virtual_firealarm/user</path>
<url>/device/stats/*/sensors/*</url> <url>/device/stats/*/sensors/*</url>
<method>GET</method> <method>GET</method>
<scope>virtual_firealarm_device</scope> <scope>virtual_firealarm_device</scope>

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - IoT Server SCEP Server API</name>
<description>WSO2 Carbon - Virtual FireAlarm SCEP Server API Implementation</description>
<url>http://wso2.org</url>
<dependencies>
<!-- CDM -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.queuing</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.base</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>commons-fileupload.wso2</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.equinox</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>virtual_firealarm_scep</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.io.InputStream;
public interface VirtualFireAlarmScepServer {
/**
* This is an API called/used by the SCEP Client of the VirtualFirealarm device in its SCEP enrollment process.
* This acts as the endpoint exposed as part of the SCEP-Server for use by a SCEP Client. This is one of the two
* method-signatures that takes different parameters according to the SCEP-Operation executed by the SCEP-Client
* of the enrolling device. The API supports 2 SCEP Operations [GetCACert] and [GetCACaps].
* <p/>
* Operation [GetCACert] returns the CA cert of the SCEP-Server for the device to verify its authenticity.
* Operation [GetCACaps] returns the CA Capabilities of the SCEP-Server.
*
* @param operation the SCEP operation requested by the client. [GetCACert] or [GetCACaps]
* @param message any messages pertaining to the requested SCEP Operation.
* @return an HTTP Response object with either the CA-Cert or the CA-Capabilities according to the operation.
*/
@GET
@Path("scep")
Response scepRequest(@QueryParam("operation") String operation, @QueryParam("message") String message);
/**
* This is an API called/used by the SCEP Client of the VirtualFirealarm device in its SCEP enrollment process.
* This acts as the endpoint exposed as part of the SCEP-Server for use by a SCEP Client. This is one of the two
* method-signatures that takes different parameters according to the SCEP-Operation executed by the SCEP-Client
* of the enrolling device. This API supports the SCEP Operation [PKIOperation].
* <p/>
* Operation [PKIOperation] returns a certificate generated by the SCEP-Server for the enrolling device.
*
* @param operation the final SCEP operation executed in the enrollment process - which is [PKIOperation]
* @param inputStream an input stream consisting of the Certificate-Signing-Request (CSR) from the device.
* @return an HTTP Response object with the signed certificate for the device by the CA of the SCEP Server.
*/
@POST
@Path("scep")
Response scepRequestPost(@QueryParam("operation") String operation, InputStream inputStream);
}

@ -0,0 +1,136 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util.scep.ContentType;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util.scep.SCEPOperation;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util.VirtualFireAlarmServiceUtils;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
@SuppressWarnings("Non-Annoted WebService")
public class VirtualFireAlarmScepServerImpl implements VirtualFireAlarmScepServer {
private static Log log = LogFactory.getLog(VirtualFireAlarmScepServerImpl.class);
@GET
@Path("scep")
public Response scepRequest(@QueryParam("operation") String operation, @QueryParam("message") String message) {
if (log.isDebugEnabled()) {
log.debug("Invoking SCEP operation " + operation);
}
if (SCEPOperation.GET_CA_CERT.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking GetCACert");
}
try {
CertificateManagementService certificateManagementService =
VirtualFireAlarmServiceUtils.getCertificateManagementService();
SCEPResponse scepResponse = certificateManagementService.getCACertSCEP();
Response.ResponseBuilder responseBuilder;
switch (scepResponse.getResultCriteria()) {
case CA_CERT_FAILED:
log.error("CA cert failed");
responseBuilder = Response.serverError();
break;
case CA_CERT_RECEIVED:
if (log.isDebugEnabled()) {
log.debug("CA certificate received in GetCACert");
}
responseBuilder = Response.ok(scepResponse.getEncodedResponse(),
ContentType.X_X509_CA_CERT);
break;
case CA_RA_CERT_RECEIVED:
if (log.isDebugEnabled()) {
log.debug("CA and RA certificates received in GetCACert");
}
responseBuilder = Response.ok(scepResponse.getEncodedResponse(),
ContentType.X_X509_CA_RA_CERT);
break;
default:
log.error("Invalid SCEP request");
responseBuilder = Response.serverError();
break;
}
return responseBuilder.build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the VirtualFireAlarm device", e);
} catch (KeystoreException e) {
log.error("Keystore error occurred while enrolling the VirtualFireAlarm device", e);
}
} else if (SCEPOperation.GET_CA_CAPS.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking GetCACaps");
}
try {
CertificateManagementService certificateManagementService = VirtualFireAlarmServiceUtils.
getCertificateManagementService();
byte caCaps[] = certificateManagementService.getCACapsSCEP();
return Response.ok(caCaps, MediaType.TEXT_PLAIN).build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the device", e);
}
} else {
log.error("Invalid SCEP operation " + operation);
}
return Response.serverError().build();
}
@POST
@Path("scep")
public Response scepRequestPost(@QueryParam("operation") String operation, InputStream inputStream) {
if (log.isDebugEnabled()) {
log.debug("Invoking SCEP operation " + operation);
}
if (SCEPOperation.PKI_OPERATION.getValue().equals(operation)) {
if (log.isDebugEnabled()) {
log.debug("Invoking PKIOperation");
}
try {
CertificateManagementService certificateManagementService = VirtualFireAlarmServiceUtils.
getCertificateManagementService();
byte pkiMessage[] = certificateManagementService.getPKIMessageSCEP(inputStream);
return Response.ok(pkiMessage, ContentType.X_PKI_MESSAGE).build();
} catch (VirtualFireAlarmException e) {
log.error("Error occurred while enrolling the device", e);
} catch (KeystoreException e) {
log.error("Keystore error occurred while enrolling the device", e);
}
}
return Response.serverError().build();
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.exception;
public class VirtualFireAlarmException extends Exception {
private static final long serialVersionUID = 118512086957330189L;
public VirtualFireAlarmException(String errorMessage) {
super(errorMessage);
}
public VirtualFireAlarmException(String errorMessage, Throwable throwable) {
super(errorMessage, throwable);
}
}

@ -0,0 +1,103 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.exception.VirtualFireAlarmException;
import java.lang.*;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
/**
*
*/
public class VirtualFireAlarmServiceUtils {
private static final Log log = LogFactory.getLog(VirtualFireAlarmServiceUtils.class);
/**
*
* @return
* @throws VirtualFireAlarmException
*/
public static CertificateManagementService getCertificateManagementService() throws VirtualFireAlarmException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
CertificateManagementService certificateManagementService = (CertificateManagementService)
ctx.getOSGiService(CertificateManagementService.class, null);
if (certificateManagementService == null) {
String msg = "EnrollmentService is not initialized";
log.error(msg);
throw new VirtualFireAlarmException(msg);
}
return certificateManagementService;
}
/**
*
* @param deviceId
* @return
* @throws VirtualFireAlarmException
*/
public static PublicKey getDevicePublicKey(String deviceId) throws VirtualFireAlarmException {
PublicKey clientPublicKey;
String alias = "";
try {
alias += deviceId.hashCode();
CertificateManagementService certificateManagementService =
VirtualFireAlarmServiceUtils.getCertificateManagementService();
X509Certificate clientCertificate = (X509Certificate) certificateManagementService.getCertificateByAlias(
alias);
clientPublicKey = clientCertificate.getPublicKey();
} catch (VirtualFireAlarmException e) {
String errorMsg = "Could not retrieve CertificateManagementService from the runtime.";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
} catch (KeystoreException e) {
String errorMsg;
if (e.getMessage().contains("NULL_CERT")) {
errorMsg = "The Device-View page might have been accessed prior to the device being started.";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
} else {
errorMsg = "An error occurred whilst trying to retrieve certificate for deviceId [" + deviceId +
"] with alias: [" + alias + "]";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
}
}
return clientPublicKey;
}
}

@ -0,0 +1,26 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util.scep;
public class ContentType {
public static final String X_PKI_MESSAGE = "application/x-pki-message";
public static final String X_X509_CA_CERT = "application/x-x509-ca-cert";
public static final String X_X509_CA_RA_CERT = "application/x-x509-ca-ra-cert";
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.util.scep;
public enum SCEPOperation {
GET_CA_CERT("GetCACert"),
GET_CA_CAPS("GetCACaps"),
PKI_OPERATION("PKIOperation");
private String value;
private SCEPOperation(String value) {
this.setValue(value);
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright 2005-2013 WSO2, Inc. (http://wso2.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="VirtualFireAlarmScepServer" address="/">
<jaxrs:serviceBeans>
<bean id="VirtualFireAlarmScepServerService"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.service.impl.VirtualFireAlarmScepServerImpl">
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
</beans>

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
metadata-complete="true">
<display-name>WSO2 IoT Server</display-name>
<description>WSO2 IoT Server</description>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>providerTenantDomain</param-name>
<param-value>carbon.super</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
</web-app>

@ -15,7 +15,7 @@
Operations Operations
</div> </div>
<div class="add-margin-top-4x"> <div class="add-margin-top-4x">
{{unit "iot.unit.device.operation-bar" device=device}} {{unit "iot.unit.device.operation-bar" device=device backendApiUri=backendApiUri}}
</div> </div>
{{/zone}} {{/zone}}

@ -24,9 +24,8 @@ function onRequest(context) {
if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) { if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
var deviceModule = require("/app/modules/device.js").deviceModule; var deviceModule = require("/app/modules/device.js").deviceModule;
var device = deviceModule.viewDevice(deviceType, deviceId); var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != "error") { if (device && device.status != "error") {
return {"device": device}; return {"device": device, "backendApiUri" : devicemgtProps["httpsURL"] + "/virtual_firealarm/"};
} else { } else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!"); response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit(); exit();

@ -140,10 +140,6 @@ function downloadAgent() {
$('#downloadForm').submit(); $('#downloadForm').submit();
hideAgentDownloadPopup(); hideAgentDownloadPopup();
$(modalPopupContent).html($('#device-agent-downloading-content').html()); $(modalPopupContent).html($('#device-agent-downloading-content').html());
showAgentDownloadPopup();
setTimeout(function () {
hideAgentDownloadPopup();
}, 1000);
} else { } else {
$("#invalid-username-error-msg span").text("Invalid device name"); $("#invalid-username-error-msg span").text("Invalid device name");
$("#invalid-username-error-msg").removeClass("hidden"); $("#invalid-username-error-msg").removeClass("hidden");

@ -38,6 +38,7 @@
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.impl</module> <module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.advanced.impl</module>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</module> <module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</module>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</module> <module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</module>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api</module>
</modules> </modules>
<build> <build>

@ -9,9 +9,6 @@ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../featur
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/datasources/,target:${installFolder}/../../conf/datasources/,overwrite:true);\ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/datasources/,target:${installFolder}/../../conf/datasources/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/jaggeryapps/);\ org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/jaggeryapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/jaggeryapps/,target:${installFolder}/../../deployment/server/jaggeryapps/,overwrite:true);\ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/jaggeryapps/,target:${installFolder}/../../deployment/server/jaggeryapps/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/android_sense/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/agent/,target:${installFolder}/../../resources/sketches/android_sense/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../database/);\ org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../database/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/database/,target:${installFolder}/../../database/,overwrite:true);\ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/database/,target:${installFolder}/../../database/,overwrite:true);\

@ -36,10 +36,10 @@
<Enabled>false</Enabled> <Enabled>false</Enabled>
<ControlClass>org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient</ControlClass> <ControlClass>org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient</ControlClass>
<Protocol>XMPP</Protocol> <Protocol>XMPP</Protocol>
<ServerURL>http://204.232.188.215</ServerURL> <ServerURL>http://localhost</ServerURL>
<Port>9090</Port> <Port>9090</Port>
<Username>admin</Username> <Username>admin</Username>
<Password>wso2iot123</Password> <Password>admin</Password>
</ControlQueue> </ControlQueue>
</ControlQueues> </ControlQueues>
</DeviceManagementConfigurations> </DeviceManagementConfigurations>

@ -46,6 +46,11 @@
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</artifactId> <artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</artifactId>
<type>war</type> <type>war</type>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api</artifactId>
<type>war</type>
</dependency>
<dependency> <dependency>
<groupId>com.h2database.wso2</groupId> <groupId>com.h2database.wso2</groupId>
<artifactId>h2-database-engine</artifactId> <artifactId>h2-database-engine</artifactId>
@ -124,6 +129,15 @@
<outputDirectory>${project.build.directory}/maven-shared-archive-resources/webapps/</outputDirectory> <outputDirectory>${project.build.directory}/maven-shared-archive-resources/webapps/</outputDirectory>
<destFileName>virtual_firealarm.war</destFileName> <destFileName>virtual_firealarm.war</destFileName>
</artifactItem> </artifactItem>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api
</artifactId>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/maven-shared-archive-resources/webapps/</outputDirectory>
<destFileName>virtual_firealarm_scep.war</destFileName>
</artifactItem>
</artifactItems> </artifactItems>
</configuration> </configuration>
</execution> </execution>

@ -20,7 +20,8 @@ server-name=${SERVER_NAME}
owner=${DEVICE_OWNER} owner=${DEVICE_OWNER}
deviceId=${DEVICE_ID} deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME} device-name=${DEVICE_NAME}
controller-context=/virtual_firealarm/controller controller-context=/virtual_firealarm/device
scep-context=/virtual_firealarm_scep
https-ep=${HTTPS_EP} https-ep=${HTTPS_EP}
http-ep=${HTTP_EP} http-ep=${HTTP_EP}
apim-ep=${APIM_EP} apim-ep=${APIM_EP}

@ -20,7 +20,8 @@ server-name=${SERVER_NAME}
owner=${DEVICE_OWNER} owner=${DEVICE_OWNER}
deviceId=${DEVICE_ID} deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME} device-name=${DEVICE_NAME}
controller-context=/virtual_firealarm/controller controller-context=/virtual_firealarm/device
scep-context=/virtual_firealarm_scep
https-ep=${HTTPS_EP} https-ep=${HTTPS_EP}
http-ep=${HTTP_EP} http-ep=${HTTP_EP}
apim-ep=${APIM_EP} apim-ep=${APIM_EP}

@ -2,7 +2,7 @@
"deviceType": { "deviceType": {
"label": "Virtual Firealarm", "label": "Virtual Firealarm",
"category": "virtual", "category": "virtual",
"downloadAgentLinkGenUri": "manager/device/virtual_firealarm/generate_link" "downloadAgentUri": "virtual_firealarm/enrollment/devices/download"
}, },
"analyticStreams": [ "analyticStreams": [
{ {

@ -19,6 +19,8 @@ instructions.unconfigure = \
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../conf/device-types/virtual_firealarm.json);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../conf/device-types/virtual_firealarm.json);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm.war);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm.war);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm_scep.war);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/webapps/virtual_firealarm_scep);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../dbscripts/cdm/plugins/virtual_firealarm);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../dbscripts/cdm/plugins/virtual_firealarm);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../resources/sketches/virtual_firealarm);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../resources/sketches/virtual_firealarm);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../resources/sketches/virtual_firealarm_advanced);\ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../resources/sketches/virtual_firealarm_advanced);\

@ -423,6 +423,12 @@
<version>${carbon.devicemgt.plugins.version}</version> <version>${carbon.devicemgt.plugins.version}</version>
<type>war</type> <type>war</type>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
<type>war</type>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>

Loading…
Cancel
Save