Search code examples
aws-lambdaquarkusaws-samaws-sam-cli

Quarkus AWS lambda - security provider does not work in AWS


I have created a http lambda with a custom security provider. But the custom security provider does not work as expected. The same works fine as @QuarkusTest. But when I deploy the code to AWS (using sam deploy), it doesn't work. I simply get a NullpointerException in my GreetingResource because the security context is null.

The security context is null because the flow doesn't go through my custom security provider - MBizSecurityProvider (which is not the case when running the test case). In AWS console -> API Gateway -> Authorization, I see

No authorizer attached to $default

Normally I expect an authorizer to be shown in the AWS console. I am using the quarkus generated sam.jvm.yaml/sam.native.yaml and sam CLI to deploy my artifacts to AWS. I don't see any authorizers mentioned in the generated sam config files neither.

Is there any additional configuration to make it work in AWS. In SAM local it works when setting QUARKUS_AWS_LAMBDA_FORCE_USER_NAME environment variable.

Here is my complete source code

My HTTP Api resource class

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext securityContext) {
        return "hello " + securityContext.getUserPrincipal().getName();
    }
}

And my security provider is

@ApplicationScoped
public class MBizSecurityProvider implements LambdaIdentityProvider {

    @Override
    public SecurityIdentity authenticate(APIGatewayV2HTTPEvent event) {
        if (event.getHeaders() == null || !event.getHeaders().containsKey("x-user")) {
            throw new RuntimeException("No auth header");
        }
        if(!event.getHeaders().get("x-user").equalsIgnoreCase("test")) {
            throw new RuntimeException("Invalid user");
        }
        Principal principal = new QuarkusPrincipal(event.getHeaders().get("x-user"));
        QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder();
        builder.setPrincipal(principal);
        return builder.build();
    }
}

I have enabled security in in application.properties with property quarkus.lambda-http.enable-security=true

This is my test case that works fine.

@QuarkusTest
public class GreetingTest {
    @Test
    public void test() {
        APIGatewayV2HTTPEvent request = request("/hello");
        request.setHeaders(ImmutableMap.of("x-user", "test"));
        request.getRequestContext().setAuthorizer(new APIGatewayV2HTTPEvent.RequestContext.Authorizer());

        given()
                .contentType("application/json")
                .accept("application/json")
                .body(request)
                .when()
                .post(AmazonLambdaApi.API_BASE_PATH_TEST)
                .then()
                .statusCode(200)
                .body("body", equalTo("hello test"));
    }

    private APIGatewayV2HTTPEvent request(String path) {
        APIGatewayV2HTTPEvent request = new APIGatewayV2HTTPEvent();
        request.setRawPath(path);
        request.setRequestContext(new APIGatewayV2HTTPEvent.RequestContext());
        request.getRequestContext().setHttp(new APIGatewayV2HTTPEvent.RequestContext.Http());
        request.getRequestContext().getHttp().setMethod("GET");
        return request;
    }
}

Solution

  • It works fine with quarkus-amazon-lambda-rest. Seems to be a bug in quarkus-amazon-lambda-http. Follow this issue for updates github.com/quarkusio/quarkus/issues/24609