This commit is contained in:
Lucio Lelii 2022-03-29 15:05:28 +02:00
parent 08b3cd590a
commit 454533abcd
13 changed files with 99 additions and 97 deletions

View File

@ -13,6 +13,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Added SecretManagerProvider thread local from authorization-utils [#22871] - Added SecretManagerProvider thread local from authorization-utils [#22871]
- Added Linux distribution version [#22933] - Added Linux distribution version [#22933]
## [v3.1.3] - 2022-03-21
- fixed bug on policies
## [v3.1.2] - 2022-01-19 ## [v3.1.2] - 2022-01-19

View File

@ -12,6 +12,7 @@
<groupId>org.gcube.core</groupId> <groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId> <artifactId>common-smartgears</artifactId>
<version>4.0.0-SNAPSHOT</version> <version>4.0.0-SNAPSHOT</version>
<name>SmartGears</name> <name>SmartGears</name>
<dependencyManagement> <dependencyManagement>

View File

@ -176,8 +176,6 @@ public class HttpController extends HttpExtension {
case OPTIONS: case OPTIONS:
resource.doOptions(request, response); resource.doOptions(request, response);
break; break;
case TRACE:
resource.doTrace(request, response);
} }
} }

View File

@ -11,7 +11,7 @@ import javax.xml.bind.annotation.XmlAttribute;
import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotEmpty;
import org.gcube.smartgears.configuration.application.Exclude; import org.gcube.smartgears.configuration.application.Exclude;
import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.ApplicationContext;
import javax.ws.rs.HttpMethod;
/** /**
* An {@link ApplicationExtension} that implements the {@link HttpServlet} interface * An {@link ApplicationExtension} that implements the {@link HttpServlet} interface
* *
@ -27,7 +27,25 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx
* *
*/ */
public static enum Method { public static enum Method {
GET, PUT, POST, HEAD, DELETE, OPTIONS, TRACE GET(HttpMethod.GET),
PUT(HttpMethod.PUT),
POST(HttpMethod.POST),
HEAD(HttpMethod.HEAD),
DELETE(HttpMethod.DELETE),
OPTIONS(HttpMethod.OPTIONS);
private String value;
private Method(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
} }
@XmlAttribute @NotEmpty @XmlAttribute @NotEmpty

View File

@ -99,4 +99,4 @@ public class RequestContextRetriever extends RequestHandler {
SecretManagerProvider.instance.reset(); SecretManagerProvider.instance.reset();
} }
} }

View File

