mharindu 9 years ago
commit 9ebf2ab6d9

@ -105,10 +105,6 @@
<groupId>org.wso2.carbon.governance</groupId> <groupId>org.wso2.carbon.governance</groupId>
<artifactId>org.wso2.carbon.governance.lcm</artifactId> <artifactId>org.wso2.carbon.governance.lcm</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</dependency>
</dependencies> </dependencies>

@ -78,7 +78,10 @@ public class APIPublisherServiceImpl implements APIPublisherService {
+ api.getId().getVersion() + "'"); + api.getId().getVersion() + "'");
} }
} else { } else {
api.setStatus(provider.getAPI(api.getId()).getStatus()); if (provider.getAPI(api.getId()).getStatus() == APIStatus.CREATED) {
provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION);
}
api.setStatus(APIStatus.PUBLISHED);
provider.updateAPI(api); provider.updateAPI(api);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("An API already exists with the name '" + api.getId().getApiName() + log.debug("An API already exists with the name '" + api.getId().getApiName() +

@ -0,0 +1,67 @@
/*
* 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.apimgt.webapp.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.core.ServerStartupObserver;
public class APIPublisherStartupHandler implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(APIPublisherStartupHandler.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
// adding temporary due to a bug in the platform
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
log.error("Error occurred while sleeping", e);
}
APIPublisherDataHolder.getInstance().setServerStarted(true);
log.info("Server has just started, hence started publishing unpublished APIs");
if (log.isDebugEnabled()) {
log.debug("Total number of unpublished APIs: "
+ APIPublisherDataHolder.getInstance().getUnpublishedApis().size());
}
APIPublisherService publisher = APIPublisherDataHolder.getInstance().getApiPublisherService();
while (!APIPublisherDataHolder.getInstance().getUnpublishedApis().isEmpty()) {
API api = APIPublisherDataHolder.getInstance().getUnpublishedApis().pop();
try {
publisher.publishAPI(api);
} catch (java.lang.Exception e) {
log.error("Error occurred while publishing API '" + api.getId().getApiName(), e);
}
}
}
});
t.start();
}
}

@ -18,6 +18,7 @@
package org.wso2.carbon.apimgt.webapp.publisher; package org.wso2.carbon.apimgt.webapp.publisher;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
@ -26,11 +27,9 @@ import org.wso2.carbon.apimgt.api.model.*;
import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder; import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig;
import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.utils.ConfigurationContextService;
import org.wso2.carbon.utils.NetworkUtils;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import java.util.*; import java.util.*;
@ -96,7 +95,7 @@ public class APIPublisherUtil {
} }
api.setResponseCache(APIConstants.DISABLED); api.setResponseCache(APIConstants.DISABLED);
String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + String endpointConfig = "{\"production_endpoints\":{\"url\":\"" + config.getEndpoint() +
"\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}"; "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}";
api.setEndpointConfig(endpointConfig); api.setEndpointConfig(endpointConfig);
@ -113,7 +112,8 @@ public class APIPublisherUtil {
// adding scopes to the api // adding scopes to the api
Set<URITemplate> uriTemplates = config.getUriTemplates(); Set<URITemplate> uriTemplates = config.getUriTemplates();
Map<String, Scope> apiScopes = new HashMap<>(); Map<String, Scope> apiScopes = new HashMap<>();
Scope existingScope;
String existingPermissions;
if (uriTemplates != null) { if (uriTemplates != null) {
// this creates distinct scopes list // this creates distinct scopes list
for (URITemplate template : uriTemplates) { for (URITemplate template : uriTemplates) {
@ -121,6 +121,12 @@ public class APIPublisherUtil {
if (scope != null) { if (scope != null) {
if (apiScopes.get(scope.getKey()) == null) { if (apiScopes.get(scope.getKey()) == null) {
apiScopes.put(scope.getKey(), scope); apiScopes.put(scope.getKey(), scope);
} else {
existingScope = apiScopes.get(scope.getKey());
existingPermissions = existingScope.getRoles();
existingPermissions = getDistinctPermissions(existingPermissions + "," + scope.getRoles());
existingScope.setRoles(existingPermissions);
apiScopes.put(scope.getKey(), existingScope);
} }
} }
} }
@ -143,24 +149,8 @@ public class APIPublisherUtil {
} }
public static String getServerBaseUrl() { public static String getServerBaseUrl() {
// Hostname WebappPublisherConfig webappPublisherConfig = WebappPublisherConfig.getInstance();
String hostName = "localhost"; return Utils.replaceSystemProperty(webappPublisherConfig.getHost());
try {
hostName = NetworkUtils.getMgtHostName();
} catch (Exception ignored) {
}
// HTTPS port
String mgtConsoleTransport = CarbonUtils.getManagementTransport();
ConfigurationContextService configContextService =
APIPublisherDataHolder.getInstance().getConfigurationContextService();
int port = CarbonUtils.getTransportPort(configContextService, mgtConsoleTransport);
int httpsProxyPort =
CarbonUtils.getTransportProxyPort(configContextService.getServerConfigContext(),
mgtConsoleTransport);
if (httpsProxyPort > 0) {
port = httpsProxyPort;
}
return "https://" + hostName + ":" + port;
} }
public static String getApiEndpointUrl(String context) { public static String getApiEndpointUrl(String context) {
@ -318,4 +308,9 @@ public class APIPublisherUtil {
return apiConfig; return apiConfig;
} }
private static String getDistinctPermissions(String permissions) {
String[] unique = new HashSet<String>(Arrays.asList(permissions.split(","))).toArray(new String[0]);
return StringUtils.join(unique, ",");
}
} }

@ -0,0 +1,75 @@
/*
* 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.apimgt.webapp.publisher;
public class InvalidConfigurationStateException extends RuntimeException {
private static final long serialVersionUID = -3151279311329070397L;
private String errorMessage;
private int errorCode;
public InvalidConfigurationStateException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public InvalidConfigurationStateException(int errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public int getErrorCode() {
return errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public InvalidConfigurationStateException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public InvalidConfigurationStateException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public InvalidConfigurationStateException(String msg) {
super(msg);
setErrorMessage(msg);
}
public InvalidConfigurationStateException() {
super();
}
public InvalidConfigurationStateException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,44 @@
/*
* 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.apimgt.webapp.publisher;
public class WebappPublisherConfigurationFailedException extends Exception {
private static final long serialVersionUID = -3151279312929070398L;
public WebappPublisherConfigurationFailedException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public WebappPublisherConfigurationFailedException(String message, Throwable cause) {
super(message, cause);
}
public WebappPublisherConfigurationFailedException(String msg) {
super(msg);
}
public WebappPublisherConfigurationFailedException() {
super();
}
public WebappPublisherConfigurationFailedException(Throwable cause) {
super(cause);
}
}

@ -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.apimgt.webapp.publisher;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
/**
* This class contains the util methods which are needed
* to web app publisher related functions.
*/
public class WebappPublisherUtil {
public static Document convertToDocument(File file) throws WebappPublisherConfigurationFailedException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new WebappPublisherConfigurationFailedException("Error occurred while parsing file, while converting " +
"to a org.w3c.dom.Document", e);
}
}
}

