diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java index 538834b..1aad5e3 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java @@ -54,8 +54,7 @@ public class ServicePublisher extends AbstractProfilePublisher { @Override protected Set getAllowedContexts() { - // TODO Auto-generated method stub - return null; + return context.container().configuration().authorizationProvider().getContexts(); } } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 74f6f03..3fad47f 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -8,8 +8,7 @@ import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.context.application.ApplicationContext; @@ -21,8 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Timer; -import io.micrometer.core.instrument.Timer.Sample; @XmlRootElement(name = Constants.request_accounting) public class RequestAccounting extends RequestHandler { @@ -40,8 +37,11 @@ public class RequestAccounting extends RequestHandler { @Override public void handleRequest(RequestEvent e) { - ApplicationContext context = e.context(); + ApplicationContext appContext = e.context(); + + String context = getContext(appContext); + String calledMethod = e.request().getHeader(Constants.called_method_header); if (calledMethod==null){ calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); @@ -54,22 +54,18 @@ public class RequestAccounting extends RequestHandler { startCallThreadLocal.set(System.currentTimeMillis()); log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", - context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, e.request().getRemoteHost(), ScopeProvider.instance.get()); + appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), + caller, e.request().getRemoteHost(), context ); } @Override public void handleResponse(ResponseEvent e) { - ApplicationContext context = e.context(); + ApplicationContext appContext = e.context(); try { - boolean resetScope = false; - if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){ - String infrastructure = e.context().container().configuration().infrastructure(); - ScopeProvider.instance.set("/"+infrastructure); - resetScope = true; - } + + String context = getContext(appContext); String caller = "Unknown"; String callerQualifier = "UNKNOWN"; @@ -80,23 +76,22 @@ public class RequestAccounting extends RequestHandler { boolean success = e.response().getStatus()<400; - if (context.container().configuration().mode()!=Mode.offline) - generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context); + if (appContext.container().configuration().mode()!=Mode.offline) + generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context, appContext); long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); Metrics.globalRegistry.timer("http.requests", "response",Integer.toString(e.response().getStatus()) - , "context", ScopeProvider.instance.get(), "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, - "caller-username", caller, "service-class", context.configuration().serviceClass(), "service-name", context.configuration().name(), + , "context", context, "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, + "caller-username", caller, "service-class", appContext.configuration().serviceClass(), "service-name", appContext.configuration().name(), "method", InnerMethodName.instance.get()).record(durationInMillis, TimeUnit.MILLISECONDS); log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", - context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, callerIp, ScopeProvider.instance.get(), success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); + appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), + caller, callerIp, context, success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); startCallThreadLocal.remove(); InnerMethodName.instance.reset(); - if (resetScope) - ScopeProvider.instance.reset(); + }catch (Exception e1) { log.error("error on accounting",e); throw e1; @@ -104,19 +99,19 @@ public class RequestAccounting extends RequestHandler { } - void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){ - AccountingPersistenceFactory.setFallbackLocation(context.container().configuration().accountingFallbackLocation()); + void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, String gcubeContext, ApplicationContext appContext){ + AccountingPersistenceFactory.setFallbackLocation(appContext.container().configuration().accountingFallbackLocation()); AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); try{ serviceUsageRecord.setConsumerId(caller); serviceUsageRecord.setCallerQualifier(callerQualifier); - serviceUsageRecord.setScope(ScopeProvider.instance.get()); - serviceUsageRecord.setServiceClass(context.configuration().serviceClass()); - serviceUsageRecord.setServiceName(context.configuration().name()); + serviceUsageRecord.setScope(gcubeContext); + serviceUsageRecord.setServiceClass(appContext.configuration().serviceClass()); + serviceUsageRecord.setServiceName(appContext.configuration().name()); - serviceUsageRecord.setHost(context.container().configuration().hostname()+":"+context.container().configuration().port()); + serviceUsageRecord.setHost(appContext.container().configuration().hostname()+":"+appContext.container().configuration().port()); serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get()); serviceUsageRecord.setCallerHost(remoteHost); serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); @@ -128,6 +123,14 @@ public class RequestAccounting extends RequestHandler { } } + private String getContext(ApplicationContext appContext) { + String infrastructure = appContext.container().configuration().infrastructure(); + String context= "/"+infrastructure; + if (SecretManagerProvider.instance.get() != null) + context = SecretManagerProvider.instance.get().getContext(); + return context; + } + @Override public String toString() { return getName(); diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index c8a39b3..3766cdd 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -6,14 +6,12 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.app import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.crypto.dsig.keyinfo.RetrievalMethod; -import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; +import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.GCubeSecret; -import org.gcube.common.security.secrets.JWTSecret; import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; @@ -54,7 +52,7 @@ public class RequestValidator extends RequestHandler { if (appContext.container().configuration().mode()!=Mode.offline) { validateScopeCall(); - validatePolicy(ScopeProvider.instance.get(), call); + validatePolicy(call); } } @@ -106,7 +104,7 @@ public class RequestValidator extends RequestHandler { Secret secret = SecretManagerProvider.instance.get(); - if (secret!= null){ + if (secret == null){ log.warn("rejecting call to {}, authorization required",appContext.name()); RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); } @@ -117,7 +115,7 @@ public class RequestValidator extends RequestHandler { return getName(); } - private void validatePolicy(String scope, RequestEvent call){ + private void validatePolicy(RequestEvent call){ //TODO: must be re-think } @@ -135,7 +133,7 @@ public class RequestValidator extends RequestHandler { Secret secret = null; if (accessToken!=null) - secret = new JWTSecret(accessToken); + secret = new AccessTokenSecret(accessToken); else if (token!=null) secret = new GCubeSecret(token); return secret; diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java index 4315a6b..701ff8d 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java @@ -71,6 +71,8 @@ public class ProfileBuilder { node.profile().description().newArchitecture().platformType(System.getProperty("os.arch")).smpSize(0) .smtSize(0); + node.profile().newSite().domain("It").country("It").location("Rome").latitude("1").longitude("1"); + ArrayList> info = cpuInfo(); Group processors = node.profile().description().processors(); diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index 08cb7b4..2393a5f 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -2,7 +2,11 @@ package org.gcube.smartgears.security; import java.util.Set; +import org.gcube.common.security.secrets.Secret; + public interface AuthorizationProvider { Set getContexts(); + + Secret getSecretForContext(String context); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index d030836..ef8e935 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -12,6 +12,8 @@ import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.security.secrets.AccessTokenSecret; +import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; @@ -46,6 +48,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { try { ScopeBean scope = new ScopeBean(context.replaceAll("%2F", "/")); contexts.add(scope.toString()); + LOG.info("found context {}",context); }catch (IllegalArgumentException e) { LOG.warn("invalid context found in token: {}", context); } @@ -57,4 +60,23 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { return contexts; } + + @Override + public Secret getSecretForContext(String context) { + try { + TokenResponse response; + if (this.endpoint == null) + response = client.queryUMAToken(credentials.getClientID(), credentials.getSecret(), context, null); + else + response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); + + return new AccessTokenSecret(response.getAccessToken()); + + } catch (Exception e) { + LOG.error("error getting OIDToken from keycloak",e); + throw new RuntimeException("error getting access token for context "+context, e); + } + + } + } diff --git a/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java b/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java deleted file mode 100644 index 632b74d..0000000 --- a/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.gcube.smartgears.utils; - -import java.io.IOException; - -import javax.servlet.ServletException; - -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; -import org.gcube.accounting.datamodel.UsageRecord.OperationResult; -import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; -import org.gcube.accounting.persistence.AccountingPersistence; -import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.scope.api.ScopeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class GcubeAccountingValve extends ValveBase { - - private static Logger log = LoggerFactory.getLogger(GcubeAccountingValve.class); - - private String infra; - private String serviceClass; - private String serviceName; - private String hostAndPort; - - public void setInfra(String infra) { - this.infra = infra; - } - - public void setServiceClass(String serviceClass) { - this.serviceClass = serviceClass; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public void setHostAndPort(String hostAndPort) { - this.hostAndPort = hostAndPort; - } - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - String callerIp = request.getHeader("x-forwarded-for"); - if (callerIp == null) { - callerIp = request.getRemoteAddr(); - } - - boolean success = response.getStatus()<400; - ScopeProvider.instance.set(infra); - AccountingPersistenceFactory.setFallbackLocation("/tmp"); - AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); - ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); - try{ - - serviceUsageRecord.setConsumerId("UNKNOWN"); - serviceUsageRecord.setCallerQualifier("UNKNOWN"); - serviceUsageRecord.setScope(infra); - serviceUsageRecord.setServiceClass(serviceClass); - serviceUsageRecord.setServiceName(serviceName); - serviceUsageRecord.setDuration(200l); - serviceUsageRecord.setHost(hostAndPort); - serviceUsageRecord.setCalledMethod(request.getRequestURI()); - serviceUsageRecord.setCallerHost(callerIp); - serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); - persistence.account(serviceUsageRecord); - log.info("Request: {} {} {} {} ", infra, request.getContextPath(), request.getRequestURI(), success); - }catch(Exception ex){ - log.warn("invalid record passed to accounting ",ex); - }finally { - ScopeProvider.instance.reset(); - } - - }catch (Exception e) { - log.error("error executing valve", e); - } - getNext().invoke(request, response); - } - - - - -}