Merge pull request #543 from ayyoob/release-2.0.x

Moved the traffic through the gateway and fixed cluster issues
4.x.x
Rasika Perera 8 years ago committed by GitHub
commit 625124da38

@ -173,6 +173,11 @@
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

@ -56,6 +56,9 @@ public class ApiPermissionFilter implements Filter {
PermissionConfiguration permissionConfiguration = (PermissionConfiguration)
unmarshaller.unmarshal(permissionStream);
permissions = permissionConfiguration.getPermissions();
for (Permission permission : permissions) {
APIUtil.putPermission(PERMISSION_PREFIX + permission.getPath());
}
} catch (JAXBException e) {
log.error("invalid permissions.xml", e);
}

@ -21,12 +21,18 @@ package org.wso2.carbon.apimgt.application.extension.api.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.core.service.RealmService;
import java.util.List;
import java.util.StringTokenizer;
/**
* This class provides utility functions used by REST-API.
@ -35,6 +41,8 @@ public class APIUtil {
private static Log log = LogFactory.getLog(APIUtil.class);
private static final String DEFAULT_CDMF_API_TAG = "device_management";
private static final String DEFAULT_CERT_API_TAG = "scep_management";
public static final String PERMISSION_PROPERTY_NAME = "name";
public static String getAuthenticatedUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
@ -48,8 +56,7 @@ public class APIUtil {
public static String getTenantDomainOftheUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String tenantDomain = threadLocalCarbonContext.getTenantDomain();
return tenantDomain;
return threadLocalCarbonContext.getTenantDomain();
}
public static APIManagementProviderService getAPIManagementProviderService() {
@ -92,6 +99,55 @@ public class APIUtil {
//Todo get allowed cdmf service tags from config.
List<String> allowedApisTags = getDeviceManagementProviderService().getAvailableDeviceTypes();
allowedApisTags.add(DEFAULT_CDMF_API_TAG);
allowedApisTags.add(DEFAULT_CERT_API_TAG);
return allowedApisTags;
}
public static void putPermission(String permission) {
try {
StringTokenizer tokenizer = new StringTokenizer(permission, "/");
String lastToken = "", currentToken, tempPath;
while (tokenizer.hasMoreTokens()) {
currentToken = tokenizer.nextToken();
tempPath = lastToken + "/" + currentToken;
if (!checkResourceExists(tempPath)) {
createRegistryCollection(tempPath, currentToken);
}
lastToken = tempPath;
}
} catch (org.wso2.carbon.registry.api.RegistryException e) {
log.error("Failed to creation permission in registry" + permission, e);
}
}
public static void createRegistryCollection(String path, String resourceName)
throws org.wso2.carbon.registry.api.RegistryException {
Resource resource = getGovernanceRegistry().newCollection();
resource.addProperty(PERMISSION_PROPERTY_NAME, resourceName);
getGovernanceRegistry().beginTransaction();
getGovernanceRegistry().put(path, resource);
getGovernanceRegistry().commitTransaction();
}
public static boolean checkResourceExists(String path)
throws RegistryException {
return getGovernanceRegistry().resourceExists(path);
}
public static Registry getGovernanceRegistry() throws RegistryException {
return getRegistryService().getGovernanceSystemRegistry(MultitenantConstants.SUPER_TENANT_ID);
}
public static RegistryService getRegistryService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RegistryService registryService =
(RegistryService) ctx.getOSGiService(RegistryService.class, null);
if (registryService == null) {
String msg = "registry service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return registryService;
}
}

@ -37,14 +37,14 @@
</Permission>
<Permission>
<name>Register application</name>
<path>/device-mgt/user/api/application</path>
<path>/device-mgt/api/application</path>
<url>/register</url>
<method>POST</method>
<scope>application_user</scope>
</Permission>
<Permission>
<name>Delete application</name>
<path>/device-mgt/user/api/application</path>
<path>/device-mgt/api/application</path>
<url>/unregister</url>
<method>DELETE</method>
<scope>application_user</scope>

@ -35,10 +35,6 @@
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>

@ -74,6 +74,7 @@ public class AnnotationProcessor {
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_VALUE = "value";
private static final String ANNOTATIONS_SCOPES = "scopes";
private static final String ANNOTATIONS_SCOPE = "scope";
private static final String DEFAULT_SCOPE_NAME = "default admin scope";
private static final String DEFAULT_SCOPE_KEY = "perm:admin";
private static final String DEFAULT_SCOPE_PERMISSION = "/permision/device-mgt";
@ -283,6 +284,8 @@ public class AnnotationProcessor {
log.warn("Scope is not defined for '" + makeContextURLReady(resourceRootContext) +
makeContextURLReady(subCtx) + "' endpoint, hence assigning the default scope");
scope = new Scope();
scope.setName(DEFAULT_SCOPE_NAME);
scope.setDescription(DEFAULT_SCOPE_NAME);
scope.setKey(DEFAULT_SCOPE_KEY);
scope.setRoles(DEFAULT_SCOPE_PERMISSION);
resource.setScope(scope);

@ -33,11 +33,6 @@
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>

@ -66,10 +66,10 @@ import javax.ws.rs.core.Response;
permissions = {"/device-mgt/admin/certificates/delete"}
),
@Scope(
name = "Verifying an SSL Certificate",
description = "Verifying an SSL Certificate",
name = "Verify SSL certificate",
description = "Verify SSL certificate",
key = "perm:admin:certificates:verify",
permissions = {"/device-mgt/admin/certificates/details"}
permissions = {"/device-mgt/admin/certificates/verify"}
)
}
)

@ -38,11 +38,6 @@
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>

@ -29,7 +29,6 @@ import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ResponseHeader;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.common.Device;

@ -22,9 +22,17 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.jaxrs.beans.AuthorizationRequest;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
@ -37,6 +45,32 @@ import javax.ws.rs.core.Response;
@Api(value = "Device Authorization Administrative Service", description = "This an API intended to be used by " +
"'internal' components to log in as an admin user and validate whether the user/device are trusted entity." +
"Further, this is strictly restricted to admin users only ")
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "DeviceAccessAuthorizationAdminService"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/admin/authorization"),
})
}
),
tags = {
@Tag(name = "device_management", description = "")
}
)
@Scopes(
scopes = {
@Scope(
name = "Verify device authorization",
description = "Verify device authorization",
key = "perm:authorization:verify",
permissions = {"/device-mgt/authorization/verify"}
)
}
)
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
/**
@ -52,7 +86,13 @@ public interface DeviceAccessAuthorizationAdminService {
value = "Check for device access authorization\n",
notes = "This is an internal API that can be used to check for authorization.",
response = DeviceAuthorizationResult.class,
tags = "Authorization Administrative Service")
tags = "Authorization Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:authorization:verify")
})
})
@ApiResponses(value = {
@ApiResponse(
code = 200,

@ -40,30 +40,10 @@
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<!--context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>managed-api-version</param-name>
<param-value>1.0.0</param-value>
</context-param>
<context-param>
<param-name>managed-api-isSecured</param-name>
<param-value>true</param-value>
</context-param-->
<!--publish to apim-->
<context-param>

@ -71,7 +71,8 @@ public class AnnotationProcessor {
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_PERMISSIONS = "permissions";
private static final String ANNOTATIONS_SCOPES = "scopes";
private static final String ANNOTATIONS_SCOPE = "scope";
private static final String DEFAULT_PERM_NAME = "default";
private static final String DEFAULT_PERM = "/device-mgt";
private static final String PERMISSION_PREFIX = "/permission/admin";
private StandardContext context;
@ -252,9 +253,14 @@ public class AnnotationProcessor {
this.setPermission(annotations[i], permission);
}
}
if (permission.getName() == null || permission.getPath() == null) {
log.warn("Permission not assigned to the resource url - " + permission.getMethod() + ":"
+ permission.getUrl());
} else {
permissions.add(permission);
}
}
}
return permissions;
}
@ -392,9 +398,15 @@ public class AnnotationProcessor {
.getMethod(SWAGGER_ANNOTATIONS_PROPERTIES_VALUE, null), null);
if (!scopeKey.isEmpty()) {
scope = apiScopes.get(scopeKey);
if (scope != null) {
permission.setName(scope.getName());
//TODO: currently permission tree supports only adding one permission per API point.
permission.setPath(scope.getRoles().split(" ")[0]);
} else {
log.warn("No Scope mapping is done for scope key: " + scopeKey);
permission.setName(DEFAULT_PERM_NAME);
permission.setPath(DEFAULT_PERM);
}
}
}
}

@ -1,7 +1,7 @@
{
"appContext": "/devicemgt/",
"httpsURL" : "https://localhost:8243",
"httpURL" : "http://localhost:8280",
"httpsURL" : "https://%server.ip%:8243",
"httpURL" : "http://%server.ip%:8280",
"wssURL" : "https://localhost:9445",
"wsURL" : "%http.ip%",
"portalURL": "https://%server.ip%:9445",

@ -59,7 +59,7 @@
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>IoT Server Impl Bundle</Bundle-Description>
<Private-Package>org.wso2.carbon.device.mgt.iot.url.printer.internal</Private-Package>
<Private-Package>org.wso2.carbon.device.mgt.url.printer.internal</Private-Package>
<Import-Package>
org.osgi.framework,
org.osgi.service.component,
@ -69,8 +69,8 @@
org.wso2.carbon.utils.*,
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.url.printer.internal,
org.wso2.carbon.device.mgt.iot.url.printer.*;version="${project.version}"
!org.wso2.carbon.device.mgt.url.printer.internal,
org.wso2.carbon.device.mgt.url.printer.*;version="${project.version}"
</Export-Package>
</instructions>
</configuration>

@ -35,6 +35,8 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
@ -86,4 +88,18 @@ public class Utils {
}
}
public static String replaceSystemProperty(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;
}
}

@ -41,7 +41,7 @@ public class WebappAuthenticationValve extends CarbonTomcatValve {
@Override
public void invoke(Request request, Response response, CompositeValve compositeValve) {
if (this.isContextSkipped(request) || (!this.isAdminService(request) && this.skipAuthentication(request))) {
if (this.isContextSkipped(request) || this.skipAuthentication(request)) {
this.getNext().invoke(request, response, compositeValve);
return;
}
@ -74,11 +74,6 @@ public class WebappAuthenticationValve extends CarbonTomcatValve {
}
}
private boolean isAdminService(Request request) {
String param = request.getContext().findParameter("isAdminService");
return (param != null && Boolean.parseBoolean(param));
}
private boolean skipAuthentication(Request request) {
String param = request.getContext().findParameter("doAuthentication");
return (param == null || !Boolean.parseBoolean(param) || isNonSecuredEndPoint(request));

@ -66,7 +66,7 @@ public class BSTAuthenticator implements WebappAuthenticator {
"are not provided");
}
String url = this.properties.getProperty("TokenValidationEndpointUrl");
String url = Utils.replaceSystemProperty(this.properties.getProperty("TokenValidationEndpointUrl"));
if ((url == null) || (url.isEmpty())) {
throw new IllegalArgumentException("OAuth token validation endpoint url is not provided");
}

@ -62,7 +62,7 @@ public class JWTAuthenticator implements WebappAuthenticator {
private static final String DEFAULT_TRUST_STORE_LOCATION = "Security.TrustStore.Location";
private static final String DEFAULT_TRUST_STORE_PASSWORD = "Security.TrustStore.Password";
private static final Map<String, PublicKey> publicKeyHolder = new HashMap<>();
private static final Map<IssuerAlias, PublicKey> publicKeyHolder = new HashMap<>();
private Properties properties;
private static void loadTenantRegistry(int tenantId) throws RegistryException {
@ -106,21 +106,17 @@ public class JWTAuthenticator implements WebappAuthenticator {
String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
String tenantDomain = MultitenantUtils.getTenantDomain(username);
int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID));
String issuer = jwsObject.getJWTClaimsSet().getIssuer();
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
PublicKey publicKey = publicKeyHolder.get(tenantDomain);
IssuerAlias issuerAlias = new IssuerAlias(issuer, tenantDomain);
PublicKey publicKey = publicKeyHolder.get(issuerAlias);
if (publicKey == null) {
loadTenantRegistry(tenantId);
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId);
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
String defaultPublicKey = properties.getProperty("DefaultPublicKey");
if (defaultPublicKey != null && !defaultPublicKey.isEmpty()) {
boolean isDefaultPublicKey = Boolean.parseBoolean(defaultPublicKey);
if (isDefaultPublicKey) {
publicKey = keyStoreManager.getDefaultPublicKey();
} else {
String alias = properties.getProperty("KeyAlias");
String alias = properties.getProperty(issuer);
if (alias != null && !alias.isEmpty()) {
ServerConfiguration serverConfig = CarbonUtils.getServerConfiguration();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
@ -133,19 +129,14 @@ public class JWTAuthenticator implements WebappAuthenticator {
authenticationInfo.setStatus(Status.FAILURE);
return authenticationInfo;
}
}
} else {
publicKey = keyStoreManager.getDefaultPublicKey();
}
} else {
String ksName = tenantDomain.trim().replace('.', '-');
String jksName = ksName + ".jks";
publicKey = keyStoreManager.getKeyStore(jksName).getCertificate(tenantDomain).getPublicKey();
}
if (publicKey != null) {
publicKeyHolder.put(tenantDomain, publicKey);
issuerAlias = new IssuerAlias(tenantDomain);
publicKeyHolder.put(issuerAlias, publicKey);
}
}
@ -205,4 +196,34 @@ public class JWTAuthenticator implements WebappAuthenticator {
}
return this.properties.getProperty(name);
}
private class IssuerAlias {
private String issuer;
private String tenantDomain;
private final String DEFAULT_ISSUER = "default";
public IssuerAlias(String tenantDomain) {
this.issuer = DEFAULT_ISSUER;
this.tenantDomain = tenantDomain;
}
public IssuerAlias(String issuer, String tenantDomain) {
this.issuer = issuer;
this.tenantDomain = tenantDomain;
}
@Override
public int hashCode() {
int result = this.issuer.hashCode();
result = 31 * result + ("@" + this.tenantDomain).hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof IssuerAlias) && issuer.equals(
((IssuerAlias) obj).issuer) && tenantDomain == ((IssuerAlias) obj).tenantDomain;
}
}
}

@ -55,7 +55,7 @@ public class OAuthAuthenticator implements WebappAuthenticator {
"are not provided");
}
String url = this.properties.getProperty("TokenValidationEndpointUrl");
String url = Utils.replaceSystemProperty(this.properties.getProperty("TokenValidationEndpointUrl"));
if ((url == null) || (url.isEmpty())) {
throw new IllegalArgumentException("OAuth token validation endpoint url is not provided");
}

@ -24,7 +24,7 @@
<WebappPublisherConfigs>
<!-- This host is used to define the host address which is used to publish APIs -->
<Host>https://localhost:${carbon.https.port}</Host>
<Host>https://${iot.core.host}:${iot.core.https.port}</Host>
<!-- If it is true, the APIs of this instance will be published to the defined host -->
<PublishAPI>true</PublishAPI>

@ -122,6 +122,9 @@
<bundleDef>
org.wso2.carbon.devicemgt:org.wso2.carbon.device.mgt.common:${carbon.device.mgt.version}
</bundleDef>
<bundleDef>
org.wso2.carbon.devicemgt:org.wso2.carbon.device.mgt.url.printer:${carbon.device.mgt.version}
</bundleDef>
<!--<bundleDef>-->
<!--org.wso2.carbon.commons:org.wso2.carbon.email.verification-->
<!--</bundleDef>-->

@ -17,13 +17,13 @@
#
#issuer of the JWT
iss=iot_default
iss=wso2.org/products/iot
TokenEndpoint=https://localhost:${carbon.https.port}/oauth2/token
TokenEndpoint=https://${iot.keymanager.host}:${iot.keymanager.https.port}/oauth2/token
#audience of JWT claim
#comma seperated values
aud=wso2.org/products/iot
aud=devicemgt
#expiration time of JWT (number of minutes from the current time)
exp=1000

@ -5,7 +5,7 @@
<ClassName>org.wso2.carbon.webapp.authenticator.framework.authenticator.OAuthAuthenticator</ClassName>
<Parameters>
<Parameter Name="IsRemote">false</Parameter>
<Parameter Name="TokenValidationEndpointUrl">https://localhost:9443</Parameter>
<Parameter Name="TokenValidationEndpointUrl">https://${iot.keymanager.host}:${iot.keymanager.https.port}</Parameter>
<Parameter Name="Username">admin</Parameter>
<Parameter Name="Password">admin</Parameter>
<Parameter Name="MaxTotalConnections">100</Parameter>
@ -20,9 +20,10 @@
<Name>JWT</Name>
<ClassName>org.wso2.carbon.webapp.authenticator.framework.authenticator.JWTAuthenticator</ClassName>
<Parameters>
<Parameter Name="DefaultPublicKey">true</Parameter>
<!--KeyAlias is alias of the certificate that is used to sign the JWT token-->
<!-- <Parameter Name="KeyAlias"></Parameter> -->
<!--Issuers list and corresponding cert alias-->
<Parameter Name="wso2.org/products/am">wso2carbon</Parameter>
<Parameter Name="wso2.org/products/iot">wso2carbon</Parameter>
<Parameter Name="wso2.org/products/analytics">wso2carbon</Parameter>
</Parameters>
</Authenticator>
<Authenticator>
@ -34,7 +35,7 @@
<ClassName>org.wso2.carbon.webapp.authenticator.framework.authenticator.BSTAuthenticator</ClassName>
<Parameters>
<Parameter Name="IsRemote">false</Parameter>
<Parameter Name="TokenValidationEndpointUrl">https://localhost:9443</Parameter>
<Parameter Name="TokenValidationEndpointUrl">https://${iot.keymanager.host}:${iot.keymanager.https.port}</Parameter>
<Parameter Name="Username">admin</Parameter>
<Parameter Name="Password">admin</Parameter>
<Parameter Name="MaxTotalConnections">100</Parameter>

Loading…
Cancel
Save