From 852477ad14cdcf93fd1a30504e35f634e5dfed90 Mon Sep 17 00:00:00 2001 From: Dmitri Bourlatchkov Date: Wed, 18 Jan 2023 09:15:35 -0500 Subject: [PATCH] Use custom CDI extension for injecting Principals (#5883) This is to avoid dependencies on CDI driven by javax.ws.rs.core.Context and resolve `Principal` suppliers at the Weld / test extension level. Overall, this reduced interference from external libs on the class path when running NessieJaxRsExtension. --- .../compatibility/jersey/JerseyServer.java | 1 + .../jersey/PrincipalExtension.java | 43 +++++++++++++++++ .../jaxrs/ext/ContextPrincipalExtension.java | 48 +++++++++++++++++++ .../jaxrs/ext/NessieJaxRsExtension.java | 9 +--- .../rest/ContextPrincipalSupplier.java | 33 ------------- 5 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/PrincipalExtension.java create mode 100644 servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/ContextPrincipalExtension.java delete mode 100644 servers/rest-services/src/main/java/org/projectnessie/services/rest/ContextPrincipalSupplier.java diff --git a/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/JerseyServer.java b/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/JerseyServer.java index eaa8f880e41..683412367f5 100644 --- a/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/JerseyServer.java +++ b/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/JerseyServer.java @@ -62,6 +62,7 @@ public JerseyServer(Supplier databaseAdapterSupplier) throws Ex weld.addPackages(true, RestConfigResource.class); weld.addPackages(true, TreeApiImpl.class); // Inject external beans + weld.addExtension(new PrincipalExtension()); weld.addExtension(new ServerConfigExtension()); weld.addExtension(PersistVersionStoreExtension.forDatabaseAdapter(databaseAdapterSupplier)); weld.addExtension(authzExtension()); diff --git a/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/PrincipalExtension.java b/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/PrincipalExtension.java new file mode 100644 index 00000000000..e07bae236d3 --- /dev/null +++ b/compatibility/jersey/src/main/java/org/projectnessie/tools/compatibility/jersey/PrincipalExtension.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.tools.compatibility.jersey; + +import java.security.Principal; +import java.util.function.Supplier; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.util.TypeLiteral; + +/** + * A CDI extension that always produces {@code null} {@link Principal} objects simulating execution + * without authentication. + */ +public class PrincipalExtension implements Extension { + @SuppressWarnings("unused") + public void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) { + Supplier principal = () -> null; + + abd.addBean() + .addType(new TypeLiteral>() {}) + .addQualifier(Default.Literal.INSTANCE) + .scope(RequestScoped.class) + .produceWith(i -> principal); + } +} diff --git a/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/ContextPrincipalExtension.java b/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/ContextPrincipalExtension.java new file mode 100644 index 00000000000..c59f57cdc9d --- /dev/null +++ b/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/ContextPrincipalExtension.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.jaxrs.ext; + +import java.security.Principal; +import java.util.function.Supplier; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.util.TypeLiteral; +import javax.ws.rs.core.SecurityContext; + +public class ContextPrincipalExtension implements Extension { + private final Supplier principal; + + public ContextPrincipalExtension(Supplier securityContext) { + this.principal = + () -> { + SecurityContext context = securityContext.get(); + return context == null ? null : context.getUserPrincipal(); + }; + } + + @SuppressWarnings("unused") + public void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) { + abd.addBean() + .addType(new TypeLiteral>() {}) + .addQualifier(Default.Literal.INSTANCE) + .scope(RequestScoped.class) + .produceWith(i -> principal); + } +} diff --git a/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/NessieJaxRsExtension.java b/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/NessieJaxRsExtension.java index ab7d5092e20..3540df17019 100644 --- a/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/NessieJaxRsExtension.java +++ b/servers/jax-rs-testextension/src/main/java/org/projectnessie/jaxrs/ext/NessieJaxRsExtension.java @@ -22,7 +22,6 @@ import java.util.function.Function; import java.util.function.Supplier; import javax.enterprise.inject.spi.Extension; -import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Application; import javax.ws.rs.core.SecurityContext; import org.glassfish.jersey.message.DeflateEncoder; @@ -219,6 +218,7 @@ public EnvHolder(Extension versionStoreExtension) throws Exception { weld.addPackages(true, RestConfigResource.class); weld.addPackages(true, TreeApiImpl.class); // Inject external beans + weld.addExtension(new ContextPrincipalExtension(() -> securityContext)); weld.addExtension(new ServerConfigExtension()); weld.addExtension(versionStoreExtension); weld.addExtension(new AuthorizerExtension().setAccessCheckerSupplier(this::createNewChecker)); @@ -250,13 +250,6 @@ protected Application configure() { config.register(EncodingFilter.class); config.register(GZipEncoder.class); config.register(DeflateEncoder.class); - config.register( - (ContainerRequestFilter) - requestContext -> { - if (securityContext != null) { - requestContext.setSecurityContext(securityContext); - } - }); // Use a dynamically allocated port, not a static default (80/443) or statically // configured port. diff --git a/servers/rest-services/src/main/java/org/projectnessie/services/rest/ContextPrincipalSupplier.java b/servers/rest-services/src/main/java/org/projectnessie/services/rest/ContextPrincipalSupplier.java deleted file mode 100644 index 87a677363f3..00000000000 --- a/servers/rest-services/src/main/java/org/projectnessie/services/rest/ContextPrincipalSupplier.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2023 Dremio - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.projectnessie.services.rest; - -import java.security.Principal; -import java.util.function.Supplier; -import javax.enterprise.context.RequestScoped; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.SecurityContext; - -@RequestScoped -public class ContextPrincipalSupplier implements Supplier { - - @Context SecurityContext securityContext; - - @Override - public Principal get() { - return securityContext == null ? null : securityContext.getUserPrincipal(); - } -}