mirror of
https://repository.entgra.net/community/device-mgt-plugins.git
synced 2025-09-16 23:42:15 +00:00
removed DCR, added global configuration values for input and output adapter
This commit is contained in:
parent
2e8279b61a
commit
ccaf47112a
@ -21,10 +21,8 @@
|
||||
<from eventAdapterType="oauth-mqtt">
|
||||
<property name="topic">carbon.super/android_sense/+/data</property>
|
||||
<property name="username">admin</property>
|
||||
<property name="password">admin</property>
|
||||
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
|
||||
<property name="contentTransformer">default</property>
|
||||
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
|
||||
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
|
||||
<property name="cleanSession">true</property>
|
||||
</from>
|
||||
<mapping customMapping="disable" type="json"/>
|
||||
|
||||
@ -18,14 +18,7 @@
|
||||
-->
|
||||
<eventReceiver name="arduino_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
|
||||
<from eventAdapterType="oauth-http">
|
||||
<property name="maximumHttpConnectionPerHost">2</property>
|
||||
<property name="username">admin</property>
|
||||
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.http.util.HTTPContentValidator</property>
|
||||
<property name="contentTransformer">default</property>
|
||||
<property name="transports">all</property>
|
||||
<property name="maximumTotalHttpConnection">100</property>
|
||||
<property name="tokenValidationEndpointUrl">https://localhost:${dcr.endpoint.port}/services/OAuth2TokenValidationService</property>
|
||||
<property name="password">admin</property>
|
||||
</from>
|
||||
<mapping customMapping="disable" type="json"/>
|
||||
<to streamName="org.wso2.iot.arduino" version="1.0.0"/>
|
||||
|
||||
@ -20,10 +20,8 @@
|
||||
<from eventAdapterType="oauth-mqtt">
|
||||
<property name="topic">carbon.super/raspberrypi/+/temperature</property>
|
||||
<property name="username">admin</property>
|
||||
<property name="password">admin</property>
|
||||
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
|
||||
<property name="contentTransformer">default</property>
|
||||
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
|
||||
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
|
||||
<property name="cleanSession">true</property>
|
||||
</from>
|
||||
<mapping customMapping="disable" type="json"/>
|
||||
|
||||
@ -20,10 +20,8 @@
|
||||
<from eventAdapterType="oauth-mqtt">
|
||||
<property name="topic">carbon.super/virtual_firealarm/+/temperature</property>
|
||||
<property name="username">admin</property>
|
||||
<property name="password">admin</property>
|
||||
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
|
||||
<property name="contentTransformer">default</property>
|
||||
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
|
||||
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
|
||||
<property name="cleanSession">true</property>
|
||||
</from>
|
||||
<mapping customMapping="disable" type="json"/>
|
||||
|
||||
@ -186,7 +186,7 @@ public final class HTTPEventAdapter implements InputEventAdapter {
|
||||
"HttpService not available, Error in registering endpoint " + endpoint);
|
||||
}
|
||||
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
|
||||
eventAdapterConfiguration),
|
||||
eventAdapterConfiguration, globalProperties),
|
||||
new Hashtable(), httpService.createDefaultHttpContext());
|
||||
} catch (ServletException | NamespaceException e) {
|
||||
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);
|
||||
|
||||
@ -75,45 +75,6 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
|
||||
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
|
||||
propertyList.add(exposedTransportsProperty);
|
||||
|
||||
// OAUTH validation endpoint admin service username
|
||||
Property username = new Property(HTTPEventAdapterConstants.USERNAME);
|
||||
username.setRequired(true);
|
||||
username.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME));
|
||||
username.setHint(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME_HINT));
|
||||
propertyList.add(username);
|
||||
|
||||
// OAUTH validation endpoint admin service password
|
||||
Property password = new Property(HTTPEventAdapterConstants.PASSWORD);
|
||||
password.setRequired(true);
|
||||
password.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD));
|
||||
password.setHint(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD_HINT));
|
||||
propertyList.add(password);
|
||||
|
||||
// OAUTH validation endpoint
|
||||
Property tokenValidationEndpoint = new Property(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL);
|
||||
tokenValidationEndpoint.setRequired(true);
|
||||
tokenValidationEndpoint.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL));
|
||||
tokenValidationEndpoint.setHint(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL_HINT));
|
||||
propertyList.add(tokenValidationEndpoint);
|
||||
|
||||
Property maximumHttpConnectionPerHost = new Property(HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST);
|
||||
maximumHttpConnectionPerHost.setRequired(true);
|
||||
maximumHttpConnectionPerHost.setDisplayName(resourceBundle.getString(
|
||||
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST));
|
||||
maximumHttpConnectionPerHost.setHint(resourceBundle.getString(
|
||||
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT));
|
||||
maximumHttpConnectionPerHost.setDefaultValue(HTTPEventAdapterConstants.MAX_HTTP_CONNECTION);
|
||||
propertyList.add(maximumHttpConnectionPerHost);
|
||||
|
||||
Property maxTotalHttpConnection = new Property(HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION);
|
||||
maxTotalHttpConnection.setRequired(true);
|
||||
maxTotalHttpConnection.setDisplayName(resourceBundle.getString(
|
||||
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION));
|
||||
maxTotalHttpConnection.setHint(resourceBundle.getString(
|
||||
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION_HINT));
|
||||
maxTotalHttpConnection.setDefaultValue(HTTPEventAdapterConstants.MAX_TOTAL_HTTP_CONNECTION);
|
||||
propertyList.add(maxTotalHttpConnection);
|
||||
|
||||
//Content Validator details
|
||||
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||
contentValidator.setDisplayName(
|
||||
|
||||
@ -60,7 +60,8 @@ public class HTTPMessageServlet extends HttpServlet {
|
||||
private static OAuthAuthenticator oAuthAuthenticator;
|
||||
|
||||
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
|
||||
InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||
InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||
Map<String, String> globalProperties) {
|
||||
this.eventAdaptorListener = eventAdaptorListener;
|
||||
this.tenantId = tenantId;
|
||||
this.exposedTransports = eventAdapterConfiguration.getProperties().get(
|
||||
@ -107,7 +108,7 @@ public class HTTPMessageServlet extends HttpServlet {
|
||||
}
|
||||
|
||||
jwtAuthenticator = new JWTAuthenticator();
|
||||
oAuthAuthenticator = new OAuthAuthenticator(eventAdapterConfiguration);
|
||||
oAuthAuthenticator = new OAuthAuthenticator(globalProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -36,6 +36,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -51,8 +52,8 @@ public class OAuthAuthenticator {
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
private static Log log = LogFactory.getLog(OAuthAuthenticator.class);
|
||||
|
||||
public OAuthAuthenticator(InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
|
||||
public OAuthAuthenticator(Map<String, String> globalProperties) {
|
||||
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(globalProperties));
|
||||
}
|
||||
|
||||
public AuthenticationInfo authenticate(HttpServletRequest req) {
|
||||
|
||||
@ -34,7 +34,6 @@ import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.wso2.carbon.core.util.Utils;
|
||||
import org.wso2.carbon.device.mgt.input.adapter.http.oauth.exception.OAuthTokenValidationException;
|
||||
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||
import org.wso2.carbon.device.mgt.input.adapter.http.util.HTTPEventAdapterConstants;
|
||||
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||
|
||||
@ -42,6 +41,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This follows object pool pattern to manage the stub for oauth validation service.
|
||||
@ -49,11 +49,11 @@ import java.security.GeneralSecurityException;
|
||||
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
|
||||
private HttpClient httpClient;
|
||||
InputEventAdapterConfiguration eventAdapterConfiguration;
|
||||
Map<String, String> globalProperties;
|
||||
|
||||
|
||||
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||
public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
|
||||
this.globalProperties = globalProperties;
|
||||
this.httpClient = createHttpClient();
|
||||
}
|
||||
|
||||
@ -92,9 +92,10 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
|
||||
OAuth2TokenValidationServiceStub stub;
|
||||
try {
|
||||
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get(
|
||||
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
|
||||
if (hostURL != null) {
|
||||
URL hostURL = new URL(Utils.replaceSystemProperty(globalProperties.get(
|
||||
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)
|
||||
+ HTTPEventAdapterConstants.TOKEN_VALIDATION_POST_FIX));
|
||||
if (hostURL != null) {
|
||||
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
|
||||
if (stub != null) {
|
||||
ServiceClient client = stub._getServiceClient();
|
||||
@ -104,10 +105,8 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
HttpTransportProperties.Authenticator auth =
|
||||
new HttpTransportProperties.Authenticator();
|
||||
auth.setPreemptiveAuthentication(true);
|
||||
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
|
||||
.USERNAME);
|
||||
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
|
||||
.PASSWORD);
|
||||
String username = globalProperties.get(HTTPEventAdapterConstants.USERNAME);
|
||||
String password = globalProperties.get(HTTPEventAdapterConstants.PASSWORD);
|
||||
auth.setPassword(username);
|
||||
auth.setUsername(password);
|
||||
Options options = client.getOptions();
|
||||
@ -151,8 +150,7 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
*/
|
||||
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
|
||||
try {
|
||||
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
|
||||
return easySSLPSFactory;
|
||||
return new EasySSLProtocolSocketFactory();
|
||||
} catch (IOException e) {
|
||||
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
|
||||
throw new OAuthTokenValidationException(errorMsg, e);
|
||||
@ -170,9 +168,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
*/
|
||||
private HttpClient createHttpClient() {
|
||||
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
|
||||
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
|
||||
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
|
||||
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(globalProperties.get(
|
||||
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||
params.setMaxTotalConnections(Integer.parseInt(globalProperties.get(
|
||||
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
|
||||
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
|
||||
connectionManager.setParams(params);
|
||||
|
||||
@ -51,8 +51,8 @@ public final class HTTPEventAdapterConstants {
|
||||
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION_HINT = "maximumTotalHttpConnection.hint";
|
||||
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
|
||||
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint";
|
||||
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
|
||||
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint";
|
||||
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "keymanagerUrl";
|
||||
public static final String TOKEN_VALIDATION_POST_FIX = "/services/OAuth2TokenValidationService";
|
||||
public static final String USERNAME = "username";
|
||||
public static final String USERNAME_HINT = "username.hint";
|
||||
public static final String PASSWORD = "password";
|
||||
|
||||
@ -22,16 +22,6 @@ http.usage.tips_mid1=/endpoints/<event_receiver_name></i></br> <
|
||||
http.usage.tips_mid2=/endpoints/<event_receiver_name></i></br></br>For other tenants:</br> <i>http://localhost:
|
||||
http.usage.tips_mid3=/endpoints/t/<tenant_domain>/<event_receiver_name></i></br> <i>https://localhost:
|
||||
http.usage.tips_postfix=/endpoints/t/<tenant_domain>/<event_receiver_name></i>
|
||||
tokenValidationEndpointUrl=tokenEndpointUrl
|
||||
tokenValidationEndpointUrl.hint=OAUTH Token Validation Endpoint
|
||||
username=username
|
||||
username.hint=username of the user to connect to the admin services
|
||||
password=password
|
||||
password.hint=password of the user to connect to the admin services.
|
||||
maximumTotalHttpConnection=maximumTotalHttpConnection
|
||||
maximumTotalHttpConnection.hint=Maximum Total connection to be made with the endpoint
|
||||
maximumHttpConnectionPerHost=maximumHttpConnectionPerHost
|
||||
maximumHttpConnectionPerHost.hint=Maximum Http connection per host.
|
||||
contentValidator=contentValidator
|
||||
contentValidator.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
|
||||
contentTransformer=contentTransformer
|
||||
|
||||
@ -60,10 +60,6 @@
|
||||
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
@ -128,7 +124,6 @@
|
||||
org.apache.http.client.methods;version="${httpclient.version.range}",
|
||||
org.apache.http.impl.client;version="${httpclient.version.range}",
|
||||
org.json.simple.*,
|
||||
org.wso2.carbon.identity.jwt.client.extension.*,
|
||||
com.jayway.jsonpath.*
|
||||
</Import-Package>
|
||||
<DynamicImport-Package>*</DynamicImport-Package>
|
||||
|
||||
@ -53,29 +53,13 @@ public class MQTTEventAdapter implements InputEventAdapter {
|
||||
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
|
||||
this.eventAdapterListener = eventAdapterListener;
|
||||
try {
|
||||
int keepAlive;
|
||||
|
||||
//If global properties are available those will be assigned else constant values will be assigned
|
||||
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
|
||||
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
|
||||
} else {
|
||||
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
|
||||
}
|
||||
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION),
|
||||
keepAlive,
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
|
||||
);
|
||||
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),
|
||||
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID),
|
||||
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
|
||||
|
||||
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration
|
||||
,globalProperties);
|
||||
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration
|
||||
,eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC)
|
||||
,eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID)
|
||||
,eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
|
||||
} catch (Throwable t) {
|
||||
throw new InputEventAdapterException(t.getMessage(), t);
|
||||
}
|
||||
|
||||
@ -59,16 +59,10 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
|
||||
//Broker Url
|
||||
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
|
||||
brokerUrl.setRequired(true);
|
||||
brokerUrl.setRequired(false);
|
||||
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
|
||||
propertyList.add(brokerUrl);
|
||||
|
||||
//DCR endpoint details
|
||||
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
|
||||
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||
dcrUrl.setRequired(false);
|
||||
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
|
||||
propertyList.add(dcrUrl);
|
||||
|
||||
//Content Validator details
|
||||
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||
@ -84,10 +78,18 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
|
||||
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||
userName.setDisplayName(
|
||||
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
|
||||
userName.setRequired(false);
|
||||
userName.setRequired(true);
|
||||
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||
propertyList.add(userName);
|
||||
|
||||
//Broker Password
|
||||
Property password = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||
userName.setDisplayName(
|
||||
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD));
|
||||
userName.setRequired(true);
|
||||
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
|
||||
propertyList.add(password);
|
||||
|
||||
//Broker Required Scopes.
|
||||
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||
scopes.setDisplayName(
|
||||
|
||||
@ -23,13 +23,9 @@ import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.http.HttpService;
|
||||
import org.wso2.carbon.device.mgt.input.adapter.mqtt.MQTTEventAdapterFactory;
|
||||
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||
import org.wso2.carbon.user.core.service.RealmService;
|
||||
|
||||
/**
|
||||
* @scr.component name="input.iot.mqtt.AdapterService.component" immediate="true"
|
||||
* @scr.reference name="user.realmservice.default"
|
||||
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
|
||||
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
|
||||
*/
|
||||
public class InputAdapterServiceComponent {
|
||||
|
||||
@ -48,14 +44,6 @@ public class InputAdapterServiceComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected void setRealmService(RealmService realmService) {
|
||||
InputAdapterServiceDataHolder.registerRealmService(realmService);
|
||||
}
|
||||
|
||||
protected void unsetRealmService(RealmService realmService) {
|
||||
InputAdapterServiceDataHolder.registerRealmService(null);
|
||||
}
|
||||
|
||||
protected void setHttpService(HttpService httpService) {
|
||||
InputAdapterServiceDataHolder.registerHTTPService(httpService);
|
||||
}
|
||||
|
||||
@ -15,28 +15,17 @@
|
||||
package org.wso2.carbon.device.mgt.input.adapter.mqtt.internal;
|
||||
|
||||
import org.osgi.service.http.HttpService;
|
||||
import org.wso2.carbon.user.core.service.RealmService;
|
||||
|
||||
/**
|
||||
* common place to hold some OSGI service references.
|
||||
*/
|
||||
public final class InputAdapterServiceDataHolder {
|
||||
|
||||
private static RealmService realmService;
|
||||
private static HttpService httpService;
|
||||
|
||||
private InputAdapterServiceDataHolder() {
|
||||
}
|
||||
|
||||
public static void registerRealmService(
|
||||
RealmService realmService) {
|
||||
InputAdapterServiceDataHolder.realmService = realmService;
|
||||
}
|
||||
|
||||
public static RealmService getRealmService() {
|
||||
return realmService;
|
||||
}
|
||||
|
||||
public static void registerHTTPService(
|
||||
HttpService httpService) {
|
||||
InputAdapterServiceDataHolder.httpService = httpService;
|
||||
|
||||
@ -17,13 +17,18 @@
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.eclipse.paho.client.mqttv3.*;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
|
||||
import org.json.simple.JSONObject;
|
||||
@ -39,9 +44,6 @@ import org.wso2.carbon.device.mgt.input.adapter.extension.DefaultContentValidato
|
||||
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
|
||||
import org.wso2.carbon.device.mgt.input.adapter.mqtt.exception.MQTTContentInitializationException;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
@ -49,7 +51,9 @@ import java.net.URL;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
@ -144,16 +148,14 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
}
|
||||
|
||||
public void startListener() throws MqttException {
|
||||
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null &&
|
||||
if (this.mqttBrokerConnectionConfiguration.getUsername() != null &&
|
||||
this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
|
||||
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
|
||||
String username = this.mqttBrokerConnectionConfiguration.getUsername();
|
||||
String password = this.mqttBrokerConnectionConfiguration.getPassword();
|
||||
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
|
||||
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
|
||||
//getJWT Client Parameters.
|
||||
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
|
||||
try {
|
||||
URL dcrUrl = new URL(dcrUrlString);
|
||||
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
|
||||
@ -163,11 +165,15 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
|
||||
registrationProfile.setOwner(username);
|
||||
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
|
||||
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
|
||||
registrationProfile.setClientName(username + "_" + tenantId);
|
||||
registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
|
||||
+ mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
|
||||
String jsonString = registrationProfile.toJSON();
|
||||
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
|
||||
postMethod.setEntity(requestEntity);
|
||||
String basicAuth = getBase64Encode(username, password);
|
||||
postMethod.setHeader(new BasicHeader(MQTTEventAdapterConstants.AUTHORIZATION_HEADER_NAME,
|
||||
MQTTEventAdapterConstants.AUTHORIZATION_HEADER_VALUE_PREFIX +
|
||||
basicAuth));
|
||||
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||
if (httpResponse != null) {
|
||||
String response = MQTTUtil.getResponseString(httpResponse);
|
||||
@ -177,16 +183,10 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
|
||||
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
|
||||
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
|
||||
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
|
||||
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
|
||||
clientId, clientSecret, username, scopes);
|
||||
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
|
||||
connectionOptions.setUserName(getToken(clientId, clientSecret));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
String msg = "error occurred while parsing client credential payload";
|
||||
log.error(msg, e);
|
||||
} catch (JWTClientException e) {
|
||||
String msg = "error occurred while parsing the response from JWT Client";
|
||||
String msg = "error occurred while parsing generating token for the adapter";
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
@ -194,8 +194,6 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
log.error("Invalid dcrUrl : " + dcrUrlString);
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
|
||||
log.error("Failed to create an https connection.", e);
|
||||
} finally {
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,4 +285,39 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||
public boolean isConnectionInitialized() {
|
||||
return connectionInitialized;
|
||||
}
|
||||
|
||||
private String getToken(String clientId, String clientSecret)
|
||||
throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, ParseException {
|
||||
URL tokenEndpoint = new URL(mqttBrokerConnectionConfiguration.getTokenUrl());
|
||||
HttpClient httpClient = MQTTUtil.getHttpClient(tokenEndpoint.getProtocol());
|
||||
HttpPost postMethod = new HttpPost(tokenEndpoint.toString());
|
||||
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<>();
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.GRANT_TYPE_PARAM_NAME,
|
||||
MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE));
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_USERNAME,
|
||||
mqttBrokerConnectionConfiguration.getUsername()));
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_PASSWORD,
|
||||
mqttBrokerConnectionConfiguration.getPassword()));
|
||||
String scopes = mqttBrokerConnectionConfiguration.getBrokerScopes();
|
||||
if (scopes != null && !scopes.isEmpty()) {
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_SCOPES, scopes));
|
||||
}
|
||||
|
||||
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
|
||||
postMethod.addHeader("Authorization", "Basic " + getBase64Encode(clientId, clientSecret));
|
||||
postMethod.addHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||
String response = MQTTUtil.getResponseString(httpResponse);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(response);
|
||||
}
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
|
||||
return (String) jsonObject.get(MQTTEventAdapterConstants.ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME);
|
||||
}
|
||||
|
||||
private String getBase64Encode(String key, String value) {
|
||||
return new String(Base64.encodeBase64((key + ":" + value).getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,28 +17,38 @@
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util;
|
||||
|
||||
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This holds the configurations related to MQTT Broker.
|
||||
*/
|
||||
public class MQTTBrokerConnectionConfiguration {
|
||||
|
||||
private String brokerUsername = null;
|
||||
private String username = null;
|
||||
private String password = null;
|
||||
private String brokerScopes = null;
|
||||
private boolean cleanSession = true;
|
||||
private int keepAlive;
|
||||
private String brokerUrl;
|
||||
private String dcrUrl;
|
||||
private String tokenUrl;
|
||||
private String contentValidatorClassName;
|
||||
private String contentTransformerClassName;
|
||||
private String adapterName;
|
||||
|
||||
public String getBrokerScopes() {
|
||||
return brokerScopes;
|
||||
}
|
||||
|
||||
public String getBrokerUsername() {
|
||||
return brokerUsername;
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean isCleanSession() {
|
||||
@ -65,21 +75,44 @@ public class MQTTBrokerConnectionConfiguration {
|
||||
return contentTransformerClassName;
|
||||
}
|
||||
|
||||
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
|
||||
String dcrUrl, String cleanSession, int keepAlive,
|
||||
String contentValidatorClassName, String contentTransformerClassName) throws InputEventAdapterException {
|
||||
this.brokerUsername = brokerUsername;
|
||||
this.brokerScopes = brokerScopes;
|
||||
public String getTokenUrl() {
|
||||
return tokenUrl;
|
||||
}
|
||||
|
||||
public String getAdapterName() {
|
||||
return adapterName;
|
||||
}
|
||||
|
||||
public MQTTBrokerConnectionConfiguration(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||
Map<String, String> globalProperties) throws InputEventAdapterException {
|
||||
|
||||
adapterName = eventAdapterConfiguration.getName();
|
||||
this.username = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||
this.password = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||
this.brokerScopes = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||
if (brokerScopes == null) {
|
||||
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
|
||||
}
|
||||
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
|
||||
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
|
||||
this.contentValidatorClassName = contentValidatorClassName;
|
||||
if (cleanSession != null) {
|
||||
this.cleanSession = Boolean.parseBoolean(cleanSession);
|
||||
String url = eventAdapterConfiguration .getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
if (url == null || url.isEmpty()) {
|
||||
url = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
}
|
||||
this.keepAlive = keepAlive;
|
||||
this.contentTransformerClassName = contentTransformerClassName;
|
||||
this.brokerUrl = PropertyUtils.replaceMqttProperty(url);
|
||||
this.dcrUrl = PropertyUtils
|
||||
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||
this.tokenUrl = PropertyUtils
|
||||
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_TOKEN_URL));
|
||||
this.contentValidatorClassName = eventAdapterConfiguration.getProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||
this.cleanSession = Boolean.parseBoolean(eventAdapterConfiguration.getProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
|
||||
//If global properties are available those will be assigned else constant values will be assigned
|
||||
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
|
||||
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
|
||||
} else {
|
||||
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
|
||||
}
|
||||
this.contentTransformerClassName = eventAdapterConfiguration.getProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,10 +27,13 @@ public class MQTTEventAdapterConstants {
|
||||
public static final String ADAPTER_CONF_URL = "url";
|
||||
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||
public static final String ADAPTER_CONF_PASSWORD = "password";
|
||||
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
|
||||
public static final String ADAPTER_CONF_SCOPES = "scopes";
|
||||
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
|
||||
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
|
||||
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
|
||||
public static final String ADAPTER_CONF_TOKEN_URL = "tokenUrl";
|
||||
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
|
||||
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidator";
|
||||
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidator.hint";
|
||||
@ -49,9 +52,10 @@ public class MQTTEventAdapterConstants {
|
||||
public static final int RECONNECTION_PROGRESS_FACTOR = 2;
|
||||
|
||||
public static final String EMPTY_STRING = "";
|
||||
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
|
||||
public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
|
||||
public static final String GRANT_TYPE = "password refresh_token";
|
||||
public static final String TOKEN_SCOPE = "production";
|
||||
public static final String APPLICATION_TYPE = "device";
|
||||
public static final String APPLICATION_NAME_PREFIX = "InputAdapter_";
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String CLIENT_SECRET = "client_secret";
|
||||
public static final String CLIENT_NAME = "client_name";
|
||||
@ -62,4 +66,12 @@ public class MQTTEventAdapterConstants {
|
||||
public static final String DEVICE_ID_JSON_PATH = "event.metaData.deviceId";
|
||||
public static final String DEVICE_TYPE_JSON_PATH = "event.metaData.deviceId";
|
||||
public static final int DEVICE_ID_TOPIC_HIERARCHY_INDEX = 2;
|
||||
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
|
||||
public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
|
||||
public static final String PASSWORD_GRANT_TYPE = "password";
|
||||
public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
|
||||
public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
|
||||
public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
|
||||
public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
|
||||
|
||||
}
|
||||
|
||||
@ -27,8 +27,6 @@ import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -84,16 +82,4 @@ public class MQTTUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static JWTClientManagerService getJWTClientManagerService() {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
JWTClientManagerService jwtClientManagerService =
|
||||
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
|
||||
if (jwtClientManagerService == null) {
|
||||
String msg = "JWT management service has not initialized.";
|
||||
log.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
return jwtClientManagerService;
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,9 +20,11 @@ topic=Topic
|
||||
topic.hint=Topic subscribed
|
||||
clientId=Client Id
|
||||
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
|
||||
url=Broker Url
|
||||
url=Broker Url (Not required), If it is not provided then it will connect to the default broker.
|
||||
username=Username
|
||||
username.hint=Username of the broker (if required)
|
||||
password=Password
|
||||
password.hint=Password of the user for the broker (if required)
|
||||
scopes=Scopes
|
||||
scopes.hint=Scopes required to connect to broker (if required)
|
||||
dcrUrl=dcrUrl
|
||||
|
||||
@ -61,10 +61,6 @@
|
||||
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
@ -122,7 +118,10 @@
|
||||
org.osgi.framework,
|
||||
org.osgi.service.component,
|
||||
org.wso2.carbon.context,
|
||||
org.wso2.carbon.identity.jwt.client.extension.*
|
||||
org.apache.commons.codec.binary,
|
||||
org.apache.http.client.entity,
|
||||
org.apache.http.message,
|
||||
org.apache.commons.ssl
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
|
||||
@ -118,19 +118,7 @@ public class MQTTEventAdapter implements OutputEventAdapter {
|
||||
@Override
|
||||
public void connect() {
|
||||
MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration =
|
||||
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
|
||||
eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||
eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
|
||||
eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
|
||||
connectionKeepAliveInterval,
|
||||
eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION)
|
||||
);
|
||||
|
||||
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration, globalProperties);
|
||||
String clientId = eventAdapterConfiguration.getStaticProperties().get(
|
||||
MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
|
||||
qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);
|
||||
|
||||
@ -50,7 +50,7 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
|
||||
//Broker Url
|
||||
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
|
||||
brokerUrl.setRequired(true);
|
||||
brokerUrl.setRequired(false);
|
||||
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
|
||||
|
||||
//Broker Username
|
||||
@ -59,11 +59,11 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
|
||||
userName.setRequired(true);
|
||||
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||
|
||||
//Broker dcr URL
|
||||
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
|
||||
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||
dcrUrl.setRequired(true);
|
||||
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
|
||||
//Broker Password
|
||||
Property password = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||
password.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD));
|
||||
password.setRequired(true);
|
||||
password.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
|
||||
|
||||
//Broker Connection Scopes
|
||||
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||
@ -95,10 +95,10 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
|
||||
|
||||
staticPropertyList.add(brokerUrl);
|
||||
staticPropertyList.add(userName);
|
||||
staticPropertyList.add(dcrUrl);
|
||||
staticPropertyList.add(scopes);
|
||||
staticPropertyList.add(clearSession);
|
||||
staticPropertyList.add(qos);
|
||||
staticPropertyList.add(password);
|
||||
return staticPropertyList;
|
||||
}
|
||||
|
||||
|
||||
@ -19,11 +19,16 @@ package org.wso2.carbon.device.mgt.output.adapter.mqtt.util;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.ssl.Base64;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
@ -36,9 +41,6 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.ConnectionUnavailableException;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
@ -46,6 +48,8 @@ import java.net.URL;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MQTT publisher related configuration initialization and publishing capabilties are implemented here.
|
||||
@ -77,10 +81,8 @@ public class MQTTAdapterPublisher {
|
||||
MqttConnectOptions connectionOptions = new MqttConnectOptions();
|
||||
connectionOptions.setCleanSession(cleanSession);
|
||||
connectionOptions.setKeepAliveInterval(keepAlive);
|
||||
if (mqttBrokerConnectionConfiguration.getBrokerUsername() != null) {
|
||||
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(),
|
||||
mqttBrokerConnectionConfiguration.getDcrUrl(),
|
||||
mqttBrokerConnectionConfiguration.getScopes()));
|
||||
if (mqttBrokerConnectionConfiguration.getUsername() != null) {
|
||||
connectionOptions.setUserName(getToken());
|
||||
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
|
||||
}
|
||||
// Construct an MQTT blocking mode client
|
||||
@ -139,7 +141,11 @@ public class MQTTAdapterPublisher {
|
||||
}
|
||||
}
|
||||
|
||||
private String getToken(String username, String dcrUrlString, String scopes) {
|
||||
private String getToken() {
|
||||
String username = this.mqttBrokerConnectionConfiguration.getUsername();
|
||||
String password = this.mqttBrokerConnectionConfiguration.getPassword();
|
||||
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
|
||||
|
||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
|
||||
try {
|
||||
@ -147,32 +153,34 @@ public class MQTTAdapterPublisher {
|
||||
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
|
||||
HttpPost postMethod = new HttpPost(dcrUrlString);
|
||||
RegistrationProfile registrationProfile = new RegistrationProfile();
|
||||
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK);
|
||||
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
|
||||
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
|
||||
registrationProfile.setOwner(username);
|
||||
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
|
||||
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
|
||||
registrationProfile.setClientName(username + "_" + tenantId);
|
||||
registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
|
||||
+ mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
|
||||
String jsonString = registrationProfile.toJSON();
|
||||
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
|
||||
postMethod.setEntity(requestEntity);
|
||||
String basicAuth = getBase64Encode(username, password);
|
||||
postMethod.setHeader(new BasicHeader(MQTTEventAdapterConstants.AUTHORIZATION_HEADER_NAME,
|
||||
MQTTEventAdapterConstants.AUTHORIZATION_HEADER_VALUE_PREFIX +
|
||||
basicAuth));
|
||||
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||
String response = MQTTUtil.getResponseString(httpResponse);
|
||||
try {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
|
||||
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
|
||||
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
|
||||
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
|
||||
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
|
||||
clientId, clientSecret, username, scopes);
|
||||
return accessTokenInfo.getAccessToken();
|
||||
} catch (ParseException e) {
|
||||
String msg = "error occurred while parsing client credential payload";
|
||||
throw new OutputEventAdapterRuntimeException(msg, e);
|
||||
} catch (JWTClientException e) {
|
||||
String msg = "error occurred while parsing the response from JWT Client";
|
||||
throw new OutputEventAdapterRuntimeException(msg, e);
|
||||
if (httpResponse != null) {
|
||||
String response = MQTTUtil.getResponseString(httpResponse);
|
||||
try {
|
||||
if (response != null) {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
|
||||
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
|
||||
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
|
||||
getToken(clientId, clientSecret);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
String msg = "error occurred while parsing generating token for the adapter";
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
|
||||
@ -183,4 +191,39 @@ public class MQTTAdapterPublisher {
|
||||
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher");
|
||||
}
|
||||
|
||||
private String getToken(String clientId, String clientSecret)
|
||||
throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, ParseException {
|
||||
URL tokenEndpoint = new URL(mqttBrokerConnectionConfiguration.getTokenUrl());
|
||||
HttpClient httpClient = MQTTUtil.getHttpClient(tokenEndpoint.getProtocol());
|
||||
HttpPost postMethod = new HttpPost(tokenEndpoint.toString());
|
||||
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<>();
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.GRANT_TYPE_PARAM_NAME,
|
||||
MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE));
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_USERNAME,
|
||||
mqttBrokerConnectionConfiguration.getUsername()));
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_PASSWORD,
|
||||
mqttBrokerConnectionConfiguration.getPassword()));
|
||||
String scopes = mqttBrokerConnectionConfiguration.getScopes();
|
||||
if (scopes != null && !scopes.isEmpty()) {
|
||||
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_SCOPES, scopes));
|
||||
}
|
||||
|
||||
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
|
||||
postMethod.addHeader("Authorization", "Basic " + getBase64Encode(clientId, clientSecret));
|
||||
postMethod.addHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||
String response = MQTTUtil.getResponseString(httpResponse);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(response);
|
||||
}
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
|
||||
return (String) jsonObject.get(MQTTEventAdapterConstants.ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME);
|
||||
}
|
||||
|
||||
private String getBase64Encode(String key, String value) {
|
||||
return new String(Base64.encodeBase64((key + ":" + value).getBytes()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -17,14 +17,25 @@
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.output.adapter.mqtt.util;
|
||||
|
||||
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class MQTTBrokerConnectionConfiguration {
|
||||
|
||||
private String brokerUsername;
|
||||
private String adapterName;
|
||||
private String username;
|
||||
private String password;
|
||||
private String dcrUrl;
|
||||
private String scopes;
|
||||
private String brokerUrl;
|
||||
private String tokenUrl;
|
||||
private boolean cleanSession = true;
|
||||
private int keepAlive;
|
||||
public String getTokenUrl() {
|
||||
return tokenUrl;
|
||||
}
|
||||
|
||||
public String getDcrUrl() {
|
||||
return dcrUrl;
|
||||
@ -34,8 +45,12 @@ public class MQTTBrokerConnectionConfiguration {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
public String getBrokerUsername() {
|
||||
return brokerUsername;
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean isCleanSession() {
|
||||
@ -50,15 +65,35 @@ public class MQTTBrokerConnectionConfiguration {
|
||||
return keepAlive;
|
||||
}
|
||||
|
||||
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername,
|
||||
String dcrUrl, String scopes, int keepAlive, String cleanSession) {
|
||||
this.brokerUsername = brokerUsername;
|
||||
this.dcrUrl = dcrUrl;
|
||||
this.scopes = scopes;
|
||||
this.brokerUrl = brokerUrl;
|
||||
this.keepAlive = keepAlive;
|
||||
if (cleanSession != null) {
|
||||
this.cleanSession = Boolean.parseBoolean(cleanSession);
|
||||
public String getAdapterName() {
|
||||
return adapterName;
|
||||
}
|
||||
|
||||
public MQTTBrokerConnectionConfiguration(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||
Map<String, String> globalProperties) {
|
||||
adapterName = eventAdapterConfiguration.getName();
|
||||
this.username = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||
this.password = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||
String url = eventAdapterConfiguration .getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
if (url == null || url.isEmpty()) {
|
||||
url = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||
}
|
||||
this.brokerUrl = PropertyUtils.replaceMqttProperty(url);
|
||||
this.dcrUrl = PropertyUtils
|
||||
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||
this.tokenUrl = PropertyUtils
|
||||
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_TOKEN_URL));
|
||||
this.scopes = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||
if (scopes == null) {
|
||||
this.scopes = MQTTEventAdapterConstants.EMPTY_STRING;
|
||||
}
|
||||
this.cleanSession = Boolean.parseBoolean(eventAdapterConfiguration.getStaticProperties()
|
||||
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
|
||||
//If global properties are available those will be assigned else constant values will be assigned
|
||||
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
|
||||
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
|
||||
} else {
|
||||
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,8 +27,10 @@ public final class MQTTEventAdapterConstants {
|
||||
public static final String ADAPTER_CONF_URL = "url";
|
||||
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||
public static final String ADAPTER_CONF_PASSWORD = "password";
|
||||
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
|
||||
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
|
||||
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
|
||||
public static final String ADAPTER_CONF_TOKEN_URL = "keymanagerUrl";
|
||||
public static final String ADAPTER_CONF_SCOPES = "scopes";
|
||||
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
|
||||
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
|
||||
@ -41,6 +43,9 @@ public final class MQTTEventAdapterConstants {
|
||||
public static final String ADAPTER_TEMP_DIRECTORY_NAME = "java.io.tmpdir";
|
||||
public static final String ADAPTER_CONF_CLIENTID = "clientId";
|
||||
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
|
||||
public static final String EMPTY_STRING = "";
|
||||
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
|
||||
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
|
||||
|
||||
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
|
||||
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
|
||||
@ -53,9 +58,19 @@ public final class MQTTEventAdapterConstants {
|
||||
|
||||
public static final String DEFAULT_CALLBACK = "";
|
||||
public static final String DEFAULT_PASSWORD = "";
|
||||
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
|
||||
public static final String GRANT_TYPE = "grant_type";
|
||||
public static final String TOKEN_SCOPE = "production";
|
||||
public static final String APPLICATION_TYPE = "device";
|
||||
public static final String APPLICATION_NAME_PREFIX = "OutputAdapter_";
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String CLIENT_SECRET = "client_secret";
|
||||
|
||||
|
||||
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
|
||||
public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
|
||||
public static final String PASSWORD_GRANT_TYPE = "password";
|
||||
public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
|
||||
public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
|
||||
public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
|
||||
public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
|
||||
public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@ import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -85,15 +84,4 @@ public class MQTTUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static JWTClientManagerService getJWTClientManagerService() {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
JWTClientManagerService jwtClientManagerService =
|
||||
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
|
||||
if (jwtClientManagerService == null) {
|
||||
String msg = "JWT management service has not initialized.";
|
||||
log.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
return jwtClientManagerService;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.output.adapter.mqtt.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class PropertyUtils {
|
||||
|
||||
//This method is only used if the mb features are within DAS.
|
||||
static String replaceMqttProperty(String urlWithPlaceholders) {
|
||||
String regex = "\\$\\{(.*?)\\}";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matchPattern = pattern.matcher(urlWithPlaceholders);
|
||||
while (matchPattern.find()) {
|
||||
String sysPropertyName = matchPattern.group(1);
|
||||
String sysPropertyValue = System.getProperty(sysPropertyName);
|
||||
if (sysPropertyValue != null && !sysPropertyName.isEmpty()) {
|
||||
urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue);
|
||||
}
|
||||
}
|
||||
return urlWithPlaceholders;
|
||||
}
|
||||
}
|
||||
@ -18,13 +18,13 @@
|
||||
|
||||
topic=Topic
|
||||
url=Broker Url
|
||||
url.hint=MQTT broker url
|
||||
username=Username
|
||||
username.hint=Username of the broker
|
||||
dcrUrl=dcrUrl
|
||||
dcrUrl.hint=Dynamic Client Registration Url
|
||||
password=Password
|
||||
password.hint=Password to connect to the server.
|
||||
scopes=scopes
|
||||
scopes.hint=Scopes that required to connect with the broker.
|
||||
url.hint=MQTT broker url
|
||||
cleanSession=Clean Session
|
||||
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
|
||||
keepAlive=Keep Alive (In seconds)
|
||||
|
||||
@ -18,6 +18,13 @@
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.output.adapter.websocket;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.Authenticator;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.Authorizer;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationService;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationServiceImpl;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.UIEventAdapterConstants;
|
||||
import org.wso2.carbon.event.output.adapter.core.MessageType;
|
||||
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
|
||||
@ -38,6 +45,9 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
|
||||
|
||||
private ResourceBundle resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.device.mgt.output.adapter.websocket.i18n" +
|
||||
".Resources", Locale.getDefault());
|
||||
private BundleContext bundleContext;
|
||||
private boolean isAuthInitialized = false;
|
||||
private static final Log log = LogFactory.getLog(UIEventAdapter.class);
|
||||
|
||||
public UIEventAdapterFactory() {
|
||||
}
|
||||
@ -74,7 +84,53 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
|
||||
@Override
|
||||
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||
Map<String, String> globalProperties) {
|
||||
if (!isAuthInitialized) {
|
||||
initializeAuthenticatorAndAuthorizor(globalProperties);
|
||||
}
|
||||
return new UIEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||
}
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
}
|
||||
|
||||
public void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
private void initializeAuthenticatorAndAuthorizor (Map<String, String> globalProperties) {
|
||||
if (!isAuthInitialized) {
|
||||
synchronized (UIEventAdapterFactory.class) {
|
||||
if (!isAuthInitialized) {
|
||||
try {
|
||||
WebsocketValidationServiceImpl websocketValidationService =
|
||||
new WebsocketValidationServiceImpl();
|
||||
String authenticatorClassName = globalProperties.get(
|
||||
UIEventAdapterConstants.AUTHENTICATOR_CLASS);
|
||||
String authorizerClassName = globalProperties.get(UIEventAdapterConstants.AUTHORIZER_CLASS);
|
||||
if (authenticatorClassName != null && !authenticatorClassName.isEmpty()) {
|
||||
Class<? extends Authenticator> authenticatorClass = Class.forName(authenticatorClassName)
|
||||
.asSubclass(Authenticator.class);
|
||||
Authenticator authenticator = authenticatorClass.newInstance();
|
||||
websocketValidationService.setAuthenticator(authenticator);
|
||||
}
|
||||
if (authorizerClassName != null && !authorizerClassName.isEmpty()) {
|
||||
Class<? extends Authorizer> authorizerClass = Class.forName(authorizerClassName)
|
||||
.asSubclass(Authorizer.class);
|
||||
Authorizer authorizer = authorizerClass.newInstance();
|
||||
websocketValidationService.setAuthorizer(authorizer);
|
||||
}
|
||||
bundleContext.registerService(
|
||||
WebsocketValidationService.class.getName(), websocketValidationService, null);
|
||||
isAuthInitialized = true;
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||
log.error("Failed to initialize the class authentication and authorization given " +
|
||||
"in the websocket validation configuration.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -22,9 +22,14 @@ import java.util.Map;
|
||||
*/
|
||||
public interface Authenticator {
|
||||
|
||||
/**
|
||||
* This is used to initialize the authenticator
|
||||
* @param globalProperties related to the output adapter
|
||||
*/
|
||||
void init(Map<String, String> globalProperties);
|
||||
|
||||
/**
|
||||
* Check whether the client is authenticated to connect.
|
||||
* @param session user object.
|
||||
* @return AuthenticationInfo which contains authentication client information.
|
||||
*/
|
||||
AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties);
|
||||
|
||||
@ -20,8 +20,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuthAuthenticator implements Authenticator {
|
||||
OAuthTokenValdiator oAuthTokenValdiator;
|
||||
@Override
|
||||
public void init(Map<String, String> globalProperties) {
|
||||
oAuthTokenValdiator = new OAuthTokenValdiator(globalProperties);
|
||||
}
|
||||
|
||||
public AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties) {
|
||||
return OAuthTokenValdiator.getInstance().validateToken(webSocketConnectionProperties);
|
||||
return oAuthTokenValdiator.validateToken(webSocketConnectionProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,24 +20,18 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants;
|
||||
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
|
||||
import org.wso2.carbon.user.api.UserStoreException;
|
||||
import org.wso2.carbon.utils.CarbonUtils;
|
||||
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* This acts as a contract point for OAuth token validation.
|
||||
@ -47,8 +41,6 @@ public class OAuthTokenValdiator {
|
||||
private static String cookie;
|
||||
private GenericObjectPool stubs;
|
||||
private static Log log = LogFactory.getLog(OAuthTokenValdiator.class);
|
||||
private static final String WEBSOCKET_CONFIG_LOCATION =
|
||||
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.properties";
|
||||
private static final String COOKIE_KEY_VALUE_SEPERATOR = "=";
|
||||
private static final String COOKIE_KEYPAIR_SEPERATOR = ";";
|
||||
private static final String COOKIE = "cookie";
|
||||
@ -56,25 +48,9 @@ public class OAuthTokenValdiator {
|
||||
private static final String TOKEN_IDENTIFIER = "websocket-token";
|
||||
private static OAuthTokenValdiator oAuthTokenValdiator;
|
||||
|
||||
public static OAuthTokenValdiator getInstance() {
|
||||
if (oAuthTokenValdiator == null) {
|
||||
synchronized (OAuthTokenValdiator.class) {
|
||||
if (oAuthTokenValdiator == null) {
|
||||
oAuthTokenValdiator = new OAuthTokenValdiator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return oAuthTokenValdiator;
|
||||
}
|
||||
|
||||
private OAuthTokenValdiator() {
|
||||
try {
|
||||
Properties properties = getWebSocketConfig();
|
||||
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(properties));
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to parse the web socket org.wso2.carbon.device.mgt.output.adapter.websocket.config file " +
|
||||
WEBSOCKET_CONFIG_LOCATION, e);
|
||||
}
|
||||
public OAuthTokenValdiator(Map<String, String> globalProperties) {
|
||||
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(globalProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,19 +150,6 @@ public class OAuthTokenValdiator {
|
||||
return authenticationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve JWT configs from registry.
|
||||
*/
|
||||
private Properties getWebSocketConfig() throws IOException {
|
||||
Properties properties = new Properties();
|
||||
List<Property> propertyList = WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthenticator()
|
||||
.getProperties().getProperty();
|
||||
for (Property property : propertyList) {
|
||||
properties.put(property.getName(), property.getValue());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieving the token from the http header
|
||||
* @param webSocketConnectionProperties WebSocket connection information including http headers
|
||||
|
||||
@ -35,13 +35,15 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.oauth.exception.OAuthTokenValidationException;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.PropertyUtils;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Properties;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This follows object pool pattern to manage the stub for oauth validation service.
|
||||
@ -49,11 +51,11 @@ import java.util.Properties;
|
||||
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
private static final Log log = LogFactory.getLog(OAuthTokenValidaterStubFactory.class);
|
||||
private HttpClient httpClient;
|
||||
Properties tokenValidationProperties;
|
||||
Map<String, String> tokenValidationProperties;
|
||||
|
||||
|
||||
public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) {
|
||||
this.tokenValidationProperties = tokenValidationProperties;
|
||||
public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
|
||||
this.tokenValidationProperties = globalProperties;
|
||||
this.httpClient = createHttpClient();
|
||||
}
|
||||
|
||||
@ -91,51 +93,46 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
*/
|
||||
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
|
||||
OAuth2TokenValidationServiceStub stub;
|
||||
try {
|
||||
URL hostURL = new URL(tokenValidationProperties.getProperty((WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
|
||||
if (hostURL != null) {
|
||||
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
|
||||
if (stub != null) {
|
||||
ServiceClient client = stub._getServiceClient();
|
||||
client.getServiceContext().getConfigurationContext().setProperty(
|
||||
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
|
||||
try {
|
||||
URL hostURL = new URL(PropertyUtils.replaceMqttProperty(tokenValidationProperties.get(
|
||||
(WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL)))
|
||||
+ WebsocketConstants.TOKEN_VALIDATION_CONTEXT);
|
||||
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
|
||||
ServiceClient client = stub._getServiceClient();
|
||||
client.getServiceContext().getConfigurationContext().setProperty(
|
||||
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
|
||||
|
||||
HttpTransportProperties.Authenticator auth =
|
||||
new HttpTransportProperties.Authenticator();
|
||||
auth.setPreemptiveAuthentication(true);
|
||||
String username = tokenValidationProperties.getProperty(WebsocketConstants.USERNAME);
|
||||
String password = tokenValidationProperties.getProperty(WebsocketConstants.PASSWORD);
|
||||
auth.setPassword(username);
|
||||
auth.setUsername(password);
|
||||
Options options = client.getOptions();
|
||||
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
|
||||
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
|
||||
client.setOptions(options);
|
||||
if (hostURL.getProtocol().equals("https")) {
|
||||
// set up ssl factory since axis2 https transport is used.
|
||||
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
|
||||
Protocol authhttps = new Protocol(hostURL.getProtocol()
|
||||
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
|
||||
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
|
||||
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
|
||||
}
|
||||
} else {
|
||||
String errorMsg = "OAuth Validation instanization failed.";
|
||||
throw new OAuthTokenValidationException(errorMsg);
|
||||
}
|
||||
} else {
|
||||
String errorMsg = "host url is invalid";
|
||||
throw new OAuthTokenValidationException(errorMsg);
|
||||
}
|
||||
} catch (AxisFault axisFault) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while parsing token endpoint URL", e);
|
||||
}
|
||||
HttpTransportProperties.Authenticator auth =
|
||||
new HttpTransportProperties.Authenticator();
|
||||
auth.setPreemptiveAuthentication(true);
|
||||
String username = tokenValidationProperties.get(WebsocketConstants.USERNAME);
|
||||
String password = tokenValidationProperties.get(WebsocketConstants.PASSWORD);
|
||||
auth.setPassword(username);
|
||||
auth.setUsername(password);
|
||||
Options options = client.getOptions();
|
||||
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
|
||||
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
|
||||
client.setOptions(options);
|
||||
if (hostURL.getProtocol().equals("https")) {
|
||||
// set up ssl factory since axis2 https transport is used.
|
||||
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
|
||||
Protocol authhttps = new Protocol(hostURL.getProtocol()
|
||||
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
|
||||
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
|
||||
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
|
||||
}
|
||||
|
||||
return stub;
|
||||
} catch (AxisFault axisFault) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while parsing token endpoint URL", e);
|
||||
} catch (OutputEventAdapterException e) {
|
||||
throw new OAuthTokenValidationException("Invalid token endpoint url", e);
|
||||
}
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,9 +162,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||
*/
|
||||
private HttpClient createHttpClient() {
|
||||
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
|
||||
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.getProperty(
|
||||
WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty(
|
||||
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.get(
|
||||
WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.get(
|
||||
WebsocketConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
|
||||
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
|
||||
connectionManager.setParams(params);
|
||||
|
||||
@ -21,12 +21,19 @@ package org.wso2.carbon.device.mgt.output.adapter.websocket.authorization;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo;
|
||||
|
||||
import javax.websocket.Session;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Check whether the client is authorized to connect.
|
||||
*/
|
||||
public interface Authorizer {
|
||||
|
||||
/**
|
||||
* This is used to initialize the authenticator
|
||||
* @param globalProperties related to the output adapter
|
||||
*/
|
||||
void init(Map<String, String> globalProperties);
|
||||
|
||||
/**
|
||||
* Check whether the client is authorized to connect with the stream.
|
||||
* @param authenticationInfo authenticated client information.
|
||||
|
||||
@ -31,13 +31,13 @@ import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.
|
||||
.DeviceAccessAuthorizationAdminService;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceAuthorizationResult;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceIdentifier;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.PropertyUtils;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebSocketSessionRequest;
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||
|
||||
import javax.websocket.Session;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -50,26 +50,34 @@ public class DeviceAuthorizer implements Authorizer {
|
||||
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
|
||||
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
|
||||
private static final String STAT_PERMISSION = "statsPermission";
|
||||
private static final String DEVICE_ID = "deviceId";
|
||||
private static final String DEVICE_TYPE = "deviceType";
|
||||
private static Log logger = LogFactory.getLog(DeviceAuthorizer.class);
|
||||
private static List<String> statPermissions;
|
||||
|
||||
public DeviceAuthorizer() {
|
||||
Properties properties =
|
||||
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
|
||||
statPermissions = getPermissions(properties);
|
||||
deviceAccessAuthorizationAdminService = Feign.builder()
|
||||
.requestInterceptor(new OAuthRequestInterceptor())
|
||||
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
|
||||
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(properties)
|
||||
+ CDMF_SERVER_BASE_CONTEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Map<String, String> globalProperties) {
|
||||
statPermissions = getPermissions(globalProperties);
|
||||
try {
|
||||
deviceAccessAuthorizationAdminService = Feign.builder()
|
||||
.requestInterceptor(new OAuthRequestInterceptor(globalProperties))
|
||||
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
|
||||
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(globalProperties)
|
||||
+ CDMF_SERVER_BASE_CONTEXT);
|
||||
} catch (OutputEventAdapterException e) {
|
||||
logger.error("Invalid value for deviceMgtServerUrl in globalProperties.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) {
|
||||
WebSocketSessionRequest webSocketSessionRequest = new WebSocketSessionRequest(session);
|
||||
Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs();
|
||||
String deviceId = queryParams.get("deviceId");
|
||||
String deviceType = queryParams.get("deviceType");
|
||||
String deviceId = queryParams.get(DEVICE_ID);
|
||||
String deviceType = queryParams.get(DEVICE_TYPE);
|
||||
|
||||
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
|
||||
|
||||
@ -102,27 +110,19 @@ public class DeviceAuthorizer implements Authorizer {
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getDeviceMgtServerUrl(Properties properties) {
|
||||
String deviceMgtServerUrl = null;
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
|
||||
deviceMgtServerUrl = property.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
private String getDeviceMgtServerUrl(Map<String, String> properties) throws OutputEventAdapterException {
|
||||
String deviceMgtServerUrl = PropertyUtils.replaceMqttProperty(properties.get(DEVICE_MGT_SERVER_URL));
|
||||
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
|
||||
logger.error("deviceMgtServerUrl can't be empty ");
|
||||
}
|
||||
return deviceMgtServerUrl;
|
||||
}
|
||||
|
||||
private List<String> getPermissions(Properties properties) {
|
||||
List<String> permission = new ArrayList<>();
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(STAT_PERMISSION)) {
|
||||
permission.add(property.getValue());
|
||||
}
|
||||
private List<String> getPermissions(Map<String, String> properties) {
|
||||
String stats = properties.get(STAT_PERMISSION);
|
||||
if (stats != null && !stats.isEmpty()) {
|
||||
return Arrays.asList(stats.replace("\n", "").split(" "));
|
||||
}
|
||||
return permission;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -28,9 +28,8 @@ import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiApplicationRegistrationService;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiRegistrationProfile;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.TokenIssuerService;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is a request interceptor to add oauth token header.
|
||||
@ -51,25 +50,27 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
private static final String CONNECTION_USERNAME = "username";
|
||||
private static final String CONNECTION_PASSWORD = "password";
|
||||
private static final String TOKEN_ENDPOINT = "tokenEndpoint";
|
||||
private static final String TOKEN_ENDPOINT = "keymanagerUrl";
|
||||
private static final String TOKEN_REFRESH_TIME_OFFSET = "tokenRefreshTimeOffset";
|
||||
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
|
||||
private static final String TOKEN_ENDPOINT_CONTEXT = "tokenEndpointContext";
|
||||
private static String username;
|
||||
private static String password;
|
||||
private static String tokenEndpoint;
|
||||
private static String deviceMgtServerUrl;
|
||||
private static Map<String, String> globalProperties;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an interceptor that authenticates all requests.
|
||||
*/
|
||||
public OAuthRequestInterceptor() {
|
||||
Properties properties =
|
||||
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
|
||||
deviceMgtServerUrl = getDeviceMgtServerUrl(properties);
|
||||
refreshTimeOffset = getRefreshTimeOffset(properties);
|
||||
username = getUsername(properties);
|
||||
password = getPassword(properties);
|
||||
tokenEndpoint = getTokenEndpoint(properties);
|
||||
public OAuthRequestInterceptor(Map<String, String> globalProperties) {
|
||||
this.globalProperties = globalProperties;
|
||||
deviceMgtServerUrl = getDeviceMgtServerUrl(globalProperties);
|
||||
refreshTimeOffset = getRefreshTimeOffset(globalProperties);
|
||||
username = getUsername(globalProperties);
|
||||
password = getPassword(globalProperties);
|
||||
tokenEndpoint = getTokenEndpoint(globalProperties);
|
||||
apiApplicationRegistrationService = Feign.builder().requestInterceptor(
|
||||
new BasicAuthRequestInterceptor(username, password))
|
||||
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
|
||||
@ -106,71 +107,42 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
|
||||
template.header("Authorization", headerValue);
|
||||
}
|
||||
|
||||
private String getUsername(Properties properties) {
|
||||
String username = null;
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(CONNECTION_USERNAME)) {
|
||||
username = property.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
private String getUsername(Map<String, String> globalProperties) {
|
||||
String username = globalProperties.get(CONNECTION_USERNAME);
|
||||
if (username == null || username.isEmpty()) {
|
||||
logger.error("username can't be empty ");
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
private String getPassword(Properties properties) {
|
||||
String password = null;
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(CONNECTION_PASSWORD)) {
|
||||
password = property.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
private String getPassword(Map<String, String> globalProperties) {
|
||||
String password = globalProperties.get(CONNECTION_PASSWORD);;
|
||||
if (password == null || password.isEmpty()) {
|
||||
logger.error("password can't be empty ");
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
private String getDeviceMgtServerUrl(Properties properties) {
|
||||
String deviceMgtServerUrl = null;
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
|
||||
deviceMgtServerUrl = property.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
private String getDeviceMgtServerUrl(Map<String, String> globalProperties) {
|
||||
String deviceMgtServerUrl = globalProperties.get(DEVICE_MGT_SERVER_URL);
|
||||
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
|
||||
logger.error("deviceMgtServerUrl can't be empty ");
|
||||
}
|
||||
return deviceMgtServerUrl;
|
||||
}
|
||||
|
||||
private String getTokenEndpoint(Properties properties) {
|
||||
String tokenEndpoint = null;
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(TOKEN_ENDPOINT)) {
|
||||
tokenEndpoint = property.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tokenEndpoint == null || tokenEndpoint.isEmpty()) {
|
||||
private String getTokenEndpoint(Map<String, String> globalProperties) {
|
||||
String tokenEndpoint = globalProperties.get(TOKEN_ENDPOINT) + globalProperties.get(TOKEN_ENDPOINT_CONTEXT);
|
||||
if ( tokenEndpoint.isEmpty()) {
|
||||
logger.error("tokenEndpoint can't be empty ");
|
||||
}
|
||||
return tokenEndpoint;
|
||||
}
|
||||
|
||||
private long getRefreshTimeOffset(Properties properties) {
|
||||
long refreshTimeOffset = 0;
|
||||
private long getRefreshTimeOffset(Map<String, String> globalProperties) {
|
||||
long refreshTimeOffset = 100;
|
||||
try {
|
||||
for (Property property : properties.getProperty()) {
|
||||
if (property.getName().equals(TOKEN_REFRESH_TIME_OFFSET)) {
|
||||
refreshTimeOffset = Long.parseLong(property.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
refreshTimeOffset = Long.parseLong(globalProperties.get(TOKEN_REFRESH_TIME_OFFSET));
|
||||
} catch (NumberFormatException e) {
|
||||
logger.error("refreshTimeOffset should be a number", e);
|
||||
}
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for Authenticator complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType name="Authenticator">
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="Properties" type="{}Properties"/>
|
||||
* </sequence>
|
||||
* <attribute name="class" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "Authenticator", propOrder = {
|
||||
"properties"
|
||||
})
|
||||
public class Authenticator {
|
||||
|
||||
@XmlElement(name = "Properties", required = false)
|
||||
protected Properties properties;
|
||||
@XmlAttribute(name = "class")
|
||||
protected String clazz;
|
||||
|
||||
/**
|
||||
* Gets the value of the properties property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Properties }
|
||||
*
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the properties property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Properties }
|
||||
*
|
||||
*/
|
||||
public void setProperties(Properties value) {
|
||||
this.properties = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the clazz property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the clazz property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setClazz(String value) {
|
||||
this.clazz = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for Authorizer complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType name="Authorizer">
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="Properties" type="{}Properties"/>
|
||||
* </sequence>
|
||||
* <attribute name="class" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "Authorizer", propOrder = {
|
||||
"properties"
|
||||
})
|
||||
public class Authorizer {
|
||||
|
||||
@XmlElement(name = "Properties", required = false)
|
||||
protected Properties properties;
|
||||
@XmlAttribute(name = "class")
|
||||
protected String clazz;
|
||||
|
||||
/**
|
||||
* Gets the value of the properties property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Properties }
|
||||
*
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the properties property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Properties }
|
||||
*
|
||||
*/
|
||||
public void setProperties(Properties value) {
|
||||
this.properties = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the clazz property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the clazz property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setClazz(String value) {
|
||||
this.clazz = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for Properties complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType name="Properties">
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="Property" type="{}Property" maxOccurs="unbounded" minOccurs="0"/>
|
||||
* </sequence>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "Properties", propOrder = {
|
||||
"property"
|
||||
})
|
||||
public class Properties {
|
||||
|
||||
@XmlElement(name = "Property")
|
||||
protected List<Property> property;
|
||||
|
||||
/**
|
||||
* Gets the value of the property property.
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the property property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getProperty().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link Property }
|
||||
*
|
||||
*
|
||||
*/
|
||||
public List<Property> getProperty() {
|
||||
if (property == null) {
|
||||
property = new ArrayList<Property>();
|
||||
}
|
||||
return this.property;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for Property complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType name="Property">
|
||||
* <simpleContent>
|
||||
* <extension base="<http://www.w3.org/2001/XMLSchema>string">
|
||||
* <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </extension>
|
||||
* </simpleContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "Property", propOrder = {
|
||||
"value"
|
||||
})
|
||||
public class Property {
|
||||
|
||||
@XmlValue
|
||||
protected String value;
|
||||
@XmlAttribute(name = "name")
|
||||
protected String name;
|
||||
|
||||
/**
|
||||
* Gets the value of the value property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the value property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the name property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setName(String value) {
|
||||
this.name = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebsocketUtils;
|
||||
import org.wso2.carbon.utils.CarbonUtils;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This class represents the configuration that are needed for scopes to permission map.
|
||||
*/
|
||||
public class WebsocketConfig {
|
||||
|
||||
private static WebsocketConfig config = new WebsocketConfig();
|
||||
private WebsocketValidationConfigs websocketValidationConfigs;
|
||||
private static final Log log = LogFactory.getLog(WebsocketConfig.class);
|
||||
|
||||
private static final String WEBSOCKET_VALIDATION_CONFIG_PATH =
|
||||
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.xml";
|
||||
|
||||
private WebsocketConfig() {
|
||||
}
|
||||
|
||||
public static WebsocketConfig getInstance() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void init() throws WebsocketValidationConfigurationFailedException {
|
||||
try {
|
||||
File deviceMgtConfig = new File(WEBSOCKET_VALIDATION_CONFIG_PATH);
|
||||
Document doc = WebsocketUtils.convertToDocument(deviceMgtConfig);
|
||||
|
||||
/* Un-marshaling DeviceMGtScope configuration */
|
||||
JAXBContext ctx = JAXBContext.newInstance(WebsocketValidationConfigs.class);
|
||||
Unmarshaller unmarshaller = ctx.createUnmarshaller();
|
||||
//unmarshaller.setSchema(getSchema());
|
||||
websocketValidationConfigs = (WebsocketValidationConfigs) unmarshaller.unmarshal(doc);
|
||||
} catch (JAXBException e) {
|
||||
throw new WebsocketValidationConfigurationFailedException("Error occurred while un-marshalling Websocket" +
|
||||
" Config", e);
|
||||
}
|
||||
}
|
||||
|
||||
public WebsocketValidationConfigs getWebsocketValidationConfigs() {
|
||||
if (websocketValidationConfigs == null) {
|
||||
try {
|
||||
init();
|
||||
} catch (WebsocketValidationConfigurationFailedException e) {
|
||||
log.error("failed to initialize the config", e);
|
||||
}
|
||||
}
|
||||
return websocketValidationConfigs;
|
||||
}
|
||||
|
||||
public void setWebsocketValidationConfigs(WebsocketValidationConfigs websocketValidationConfigs) {
|
||||
websocketValidationConfigs = websocketValidationConfigs;
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for WebsocketValidationConfigs complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType name="WebsocketValidationConfigs">
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="Authenticator" type="{}Authenticator"/>
|
||||
* <element name="Authorizer" type="{}Authorizer"/>
|
||||
* </sequence>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@XmlRootElement(name = "WebsocketValidationConfigs")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class WebsocketValidationConfigs {
|
||||
|
||||
@XmlElement(name = "Authenticator", required = true)
|
||||
protected Authenticator authenticator;
|
||||
@XmlElement(name = "Authorizer", required = true)
|
||||
protected Authorizer authorizer;
|
||||
|
||||
/**
|
||||
* Gets the value of the authenticator property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Authenticator }
|
||||
*
|
||||
*/
|
||||
public Authenticator getAuthenticator() {
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the authenticator property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Authenticator }
|
||||
*
|
||||
*/
|
||||
public void setAuthenticator(Authenticator value) {
|
||||
this.authenticator = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the authorizer property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Authorizer }
|
||||
*
|
||||
*/
|
||||
public Authorizer getAuthorizer() {
|
||||
return authorizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the authorizer property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Authorizer }
|
||||
*
|
||||
*/
|
||||
public void setAuthorizer(Authorizer value) {
|
||||
this.authorizer = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.config;
|
||||
|
||||
public class WebsocketValidationConfigurationFailedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3151279329290703928L;
|
||||
|
||||
public WebsocketValidationConfigurationFailedException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
}
|
||||
|
||||
public WebsocketValidationConfigurationFailedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public WebsocketValidationConfigurationFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public WebsocketValidationConfigurationFailedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WebsocketValidationConfigurationFailedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,8 @@ public class WebsocketConstants {
|
||||
public static final String SCOPE_IDENTIFIER = "scopes";
|
||||
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
|
||||
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
|
||||
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpoint";
|
||||
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "keymanagerUrl";
|
||||
public static final String TOKEN_VALIDATION_CONTEXT = "/services/OAuth2TokenValidationService";
|
||||
public static final String USERNAME = "username";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TOKEN_PARAM = "token";
|
||||
|
||||
@ -23,12 +23,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIEventAdapterFactory;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerServiceImpl;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.Authenticator;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.Authorizer;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketValidationConfigurationFailedException;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationService;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationServiceImpl;
|
||||
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerService;
|
||||
import org.wso2.carbon.event.stream.core.EventStreamService;
|
||||
@ -51,45 +45,20 @@ public class UILocalEventAdapterServiceComponent {
|
||||
protected void activate(ComponentContext context) {
|
||||
|
||||
try {
|
||||
OutputEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory();
|
||||
UIEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory();
|
||||
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), uiEventAdapterFactory, null);
|
||||
UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl =
|
||||
new UIOutputCallbackControllerServiceImpl();
|
||||
context.getBundleContext().registerService(UIOutputCallbackControllerService.class.getName(),
|
||||
UIOutputCallbackRegisterServiceImpl, null);
|
||||
|
||||
uiEventAdapterFactory.setBundleContext(context.getBundleContext());
|
||||
|
||||
UIEventAdaptorServiceDataHolder.registerUIOutputCallbackRegisterServiceInternal(
|
||||
UIOutputCallbackRegisterServiceImpl);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Successfully deployed the output websocket adapter service");
|
||||
}
|
||||
try {
|
||||
WebsocketConfig.getInstance().init();
|
||||
WebsocketValidationServiceImpl websocketValidationService = new WebsocketValidationServiceImpl();
|
||||
String authenticatorClassName = WebsocketConfig.getInstance().getWebsocketValidationConfigs()
|
||||
.getAuthenticator().getClazz();
|
||||
String authorizerClassName = WebsocketConfig.getInstance().getWebsocketValidationConfigs()
|
||||
.getAuthorizer().getClazz();
|
||||
if (authenticatorClassName != null && !authenticatorClassName.isEmpty()) {
|
||||
Class<? extends Authenticator> authenticatorClass = Class.forName(authenticatorClassName)
|
||||
.asSubclass(Authenticator.class);
|
||||
Authenticator authenticator = authenticatorClass.newInstance();
|
||||
websocketValidationService.setAuthenticator(authenticator);
|
||||
}
|
||||
if (authorizerClassName != null && !authorizerClassName.isEmpty()) {
|
||||
Class<? extends Authorizer> authorizerClass = Class.forName(authorizerClassName)
|
||||
.asSubclass(Authorizer.class);
|
||||
Authorizer authorizer = authorizerClass.newInstance();
|
||||
websocketValidationService.setAuthorizer(authorizer);
|
||||
}
|
||||
context.getBundleContext().registerService(
|
||||
WebsocketValidationService.class.getName(), websocketValidationService, null);
|
||||
} catch (WebsocketValidationConfigurationFailedException e) {
|
||||
log.error("Failed to initialize configuration for websocket.", e);
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||
log.error("Failed to initialize the class authentication and authorization given " +
|
||||
"in the websocket validation configuration.", e);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Can not create the output websocket adapter service ", e);
|
||||
} catch (Throwable e) {
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.util;
|
||||
|
||||
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PropertyUtils {
|
||||
|
||||
//This method is only used if the mb features are within DAS.
|
||||
public static String replaceMqttProperty(String urlWithPlaceholders) throws OutputEventAdapterException {
|
||||
String regex = "\\$\\{(.*?)\\}";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matchPattern = pattern.matcher(urlWithPlaceholders);
|
||||
while (matchPattern.find()) {
|
||||
String sysPropertyName = matchPattern.group(1);
|
||||
String sysPropertyValue = System.getProperty(sysPropertyName);
|
||||
if (sysPropertyValue != null && !sysPropertyName.isEmpty()) {
|
||||
urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue);
|
||||
} else {
|
||||
throw new OutputEventAdapterException("System property - " + sysPropertyName
|
||||
+ " is not defined, hence cannot resolve : " + urlWithPlaceholders);
|
||||
}
|
||||
}
|
||||
return urlWithPlaceholders;
|
||||
}
|
||||
}
|
||||
@ -46,5 +46,7 @@ public class UIEventAdapterConstants {
|
||||
|
||||
public static final String ADAPTER_EVENT_QUEUE_SIZE_NAME = "eventQueueSize";
|
||||
public static final int EVENTS_QUEUE_SIZE = 30;
|
||||
public static final String AUTHENTICATOR_CLASS = "authenticator";
|
||||
public static final String AUTHORIZER_CLASS = "authorizer";
|
||||
|
||||
}
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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.output.adapter.websocket.util;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketValidationConfigurationFailedException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This class holds util methods used by OAuth extension bundle.
|
||||
*/
|
||||
public class WebsocketUtils {
|
||||
|
||||
public static Document convertToDocument(File file) throws WebsocketValidationConfigurationFailedException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
try {
|
||||
DocumentBuilder docBuilder = factory.newDocumentBuilder();
|
||||
return docBuilder.parse(file);
|
||||
} catch (Exception e) {
|
||||
throw new WebsocketValidationConfigurationFailedException("Error occurred while parsing file, while converting " +
|
||||
"to a org.w3c.dom.Document", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -56,10 +56,9 @@
|
||||
<FileBasedProperties>true</FileBasedProperties>
|
||||
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
|
||||
<ConfigProperties>
|
||||
<Property Name="mqtt.adapter.name">androidsense.mqtt.adapter</Property>
|
||||
<Property Name="url">tcp://localhost:1886</Property>
|
||||
<Property Name="mqttAdapterName">androidsense.mqtt.adapter</Property>
|
||||
<Property Name="username">admin</Property>
|
||||
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
|
||||
<Property Name="password">admin</Property>
|
||||
<Property Name="qos">0</Property>
|
||||
<Property Name="scopes"/>
|
||||
<Property Name="clearSession">true</Property>
|
||||
|
||||
@ -38,10 +38,9 @@
|
||||
<FileBasedProperties>true</FileBasedProperties>
|
||||
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
|
||||
<ConfigProperties>
|
||||
<Property Name="mqtt.adapter.name">raspberrypi.mqtt.adapter</Property>
|
||||
<Property Name="url">tcp://localhost:1886</Property>
|
||||
<Property Name="mqttAdapterName">raspberrypi.mqtt.adapter</Property>
|
||||
<Property Name="username">admin</Property>
|
||||
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
|
||||
<Property Name="password">admin</Property>
|
||||
<Property Name="qos">0</Property>
|
||||
<Property Name="scopes"/>
|
||||
<Property Name="clearSession">true</Property>
|
||||
|
||||
@ -22,10 +22,9 @@
|
||||
<!--MQTT Config-->
|
||||
<EventListenerProvider>MQTT</EventListenerProvider>
|
||||
<Properties>
|
||||
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property>
|
||||
<Property Name="url">tcp://localhost:1886</Property>
|
||||
<Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
|
||||
<Property Name="username">admin</Property>
|
||||
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
|
||||
<Property Name="password">admin</Property>
|
||||
<Property Name="qos">0</Property>
|
||||
<Property Name="scopes"/>
|
||||
<Property Name="clearSession">true</Property>
|
||||
|
||||
@ -38,10 +38,9 @@
|
||||
<FileBasedProperties>true</FileBasedProperties>
|
||||
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
|
||||
<ConfigProperties>
|
||||
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property>
|
||||
<Property Name="url">tcp://localhost:1886</Property>
|
||||
<Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
|
||||
<Property Name="username">admin</Property>
|
||||
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
|
||||
<Property Name="password">admin</Property>
|
||||
<Property Name="qos">0</Property>
|
||||
<Property Name="scopes"/>
|
||||
<Property Name="clearSession">true</Property>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user