This is an automated email from the ASF dual-hosted git repository. nixonrodrigues pushed a commit to branch ATLAS-5409 in repository https://gitbox.apache.org/repos/asf/atlas.git
commit d28deccff8f0048b3e1c9388beb998ae3de6e83e Author: Ramachandran Krishnan <[email protected]> AuthorDate: Wed Aug 19 15:31:11 2026 +0530 ATLAS-5385: Rename header authentication config to atlas.authentication.method.header.* Replace legacy atlas.authn.header.* properties with a generic logical-key to HTTP-header mapping scheme so deployers can configure any proxy header names without vendor-specific defaults in OSS code. --- distro/src/conf/atlas-application.properties | 8 +- .../web/filters/AtlasHeaderAuthConfiguration.java | 141 +++++++++++++++++++++ .../web/filters/AtlasHeaderPreAuthFilter.java | 48 +++---- .../filters/AtlasHeaderAuthConfigurationTest.java | 112 ++++++++++++++++ .../web/filters/AtlasHeaderPreAuthFilterTest.java | 97 ++++++++------ 5 files changed, 334 insertions(+), 72 deletions(-) diff --git a/distro/src/conf/atlas-application.properties b/distro/src/conf/atlas-application.properties index 735fb6709..be1c24c59 100755 --- a/distro/src/conf/atlas-application.properties +++ b/distro/src/conf/atlas-application.properties @@ -297,7 +297,7 @@ atlas.rest.notification.enableTLS=false #atlas.skip.check.for.parent.child.attribute.name=true ######### Header Based Authentication ######### -#atlas.authn.header.enabled=false -#atlas.authn.header.username=x-awc-username -#atlas.authn.header.roles=x-awc-roles -#atlas.authn.header.requestid=x-awc-requestid \ No newline at end of file +#atlas.authentication.header.enabled=false +#atlas.authentication.method.header.username=username +#atlas.authentication.method.header.roles=roles +#atlas.authentication.method.header.request-id=requestid \ No newline at end of file diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfiguration.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfiguration.java new file mode 100644 index 000000000..b7ed26c7c --- /dev/null +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfiguration.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.atlas.web.filters; + +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +public final class AtlasHeaderAuthConfiguration { + private static final Logger LOG = LoggerFactory.getLogger(AtlasHeaderAuthConfiguration.class); + + public static final String PROP_HEADER_AUTH_ENABLED = "atlas.authentication.header.enabled"; + public static final String PROP_METHOD_HEADER_PREFIX = "atlas.authentication.method.header"; + + public static final String KEY_USERNAME = "username"; + public static final String KEY_ROLES = "roles"; + public static final String KEY_REQUEST_ID = "requestid"; + + private final boolean enabled; + private final Map<String, String> headerNamesByKey; + + private AtlasHeaderAuthConfiguration(boolean enabled, Map<String, String> headerNamesByKey) { + this.enabled = enabled; + this.headerNamesByKey = headerNamesByKey; + } + + public static AtlasHeaderAuthConfiguration load(Configuration configuration) { + if (configuration == null || !configuration.getBoolean(PROP_HEADER_AUTH_ENABLED, false)) { + return disabled(); + } + + Map<String, String> headerNamesByKey = new HashMap<>(); + + applyMethodHeaderMappings(configuration.subset(PROP_METHOD_HEADER_PREFIX), headerNamesByKey); + + return new AtlasHeaderAuthConfiguration(true, Collections.unmodifiableMap(headerNamesByKey)); + } + + public boolean isEnabled() { + return enabled; + } + + public Set<String> getKeys() { + return headerNamesByKey.keySet(); + } + + public String getHeaderName(String key) { + return headerNamesByKey.get(key); + } + + public String readHeaderValue(HttpServletRequest request, String key) { + String headerName = getHeaderName(key); + + if (headerName == null || request == null) { + return null; + } + + return StringUtils.trimToNull(request.getHeader(headerName)); + } + + private static AtlasHeaderAuthConfiguration disabled() { + return new AtlasHeaderAuthConfiguration(false, Collections.emptyMap()); + } + + private static void applyMethodHeaderMappings(Configuration methodHeaders, Map<String, String> headerNamesByKey) { + if (methodHeaders == null) { + return; + } + + Iterator<String> keys = methodHeaders.getKeys(); + + while (keys.hasNext()) { + String propertyKey = keys.next(); + String logicalKey = normalizeLogicalKey(propertyKey); + String httpHeaderName = StringUtils.trimToNull(methodHeaders.getString(propertyKey)); + + if (logicalKey == null) { + LOG.warn("Ignoring unrecognized header property key '{}'", propertyKey); + continue; + } + + if (httpHeaderName == null) { + headerNamesByKey.remove(logicalKey); + continue; + } + + headerNamesByKey.put(logicalKey, httpHeaderName); + } + } + + private static String normalizeLogicalKey(String propertyKey) { + if (StringUtils.isBlank(propertyKey)) { + return null; + } + + String normalized = propertyKey.trim().toLowerCase(Locale.ROOT).replace('-', '_'); + + switch (normalized) { + case KEY_USERNAME: + case "user": + return KEY_USERNAME; + + case KEY_ROLES: + case "role": + case "groups": + return KEY_ROLES; + + case KEY_REQUEST_ID: + case "request_id": + return KEY_REQUEST_ID; + + default: + return null; + } + } +} diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilter.java index 2a490ee41..414e7d645 100644 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilter.java @@ -21,8 +21,7 @@ package org.apache.atlas.web.filters; import org.apache.atlas.ApplicationProperties; import org.apache.atlas.server.common.filters.AtlasResponseRequestWrapper; import org.apache.atlas.server.common.filters.HeadersUtil; -import org.apache.atlas.server.common.model.User; -import org.apache.commons.configuration2.Configuration; +import org.apache.atlas.web.model.User; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,16 +51,9 @@ import java.util.UUID; public class AtlasHeaderPreAuthFilter implements Filter { private static final Logger LOG = LoggerFactory.getLogger(AtlasHeaderPreAuthFilter.class); - public static final String PROP_HEADER_AUTH_ENABLED = "atlas.authn.header.enabled"; - public static final String PROP_USERNAME_HEADER = "atlas.authn.header.username"; - public static final String PROP_ROLES_HEADER = "atlas.authn.header.roles"; - public static final String PROP_REQUEST_ID_HEADER = "atlas.authn.header.requestid"; - public static final String REQUEST_ID_ATTRIBUTE = "atlas.request.id"; + private static final String REQUEST_ID_ATTRIBUTE = "atlas.request.id"; - private Configuration configuration; - private boolean headerAuthEnabled; - private String userNameHeaderName; - private String rolesHeaderName; + private AtlasHeaderAuthConfiguration headerAuthConfiguration; @Inject public AtlasHeaderPreAuthFilter() { @@ -70,30 +62,23 @@ public class AtlasHeaderPreAuthFilter implements Filter { private void loadConfiguration() { try { - configuration = ApplicationProperties.get(); + headerAuthConfiguration = AtlasHeaderAuthConfiguration.load(ApplicationProperties.get()); } catch (Exception e) { LOG.error("Error loading application properties for header pre-auth", e); - configuration = null; + headerAuthConfiguration = AtlasHeaderAuthConfiguration.load(null); } - if (configuration == null) { - headerAuthEnabled = false; - userNameHeaderName = null; - rolesHeaderName = null; - return; - } - headerAuthEnabled = configuration.getBoolean(PROP_HEADER_AUTH_ENABLED, false); - userNameHeaderName = StringUtils.trimToNull(configuration.getString(PROP_USERNAME_HEADER, "")); - rolesHeaderName = StringUtils.trimToNull(configuration.getString(PROP_ROLES_HEADER, "")); } private List<GrantedAuthority> getAuthoritiesFromRolesHeader(String rolesHeader) { List<GrantedAuthority> ret = new ArrayList<>(); + if (StringUtils.isBlank(rolesHeader)) { return ret; } for (String role : rolesHeader.split(",")) { String trimmed = StringUtils.trimToNull(role); + if (trimmed != null) { ret.add(new org.springframework.security.core.authority.SimpleGrantedAuthority(trimmed)); } @@ -117,15 +102,15 @@ public class AtlasHeaderPreAuthFilter implements Filter { HeadersUtil.setSecurityHeaders(responseWrapper); try { - if (headerAuthEnabled) { + if (headerAuthConfiguration.isEnabled()) { Authentication pre = SecurityContextHolder.getContext().getAuthentication(); if (pre == null || !pre.isAuthenticated()) { - String username = StringUtils.trimToNull(httpRequest.getHeader(userNameHeaderName)); + String username = headerAuthConfiguration.readHeaderValue(httpRequest, AtlasHeaderAuthConfiguration.KEY_USERNAME); if (username != null) { - List<GrantedAuthority> grantedAuths = - getAuthoritiesFromRolesHeader(httpRequest.getHeader(rolesHeaderName)); + String rolesHeaderValue = headerAuthConfiguration.readHeaderValue(httpRequest, AtlasHeaderAuthConfiguration.KEY_ROLES); + List<GrantedAuthority> grantedAuths = getAuthoritiesFromRolesHeader(rolesHeaderValue); UserDetails principal = new User(username, "", grantedAuths); @@ -140,8 +125,9 @@ public class AtlasHeaderPreAuthFilter implements Filter { } } - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String requestId = getRequestId(auth, httpRequest); + httpRequest.setAttribute(REQUEST_ID_ATTRIBUTE, requestId); chain.doFilter(servletRequest, responseWrapper); @@ -153,12 +139,10 @@ public class AtlasHeaderPreAuthFilter implements Filter { } private String getRequestId(Authentication auth, HttpServletRequest request) { - String requestIdHeaderName = configuration != null ? configuration.getString(PROP_REQUEST_ID_HEADER) : null; - - if (requestIdHeaderName != null && - auth instanceof AtlasAuthenticationToken && + if (auth instanceof AtlasAuthenticationToken && ((AtlasAuthenticationToken) auth).getAuthType() == AtlasAuthenticationToken.AUTH_TYPE_TRUSTED_PROXY) { - String requestId = StringUtils.trimToNull(request.getHeader(requestIdHeaderName)); + String requestId = headerAuthConfiguration.readHeaderValue(request, AtlasHeaderAuthConfiguration.KEY_REQUEST_ID); + if (requestId != null) { return requestId; } diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfigurationTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfigurationTest.java new file mode 100644 index 000000000..6695b32c7 --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderAuthConfigurationTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.atlas.web.filters; + +import org.apache.commons.configuration2.MapConfiguration; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +public class AtlasHeaderAuthConfigurationTest { + @Test + public void testDisabledWhenNotConfigured() { + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(new HashMap<>())); + + assertFalse(config.isEnabled()); + assertTrue(config.getKeys().isEmpty()); + } + + @Test + public void testEnabledWithoutMappingsHasNoHeaders() { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(properties)); + + assertTrue(config.isEnabled()); + assertTrue(config.getKeys().isEmpty()); + } + + @Test + public void testMethodHeaderMappings() { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "username"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".roles", "roles"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".request-id", "requestid"); + + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(properties)); + + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_USERNAME), "username"); + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_ROLES), "roles"); + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_REQUEST_ID), "requestid"); + } + + @Test + public void testCustomProxyHeaderNames() { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "X-Forwarded-User"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".roles", "X-Forwarded-Groups"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".request-id", "X-Request-Id"); + + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(properties)); + + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_USERNAME), "X-Forwarded-User"); + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_ROLES), "X-Forwarded-Groups"); + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_REQUEST_ID), "X-Request-Id"); + } + + @Test + public void testOnlyConfiguredHeadersAreMapped() { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "X-Forwarded-User"); + + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(properties)); + + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_USERNAME), "X-Forwarded-User"); + assertNull(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_ROLES)); + assertNull(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_REQUEST_ID)); + } + + @Test + public void testBlankPropertyRemovesMapping() { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "username"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".roles", " "); + + AtlasHeaderAuthConfiguration config = AtlasHeaderAuthConfiguration.load(new MapConfiguration(properties)); + + assertEquals(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_USERNAME), "username"); + assertNull(config.getHeaderName(AtlasHeaderAuthConfiguration.KEY_ROLES)); + } +} diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilterTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilterTest.java index cd959aaa6..4c820f8e5 100644 --- a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilterTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasHeaderPreAuthFilterTest.java @@ -20,6 +20,7 @@ package org.apache.atlas.web.filters; import org.apache.atlas.ApplicationProperties; import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.MapConfiguration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; @@ -36,6 +37,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -43,6 +46,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; @@ -56,9 +60,6 @@ public class AtlasHeaderPreAuthFilterTest { @Mock private FilterChain filterChain; - @Mock - private Configuration configuration; - @BeforeMethod public void setUp() { MockitoAnnotations.initMocks(this); @@ -72,20 +73,16 @@ public class AtlasHeaderPreAuthFilterTest { @Test public void testDoFilterEnabledWithUsernameAndRoles() throws Exception { - when(configuration.getBoolean(AtlasHeaderPreAuthFilter.PROP_HEADER_AUTH_ENABLED, false)).thenReturn(true); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_USERNAME_HEADER, "")) - .thenReturn("x-user"); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_ROLES_HEADER, "")) - .thenReturn("x-roles"); - when(request.getHeader("x-user")).thenReturn("alice"); - when(request.getHeader("x-roles")).thenReturn("ROLE_ADMIN, ROLE_USER"); + Map<String, Object> properties = new HashMap<>(); - try (MockedStatic<ApplicationProperties> appProps = org.mockito.Mockito.mockStatic(ApplicationProperties.class)) { - appProps.when(ApplicationProperties::get).thenReturn(configuration); + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "X-Forwarded-User"); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".roles", "X-Forwarded-Groups"); - AtlasHeaderPreAuthFilter filter = new AtlasHeaderPreAuthFilter(); - filter.doFilter(request, response, filterChain); - } + when(request.getHeader("X-Forwarded-User")).thenReturn("alice"); + when(request.getHeader("X-Forwarded-Groups")).thenReturn("ROLE_ADMIN, ROLE_USER"); + + runFilter(new MapConfiguration(properties)); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); assertNotNull(auth); @@ -102,45 +99,73 @@ public class AtlasHeaderPreAuthFilterTest { @Test public void testDoFilterEnabledWithoutUsernameDoesNotAuthenticate() throws IOException, ServletException { - when(configuration.getBoolean(AtlasHeaderPreAuthFilter.PROP_HEADER_AUTH_ENABLED, false)).thenReturn(true); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_USERNAME_HEADER, "")) - .thenReturn("x-user"); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_ROLES_HEADER, "")) - .thenReturn("x-roles"); - when(request.getHeader("x-user")).thenReturn(" "); + Map<String, Object> properties = new HashMap<>(); - try (MockedStatic<ApplicationProperties> appProps = org.mockito.Mockito.mockStatic(ApplicationProperties.class)) { - appProps.when(ApplicationProperties::get).thenReturn(configuration); + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "X-Forwarded-User"); - AtlasHeaderPreAuthFilter filter = new AtlasHeaderPreAuthFilter(); - filter.doFilter(request, response, filterChain); - } + when(request.getHeader("X-Forwarded-User")).thenReturn(" "); + + runFilter(new MapConfiguration(properties)); + + assertNull(SecurityContextHolder.getContext().getAuthentication()); + verify(filterChain).doFilter(eq(request), any(HttpServletResponse.class)); + } + + @Test + public void testDoFilterEnabledWithoutAnyHeadersContinuesUnauthenticated() throws Exception { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); - assertEquals(SecurityContextHolder.getContext().getAuthentication(), null); + runFilter(new MapConfiguration(properties)); + + assertNull(SecurityContextHolder.getContext().getAuthentication()); verify(filterChain).doFilter(eq(request), any(HttpServletResponse.class)); } + @Test + public void testDoFilterAuthenticatesWithUsernameOnly() throws Exception { + Map<String, Object> properties = new HashMap<>(); + + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "username"); + + when(request.getHeader("username")).thenReturn("alice"); + + runFilter(new MapConfiguration(properties)); + + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + assertNotNull(auth); + assertEquals(((UserDetails) auth.getPrincipal()).getUsername(), "alice"); + assertTrue(auth.getAuthorities().isEmpty()); + } + @Test public void testDoFilterEnabledKeepsExistingAuthentication() throws IOException, ServletException { Authentication existing = org.mockito.Mockito.mock(Authentication.class); when(existing.isAuthenticated()).thenReturn(true); SecurityContextHolder.getContext().setAuthentication(existing); - when(configuration.getBoolean(AtlasHeaderPreAuthFilter.PROP_HEADER_AUTH_ENABLED, false)).thenReturn(true); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_USERNAME_HEADER, "")) - .thenReturn("x-user"); - when(configuration.getString(AtlasHeaderPreAuthFilter.PROP_ROLES_HEADER, "")) - .thenReturn("x-roles"); - when(request.getHeader("x-user")).thenReturn("alice"); + Map<String, Object> properties = new HashMap<>(); + properties.put(AtlasHeaderAuthConfiguration.PROP_HEADER_AUTH_ENABLED, true); + properties.put(AtlasHeaderAuthConfiguration.PROP_METHOD_HEADER_PREFIX + ".username", "X-Forwarded-User"); + + when(request.getHeader("X-Forwarded-User")).thenReturn("alice"); + + runFilter(new MapConfiguration(properties)); + + assertSame(SecurityContextHolder.getContext().getAuthentication(), existing); + verify(filterChain).doFilter(eq(request), any(HttpServletResponse.class)); + } + + private void runFilter(Configuration configuration) throws Exception { try (MockedStatic<ApplicationProperties> appProps = org.mockito.Mockito.mockStatic(ApplicationProperties.class)) { appProps.when(ApplicationProperties::get).thenReturn(configuration); AtlasHeaderPreAuthFilter filter = new AtlasHeaderPreAuthFilter(); filter.doFilter(request, response, filterChain); } - - assertSame(SecurityContextHolder.getContext().getAuthentication(), existing); - verify(filterChain).doFilter(eq(request), any(HttpServletResponse.class)); } }