@ -1,21 +1,12 @@
package org.gcube.smartgears.handlers.application.request; package org.gcube.smartgears.handlers.application.request;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error; import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error; import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.common.authorization.utils.manager.SecretManager;
import org.gcube.common.authorization.library.PolicyUtils;
import org.gcube.common.authorization.library.policies.Policy;
import org.gcube.common.authorization.library.policies.User2ServicePolicy;
import org.gcube.common.authorization.library.policies.UserEntity;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.provider.ServiceIdentifier;
import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean;
@ -26,7 +17,6 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.RequestEvent; import org.gcube.smartgears.handlers.application.RequestEvent;
import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -83,30 +73,30 @@ public class RequestValidator extends RequestHandler {
private void validateScopeCall() { private void validateScopeCall() {
String scope = ScopeProvider.instance.get(); String context = SecretManagerProvider.instance.get().getContext();
if (scope == null) { if (context == null) {
log.warn("rejecting unscoped call to {}",appContext.name()); log.warn("rejecting unscoped call to {}",appContext.name());
invalid_request_error.fire("call is unscoped"); invalid_request_error.fire("call is unscoped");
} }
ScopeBean bean = new ScopeBean(scope); ScopeBean bean = new ScopeBean(context);
ContainerConfiguration conf = appContext.container().configuration(); ContainerConfiguration conf = appContext.container().configuration();
if (!conf.allowedContexts().contains(scope) && if (!conf.allowedContexts().contains(context) &&
!(conf.authorizeChildrenContext() && bean.is(Type.VRE) && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) { !(conf.authorizeChildrenContext() && bean.is(Type.VRE)
log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),scope,appContext.container().configuration().allowedContexts()); && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) {
invalid_request_error.fire(appContext.name()+" cannot be called in scope "+scope); log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),context,appContext.container().configuration().allowedContexts());
invalid_request_error.fire(appContext.name()+" cannot be called in scope "+context);
} }
} }
private void rejectUnauthorizedCalls(RequestEvent call){ private void rejectUnauthorizedCalls(RequestEvent call){
String token = SecurityTokenProvider.instance.get(); SecretManager secretManager = SecretManagerProvider.instance.get();
String context = SecretManagerProvider.instance.get().getContext();
if (secretManager.getCurrentSecretHolder().getSecrets().size()>0){
if (token == null && context==null){ log.warn("rejecting call to {}, authorization required",appContext.name());
log.warn("rejecting call to {}, authorization required",appContext.name(),token);
RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required");
} }
} }
@ -117,40 +107,10 @@ public class RequestValidator extends RequestHandler {
} }
private void validatePolicy(String scope, RequestEvent call){ private void validatePolicy(String scope, RequestEvent call){
log.info("accessing policy validator in scope {} ", scope); //TODO: must be re-think
ServiceIdentifier serviceIdentifier = Utils.getServiceInfo(call.context()).getServiceIdentifier();
String callerId = SecretManagerProvider.instance.get().getUser().getUsername();
List<Policy> policies = null;
try {
policies = authorizationService().getPolicies(scope);
}catch (Exception e) {
invalid_request_error.fire("error contating authorization for polices");
}
for (Policy policy: policies) {
log.debug("policy: {}", policy.getPolicyAsString() );
if (PolicyUtils.isPolicyValidForClient(policy.getServiceAccess(), serviceIdentifier )) {
boolean toReject = false;
UserEntity entity = (((User2ServicePolicy) policy).getEntity());
if (entity.getIdentifier()!=null)
toReject = entity.getIdentifier().equals(callerId);
else if (entity.getExcludes().isEmpty())
toReject = true;
else toReject = !entity.getExcludes().contains(callerId);
if (toReject) {
log.error("rejecting call to {} : {} is not allowed to contact the service ",appContext.name(), callerId);
RequestError.request_not_authorized_error.fire("rejecting call to "+appContext.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() );
}
}
}
} }
} }

View File

@ -1,6 +1,7 @@
package app; package app;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -10,6 +11,7 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.Invocation.Builder;
@ -17,6 +19,7 @@ import javax.ws.rs.client.Invocation.Builder;
import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.smartgears.extensions.HttpExtension.Method;
import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.logging.LoggingFeature; import org.glassfish.jersey.logging.LoggingFeature;
@ -63,12 +66,12 @@ public class Request {
} }
public Request with(String name, String value) { public Request with(String name, String value) {
this.headers.put(name, value); this.headers.put(name, Collections.singletonList(value));
return this; return this;
} }
public Request using(String method) { public Request using(Method method) {
this.method=method; this.method=method.getValue();
return this; return this;
} }
@ -98,7 +101,7 @@ public class Request {
class Box { class Box {
volatile Exception failure; volatile WebApplicationException failure;
volatile ClientResponse response; volatile ClientResponse response;
} }
@ -143,13 +146,13 @@ public class Request {
//throws an exception if there response has error status //throws an exception if there response has error status
if (response.getStatus()>300) if (response.getStatus()>300)
throw new Exception(response.getStatus()); throw new WebApplicationException(response.getStatus());
box.response=response; box.response=response;
} }
} catch (Exception t) { } catch (WebApplicationException t) {
box.failure=t; box.failure=t;
} }
@ -178,7 +181,7 @@ public class Request {
path = (path.isEmpty() || path.startsWith("/"))?path:"/"+path; path = (path.isEmpty() || path.startsWith("/"))?path:"/"+path;
return "http://localhost:" + port+ "/" + context_root+path; return "http://localhost:" + port+ "/" + TestUtils.context_root+path;
} }
} }

View File

