This is an automated email from the ASF dual-hosted git repository.

smolnar82 pushed a commit to branch v3.0.0
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/v3.0.0 by this push:
     new 1ff236bc6 KNOX-3397: Add preauth.auth.header.actor.groups to set actor 
groups header name explicitly (#1329)
1ff236bc6 is described below

commit 1ff236bc61ce9e536de2c8ac1c851523e3ab8902
Author: Sandor Molnar <[email protected]>
AuthorDate: Mon Jul 27 11:55:10 2026 +0200

    KNOX-3397: Add preauth.auth.header.actor.groups to set actor groups header 
name explicitly (#1329)
---
 .../gateway/service/auth/AbstractAuthResource.java | 17 ++++++++++++--
 .../gateway/service/auth/PreAuthResourceTest.java  | 27 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git 
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AbstractAuthResource.java
 
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AbstractAuthResource.java
index 8ed3aa660..358b68b0f 100644
--- 
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AbstractAuthResource.java
+++ 
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AbstractAuthResource.java
@@ -43,6 +43,7 @@ import static javax.ws.rs.core.Response.status;
 
 public abstract class AbstractAuthResource {
   public static final String AUTH_ACTOR_ID_HEADER_NAME = 
"preauth.auth.header.actor.id.name";
+  public static final String AUTH_ACTOR_GROUPS_HEADER_NAME = 
"preauth.auth.header.actor.groups";
   public static final String AUTH_ACTOR_GROUPS_HEADER_PREFIX = 
"preauth.auth.header.actor.groups.prefix";
   public static final String GROUP_HEADER_LENGTH_LIMIT = 
"preauth.auth.header.groups.length.limit";
   public static final String GROUP_HEADER_SIZE_LIMIT = 
"preauth.auth.header.groups.size.limit";
@@ -60,6 +61,7 @@ public abstract class AbstractAuthResource {
   private static final String ACTOR_GROUPS_HEADER_FORMAT = "%s-%d";
 
   protected String authHeaderActorIDName;
+  protected String authHeaderActorGroupsName;
   protected String authHeaderActorGroupsPrefix;
   private int groupHeaderLengthLimit;
   private int groupHeaderSizeLimit;
@@ -69,6 +71,7 @@ public abstract class AbstractAuthResource {
 
   protected void initialize() {
     authHeaderActorIDName = getInitParameter(AUTH_ACTOR_ID_HEADER_NAME, 
DEFAULT_AUTH_ACTOR_ID_HEADER_NAME);
+    authHeaderActorGroupsName = 
getInitParameter(AUTH_ACTOR_GROUPS_HEADER_NAME, null);
     authHeaderActorGroupsPrefix = 
getInitParameter(AUTH_ACTOR_GROUPS_HEADER_PREFIX, 
DEFAULT_AUTH_ACTOR_GROUPS_HEADER_PREFIX);
     groupHeaderLengthLimit = 
Integer.parseInt(getInitParameter(GROUP_HEADER_LENGTH_LIMIT, 
DEFAULT_GROUP_HEADER_LENGTH_LIMIT));
     groupHeaderSizeLimit = 
Integer.parseInt(getInitParameter(GROUP_HEADER_SIZE_LIMIT, 
DEFAULT_GROUP_HEADER_SIZE_LIMIT));
@@ -114,13 +117,23 @@ public abstract class AbstractAuthResource {
       final boolean useRoles = !roles.isEmpty();
       final List<String> groupStrings = GroupUtils.getGroupStrings(useRoles ? 
roles : matchingGroupNames, groupHeaderLengthLimit, groupHeaderSizeLimit);
       for (int i = 0; i < groupStrings.size(); i++) {
-        final String headerName = useRoles || rolesLookupExecuted() ? 
authHeaderActorGroupsPrefix : String.format(Locale.ROOT, 
ACTOR_GROUPS_HEADER_FORMAT, authHeaderActorGroupsPrefix, i + 1);
-        getResponse().addHeader(headerName, groupStrings.get(i));
+        getResponse().addHeader(createGroupsHeaderName(useRoles, i), 
groupStrings.get(i));
       }
     }
     return ok().build();
   }
 
+  private String createGroupsHeaderName(boolean useRoles, int index) {
+    if (authHeaderActorGroupsName != null) {
+      // explicit groups header takes precedence over the prefix and is used 
directly, without an index suffix
+      return authHeaderActorGroupsName;
+    } else if (useRoles || rolesLookupExecuted()) {
+      return authHeaderActorGroupsPrefix;
+    } else {
+      return String.format(Locale.ROOT, ACTOR_GROUPS_HEADER_FORMAT, 
authHeaderActorGroupsPrefix, index + 1);
+    }
+  }
+
   private Collection<String> lookupRoles(String userName, Collection<String> 
groups) {
     Collection<String> roles = null;
       try {
diff --git 
a/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/PreAuthResourceTest.java
 
b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/PreAuthResourceTest.java
index 5e1496c83..136b0ed39 100644
--- 
a/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/PreAuthResourceTest.java
+++ 
b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/PreAuthResourceTest.java
@@ -169,6 +169,33 @@ public class PreAuthResourceTest {
     EasyMock.verify(response);
   }
 
+  @Test
+  public void testExplicitGroupsHeaderTakesPrecedenceOverPrefix() throws 
Exception {
+    final String explicitGroupsHeader = "X-Knox-Actor-Groups";
+    subject.getPrincipals().add(new GroupPrincipal("group1"));
+
+    context = EasyMock.createNiceMock(ServletContext.class);
+    
EasyMock.expect(context.getInitParameter(PreAuthResource.AUTH_ACTOR_GROUPS_HEADER_NAME)).andReturn(explicitGroupsHeader).anyTimes();
+    // a prefix is configured as well, to prove the explicit header wins and 
no index suffix is appended
+    
EasyMock.expect(context.getInitParameter(PreAuthResource.AUTH_ACTOR_GROUPS_HEADER_PREFIX)).andReturn("X-Knox-Prefixed-Groups").anyTimes();
+    request = EasyMock.createNiceMock(HttpServletRequest.class);
+    
EasyMock.expect(request.getAttribute(AbstractIdentityAssertionBase.ROLES_LOOKUP_EXECUTED)).andReturn(false).anyTimes();
+    response = EasyMock.createNiceMock(HttpServletResponse.class);
+    response.setHeader(PreAuthResource.DEFAULT_AUTH_ACTOR_ID_HEADER_NAME, 
USER_NAME);
+    EasyMock.expectLastCall();
+    // the explicit header name is used directly, without an index suffix
+    response.addHeader(EasyMock.eq(explicitGroupsHeader), 
EasyMock.anyString());
+    EasyMock.expectLastCall().times(1);
+    EasyMock.replay(context, request, response);
+
+    final PreAuthResource preAuthResource = new PreAuthResource();
+    preAuthResource.context = context;
+    preAuthResource.response = response;
+    preAuthResource.request = request;
+    executeResourceWithSubject(preAuthResource);
+    EasyMock.verify(response);
+  }
+
   @Test
   public void testPopulatingGroupsWithRoles() throws Exception {
     final String rolesHeader = "X-Knox-Roles";

Reply via email to