Search in sources :

Example 11 with SecurityLevel

use of io.helidon.security.SecurityLevel in project helidon by oracle.

the class ScopeValidatorTest method testScopesOrPermit.

@Test
public void testScopesOrPermit() {
    ScopeValidator validator = ScopeValidator.builder().useOrOperator(true).build();
    ScopeValidator.Scope annot = mock(ScopeValidator.Scope.class);
    when(annot.value()).thenReturn("calendar_get");
    ScopeValidator.Scope annotTwo = mock(ScopeValidator.Scope.class);
    when(annotTwo.value()).thenReturn("calendar_update");
    ScopeValidator.Scopes scopes = mock(ScopeValidator.Scopes.class);
    when(scopes.value()).thenReturn(new ScopeValidator.Scope[] { annot, annotTwo });
    SecurityLevel appSecurityLevel = mock(SecurityLevel.class);
    SecurityLevel classSecurityLevel = mock(SecurityLevel.class);
    List<SecurityLevel> securityLevels = new ArrayList<>();
    securityLevels.add(appSecurityLevel);
    securityLevels.add(classSecurityLevel);
    EndpointConfig ep = mock(EndpointConfig.class);
    when(ep.securityLevels()).thenReturn(securityLevels);
    when(classSecurityLevel.filterAnnotations(ScopeValidator.Scopes.class, EndpointConfig.AnnotationScope.METHOD)).thenReturn(List.of(scopes));
    ScopeValidator.ScopesConfig sConfig = validator.fromAnnotations(ep);
    Errors.Collector collector = Errors.collector();
    ProviderRequest request = mock(ProviderRequest.class);
    when(request.subject()).thenReturn(Optional.of(Subject.builder().principal(Principal.create("myAdmin")).addGrant(Grant.builder().type("scope").name("calendar_get").build()).build()));
    when(request.service()).thenReturn(Optional.empty());
    validator.validate(sConfig, collector, request);
    collector.collect().checkValid();
}
Also used : Errors(io.helidon.common.Errors) SecurityLevel(io.helidon.security.SecurityLevel) ArrayList(java.util.ArrayList) EndpointConfig(io.helidon.security.EndpointConfig) ProviderRequest(io.helidon.security.ProviderRequest) Test(org.junit.jupiter.api.Test)

Example 12 with SecurityLevel

use of io.helidon.security.SecurityLevel in project helidon by oracle.

the class ScopeValidatorTest method testScopesAndPermit.

@Test
public void testScopesAndPermit() {
    ScopeValidator validator = ScopeValidator.create();
    ScopeValidator.Scope annot = mock(ScopeValidator.Scope.class);
    when(annot.value()).thenReturn("calendar_get");
    ScopeValidator.Scope annotTwo = mock(ScopeValidator.Scope.class);
    when(annotTwo.value()).thenReturn("calendar_update");
    ScopeValidator.Scopes scopes = mock(ScopeValidator.Scopes.class);
    when(scopes.value()).thenReturn(new ScopeValidator.Scope[] { annot, annotTwo });
    SecurityLevel appSecurityLevel = mock(SecurityLevel.class);
    SecurityLevel classSecurityLevel = mock(SecurityLevel.class);
    List<SecurityLevel> securityLevels = new ArrayList<>();
    securityLevels.add(appSecurityLevel);
    securityLevels.add(classSecurityLevel);
    EndpointConfig ep = mock(EndpointConfig.class);
    when(ep.securityLevels()).thenReturn(securityLevels);
    when(classSecurityLevel.filterAnnotations(ScopeValidator.Scopes.class, EndpointConfig.AnnotationScope.METHOD)).thenReturn(List.of(scopes));
    ScopeValidator.ScopesConfig sConfig = validator.fromAnnotations(ep);
    Errors.Collector collector = Errors.collector();
    ProviderRequest request = mock(ProviderRequest.class);
    when(request.subject()).thenReturn(Optional.of(Subject.builder().principal(Principal.create("myAdmin")).addGrant(Grant.builder().type("scope").name("calendar_get").build()).addGrant(Grant.builder().type("scope").name("calendar_update").build()).build()));
    when(request.service()).thenReturn(Optional.empty());
    validator.validate(sConfig, collector, request);
    collector.collect().checkValid();
}
Also used : Errors(io.helidon.common.Errors) SecurityLevel(io.helidon.security.SecurityLevel) ArrayList(java.util.ArrayList) EndpointConfig(io.helidon.security.EndpointConfig) ProviderRequest(io.helidon.security.ProviderRequest) Test(org.junit.jupiter.api.Test)

