Skip to content

Commit

Permalink
Merge pull request #10487 from stuartwdouglas/enable-test-security
Browse files Browse the repository at this point in the history
Add ability to disable security on a per test basis
  • Loading branch information
geoand authored Jul 6, 2020
2 parents becad6b + fa6cede commit 683d783
Show file tree
Hide file tree
Showing 26 changed files with 570 additions and 7 deletions.
10 changes: 10 additions & 0 deletions bom/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,11 @@
<artifactId>quarkus-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-runtime-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-deployment</artifactId>
Expand Down Expand Up @@ -1787,6 +1792,11 @@
<artifactId>quarkus-junit5</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
Expand Down
47 changes: 47 additions & 0 deletions docs/src/main/asciidoc/security.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,50 @@ This will allow you to propagate the identity throughout the reactive callbacks.
are using an executor that is capable of propagating the identity (e.g. no `CompletableFuture.supplyAsync`),
to make sure that quarkus can propagate it. For more information see the
link:context-propagation[Context Propagation Guide].

== Testing Security

Quarkus provides explicit support for testing with different users, and with the security subsystem disabled. To use
this you must include the `quarkus-test-security` artifact:

[source,xml]
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
----

This artifact provides the `io.quarkus.test.security.TestSecurity` annotation, that can be applied to test methods and
test classes to control the security context that the test is run with. This allows you to do two things, you can disable
authorization so tests can access secured endpoints without needing to be authenticated, and you can specify the identity
that you want the tests to run under.

A test that runs with authorization disabled can just set the enabled property to false:

[source,java]
----
@Test
@TestSecurity(authorizationEnabled = false)
void someTestMethod() {
...
}
----

This will disable all access checks, which allows the test to access secured endpoints without needing to authenticate.

You can also use this to configure the current user that the test will run as:

[source,java]
----
@Test
@TestSecurity(user = "testUser", roles = {"admin", "user"})
void someTestMethod() {
...
}
----

This will run the test with an identity with the given username and roles. Note that these can be combined, so you can
disable authorisation and also provide an identity to run the test under, which can be userful if the endpoint expects an
identity to be present.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ public Response toResponse(UnauthorizedException exception) {
if (authenticator != null) {
ChallengeData challengeData = authenticator.getChallenge(context)
.await().indefinitely();
Response.ResponseBuilder status = Response.status(challengeData.status);
if (challengeData.headerName != null) {
status.header(challengeData.headerName.toString(), challengeData.headerContent);
if (challengeData != null) {
Response.ResponseBuilder status = Response.status(challengeData.status);
if (challengeData.headerName != null) {
status.header(challengeData.headerName.toString(), challengeData.headerContent);
}
return status.build();
} else {
return Response.status(401).build();
}
return status.build();
}
}
return Response.status(401).entity("Not authorized").build();
Expand Down
4 changes: 4 additions & 0 deletions extensions/security/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-runtime-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import io.quarkus.security.runtime.interceptor.SecurityHandler;
import io.quarkus.security.runtime.interceptor.check.SecurityCheck;
import io.quarkus.security.spi.AdditionalSecuredClassesBuildIem;
import io.quarkus.security.spi.runtime.AuthorizationController;

public class SecurityProcessor {

Expand All @@ -83,6 +84,11 @@ void services(BuildProducer<JCAProviderBuildItem> jcaProviders) {
}
}

@BuildStep
AdditionalBeanBuildItem authorizationController() {
return AdditionalBeanBuildItem.builder().addBeanClass(AuthorizationController.class).build();
}

/**
* Register the classes for reflection in the requested named providers
*
Expand Down
1 change: 1 addition & 0 deletions extensions/security/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
<module>runtime</module>
<module>spi</module>
<module>test-utils</module>
<module>runtime-spi</module>
</modules>
</project>
39 changes: 39 additions & 0 deletions extensions/security/runtime-spi/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-security-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-security-runtime-spi</artifactId>
<name>Quarkus - Security - Runtime SPI</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.security.spi.runtime;

import javax.inject.Singleton;

/**
* controller that allows authorization to be disabled in tests.
*/
@Singleton
public class AuthorizationController {

public boolean isAuthorizationEnabled() {
return true;
}
}
4 changes: 4 additions & 0 deletions extensions/security/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-runtime-spi</artifactId>
</dependency>
<dependency>
<groupId>jakarta.interceptor</groupId>
<artifactId>jakarta.interceptor-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import javax.interceptor.InvocationContext;

import io.quarkus.security.Authenticated;
import io.quarkus.security.spi.runtime.AuthorizationController;

/**
* @author Michal Szynkiewicz, [email protected]
Expand All @@ -19,8 +20,15 @@ public class AuthenticatedInterceptor {
@Inject
SecurityHandler handler;

@Inject
AuthorizationController controller;

@AroundInvoke
public Object intercept(InvocationContext ic) throws Exception {
return handler.handle(ic);
if (controller.isAuthorizationEnabled()) {
return handler.handle(ic);
} else {
return ic.proceed();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

import io.quarkus.security.spi.runtime.AuthorizationController;

/**
* @author Michal Szynkiewicz, [email protected]
*/
Expand All @@ -18,8 +20,15 @@ public class RolesAllowedInterceptor {
@Inject
SecurityHandler handler;

@Inject
AuthorizationController controller;

@AroundInvoke
public Object intercept(InvocationContext ic) throws Exception {
return handler.handle(ic);
if (controller.isAuthorizationEnabled()) {
return handler.handle(ic);
} else {
return ic.proceed();
}
}
}
4 changes: 4 additions & 0 deletions extensions/vertx-http/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-runtime-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-development-mode-spi</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.quarkus.runtime.ExecutorRecorder;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.spi.runtime.AuthorizationController;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.subscription.UniEmitter;
import io.smallrye.mutiny.subscription.UniSubscriber;
Expand All @@ -31,6 +32,9 @@ public class HttpAuthorizer {
@Inject
IdentityProviderManager identityProviderManager;

@Inject
AuthorizationController controller;

final List<HttpSecurityPolicy> policies;

@Inject
Expand Down Expand Up @@ -87,6 +91,10 @@ public void run() {
*
*/
public void checkPermission(RoutingContext routingContext) {
if (!controller.isAuthorizationEnabled()) {
routingContext.next();
return;
}
//check their permissions
doPermissionCheck(routingContext, QuarkusHttpUser.getSecurityIdentity(routingContext, identityProviderManager), 0, null,
policies);
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/elytron-resteasy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.it.resteasy.elytron;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
Expand All @@ -9,6 +10,8 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;

import io.quarkus.security.Authenticated;

@Path("/")
public class RootResource {

Expand All @@ -32,4 +35,19 @@ public String approval(@Context SecurityContext sec) {
}
return "get success";
}

@GET
@Path("/secure")
@Authenticated
public String getSecure() {
return "secure";
}

@GET
@Path("/user")
@RolesAllowed("user")
public String user(@Context SecurityContext sec) {
return sec.getUserPrincipal().getName();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ quarkus.security.users.embedded.users.mary=mary
quarkus.security.users.embedded.roles.mary=managers
quarkus.security.users.embedded.users.poul=poul
quarkus.security.users.embedded.roles.poul=interns
quarkus.security.users.embedded.auth-mechanism=BASIC
quarkus.security.users.embedded.plain-text=true
quarkus.http.auth.basic=true
Loading

0 comments on commit 683d783

Please sign in to comment.