@ -27,14 +27,13 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.managers.ContainerManager; import org.gcube.smartgears.managers.ContainerManager;
import org.gcube.smartgears.provider.ProviderFactory; import org.gcube.smartgears.provider.ProviderFactory;
import org.glassfish.jersey.client.ClientResponse;
import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.impl.base.path.BasicPath; import org.jboss.shrinkwrap.impl.base.path.BasicPath;
import com.sun.jersey.api.client.ClientResponse;
import utils.TestProvider; import utils.TestProvider;
import utils.TestUtils; import utils.TestUtils;
@ -308,7 +307,7 @@ public class SomeApp {
*/ */
public String send(Request call) { public String send(Request call) {
return call.make(port()).getEntity(String.class); return (String) call.make(port()).getEntity();
} }
/** /**

View File

@ -14,6 +14,8 @@ import static utils.TestUtils.scope;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.ws.rs.WebApplicationException;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.smartgears.Constants; import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.application.Exclude; import org.gcube.smartgears.configuration.application.Exclude;
@ -24,7 +26,6 @@ import org.junit.Test;
import app.SomeApp; import app.SomeApp;
import com.sun.jersey.api.client.UniformInterfaceException;
public class CallValidationTest { public class CallValidationTest {
@ -52,7 +53,7 @@ public class CallValidationTest {
try { try {
app.send(request()); app.send(request());
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(application_unavailable_error.code(), e.getResponse().getStatus()); assertEquals(application_unavailable_error.code(), e.getResponse().getStatus());
} }
@ -62,7 +63,7 @@ public class CallValidationTest {
try { try {
app.send(request()); app.send(request());
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(application_failed_error.code(), e.getResponse().getStatus()); assertEquals(application_failed_error.code(), e.getResponse().getStatus());
} }
@ -82,7 +83,7 @@ public class CallValidationTest {
app.send(request().inScope(null));; //call in no scope app.send(request().inScope(null));; //call in no scope
fail(); fail();
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(request_not_authorized_error.code(), e.getResponse().getStatus()); assertEquals(request_not_authorized_error.code(), e.getResponse().getStatus());
} }
@ -101,7 +102,7 @@ public class CallValidationTest {
app.send(request().inScope("/bad/scope")); //call in no scope app.send(request().inScope("/bad/scope")); //call in no scope
fail(); fail();
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(invalid_request_error.code(), e.getResponse().getStatus()); assertEquals(invalid_request_error.code(), e.getResponse().getStatus());
} }

View File

@ -1,31 +1,42 @@
package test.application; package test.application;
import static app.Request.*; import static app.Request.request;
import static org.gcube.smartgears.Constants.*; import static org.gcube.smartgears.Constants.accept;
import static org.gcube.smartgears.extensions.ApiResource.*; import static org.gcube.smartgears.Constants.allow;
import static org.gcube.smartgears.extensions.HttpExtension.Method.*; import static org.gcube.smartgears.Constants.content_type;
import static org.gcube.smartgears.handlers.application.request.RequestError.*; import static org.gcube.smartgears.extensions.ApiResource.handles;
import static org.junit.Assert.*; import static org.gcube.smartgears.extensions.ApiResource.method;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import static org.gcube.smartgears.extensions.HttpExtension.Method.POST;
import static org.gcube.smartgears.extensions.HttpExtension.Method.PUT;
import static org.gcube.smartgears.handlers.application.request.RequestError.incoming_contenttype_unsupported_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.method_unsupported_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.outgoing_contenttype_unsupported_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.resource_notfound_error;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.WebApplicationException;
import org.gcube.smartgears.Constants; import org.gcube.smartgears.Constants;
import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature; import org.gcube.smartgears.extensions.ApiSignature;
import org.gcube.smartgears.extensions.HttpController; import org.gcube.smartgears.extensions.HttpController;
import org.gcube.smartgears.extensions.HttpExtension; import org.gcube.smartgears.extensions.HttpExtension;
import org.glassfish.jersey.client.ClientResponse;
import org.junit.Test; import org.junit.Test;
import app.Request; import app.Request;
import app.SomeApp; import app.SomeApp;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
public class ControllerTest { public class ControllerTest {
String name = "name"; String name = "name";
@ -74,7 +85,7 @@ public class ControllerTest {
try { try {
app.send(request); app.send(request);
fail(); fail();
} catch (UniformInterfaceException e) { } catch (WebApplicationException e) {
assertEquals(resource_notfound_error.code(), e.getResponse().getStatus()); assertEquals(resource_notfound_error.code(), e.getResponse().getStatus());
} }
} }
@ -91,7 +102,7 @@ public class ControllerTest {
try { try {
app.send(request); app.send(request);
fail(); fail();
} catch (UniformInterfaceException e) { } catch (WebApplicationException e) {
assertEquals(method_unsupported_error.code(), e.getResponse().getStatus()); assertEquals(method_unsupported_error.code(), e.getResponse().getStatus());
assertNotNull(e.getResponse().getHeaders().toString(),e.getResponse().getHeaders().get(allow)); assertNotNull(e.getResponse().getHeaders().toString(),e.getResponse().getHeaders().get(allow));
} }
@ -109,7 +120,7 @@ public class ControllerTest {
try { try {
app.send(request); app.send(request);
fail(); fail();
} catch (UniformInterfaceException e) { } catch (WebApplicationException e) {
assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus());
} }
@ -127,7 +138,7 @@ public class ControllerTest {
try { try {
app.send(request); app.send(request);
fail(); fail();
} catch (UniformInterfaceException e) { } catch (WebApplicationException e) {
assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus());
} }
} }
@ -189,7 +200,7 @@ public class ControllerTest {
try { try {
app.send(request); app.send(request);
fail(); fail();
} catch (UniformInterfaceException e) { } catch (WebApplicationException e) {
assertEquals(incoming_contenttype_unsupported_error.code(), e.getResponse().getStatus()); assertEquals(incoming_contenttype_unsupported_error.code(), e.getResponse().getStatus());
} }
} }

View File

@ -12,6 +12,7 @@ import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.smartgears.Constants; import org.gcube.smartgears.Constants;
@ -24,8 +25,6 @@ import org.junit.Test;
import app.SomeApp; import app.SomeApp;
import com.sun.jersey.api.client.UniformInterfaceException;
public class ExtensionsTest { public class ExtensionsTest {
String name = "name"; String name = "name";
@ -144,7 +143,7 @@ public class ExtensionsTest {
app.send(request().at(Constants.root_mapping+extension_path)); app.send(request().at(Constants.root_mapping+extension_path));
fail(); fail();
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(error.code(),e.getResponse().getStatus()); assertEquals(error.code(),e.getResponse().getStatus());
} }
@ -177,9 +176,9 @@ public class ExtensionsTest {
app.send(request().at(Constants.root_mapping+extension_path).inScope(null)); app.send(request().at(Constants.root_mapping+extension_path).inScope(null));
fail(); fail();
} }
catch(UniformInterfaceException e) { catch(WebApplicationException e) {
assertEquals(e.getResponse().getEntity(String.class),invalid_request_error.code(),e.getResponse().getStatus()); assertEquals((String)e.getResponse().getEntity(),invalid_request_error.code(),e.getResponse().getStatus());
} }
} }
} }

View File

@ -8,6 +8,7 @@ import org.gcube.smartgears.lifecycle.application.ApplicationState;
import org.gcube.smartgears.lifecycle.container.ContainerState; import org.gcube.smartgears.lifecycle.container.ContainerState;
import org.gcube.smartgears.managers.ContainerManager; import org.gcube.smartgears.managers.ContainerManager;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -15,7 +16,14 @@ import app.SomeApp;
public class ContainerLifecycleTest { public class ContainerLifecycleTest {
SomeApp app = new SomeApp();
SomeApp app;
@Before
public void init() {
app = new SomeApp();
}
@After @After
public void teardown() { public void teardown() {

View File

@ -18,7 +18,7 @@ import org.gcube.smartgears.handlers.application.ApplicationHandler;
public class TestUtils { public class TestUtils {
public static String location = "target/ghn-home"; public static String location = "/tmp/ghn-home";
public static String context_root = "test-app"; public static String context_root = "test-app";
public static String context_root_path = "/" + context_root; public static String context_root_path = "/" + context_root;
public static String servlet_name = "test"; public static String servlet_name = "test";