Example 13 with SecurityLevel

use of io.helidon.security.SecurityLevel in project helidon by oracle.

the class ScopeValidatorTest method testScopesOrDeny.

@Test
public void testScopesOrDeny() {
    ScopeValidator validator = ScopeValidator.builder().useOrOperator(true).build();
    ScopeValidator.Scope annot = mock(ScopeValidator.Scope.class);
    when(annot.value()).thenReturn("calendar_get");
    ScopeValidator.Scope annotTwo = mock(ScopeValidator.Scope.class);
    when(annotTwo.value()).thenReturn("calendar_update");
    ScopeValidator.Scopes scopes = mock(ScopeValidator.Scopes.class);
    when(scopes.value()).thenReturn(new ScopeValidator.Scope[] { annot, annotTwo });
    SecurityLevel appSecurityLevel = mock(SecurityLevel.class);
    SecurityLevel classSecurityLevel = mock(SecurityLevel.class);
    List<SecurityLevel> securityLevels = new ArrayList<>();
    securityLevels.add(appSecurityLevel);
    securityLevels.add(classSecurityLevel);
    EndpointConfig ep = mock(EndpointConfig.class);
    when(ep.securityLevels()).thenReturn(securityLevels);
    when(classSecurityLevel.filterAnnotations(ScopeValidator.Scopes.class, EndpointConfig.AnnotationScope.METHOD)).thenReturn(List.of(scopes));
    ScopeValidator.ScopesConfig sConfig = validator.fromAnnotations(ep);
    Errors.Collector collector = Errors.collector();
    ProviderRequest request = mock(ProviderRequest.class);
    when(request.subject()).thenReturn(Optional.of(Subject.builder().principal(Principal.create("myAdmin")).addGrant(Grant.builder().type("scope").name("calendar_other").build()).build()));
    when(request.service()).thenReturn(Optional.empty());
    validator.validate(sConfig, collector, request);
    if (collector.collect().isValid()) {
        fail("User does not have any of the required scopes, should have failed");
    }
}
Also used : Errors(io.helidon.common.Errors) SecurityLevel(io.helidon.security.SecurityLevel) ArrayList(java.util.ArrayList) EndpointConfig(io.helidon.security.EndpointConfig) ProviderRequest(io.helidon.security.ProviderRequest) Test(org.junit.jupiter.api.Test)

Example 14 with SecurityLevel

use of io.helidon.security.SecurityLevel in project helidon by oracle.

the class TimeValidator method fromAnnotations.

@Override
public TimeConfig fromAnnotations(EndpointConfig endpointConfig) {
    TimeConfig.Builder builder = TimeConfig.builder();
    for (SecurityLevel securityLevel : endpointConfig.securityLevels()) {
        for (EndpointConfig.AnnotationScope scope : EndpointConfig.AnnotationScope.values()) {
            List<Annotation> annotations = new ArrayList<>();
            for (Class<? extends Annotation> annotation : supportedAnnotations()) {
                annotations.addAll(securityLevel.filterAnnotations(annotation, scope));
            }
            for (Annotation annotation : annotations) {
                if (annotation instanceof DaysOfWeek) {
                    DaysOfWeek daw = (DaysOfWeek) annotation;
                    for (DayOfWeek dayOfWeek : daw.value()) {
                        builder.addDaysOfWeek(dayOfWeek);
                    }
                } else if (annotation instanceof TimesOfDay) {
                    TimesOfDay tods = (TimesOfDay) annotation;
                    for (TimeOfDay tod : tods.value()) {
                        builder.addBetween(LocalTime.parse(tod.from()), LocalTime.parse(tod.to()));
                    }
                } else if (annotation instanceof TimeOfDay) {
                    TimeOfDay tod = (TimeOfDay) annotation;
                    builder.addBetween(LocalTime.parse(tod.from()), LocalTime.parse(tod.to()));
                }
            }
        }
    }
    return builder.build();
}
Also used : DayOfWeek(java.time.DayOfWeek) ArrayList(java.util.ArrayList) AbacAnnotation(io.helidon.security.providers.abac.AbacAnnotation) Annotation(java.lang.annotation.Annotation) SecurityLevel(io.helidon.security.SecurityLevel) EndpointConfig(io.helidon.security.EndpointConfig)

