2016-11-25 15:42:29 +01:00
package org.gcube.smartgears.handlers.application.request ;
2022-05-23 17:15:46 +02:00
import static org.gcube.smartgears.Constants.token_header ;
2016-11-25 15:42:29 +01:00
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.invalid_request_error ;
import javax.xml.bind.annotation.XmlRootElement ;
2022-05-23 17:15:46 +02:00
import javax.xml.crypto.dsig.keyinfo.RetrievalMethod ;
2016-11-25 15:42:29 +01:00
import org.gcube.common.scope.api.ScopeProvider ;
2017-03-21 14:42:21 +01:00
import org.gcube.common.scope.impl.ScopeBean ;
import org.gcube.common.scope.impl.ScopeBean.Type ;
2022-05-23 17:15:46 +02:00
import org.gcube.common.security.providers.SecretManagerProvider ;
import org.gcube.common.security.secrets.GCubeSecret ;
import org.gcube.common.security.secrets.JWTSecret ;
import org.gcube.common.security.secrets.Secret ;
2016-11-25 15:42:29 +01:00
import org.gcube.smartgears.Constants ;
2022-02-07 09:44:31 +01:00
import org.gcube.smartgears.configuration.Mode ;
2017-03-21 14:42:21 +01:00
import org.gcube.smartgears.configuration.container.ContainerConfiguration ;
2016-11-25 15:42:29 +01:00
import org.gcube.smartgears.context.application.ApplicationContext ;
import org.gcube.smartgears.handlers.application.RequestEvent ;
import org.gcube.smartgears.handlers.application.RequestHandler ;
2022-05-23 17:15:46 +02:00
import org.gcube.smartgears.handlers.application.ResponseEvent ;
2016-11-25 15:42:29 +01:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@XmlRootElement ( name = Constants . request_validation )
public class RequestValidator extends RequestHandler {
private static Logger log = LoggerFactory . getLogger ( RequestValidator . class ) ;
2022-05-23 17:15:46 +02:00
private static final String BEARER_AUTH_PREFIX = " Bearer " ;
2022-03-17 17:17:15 +01:00
private ApplicationContext appContext ;
2016-11-25 15:42:29 +01:00
@Override
public String getName ( ) {
return Constants . request_validation ;
}
2022-02-07 09:44:31 +01:00
2016-11-25 15:42:29 +01:00
@Override
public void handleRequest ( RequestEvent call ) {
log . trace ( " executing request validator ON REQUEST " ) ;
2022-03-17 17:17:15 +01:00
appContext = call . context ( ) ;
2022-05-23 17:15:46 +02:00
SecretManagerProvider . instance . set ( getSecret ( call ) ) ;
2016-11-25 15:42:29 +01:00
validateAgainstLifecycle ( call ) ;
2022-02-07 09:44:31 +01:00
2017-07-28 12:09:32 +02:00
rejectUnauthorizedCalls ( call ) ;
2022-02-07 09:44:31 +01:00
2022-03-17 17:17:15 +01:00
if ( appContext . container ( ) . configuration ( ) . mode ( ) ! = Mode . offline ) {
2022-02-07 09:44:31 +01:00
validateScopeCall ( ) ;
validatePolicy ( ScopeProvider . instance . get ( ) , call ) ;
}
2016-11-25 15:42:29 +01:00
}
2022-02-07 09:44:31 +01:00
2022-05-23 17:15:46 +02:00
@Override
public void handleResponse ( ResponseEvent e ) {
log . debug ( " resetting all the Thread local for this call. " ) ;
SecretManagerProvider . instance . reset ( ) ;
}
2016-11-25 15:42:29 +01:00
private void validateAgainstLifecycle ( RequestEvent call ) {
2022-03-17 17:17:15 +01:00
switch ( appContext . lifecycle ( ) . state ( ) ) {
2016-11-25 15:42:29 +01:00
case stopped :
application_unavailable_error . fire ( ) ; break ;
case failed :
application_failed_error . fire ( ) ; break ;
default :
//nothing to do, but avoids warnings
}
}
2017-07-28 12:09:32 +02:00
private void validateScopeCall ( ) {
2022-02-07 09:44:31 +01:00
2022-03-29 15:05:28 +02:00
String context = SecretManagerProvider . instance . get ( ) . getContext ( ) ;
2022-02-07 09:44:31 +01:00
2022-03-29 15:05:28 +02:00
if ( context = = null ) {
2022-03-17 17:17:15 +01:00
log . warn ( " rejecting unscoped call to {} " , appContext . name ( ) ) ;
2016-11-25 15:42:29 +01:00
invalid_request_error . fire ( " call is unscoped " ) ;
}
2022-02-07 09:44:31 +01:00
2022-03-29 15:05:28 +02:00
ScopeBean bean = new ScopeBean ( context ) ;
2022-02-07 09:44:31 +01:00
2022-03-17 17:17:15 +01:00
ContainerConfiguration conf = appContext . container ( ) . configuration ( ) ;
2022-03-29 15:05:28 +02:00
if ( ! conf . allowedContexts ( ) . contains ( context ) & &
! ( conf . authorizeChildrenContext ( ) & & bean . is ( Type . VRE )
& & conf . allowedContexts ( ) . contains ( bean . enclosingScope ( ) . toString ( ) ) ) ) {
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 ) ;
2016-11-25 15:42:29 +01:00
}
}
2017-07-28 12:09:32 +02:00
private void rejectUnauthorizedCalls ( RequestEvent call ) {
2022-05-23 17:15:46 +02:00
Secret secret = SecretManagerProvider . instance . get ( ) ;
if ( secret ! = null ) {
2022-03-29 15:05:28 +02:00
log . warn ( " rejecting call to {}, authorization required " , appContext . name ( ) ) ;
2022-03-17 17:17:15 +01:00
RequestError . request_not_authorized_error . fire ( appContext . name ( ) + " : authorization required " ) ;
2016-11-25 15:42:29 +01:00
}
}
@Override
public String toString ( ) {
2016-11-30 17:27:21 +01:00
return getName ( ) ;
2016-11-25 15:42:29 +01:00
}
2022-02-07 09:44:31 +01:00
private void validatePolicy ( String scope , RequestEvent call ) {
2022-03-29 15:05:28 +02:00
//TODO: must be re-think
2022-02-07 09:44:31 +01:00
}
2016-11-25 15:42:29 +01:00
2022-05-23 17:15:46 +02:00
private Secret getSecret ( RequestEvent call ) {
String token = call . request ( ) . getParameter ( token_header ) = = null ? call . request ( ) . getHeader ( token_header ) : call . request ( ) . getParameter ( token_header ) ;
String authHeader = call . request ( ) . getHeader ( Constants . authorization_header ) ;
log . trace ( " authorization header is {} " , authHeader ) ;
log . trace ( " token header is {} " , token ) ;
String accessToken = null ;
if ( authHeader ! = null & & ! authHeader . isEmpty ( ) )
if ( authHeader . startsWith ( BEARER_AUTH_PREFIX ) )
accessToken = authHeader . substring ( BEARER_AUTH_PREFIX . length ( ) ) . trim ( ) ;
Secret secret = null ;
if ( accessToken ! = null )
secret = new JWTSecret ( accessToken ) ;
else if ( token ! = null )
secret = new GCubeSecret ( token ) ;
return secret ;
}
2016-11-25 15:42:29 +01:00
2022-03-29 15:05:28 +02:00
2016-11-25 15:42:29 +01:00
}