@ -0,0 +1,94 @@
/*
* 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.apimgt.webapp.publisher.config;
import org.w3c.dom.Document;
import org.wso2.carbon.apimgt.webapp.publisher.InvalidConfigurationStateException;
import org.wso2.carbon.apimgt.webapp.publisher.WebappPublisherConfigurationFailedException;
import org.wso2.carbon.apimgt.webapp.publisher.WebappPublisherUtil;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
/**
* This class represents the configuration that are needed
* when publishing APIs to API Manager.
*/
@XmlRootElement(name = "WebappPublisherConfigs")
public class WebappPublisherConfig {
private String host;
private boolean isPublished;
private static WebappPublisherConfig config;
private static final String WEBAPP_PUBLISHER_CONFIG_PATH =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "webapp-publisher-config.xml";
private WebappPublisherConfig() {
}
public static WebappPublisherConfig getInstance() {
if (config == null) {
throw new InvalidConfigurationStateException("Webapp Authenticator Configuration is not " +
"initialized properly");
}
return config;
}
@XmlElement(name = "Host", required = true)
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
@XmlElement(name = "PublishAPI", required = true)
public boolean isPublished() {
return isPublished;
}
public void setPublished(boolean published) {
isPublished = published;
}
public static void init() throws WebappPublisherConfigurationFailedException {
try {
File emailSenderConfig = new File(WEBAPP_PUBLISHER_CONFIG_PATH);
Document doc = WebappPublisherUtil.convertToDocument(emailSenderConfig);
/* Un-marshaling Email Sender configuration */
JAXBContext ctx = JAXBContext.newInstance(WebappPublisherConfig.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
//unmarshaller.setSchema(getSchema());
config = (WebappPublisherConfig) unmarshaller.unmarshal(doc);
} catch (JAXBException e) {
throw new WebappPublisherConfigurationFailedException("Error occurred while un-marshalling Webapp " +
"Publisher Config", e);
}
}
}

@ -19,12 +19,15 @@
package org.wso2.carbon.apimgt.webapp.publisher.internal; package org.wso2.carbon.apimgt.webapp.publisher.internal;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService;
import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.user.core.tenant.TenantManager;
import org.wso2.carbon.utils.ConfigurationContextService; import org.wso2.carbon.utils.ConfigurationContextService;
import java.util.Stack;
public class APIPublisherDataHolder { public class APIPublisherDataHolder {
private APIPublisherService apiPublisherService; private APIPublisherService apiPublisherService;
@ -32,6 +35,8 @@ public class APIPublisherDataHolder {
private RealmService realmService; private RealmService realmService;
private TenantManager tenantManager; private TenantManager tenantManager;
private RegistryService registryService; private RegistryService registryService;
private boolean isServerStarted;
private Stack<API> unpublishedApis = new Stack<>();
private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder(); private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder();
@ -94,4 +99,20 @@ public class APIPublisherDataHolder {
public void setRegistryService(RegistryService registryService) { public void setRegistryService(RegistryService registryService) {
this.registryService = registryService; this.registryService = registryService;
} }
public boolean isServerStarted() {
return isServerStarted;
}
public void setServerStarted(boolean serverStarted) {
isServerStarted = serverStarted;
}
public Stack<API> getUnpublishedApis() {
return unpublishedApis;
}
public void setUnpublishedApis(Stack<API> unpublishedApis) {
this.unpublishedApis = unpublishedApis;
}
} }

@ -25,6 +25,9 @@ import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService;
import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherServiceImpl; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherServiceImpl;
import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherStartupHandler;
import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.ConfigurationContextService; import org.wso2.carbon.utils.ConfigurationContextService;
@ -57,16 +60,23 @@ public class APIPublisherServiceComponent {
protected void activate(ComponentContext componentContext) { protected void activate(ComponentContext componentContext) {
try { try {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Initializing device management core bundle"); log.debug("Initializing webapp publisher bundle");
} }
if (log.isDebugEnabled()) {
log.debug("Loading webapp publisher configurations");
}
/* Initializing webapp publisher configuration */
WebappPublisherConfig.init();
/* Registering declarative service instances exposed by DeviceManagementServiceComponent */ /* Registering declarative service instances exposed by DeviceManagementServiceComponent */
this.registerServices(componentContext); this.registerServices(componentContext);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Device management core bundle has been successfully initialized"); log.debug("Webapp publisher bundle has been successfully initialized");
} }
} catch (Throwable e) { } catch (Throwable e) {
log.error("Error occurred while initializing device management core bundle", e); log.error("Error occurred while initializing webapp publisher bundle", e);
} }
} }
@ -84,6 +94,7 @@ public class APIPublisherServiceComponent {
APIPublisherService publisher = new APIPublisherServiceImpl(); APIPublisherService publisher = new APIPublisherServiceImpl();
APIPublisherDataHolder.getInstance().setApiPublisherService(publisher); APIPublisherDataHolder.getInstance().setApiPublisherService(publisher);
bundleContext.registerService(APIPublisherService.class, publisher, null); bundleContext.registerService(APIPublisherService.class, publisher, null);
bundleContext.registerService(ServerStartupObserver.class, new APIPublisherStartupHandler(), null);
} }
protected void setAPIManagerConfigurationService(APIManagerConfigurationService service) { protected void setAPIManagerConfigurationService(APIManagerConfigurationService service) {

@ -31,7 +31,6 @@ import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherUtil;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder; import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.AnnotationProcessor; import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.AnnotationProcessor;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import java.io.IOException; import java.io.IOException;
@ -43,6 +42,9 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class); private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class);
private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled"; private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled";
public static final String PROPERTY_PROFILE = "profile";
public static final String PROFILE_DT_WORKER = "dtWorker";
public static final String PROFILE_DEFAULT = "default";
@Override @Override
public void lifecycleEvent(LifecycleEvent lifecycleEvent) { public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
@ -52,10 +54,10 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED);
boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param);
String profile = System.getProperty(DeviceManagementConstants.Common.PROPERTY_PROFILE); String profile = System.getProperty(PROPERTY_PROFILE);
if ((profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DT_WORKER) || if ((profile.equalsIgnoreCase(PROFILE_DT_WORKER) ||
profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DEFAULT)) && isManagedApi) { profile.equalsIgnoreCase(PROFILE_DEFAULT)) && isManagedApi) {
try { try {
AnnotationProcessor annotationProcessor = new AnnotationProcessor(context); AnnotationProcessor annotationProcessor = new AnnotationProcessor(context);
Set<String> annotatedAPIClasses = annotationProcessor. Set<String> annotatedAPIClasses = annotationProcessor.
@ -78,13 +80,22 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
if (isTenantActive) { if (isTenantActive) {
apiConfig.init(); apiConfig.init();
API api = APIPublisherUtil.getAPI(apiConfig); API api = APIPublisherUtil.getAPI(apiConfig);
APIPublisherService apiPublisherService = boolean isServerStarted = APIPublisherDataHolder.getInstance().isServerStarted();
APIPublisherDataHolder.getInstance().getApiPublisherService(); if (isServerStarted) {
if (apiPublisherService == null) { APIPublisherService apiPublisherService =
throw new IllegalStateException( APIPublisherDataHolder.getInstance().getApiPublisherService();
"API Publisher service is not initialized properly"); if (apiPublisherService == null) {
throw new IllegalStateException(
"API Publisher service is not initialized properly");
}
apiPublisherService.publishAPI(api);
} else {
if (log.isDebugEnabled()) {
log.debug("Server has not started yet. Hence adding API '" +
api.getId().getApiName() + "' to the queue");
}
APIPublisherDataHolder.getInstance().getUnpublishedApis().push(api);
} }
apiPublisherService.publishAPI(api);
} else { } else {
log.error("No tenant [" + apiConfig.getTenantDomain() + "] " + log.error("No tenant [" + apiConfig.getTenantDomain() + "] " +
"found when publishing the Web app"); "found when publishing the Web app");

@ -28,12 +28,11 @@ import org.scannotation.WarUrlFinder;
import org.wso2.carbon.apimgt.annotations.api.API; import org.wso2.carbon.apimgt.annotations.api.API;
import org.wso2.carbon.apimgt.annotations.api.Permission; import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.Scope;
import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherUtil;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionManagementException; import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionManagementException;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.deviceType.DTConfiguration;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.ws.rs.*; import javax.ws.rs.*;
@ -225,13 +224,7 @@ public class AnnotationProcessor {
APIResource resource = new APIResource(); APIResource resource = new APIResource();
resource.setUriTemplate(makeContextURLReady(apiRootContext + subCtx)); resource.setUriTemplate(makeContextURLReady(apiRootContext + subCtx));
DTConfiguration deviceTypeConfig = DeviceConfigurationManager.getInstance(). resource.setUri(APIPublisherUtil.getServerBaseUrl() + makeContextURLReady(
getDeviceManagementConfig().getDTDeploymentConfiguration();
String serverIP = deviceTypeConfig.getDtHostAddress();
String httpServerPort = deviceTypeConfig.getDtHostPort();
resource.setUri(PROTOCOL_HTTP + "://" + serverIP + ":" + httpServerPort + makeContextURLReady(
resourceRootContext) + makeContextURLReady(subCtx)); resourceRootContext) + makeContextURLReady(subCtx));
resource.setAuthType(AUTH_TYPE); resource.setAuthType(AUTH_TYPE);

@ -143,7 +143,7 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.commons</groupId> <groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId> <artifactId>org.wso2.carbon.user.mgt</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>

@ -28,9 +28,6 @@ public final class DeviceManagementConstants {
public static final String PROPERTY_SETUP = "setup"; public static final String PROPERTY_SETUP = "setup";
public static final String DEFAULT_LICENSE_CONFIG_XML_NAME = "license-config.xml"; public static final String DEFAULT_LICENSE_CONFIG_XML_NAME = "license-config.xml";
public static final String PROPERTY_PROFILE = "profile";
public static final String PROFILE_DT_WORKER = "dtWorker";
public static final String PROFILE_DEFAULT = "default";
} }
public static final class AppManagement { public static final class AppManagement {

@ -47,7 +47,7 @@ import java.util.Map;
*/ */
public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthorizationService { public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthorizationService {
private final static String EMM_ADMIN_PERMISSION = "/device-mgt/admin-device-access"; private final static String CDM_ADMIN_PERMISSION = "/device-mgt/admin";
private static Log log = LogFactory.getLog(DeviceAccessAuthorizationServiceImpl.class); private static Log log = LogFactory.getLog(DeviceAccessAuthorizationServiceImpl.class);
public DeviceAccessAuthorizationServiceImpl() { public DeviceAccessAuthorizationServiceImpl() {
@ -221,7 +221,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori
if (userRealm != null && userRealm.getAuthorizationManager() != null) { if (userRealm != null && userRealm.getAuthorizationManager() != null) {
return userRealm.getAuthorizationManager() return userRealm.getAuthorizationManager()
.isUserAuthorized(removeTenantDomain(username), .isUserAuthorized(removeTenantDomain(username),
PermissionUtils.getAbsolutePermissionPath(EMM_ADMIN_PERMISSION), PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION),
PermissionMethod.UI_EXECUTE); PermissionMethod.UI_EXECUTE);
} }
return false; return false;
@ -249,7 +249,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori
private boolean addAdminPermissionToRegistry() throws PermissionManagementException { private boolean addAdminPermissionToRegistry() throws PermissionManagementException {
Permission permission = new Permission(); Permission permission = new Permission();
permission.setPath(PermissionUtils.getAbsolutePermissionPath(EMM_ADMIN_PERMISSION)); permission.setPath(PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION));
return PermissionUtils.putPermission(permission); return PermissionUtils.putPermission(permission);
} }

@ -17,15 +17,12 @@
*/ */
package org.wso2.carbon.device.mgt.core.config; package org.wso2.carbon.device.mgt.core.config;
import org.wso2.carbon.device.mgt.core.config.deviceType.DTConfiguration;
import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations;
import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration; import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration;
import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration; import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
/** /**
* Represents Device Mgt configuration. * Represents Device Mgt configuration.
@ -37,8 +34,6 @@ public final class DeviceManagementConfig {
private TaskConfiguration taskConfiguration; private TaskConfiguration taskConfiguration;
private IdentityConfigurations identityConfigurations; private IdentityConfigurations identityConfigurations;
private PolicyConfiguration policyConfiguration; private PolicyConfiguration policyConfiguration;
//private List<String> pushNotificationProviders;
private DTConfiguration dTDepyloymentConfiguration;
@XmlElement(name = "ManagementRepository", required = true) @XmlElement(name = "ManagementRepository", required = true)
public DeviceManagementConfigRepository getDeviceManagementConfigRepository() { public DeviceManagementConfigRepository getDeviceManagementConfigRepository() {
@ -77,15 +72,6 @@ public final class DeviceManagementConfig {
this.taskConfiguration = taskConfiguration; this.taskConfiguration = taskConfiguration;
} }
@XmlElement(name = "DTDeploymentConfiguration", required = true)
public DTConfiguration getDTDeploymentConfiguration() {
return dTDepyloymentConfiguration;
}
public void setDTDeploymentConfiguration(DTConfiguration dTDeploymentConfiguration) {
this.dTDepyloymentConfiguration = dTDeploymentConfiguration;
}
// @XmlElementWrapper(name = "PushNotificationProviders", required = true) // @XmlElementWrapper(name = "PushNotificationProviders", required = true)
// @XmlElement(name = "Provider", required = true) // @XmlElement(name = "Provider", required = true)
// public List<String> getPushNotificationProviders() { // public List<String> getPushNotificationProviders() {

@ -1,53 +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.
*/
/**
* This class will read the configurations related to task. This task will be responsible for adding the operations.
*/
package org.wso2.carbon.device.mgt.core.config.deviceType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "DTDepyloymentConfiguration")
public class DTConfiguration {
private String dtHostAddress;
private String dtHostPort;
@XmlElement(name = "DTHostAddress", required = true)
public String getDtHostAddress() {
return dtHostAddress;
}
public void setDtHostAddress(String dtHostAddress) {
this.dtHostAddress = dtHostAddress;
}
@XmlElement(name = "DTHostPort", required = true)
public String getDtHostPort() {
return dtHostPort;
}
public void setDtHostPort(String dtHostPort) {
this.dtHostPort = dtHostPort;
}
}

@ -24,7 +24,6 @@ import org.apache.catalina.core.StandardContext;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.Feature; import org.wso2.carbon.device.mgt.common.Feature;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.GenericFeatureManager; import org.wso2.carbon.device.mgt.extensions.feature.mgt.GenericFeatureManager;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType; import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.util.AnnotationProcessor; import org.wso2.carbon.device.mgt.extensions.feature.mgt.util.AnnotationProcessor;
@ -44,6 +43,9 @@ public class FeatureManagementLifecycleListener implements LifecycleListener {
private static final Log log = LogFactory.getLog(FeatureManagementLifecycleListener.class); private static final Log log = LogFactory.getLog(FeatureManagementLifecycleListener.class);
private static final String UNLIMITED = "Unlimited"; private static final String UNLIMITED = "Unlimited";
public static final String PROPERTY_PROFILE = "profile";
public static final String PROFILE_DT_WORKER = "dtWorker";
public static final String PROFILE_DEFAULT = "default";
@Override @Override
public void lifecycleEvent(LifecycleEvent lifecycleEvent) { public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
@ -53,10 +55,10 @@ public class FeatureManagementLifecycleListener implements LifecycleListener {
String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED);
boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param);
String profile = System.getProperty(DeviceManagementConstants.Common.PROPERTY_PROFILE); String profile = System.getProperty(PROPERTY_PROFILE);
if ((profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DT_WORKER) || if ((profile.equalsIgnoreCase(PROFILE_DT_WORKER) ||
profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DEFAULT)) && isManagedApi) { profile.equalsIgnoreCase(PROFILE_DEFAULT)) && isManagedApi) {
try { try {
AnnotationProcessor annotationProcessor = new AnnotationProcessor(context); AnnotationProcessor annotationProcessor = new AnnotationProcessor(context);
Set<String> annotatedAPIClasses = annotationProcessor.scanStandardContext(DeviceType.class.getName()); Set<String> annotatedAPIClasses = annotationProcessor.scanStandardContext(DeviceType.class.getName());

@ -65,7 +65,7 @@ public class EmailSenderServiceComponent {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Initializing email sender core bundle"); log.debug("Initializing email sender core bundle");
} }
/* Initializing email sende configuration */ /* Initializing email sender configuration */
EmailSenderConfig.init(); EmailSenderConfig.init();
/* Setting up default email templates */ /* Setting up default email templates */

@ -113,7 +113,12 @@
org.wso2.carbon.user.core, org.wso2.carbon.user.core,
org.wso2.carbon.user.core.config, org.wso2.carbon.user.core.config,
org.wso2.carbon.user.core.util, org.wso2.carbon.user.core.util,
org.wso2.carbon.utils org.wso2.carbon.utils,
org.wso2.carbon.context,
org.wso2.carbon.identity.oauth.cache,
org.wso2.carbon.identity.oauth.config,
org.wso2.carbon.identity.oauth2.dao,
org.wso2.carbon.utils.multitenancy
</Import-Package> </Import-Package>
</instructions> </instructions>
</configuration> </configuration>

@ -47,6 +47,7 @@ public class OAuthExtUtils {
private static final String DEFAULT_SCOPE_NAME = "default"; private static final String DEFAULT_SCOPE_NAME = "default";
private static final String UI_EXECUTE = "ui.execute"; private static final String UI_EXECUTE = "ui.execute";
private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE"; private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE";
private static final int START_INDEX = 0;
/** /**
* This method is used to get the tenant id when given tenant domain. * This method is used to get the tenant id when given tenant domain.
@ -260,4 +261,12 @@ public class OAuthExtUtils {
return authorizedScopes; return authorizedScopes;
} }
public static String extractUserName(String username) {
if (username == null || username.isEmpty()) {
return null;
}
String trimmedName = username.trim();
return trimmedName.substring(START_INDEX, trimmedName.lastIndexOf('@'));
}
} }

@ -0,0 +1,200 @@
/*
* 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.oauth.extensions.validators;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
import org.wso2.carbon.identity.application.common.model.User;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth.cache.CacheEntry;
import org.wso2.carbon.identity.oauth.cache.OAuthCache;
import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey;
import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO;
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
import org.wso2.carbon.identity.oauth2.model.ResourceScopeCacheEntry;
import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@SuppressWarnings("unused")
public class ExtendedJDBCScopeValidator extends OAuth2ScopeValidator{
private static final Log log = LogFactory.getLog(ExtendedJDBCScopeValidator.class);
private static final String UI_EXECUTE = "ui.execute";
@Override
public boolean validateScope(AccessTokenDO accessTokenDO, String resource) throws IdentityOAuth2Exception {
//Get the list of scopes associated with the access token
String[] scopes = accessTokenDO.getScope();
//If no scopes are associated with the token
if (scopes == null || scopes.length == 0) {
return true;
}
String resourceScope = null;
TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
boolean cacheHit = false;
// Check the cache, if caching is enabled.
if (OAuthServerConfiguration.getInstance().isCacheEnabled()) {
OAuthCache oauthCache = OAuthCache.getInstance();
OAuthCacheKey cacheKey = new OAuthCacheKey(resource);
CacheEntry result = oauthCache.getValueFromCache(cacheKey);
//Cache hit
if (result instanceof ResourceScopeCacheEntry) {
resourceScope = ((ResourceScopeCacheEntry) result).getScope();
cacheHit = true;
}
}
if (!cacheHit) {
resourceScope = tokenMgtDAO.findScopeOfResource(resource);
if (OAuthServerConfiguration.getInstance().isCacheEnabled()) {
OAuthCache oauthCache = OAuthCache.getInstance();
OAuthCacheKey cacheKey = new OAuthCacheKey(resource);
ResourceScopeCacheEntry cacheEntry = new ResourceScopeCacheEntry(resourceScope);
//Store resourceScope in cache even if it is null (to avoid database calls when accessing resources for
//which scopes haven't been defined).
oauthCache.addToCache(cacheKey, cacheEntry);
}
}
//Return TRUE if - There does not exist a scope definition for the resource
if (resourceScope == null) {
if(log.isDebugEnabled()){
log.debug("Resource '" + resource + "' is not protected with a scope");
}
return true;
}
List<String> scopeList = new ArrayList<>(Arrays.asList(scopes));
//If the access token does not bear the scope required for accessing the Resource.
if(!scopeList.contains(resourceScope)){
if(log.isDebugEnabled()){
log.debug("Access token '" + accessTokenDO.getAccessToken() + "' does not bear the scope '" +
resourceScope + "'");
}
return false;
}
try {
//Get the permissions associated with the scope, if any
Set<String> permissionsOfScope = tokenMgtDAO.getRolesOfScopeByScopeKey(resourceScope);
//If the scope doesn't have any permissions associated with it.
if(permissionsOfScope == null || permissionsOfScope.isEmpty()){
if(log.isDebugEnabled()){
log.debug("Did not find any roles associated to the scope " + resourceScope);
}
return true;
}
if(log.isDebugEnabled()){
StringBuilder logMessage = new StringBuilder("Found permissions of scope '" + resourceScope + "' ");
for(String permission : permissionsOfScope){
logMessage.append(permission);
logMessage.append(", ");
}
log.debug(logMessage.toString());
}
User authorizedUser = accessTokenDO.getAuthzUser();
RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
int tenantId = realmService.getTenantManager().getTenantId(authorizedUser.getTenantDomain());
if (tenantId == 0 || tenantId == -1) {
tenantId = IdentityTenantUtil.getTenantIdOfUser(authorizedUser.getUserName());
}
AuthorizationManager authorizationManager;
String[] userRoles;
boolean tenantFlowStarted = false;
try{
//If this is a tenant user
if(tenantId != MultitenantConstants.SUPER_TENANT_ID){
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
realmService.getTenantManager().getDomain(tenantId),true);
tenantFlowStarted = true;
}
authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
} finally {
if (tenantFlowStarted) {
PrivilegedCarbonContext.endTenantFlow();
}
}
boolean status = false;
String username = MultitenantUtils.getTenantAwareUsername(authorizedUser.getUserName());
for (String permission : permissionsOfScope) {
if (authorizationManager != null) {
String userStore = authorizedUser.getUserStoreDomain();
if (userStore != null) {
status = authorizationManager
.isUserAuthorized(userStore + "/" + username, permission, UI_EXECUTE);
} else {
status = authorizationManager.isUserAuthorized(username , permission, UI_EXECUTE);
}
if (status) {
break;
}
}
}
if (status) {
if(log.isDebugEnabled()){
log.debug("User '" + authorizedUser.getUserName() + "' is authorized");
}
return true;
}
if(log.isDebugEnabled()){
log.debug("No permissions associated for the user " + authorizedUser.getUserName());
}
return false;
} catch (UserStoreException e) {
//Log and return since we do not want to stop issuing the token in case of scope validation failures.
log.error("Error when getting the tenant's UserStoreManager or when getting roles of user ", e);
return false;
}
}
}

@ -117,7 +117,10 @@
org.apache.axiom.soap.impl.builder, org.apache.axiom.soap.impl.builder,
org.apache.axiom.om, org.apache.axiom.om,
org.apache.axiom.om.impl.builder, org.apache.axiom.om.impl.builder,
org.apache.axiom.om.util org.apache.axiom.om.util,
org.wso2.carbon.registry.core.*,
org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}",
org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}",
</Import-Package> </Import-Package>
</instructions> </instructions>
</configuration> </configuration>
@ -214,6 +217,14 @@
<groupId>commons-pool.wso2</groupId> <groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId> <artifactId>commons-pool</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.registry</groupId>
<artifactId>org.wso2.carbon.registry.indexing</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.core</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -21,6 +21,8 @@ package org.wso2.carbon.webapp.authenticator.framework;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.device.mgt.core.scep.SCEPManager; import org.wso2.carbon.device.mgt.core.scep.SCEPManager;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
public class AuthenticatorFrameworkDataHolder { public class AuthenticatorFrameworkDataHolder {
@ -30,6 +32,8 @@ public class AuthenticatorFrameworkDataHolder {
private CertificateManagementService certificateManagementService; private CertificateManagementService certificateManagementService;
private SCEPManager scepManager; private SCEPManager scepManager;
private OAuth2TokenValidationService oAuth2TokenValidationService; private OAuth2TokenValidationService oAuth2TokenValidationService;
private TenantIndexingLoader tenantIndexingLoader;
private TenantRegistryLoader tenantRegistryLoader;
private static AuthenticatorFrameworkDataHolder private static AuthenticatorFrameworkDataHolder
thisInstance = new AuthenticatorFrameworkDataHolder(); thisInstance = new AuthenticatorFrameworkDataHolder();
@ -92,4 +96,21 @@ public class AuthenticatorFrameworkDataHolder {
OAuth2TokenValidationService oAuth2TokenValidationService) { OAuth2TokenValidationService oAuth2TokenValidationService) {
this.oAuth2TokenValidationService = oAuth2TokenValidationService; this.oAuth2TokenValidationService = oAuth2TokenValidationService;
} }
public TenantIndexingLoader getTenantIndexingLoader() {
return tenantIndexingLoader;
}
public void setTenantIndexingLoader(
TenantIndexingLoader tenantIndexingLoader) {
this.tenantIndexingLoader = tenantIndexingLoader;
}
public void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
this.tenantRegistryLoader = tenantRegistryLoader;
}
public TenantRegistryLoader getTenantRegistryLoader() {
return tenantRegistryLoader;
}
} }

@ -22,23 +22,24 @@ import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.SignedJWT;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response; import org.apache.catalina.connector.Response;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.user.api.TenantManager; import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkDataHolder; import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkDataHolder;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.text.ParseException; import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -47,11 +48,12 @@ import java.util.StringTokenizer;
*/ */
public class JWTAuthenticator implements WebappAuthenticator { public class JWTAuthenticator implements WebappAuthenticator {
private static final Log log = LogFactory.getLog(JWTAuthenticator.class); private static final Log log = LogFactory.getLog(JWTAuthenticator.class);
public static final String SIGNED_JWT_AUTH_USERNAME = "Username"; private static final String SIGNED_JWT_AUTH_USERNAME = "http://wso2.org/claims/enduser";
private static final String JWT_AUTHENTICATOR = "JWT"; private static final String SIGNED_JWT_AUTH_TENANT_ID = "http://wso2.org/claims/enduserTenantId";
private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion"; private static final String JWT_AUTHENTICATOR = "JWT";
private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion";
private static final Map<String, PublicKey> publicKeyHolder = new HashMap<>();
@Override @Override
public void init() { public void init() {
@ -59,46 +61,50 @@ public class JWTAuthenticator implements WebappAuthenticator {
@Override @Override
public boolean canHandle(Request request) { public boolean canHandle(Request request) {
String authorizationHeader = request.getHeader(JWTAuthenticator.JWT_ASSERTION_HEADER); String authorizationHeader = request.getHeader(JWTAuthenticator.JWT_ASSERTION_HEADER);
if((authorizationHeader != null) && !authorizationHeader.isEmpty()){ if ((authorizationHeader != null) && !authorizationHeader.isEmpty()) {
return true; return true;
} }
return false; return false;
} }
@Override @Override
public AuthenticationInfo authenticate(Request request, Response response) { public AuthenticationInfo authenticate(Request request, Response response) {
String requestUri = request.getRequestURI(); String requestUri = request.getRequestURI();
AuthenticationInfo authenticationInfo = new AuthenticationInfo(); AuthenticationInfo authenticationInfo = new AuthenticationInfo();
if (requestUri == null || "".equals(requestUri)) { if (requestUri == null || "".equals(requestUri)) {
authenticationInfo.setStatus(Status.CONTINUE); authenticationInfo.setStatus(Status.CONTINUE);
} }
StringTokenizer tokenizer = new StringTokenizer(requestUri, "/"); StringTokenizer tokenizer = new StringTokenizer(requestUri, "/");
String context = tokenizer.nextToken(); String context = tokenizer.nextToken();
if (context == null || "".equals(context)) { if (context == null || "".equals(context)) {
authenticationInfo.setStatus(Status.CONTINUE); authenticationInfo.setStatus(Status.CONTINUE);
} }
//Get the filesystem keystore default primary certificate try {
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID); String authorizationHeader = request.getHeader(JWT_ASSERTION_HEADER);
try {
keyStoreManager.getDefaultPrimaryCertificate(); SignedJWT jwsObject = SignedJWT.parse(authorizationHeader);
String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION); String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
String headerData = decodeAuthorizationHeader(authorizationHeader); String tenantDomain = MultitenantUtils.getTenantDomain(username);
JWSVerifier verifier = int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID));
new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey()); PublicKey publicKey = publicKeyHolder.get(tenantDomain);
SignedJWT jwsObject = SignedJWT.parse(headerData); if (publicKey == null) {
if (jwsObject.verify(verifier)) { loadTenantRegistry(tenantId);
String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId);
String tenantDomain = MultitenantUtils.getTenantDomain(username); publicKey = keyStoreManager.getDefaultPublicKey();
username = MultitenantUtils.getTenantAwareUsername(username); publicKeyHolder.put(tenantDomain, publicKey);
TenantManager tenantManager = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). }
getTenantManager();
int tenantId = tenantManager.getTenantId(tenantDomain); //Get the filesystem keystore default primary certificate
if (tenantId == -1) { JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " + //https://wso2.org/jira/browse/APIMANAGER-4504 need to change this to jwsObject.verify(verifier)
": " + tenantDomain); if (username != null && !username.isEmpty() && tenantDomain != null && !tenantDomain.isEmpty()) {
} else { username = MultitenantUtils.getTenantAwareUsername(username);
if (tenantId == -1) {
log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " +
": " + tenantDomain);
} else {
UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService().
getTenantUserRealm(tenantId).getUserStoreManager(); getTenantUserRealm(tenantId).getUserStoreManager();
if (userStore.isExistingUser(username)) { if (userStore.isExistingUser(username)) {
@ -108,41 +114,25 @@ public class JWTAuthenticator implements WebappAuthenticator {
authenticationInfo.setStatus(Status.CONTINUE); authenticationInfo.setStatus(Status.CONTINUE);
} }
} }
} } else {
} catch (UserStoreException e) { authenticationInfo.setStatus(Status.FAILURE);
log.error("Error occurred while obtaining the user.", e); }
} catch (ParseException e) { } catch (UserStoreException e) {
log.error("Error occurred while parsing the JWT header.", e); log.error("Error occurred while obtaining the user.", e);
} catch (JOSEException e) { } catch (ParseException e) {
log.error("Error occurred while verifying the JWT header.", e); log.error("Error occurred while parsing the JWT header.", e);
} catch (Exception e) { } catch (JOSEException e) {
log.error("Error occurred while verifying the JWT header.", e); log.error("Error occurred while verifying the JWT header.", e);
} } catch (Exception e) {
return authenticationInfo; log.error("Error occurred while verifying the JWT header.", e);
} }
return authenticationInfo;
private String decodeAuthorizationHeader(String authorizationHeader) { }
if(authorizationHeader == null) { @Override
return null; public String getName() {
} return JWTAuthenticator.JWT_AUTHENTICATOR;
}
String[] splitValues = authorizationHeader.trim().split(" ");
byte[] decodedBytes = Base64Utils.decode(splitValues[1].trim());
if (decodedBytes != null) {
return new String(decodedBytes);
} else {
if (log.isDebugEnabled()) {
log.debug("Error decoding authorization header.");
}
return null;
}
}
@Override
public String getName() {
return JWTAuthenticator.JWT_AUTHENTICATOR;
}
@Override @Override
public void setProperties(Properties properties) { public void setProperties(Properties properties) {
@ -158,4 +148,11 @@ public class JWTAuthenticator implements WebappAuthenticator {
public String getProperty(String name) { public String getProperty(String name) {
return null; return null;
} }
private static void loadTenantRegistry(int tenantId) throws RegistryException {
TenantRegistryLoader tenantRegistryLoader = AuthenticatorFrameworkDataHolder.getInstance().
getTenantRegistryLoader();
AuthenticatorFrameworkDataHolder.getInstance().getTenantIndexingLoader().loadTenantIndex(tenantId);
tenantRegistryLoader.loadTenantRegistry(tenantId);
}
} }

@ -25,6 +25,8 @@ import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.device.mgt.core.scep.SCEPManager; import org.wso2.carbon.device.mgt.core.scep.SCEPManager;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader;
import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve;
import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer; import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
@ -67,6 +69,17 @@ import java.util.Properties;
* policy="dynamic" * policy="dynamic"
* bind="setOAuth2ValidationService" * bind="setOAuth2ValidationService"
* unbind="unsetOAuth2ValidationService" * unbind="unsetOAuth2ValidationService"
* @scr.reference name="tenant.indexloader"
* interface="org.wso2.carbon.registry.indexing.service.TenantIndexingLoader"
* cardinality="1..1"
* policy="dynamic"
* bind="setTenantIndexLoader"
* unbind="unsetTenantIndexLoader"
* @scr.reference name="tenant.registryloader"
* interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader"
* cardinality="1..1" policy="dynamic"
* bind="setTenantRegistryLoader"
* unbind="unsetTenantRegistryLoader"
*/ */
public class WebappAuthenticatorFrameworkServiceComponent { public class WebappAuthenticatorFrameworkServiceComponent {
@ -183,4 +196,20 @@ public class WebappAuthenticatorFrameworkServiceComponent {
} }
AuthenticatorFrameworkDataHolder.getInstance().setOAuth2TokenValidationService(null); AuthenticatorFrameworkDataHolder.getInstance().setOAuth2TokenValidationService(null);
} }
protected void setTenantIndexLoader(TenantIndexingLoader tenantIndexLoader) {
AuthenticatorFrameworkDataHolder.getInstance().setTenantIndexingLoader(tenantIndexLoader);
}
protected void unsetTenantIndexLoader(TenantIndexingLoader tenantIndexLoader) {
AuthenticatorFrameworkDataHolder.getInstance().setTenantIndexingLoader(null);
}
protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(tenantRegistryLoader);
}
protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(null);
}
} }

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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.
-->
<!--
This configuration file represents the configuration that are needed
when publishing APIs to API Manager
-->
<WebappPublisherConfigs>
<!-- This host is used to define the host address which is used to publish APIs -->
<Host>http://localhost:${carbon.http.port}</Host>
<!-- If it is true, the APIs of this instance will be published to the defined host -->
<PublishAPI>true</PublishAPI>
</WebappPublisherConfigs>

@ -0,0 +1,2 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.webapp.publisher_${feature.version}/conf/webapp-publisher-config.xml,target:${installFolder}/../../conf/etc/webapp-publisher-config.xml,overwrite:true);\

@ -120,6 +120,7 @@
<bundleDef> <bundleDef>
org.wso2.carbon.identity:org.wso2.carbon.identity.oauth.stub:${carbon.identity.version} org.wso2.carbon.identity:org.wso2.carbon.identity.oauth.stub:${carbon.identity.version}
</bundleDef> </bundleDef>
<!-- Below should be bundled with the email verification -->
</bundles> </bundles>
<importFeatures> <importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef> <importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef>

@ -1375,16 +1375,16 @@
<artifactId>org.wso2.carbon.databridge.core</artifactId> <artifactId>org.wso2.carbon.databridge.core</artifactId>
<version>${carbon.analytics.common.version}</version> <version>${carbon.analytics.common.version}</version>
</dependency> </dependency>
<dependency> <!--<dependency>-->
<groupId>org.wso2.carbon.commons</groupId> <!--<groupId>org.wso2.carbon.commons</groupId>-->
<artifactId>org.wso2.carbon.databridge.commons</artifactId> <!--<artifactId>org.wso2.carbon.databridge.commons</artifactId>-->
<version>${carbon.commons.version}</version> <!--<version>${carbon.commons.version}</version>-->
</dependency> <!--</dependency>-->
<dependency> <!--<dependency>-->
<groupId>org.wso2.carbon.commons</groupId> <!--<groupId>org.wso2.carbon.commons</groupId>-->
<artifactId>org.wso2.carbon.databridge.commons.thrift</artifactId> <!--<artifactId>org.wso2.carbon.databridge.commons.thrift</artifactId>-->
<version>${carbon.commons.version}</version> <!--<version>${carbon.commons.version}</version>-->
</dependency> <!--</dependency>-->
<dependency> <dependency>
<groupId>org.wso2.carbon.analytics-common</groupId> <groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.databridge.commons</artifactId> <artifactId>org.wso2.carbon.databridge.commons</artifactId>
@ -1445,9 +1445,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.commons</groupId> <groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId> <artifactId>org.wso2.carbon.user.mgt</artifactId>
<version>${carbon.commons.version}</version> <version>${carbon.identity.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -1696,7 +1696,7 @@
<properties> <properties>
<testng.version>6.1.1</testng.version> <testng.version>6.1.1</testng.version>
<carbon.kernel.version>4.4.3</carbon.kernel.version> <carbon.kernel.version>4.4.3</carbon.kernel.version>
<carbon.kernel.version.range>[4.4.0, 4.5.0)</carbon.kernel.version.range> <carbon.kernel.version.range>[4.4.0, 5.0.0)</carbon.kernel.version.range>
<carbon.p2.plugin.version>1.5.4</carbon.p2.plugin.version> <carbon.p2.plugin.version>1.5.4</carbon.p2.plugin.version>
<maven-buildnumber-plugin.version>1.3</maven-buildnumber-plugin.version> <maven-buildnumber-plugin.version>1.3</maven-buildnumber-plugin.version>
@ -1743,9 +1743,6 @@
<!-- Carbon Multi-tenancy --> <!-- Carbon Multi-tenancy -->
<carbon.multitenancy.version>4.5.0</carbon.multitenancy.version> <carbon.multitenancy.version>4.5.0</carbon.multitenancy.version>
<!-- Carbon Registry -->
<carbon.registry.version>4.4.8</carbon.registry.version>
<!-- Carbon Governance --> <!-- Carbon Governance -->
<carbon.governance.version>4.5.8</carbon.governance.version> <carbon.governance.version>4.5.8</carbon.governance.version>

Loading…
Cancel
Save