Example 15 with SecurityLevel

use of io.helidon.security.SecurityLevel in project helidon by oracle.

the class SecurityFilter method getMethodSecurity.

private SecurityDefinition getMethodSecurity(InvokedResource invokedResource, Method definitionMethod, ExtendedUriInfo uriInfo) {
    // Check cache
    // Jersey model 'definition method' is the method that contains JAX-RS/Jersey annotations. JAX-RS does not support
    // merging annotations from a parent, so we don't have to look for annotations on corresponding methods of interfaces
    // and abstract classes implemented by the definition method.
    // Jersey model does not have a 'definition class', so we have to find it from a handler class
    Class<?> obtainedClass = invokedResource.definitionClass().orElseThrow(() -> new SecurityException("Got definition method, cannot get definition class"));
    Class<?> definitionClass = getRealClass(obtainedClass);
    // Get the application for this request in case there's more than one
    Application appInstance = serverRequest.context().get(Application.class).get();
    // Create and cache security definition for application
    Class<?> appRealClass = getRealClass(appInstance.getClass());
    SecurityDefinition appClassSecurity = appClassSecurity(appRealClass);
    if (definitionClass.getAnnotation(Path.class) == null) {
        // this is a sub-resource
        // I must locate the resource class and method that was invoked
        PathVisitor visitor = new PathVisitor();
        visitor.visit(uriInfo.getMatchedRuntimeResources());
        Collections.reverse(visitor.list);
        StringBuilder fullPathBuilder = new StringBuilder();
        List<Method> methodsToProcess = new LinkedList<>();
        for (Invocable m : visitor.list) {
            // first the top most class (MpMainResource.sub())
            // then the one under it (MpSubResource.sub())
            // these methods are above our sub resource
            Method parentDefMethod = m.getDefinitionMethod();
            Class<?> parentClass = parentDefMethod.getDeclaringClass();
            fullPathBuilder.append("/").append(parentClass.getName()).append(".").append(parentDefMethod.getName());
            methodsToProcess.add(parentDefMethod);
        }
        fullPathBuilder.append("/").append(definitionClass.getName()).append(".").append(definitionMethod.getName());
        methodsToProcess.add(definitionMethod);
        String fullPath = fullPathBuilder.toString();
        // now full path can be used as a cache
        if (subResourceMethodSecurity(appRealClass).containsKey(fullPath)) {
            return subResourceMethodSecurity(appRealClass).get(fullPath);
        }
        // now process each definition method and class
        SecurityDefinition current = appClassSecurity;
        for (Method method : methodsToProcess) {
            Class<?> clazz = method.getDeclaringClass();
            current = securityForClass(clazz, current);
            Authenticated atn = method.getAnnotation(Authenticated.class);
            Authorized atz = method.getAnnotation(Authorized.class);
            Audited audited = method.getAnnotation(Audited.class);
            SecurityDefinition methodDef = current.copyMe();
            methodDef.add(atn);
            methodDef.add(atz);
            methodDef.add(audited);
            SecurityLevel currentSecurityLevel = methodDef.getSecurityLevels().get(methodDef.getSecurityLevels().size() - 1);
            Map<Class<? extends Annotation>, List<Annotation>> methodAnnotations = new HashMap<>();
            addCustomAnnotations(methodAnnotations, method);
            SecurityLevel newSecurityLevel = SecurityLevel.create(currentSecurityLevel).withMethodName(method.getName()).withMethodAnnotations(methodAnnotations).build();
            methodDef.getSecurityLevels().set(methodDef.getSecurityLevels().size() - 1, newSecurityLevel);
            for (AnnotationAnalyzer analyzer : analyzers) {
                AnnotationAnalyzer.AnalyzerResponse analyzerResponse = analyzer.analyze(method, current.analyzerResponse(analyzer));
                methodDef.analyzerResponse(analyzer, analyzerResponse);
            }
            current = methodDef;
        }
        subResourceMethodSecurity(appRealClass).put(fullPath, current);
        return current;
    }
    if (resourceMethodSecurity(appRealClass).containsKey(definitionMethod)) {
        return resourceMethodSecurity(appRealClass).get(definitionMethod);
    }
    SecurityDefinition resClassSecurity = resourceClassSecurity(appRealClass).computeIfAbsent(definitionClass, aClass -> securityForClass(definitionClass, appClassSecurity));
    Authenticated atn = definitionMethod.getAnnotation(Authenticated.class);
    Authorized atz = definitionMethod.getAnnotation(Authorized.class);
    Audited audited = definitionMethod.getAnnotation(Audited.class);
    SecurityDefinition methodDef = resClassSecurity.copyMe();
    methodDef.add(atn);
    methodDef.add(atz);
    methodDef.add(audited);
    int index = methodDef.getSecurityLevels().size() - 1;
    SecurityLevel currentSecurityLevel = methodDef.getSecurityLevels().get(index);
    Map<Class<? extends Annotation>, List<Annotation>> methodLevelAnnots = new HashMap<>();
    addCustomAnnotations(methodLevelAnnots, definitionMethod);
    methodDef.getSecurityLevels().set(index, SecurityLevel.create(currentSecurityLevel).withMethodName(definitionMethod.getName()).withMethodAnnotations(methodLevelAnnots).build());
    resourceMethodSecurity(appRealClass).put(definitionMethod, methodDef);
    for (AnnotationAnalyzer analyzer : analyzers) {
        AnnotationAnalyzer.AnalyzerResponse analyzerResponse = analyzer.analyze(definitionMethod, resClassSecurity.analyzerResponse(analyzer));
        methodDef.analyzerResponse(analyzer, analyzerResponse);
    }
    return methodDef;
}
Also used : Path(jakarta.ws.rs.Path) Authenticated(io.helidon.security.annotations.Authenticated) Authorized(io.helidon.security.annotations.Authorized) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AnnotationAnalyzer(io.helidon.security.providers.common.spi.AnnotationAnalyzer) ResourceMethod(org.glassfish.jersey.server.model.ResourceMethod) Method(java.lang.reflect.Method) LinkedList(java.util.LinkedList) Annotation(java.lang.annotation.Annotation) Invocable(org.glassfish.jersey.server.model.Invocable) Audited(io.helidon.security.annotations.Audited) SecurityLevel(io.helidon.security.SecurityLevel) LinkedList(java.util.LinkedList) List(java.util.List) Application(jakarta.ws.rs.core.Application)

Aggregations

SecurityLevel (io.helidon.security.SecurityLevel)36 EndpointConfig (io.helidon.security.EndpointConfig)30 ArrayList (java.util.ArrayList)26 ProviderRequest (io.helidon.security.ProviderRequest)25 Test (org.junit.jupiter.api.Test)22 Errors (io.helidon.common.Errors)17 Annotation (java.lang.annotation.Annotation)9 RolesAllowed (jakarta.annotation.security.RolesAllowed)8 DenyAll (jakarta.annotation.security.DenyAll)7 PermitAll (jakarta.annotation.security.PermitAll)6 AuthorizationResponse (io.helidon.security.AuthorizationResponse)5 LinkedList (java.util.LinkedList)5 List (java.util.List)5 SecurityEnvironment (io.helidon.security.SecurityEnvironment)3 AbacAnnotation (io.helidon.security.providers.abac.AbacAnnotation)3 Config (io.helidon.config.Config)2 AuthenticationResponse (io.helidon.security.AuthenticationResponse)2 Subject (io.helidon.security.Subject)2 Audited (io.helidon.security.annotations.Audited)2 Authenticated (io.helidon.security.annotations.Authenticated)2