This is an automated email from the ASF dual-hosted git repository.
smolnar82 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 6110aea62 KNOX-3374: Skip redundant roles lookup in PreAuth/ExtAuthz
when the identity-assertion layer already resolved roles (#1306)
6110aea62 is described below
commit 6110aea6251b06eb563b6919192671f6913bb7c7
Author: Sandor Molnar <[email protected]>
AuthorDate: Wed Jul 15 17:36:50 2026 +0200
KNOX-3374: Skip redundant roles lookup in PreAuth/ExtAuthz when the
identity-assertion layer already resolved roles (#1306)
---
.../filter/AbstractIdentityAssertionFilter.java | 11 ++---
.../filter/CommonIdentityAssertionFilter.java | 4 +-
.../filter/CommonIdentityAssertionFilterTest.java | 2 +-
.../filter/ConcatIdentityAssertionFilter.java | 4 +-
.../filter/ConcatIdentityAssertionFilterTest.java | 2 +-
.../groups/filter/HadoopGroupProviderFilter.java | 14 +++---
.../filter/HadoopGroupProviderFilterTest.java | 41 ++++++++++++-----
.../filter/NoImpersonationFilter.java | 2 +-
.../filter/NoImpersonationFilterTest.java | 10 ++---
.../filter/IdentityAsserterFilter.java | 4 +-
.../filter/DefaultIdentityAssertionFilterTest.java | 10 ++---
.../regex/filter/RegexIdentityAssertionFilter.java | 3 +-
.../filter/RegexIdentityAssertionFilterTest.java | 2 +-
.../SwitchCaseIdentityAssertionFilter.java | 3 +-
.../SwitchCaseIdentityAssertionFilterTest.java | 16 +++----
.../services/ldap/KnoxLDAPServerManager.java | 13 +++---
.../gateway/services/ldap/KnoxLDAPService.java | 4 ++
.../services/ldap/KnoxLDAPServerManagerTest.java | 47 -------------------
.../ConfigurableEntriesTestInterceptor.java | 2 +-
.../gateway/service/auth/AbstractAuthResource.java | 13 +++++-
.../gateway/service/auth/ExtAuthzResource.java | 9 ++++
.../knox/gateway/service/auth/PreAuthResource.java | 9 ++++
.../gateway/service/auth/ExtAuthzResourceTest.java | 9 +++-
.../gateway/service/auth/PreAuthResourceTest.java | 52 ++++++++++++++++------
.../security/AbstractIdentityAssertionBase.java | 2 +
25 files changed, 170 insertions(+), 118 deletions(-)
diff --git
a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
index 81efb1511..128dd9dc3 100644
---
a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
+++
b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
@@ -54,8 +54,7 @@ import org.apache.knox.gateway.security.SubjectUtils;
import org.apache.knox.gateway.security.TokenExchangePrincipal;
import org.apache.knox.gateway.security.TokenIdPrincipal;
-public abstract class AbstractIdentityAssertionFilter extends
- AbstractIdentityAssertionBase implements Filter {
+public abstract class AbstractIdentityAssertionFilter extends
AbstractIdentityAssertionBase implements Filter {
private IdentityAsserterMessages LOG =
MessagesFactory.get(IdentityAsserterMessages.class);
@@ -70,15 +69,17 @@ public abstract class AbstractIdentityAssertionFilter
extends
}
/**
- * This method returns a Stringp[] of new group principal names to use
+ * This method returns a String[] of new group principal names to use
* based on implementation specific mapping or lookup mechanisms.
* Returning null means that whatever set of GroupPrincipals is in the
* provided Subject is sufficient to use and no additional mapping is
required.
+ *
* @param mappedPrincipalName username for the authenticated identity - post
mapUserPrincipal mapping.
- * @param subject the existing Subject from the authentication event which
may or may not contain GroupPrincipals.
+ * @param subject the existing Subject from the authentication
event which may or may not contain GroupPrincipals.
+ * @param request the request which may or may not be decorated
with extra attributes (e.g. if LDAP roles lookup happened already)
* @return String[] of new principal names to use as GroupPrincipals or null.
*/
- public abstract String[] mapGroupPrincipals(String mappedPrincipalName,
Subject subject);
+ public abstract String[] mapGroupPrincipals(String mappedPrincipalName,
Subject subject, ServletRequest request);
/**
* This method is used to map the username of the authenticated identity to
some other
diff --git
a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
index a9a3d154c..51a33de5a 100644
---
a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
+++
b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
@@ -270,7 +270,7 @@ public class CommonIdentityAssertionFilter extends
AbstractIdentityAssertionFilt
private String[] getGroupsForPrincipal(String mappedPrincipalName, Subject
subject, ServletRequest request) {
String[] mappedGroups = mapGroupPrincipalsBase(mappedPrincipalName,
subject);
- String[] groups = mapGroupPrincipals(mappedPrincipalName, subject);
+ String[] groups = mapGroupPrincipals(mappedPrincipalName, subject,
request);
String[] virtualGroups =
virtualGroupMapper.mapGroups(mappedPrincipalName, combine(subject, groups),
request).toArray(new String[0]);
groups = combineGroupMappings(mappedGroups, groups);
groups = combineGroupMappings(virtualGroups, groups);
@@ -353,7 +353,7 @@ public class CommonIdentityAssertionFilter extends
AbstractIdentityAssertionFilt
}
@Override
- public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject, ServletRequest request) {
// NOP
return null;
}
diff --git
a/gateway-provider-identity-assertion-common/src/test/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilterTest.java
b/gateway-provider-identity-assertion-common/src/test/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilterTest.java
index 942065b8a..92ee96305 100644
---
a/gateway-provider-identity-assertion-common/src/test/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilterTest.java
+++
b/gateway-provider-identity-assertion-common/src/test/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilterTest.java
@@ -75,7 +75,7 @@ public class CommonIdentityAssertionFilterTest {
}
@Override
- public String[] mapGroupPrincipals(String principalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String principalName, Subject
subject, ServletRequest request) {
String[] groups = new String[4];
int i = 0;
for(GroupPrincipal p :
subject.getPrincipals(GroupPrincipal.class)) {
diff --git
a/gateway-provider-identity-assertion-concat/src/main/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
index 655fec7f2..6c6f7323c 100644
---
a/gateway-provider-identity-assertion-concat/src/main/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
+++
b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
@@ -20,6 +20,8 @@ package
org.apache.knox.gateway.identityasserter.concat.filter;
import javax.security.auth.Subject;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+
import
org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
public class ConcatIdentityAssertionFilter extends
CommonIdentityAssertionFilter {
@@ -41,7 +43,7 @@ public class ConcatIdentityAssertionFilter extends
CommonIdentityAssertionFilter
}
@Override
- public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject, ServletRequest request) {
return null;
}
diff --git
a/gateway-provider-identity-assertion-concat/src/test/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
index 6286158fc..bcac87649 100644
---
a/gateway-provider-identity-assertion-concat/src/test/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
+++
b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/knox/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
@@ -55,7 +55,7 @@ public class ConcatIdentityAssertionFilterTest {
filter.init(config);
String username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(username, subject);
+ String[] groups = filter.mapGroupPrincipals(username, subject, null);
assertEquals(username, "larry");
assertNull(groups); // means for the caller to use the existing subject
groups
diff --git
a/gateway-provider-identity-assertion-hadoop-groups/src/main/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilter.java
b/gateway-provider-identity-assertion-hadoop-groups/src/main/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilter.java
index ae3936d67..16bf52980 100644
---
a/gateway-provider-identity-assertion-hadoop-groups/src/main/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilter.java
+++
b/gateway-provider-identity-assertion-hadoop-groups/src/main/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilter.java
@@ -23,6 +23,7 @@ import java.util.List;
import javax.security.auth.Subject;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.LdapGroupsMapping;
@@ -106,12 +107,11 @@ public class HadoopGroupProviderFilter extends
CommonIdentityAssertionFilter {
* provided user.
*/
@Override
- public String[] mapGroupPrincipals(final String mappedPrincipalName,
- final Subject subject) {
+ public String[] mapGroupPrincipals(final String mappedPrincipalName, final
Subject subject, ServletRequest request) {
/* return the groups as seen by Hadoop */
String[] groups;
try {
- final List<String> groupList = hadoopGroups(mappedPrincipalName);
+ final List<String> groupList = hadoopGroups(mappedPrincipalName,
request);
LOG.groupsFound(mappedPrincipalName, groupList.toString());
groups = groupList.toArray(new String[0]);
@@ -128,12 +128,16 @@ public class HadoopGroupProviderFilter extends
CommonIdentityAssertionFilter {
return groups;
}
- protected List<String> hadoopGroups(String mappedPrincipalName) throws
Exception {
+ protected List<String> hadoopGroups(String mappedPrincipalName,
ServletRequest request) throws Exception {
if (ldapService == null) {
return hadoopGroups == null ? List.of() :
hadoopGroups.getGroups(mappedPrincipalName);
} else {
LOG.useKnoxLDAPService();
- return ldapService.getUserGroups(mappedPrincipalName);
+ final List<String> groups =
ldapService.getUserGroups(mappedPrincipalName);
+ if (request != null && ldapService.hasRolesLookupInterceptor()) {
+ request.setAttribute(ROLES_LOOKUP_EXECUTED, Boolean.TRUE.toString());
+ }
+ return groups;
}
}
diff --git
a/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
b/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
index 52dad11ad..660bb4dda 100644
---
a/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
+++
b/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
@@ -34,6 +34,7 @@ import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
@@ -42,6 +43,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.security.GroupMappingServiceProvider;
import org.apache.hadoop.security.LdapGroupsMapping;
import org.apache.knox.gateway.config.GatewayConfig;
+import
org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter;
import
org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
import org.apache.knox.gateway.security.PrimaryPrincipal;
import org.apache.knox.gateway.services.GatewayServices;
@@ -99,7 +101,7 @@ public class HadoopGroupProviderFilterTest {
final String principal = filter.mapUserPrincipal(
((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
.getName());
- final String[] groups = filter.mapGroupPrincipals(principal, subject);
+ final String[] groups = filter.mapGroupPrincipals(principal, subject,
null);
assertThat(principal, is(username));
assertThat(
@@ -133,7 +135,7 @@ public class HadoopGroupProviderFilterTest {
final String principal = filter.mapUserPrincipal(
((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
.getName());
- final String[] groups = filter.mapGroupPrincipals(principal, subject);
+ final String[] groups = filter.mapGroupPrincipals(principal, subject,
null);
assertThat(principal, is(failUsername));
assertThat(
@@ -209,7 +211,7 @@ public class HadoopGroupProviderFilterTest {
final String principal = filter.mapUserPrincipal(
((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
.getName());
- final String[] groups = filter.mapGroupPrincipals(principal, subject);
+ final String[] groups = filter.mapGroupPrincipals(principal, subject,
null);
assertThat(principal, is(username));
@@ -253,7 +255,7 @@ public class HadoopGroupProviderFilterTest {
}
@Override
- protected List<String> hadoopGroups(String mappedPrincipalName) {
+ protected List<String> hadoopGroups(String mappedPrincipalName,
ServletRequest request) {
return Collections.singletonList("hadoop-group");
}
};
@@ -280,7 +282,7 @@ public class HadoopGroupProviderFilterTest {
subject.getPrincipals().add(new PrimaryPrincipal(username));
// no init() method called -> hadoopGroups is null
- final String[] groups = filter.mapGroupPrincipals(username, subject);
+ final String[] groups = filter.mapGroupPrincipals(username, subject, null);
assertThat(groups.length, is(0));
}
@@ -288,15 +290,21 @@ public class HadoopGroupProviderFilterTest {
@Test
public void testLdapServiceIntegration() throws Exception {
KnoxLDAPService ldapService =
EasyMock.createNiceMock(KnoxLDAPService.class);
- doTestLdapServiceIntegration(true, Arrays.asList("group1", "group2"),
ldapService);
+ doTestLdapServiceIntegration(true, Arrays.asList("group1", "group2"),
ldapService, false);
}
@Test
public void testFallbackToHadoopGroupsWhenLdapDisabled() throws Exception {
- doTestLdapServiceIntegration(false,
Collections.singletonList("hadoop-group"), null);
+ doTestLdapServiceIntegration(false,
Collections.singletonList("hadoop-group"), null, false);
}
- private void doTestLdapServiceIntegration(boolean ldapEnabled, List<String>
expectedGroups, KnoxLDAPService ldapService) throws Exception {
+ @Test
+ public void testLdapServiceIntegrationWithRolesLookupInterceptor() throws
Exception {
+ KnoxLDAPService ldapService =
EasyMock.createNiceMock(KnoxLDAPService.class);
+ doTestLdapServiceIntegration(true, Arrays.asList("group1", "group2"),
ldapService, true);
+ }
+
+ private void doTestLdapServiceIntegration(boolean ldapEnabled, List<String>
expectedGroups, KnoxLDAPService ldapService, boolean hasRolesLookupInterceptor)
throws Exception {
final String principalName = "test-user";
FilterConfig config = EasyMock.createNiceMock(FilterConfig.class);
@@ -314,6 +322,7 @@ public class HadoopGroupProviderFilterTest {
EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(services).anyTimes();
EasyMock.expect(services.getService(ServiceType.LDAP_SERVICE)).andReturn(ldapService).anyTimes();
EasyMock.expect(ldapService.getUserGroups(principalName)).andReturn(expectedGroups).anyTimes();
+
EasyMock.expect(ldapService.hasRolesLookupInterceptor()).andReturn(hasRolesLookupInterceptor).anyTimes();
EasyMock.replay(services, ldapService);
} else {
EasyMock.expect(config.getInitParameterNames()).andReturn(Collections.emptyEnumeration()).anyTimes();
@@ -323,8 +332,8 @@ public class HadoopGroupProviderFilterTest {
HadoopGroupProviderFilter filter = new HadoopGroupProviderFilter() {
@Override
- protected List<String> hadoopGroups(String mappedPrincipalName) throws
Exception {
- return ldapEnabled ? super.hadoopGroups(mappedPrincipalName) :
expectedGroups;
+ protected List<String> hadoopGroups(String mappedPrincipalName,
ServletRequest request) throws Exception {
+ return ldapEnabled ? super.hadoopGroups(mappedPrincipalName, request)
: expectedGroups;
}
};
filter.init(config);
@@ -332,11 +341,21 @@ public class HadoopGroupProviderFilterTest {
Subject subject = new Subject();
subject.getPrincipals().add(new PrimaryPrincipal(principalName));
- String[] groups = filter.mapGroupPrincipals(principalName, subject);
+ final ServletRequest request =
EasyMock.createNiceMock(ServletRequest.class);
+ if (hasRolesLookupInterceptor) {
+
request.setAttribute(AbstractIdentityAssertionFilter.ROLES_LOOKUP_EXECUTED,
"true");
+ EasyMock.expectLastCall().atLeastOnce();
+ }
+ EasyMock.replay(request);
+
+ String[] groups = filter.mapGroupPrincipals(principalName, subject,
request);
assertThat(Arrays.asList(groups), is(expectedGroups));
if (ldapEnabled) {
EasyMock.verify(ldapService);
+ if (hasRolesLookupInterceptor) {
+ EasyMock.verify(request);
+ }
}
}
}
diff --git
a/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
index b276f5364..c403ce787 100644
---
a/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
+++
b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
@@ -35,7 +35,7 @@ public class NoImpersonationFilter extends
CommonIdentityAssertionFilter {
}
@Override
- public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject, ServletRequest request) {
return mapGroupPrincipalsBase(mappedPrincipalName, subject);
}
diff --git
a/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
index 197af20d3..434141127 100644
---
a/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
+++
b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
@@ -63,7 +63,7 @@ public class NoImpersonationFilterTest {
filter.init(config);
String username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(username, subject);
+ String[] groups = filter.mapGroupPrincipals(username, subject, null);
assertEquals("lmccay", username);
assertNull(groups); // means for the caller to use the existing subject
groups
@@ -81,7 +81,7 @@ public class NoImpersonationFilterTest {
EasyMock.replay( context, config );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ String[] mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("mrgroup not found in groups: " +
Arrays.toString(mappedGroups), groupFoundIn("mrgroup", mappedGroups));
assertTrue("mrducks not found in groups: " +
Arrays.toString(mappedGroups), groupFoundIn("mrducks", mappedGroups));
@@ -107,7 +107,7 @@ public class NoImpersonationFilterTest {
EasyMock.replay(context, config );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("group1 not found in groups: " + Arrays.toString(mappedGroups),
groupFoundIn("group1", mappedGroups));
}
@@ -148,7 +148,7 @@ public class NoImpersonationFilterTest {
filter.init(config);
String username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ String[] groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("lmccay", username);
assertNull(groups); // means for the caller to use the existing subject
groups
@@ -165,7 +165,7 @@ public class NoImpersonationFilterTest {
EasyMock.replay( context );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("mrgroup not found in groups: " + Arrays.toString(groups),
groupFoundIn("mrgroup", groups));
assertTrue("mrducks not found in groups: " + Arrays.toString(groups),
groupFoundIn("mrducks", groups));
diff --git
a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/knox/gateway/identityasserter/filter/IdentityAsserterFilter.java
b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/knox/gateway/identityasserter/filter/IdentityAsserterFilter.java
index db19c226e..44717c1fe 100644
---
a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/knox/gateway/identityasserter/filter/IdentityAsserterFilter.java
+++
b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/knox/gateway/identityasserter/filter/IdentityAsserterFilter.java
@@ -21,6 +21,8 @@ package org.apache.knox.gateway.identityasserter.filter;
import javax.security.auth.Subject;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+
import
org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
public class IdentityAsserterFilter extends CommonIdentityAssertionFilter {
@@ -31,7 +33,7 @@ public class IdentityAsserterFilter extends
CommonIdentityAssertionFilter {
}
@Override
- public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject, ServletRequest request) {
return mapGroupPrincipalsBase(mappedPrincipalName, subject);
}
diff --git
a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/knox/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/knox/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
index 6ba32b298..f64a8db04 100644
---
a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/knox/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
+++
b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/knox/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
@@ -63,7 +63,7 @@ public class DefaultIdentityAssertionFilterTest {
filter.init(config);
String username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(username, subject);
+ String[] groups = filter.mapGroupPrincipals(username, subject, null);
assertEquals("lmccay", username);
assertNull(groups); // means for the caller to use the existing subject
groups
@@ -81,7 +81,7 @@ public class DefaultIdentityAssertionFilterTest {
EasyMock.replay( context, config );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ String[] mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("mrgroup not found in groups: " +
Arrays.toString(mappedGroups), groupFoundIn("mrgroup", mappedGroups));
assertTrue("mrducks not found in groups: " +
Arrays.toString(mappedGroups), groupFoundIn("mrducks", mappedGroups));
@@ -107,7 +107,7 @@ public class DefaultIdentityAssertionFilterTest {
EasyMock.replay( context, config );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ mappedGroups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("group1 not found in groups: " + Arrays.toString(mappedGroups),
groupFoundIn("group1", mappedGroups));
}
@@ -148,7 +148,7 @@ public class DefaultIdentityAssertionFilterTest {
filter.init(config);
String username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ String[] groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("lmccay", username);
assertNull(groups); // means for the caller to use the existing subject
groups
@@ -165,7 +165,7 @@ public class DefaultIdentityAssertionFilterTest {
EasyMock.replay( context );
filter.init(config);
username = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ groups = filter.mapGroupPrincipals(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject,
null);
assertEquals("hdfs", username);
assertTrue("mrgroup not found in groups: " + Arrays.toString(groups),
groupFoundIn("mrgroup", groups));
assertTrue("mrducks not found in groups: " + Arrays.toString(groups),
groupFoundIn("mrducks", groups));
diff --git
a/gateway-provider-identity-assertion-regex/src/main/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilter.java
b/gateway-provider-identity-assertion-regex/src/main/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilter.java
index 3ddc41a1c..d1496ed34 100644
---
a/gateway-provider-identity-assertion-regex/src/main/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilter.java
+++
b/gateway-provider-identity-assertion-regex/src/main/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilter.java
@@ -20,6 +20,7 @@ package org.apache.knox.gateway.identityasserter.regex.filter;
import javax.security.auth.Subject;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
import
org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
import org.apache.knox.gateway.security.principal.PrincipalMappingException;
@@ -57,7 +58,7 @@ public class RegexIdentityAssertionFilter extends
}
@Override
- public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject) {
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject
subject, ServletRequest request) {
// Returning null will allow existing Subject group principals to remain
the same
return null;
}
diff --git
a/gateway-provider-identity-assertion-regex/src/test/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilterTest.java
b/gateway-provider-identity-assertion-regex/src/test/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilterTest.java
index 21d77cc72..5ff263e8e 100644
---
a/gateway-provider-identity-assertion-regex/src/test/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilterTest.java
+++
b/gateway-provider-identity-assertion-regex/src/test/java/org/apache/knox/gateway/identityasserter/regex/filter/RegexIdentityAssertionFilterTest.java
@@ -58,7 +58,7 @@ public class RegexIdentityAssertionFilterTest {
// First test is with no config. Since the output template is the empty
string that should be the result.
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "" ) );
assertThat( groups, is( nullValue() ) ); // means for the caller to use
the existing subject groups
diff --git
a/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
b/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
index 3e83ea02f..0cc2481a0 100644
---
a/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
+++
b/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
@@ -23,6 +23,7 @@ import org.apache.knox.gateway.security.GroupPrincipal;
import javax.security.auth.Subject;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
import java.util.Locale;
import java.util.Set;
@@ -69,7 +70,7 @@ public class SwitchCaseIdentityAssertionFilter extends
}
@Override
- public String[] mapGroupPrincipals( String mappedPrincipalName, Subject
subject ) {
+ public String[] mapGroupPrincipals( String mappedPrincipalName, Subject
subject, ServletRequest request) {
String[] groupNames = null;
if ( groupCase != SwitchCase.NONE ) {
Set<GroupPrincipal> groups = subject.getPrincipals( GroupPrincipal.class
);
diff --git
a/gateway-provider-identity-assertion-switchcase/src/test/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilterTest.java
b/gateway-provider-identity-assertion-switchcase/src/test/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilterTest.java
index bfb25ea57..d322b1499 100644
---
a/gateway-provider-identity-assertion-switchcase/src/test/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilterTest.java
+++
b/gateway-provider-identity-assertion-switchcase/src/test/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilterTest.java
@@ -57,7 +57,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( arrayContainingInAnyOrder( "admin", "users" ) ) );
@@ -86,7 +86,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( arrayContainingInAnyOrder( "ADMIN", "USERS" ) ) );
@@ -114,7 +114,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( arrayContainingInAnyOrder( "admin", "users" ) ) );
@@ -140,7 +140,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( nullValue() ) );
@@ -168,7 +168,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( arrayContainingInAnyOrder( "ADMIN", "USERS" ) ) );
@@ -196,7 +196,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( nullValue() ) );
@@ -224,7 +224,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( nullValue() ) );
@@ -251,7 +251,7 @@ public class SwitchCaseIdentityAssertionFilterTest {
filter.init(config);
String actual = filter.mapUserPrincipal(((Principal)
subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
- String[] groups = filter.mapGroupPrincipals(actual, subject);
+ String[] groups = filter.mapGroupPrincipals(actual, subject, null);
assertThat( actual, is( "[email protected]" ) );
assertThat( groups, is( nullValue() ) );
diff --git
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
index 4f30fa80c..30b6d0d0b 100644
---
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
+++
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
@@ -46,8 +46,8 @@ import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.services.GatewayServices;
import
org.apache.knox.gateway.services.ldap.control.RolesLookupBypassControlFactory;
-import
org.apache.knox.gateway.services.ldap.control.RolesLookupBypassControlImpl;
import org.apache.knox.gateway.services.ldap.interceptor.InterceptorFactory;
+import
org.apache.knox.gateway.services.ldap.interceptor.LDAPRolesLookupInterceptor;
import org.apache.knox.gateway.services.security.AliasService;
import java.io.File;
@@ -75,6 +75,7 @@ public class KnoxLDAPServerManager {
private LdapServer ldapServer;
private GatewayConfig gatewayConfig;
private List<Interceptor> interceptors;
+ private boolean hasRolesLookupInterceptor;
private File workDir;
private int port;
private String baseDn;
@@ -126,6 +127,8 @@ public class KnoxLDAPServerManager {
createInterceptors(config);
+ hasRolesLookupInterceptor = interceptors.stream().anyMatch(interceptor
-> interceptor instanceof LDAPRolesLookupInterceptor);
+
// Clean up previous run if it didn't shut down cleanly
File lockFile = new File(workDir, "run/instance.lock");
if (lockFile.exists()) {
@@ -455,10 +458,6 @@ public class KnoxLDAPServerManager {
searchRequest.setFilter("(uid=" + username + ")");
searchRequest.addAttributes("*");
- RolesLookupBypassControlImpl bypassControl = new
RolesLookupBypassControlImpl();
- bypassControl.setBypassRolesLookup(true);
- searchRequest.addControl(bypassControl);
-
List<String> groups = new ArrayList<>();
try (Cursor<Entry> cursor =
directoryService.getAdminSession().search(searchRequest)) {
if (cursor.next()) {
@@ -481,6 +480,10 @@ public class KnoxLDAPServerManager {
return groups;
}
+ public boolean hasRolesLookupInterceptor() {
+ return hasRolesLookupInterceptor;
+ }
+
/**
* Check if the LDAP server is currently running.
*
diff --git
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
index f1ccbb321..25dae6fbf 100644
---
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
+++
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
@@ -144,4 +144,8 @@ public class KnoxLDAPService implements Service,
GatewayConfigChangeListener {
public List<String> getUserGroups(String username) throws Exception {
return ldapServerManager == null ? List.of() :
ldapServerManager.getUserGroups(username);
}
+
+ public boolean hasRolesLookupInterceptor() {
+ return ldapServerManager != null &&
ldapServerManager.hasRolesLookupInterceptor();
+ }
}
diff --git
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
index 78631552c..bb7dde208 100644
---
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
+++
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
@@ -19,14 +19,11 @@ package org.apache.knox.gateway.services.ldap;
import org.apache.directory.api.ldap.codec.api.ControlFactory;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
-import org.apache.directory.api.ldap.model.entry.Entry;
import
org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapException;
import
org.apache.directory.api.ldap.model.exception.LdapProtocolErrorException;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.server.core.api.interceptor.Interceptor;
@@ -34,8 +31,6 @@ import org.apache.knox.gateway.util.X509CertificateUtil;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.security.AliasService;
import
org.apache.knox.gateway.services.ldap.control.RolesLookupBypassControlFactory;
-import
org.apache.knox.gateway.services.ldap.interceptor.ConfigurableEntriesTestInterceptor;
-import
org.apache.knox.gateway.services.ldap.interceptor.LDAPRolesLookupInterceptor;
import org.apache.knox.gateway.services.ldap.model.constants.SchemaConstants;
import org.easymock.EasyMock;
import org.apache.directory.api.ldap.model.name.Dn;
@@ -60,15 +55,12 @@ import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
@@ -435,45 +427,6 @@ public class KnoxLDAPServerManagerTest {
assertTrue(controlFactoryMap.get(SchemaConstants.ROLES_LOOKUP_BYPASS_CONTROL_OID)
instanceof RolesLookupBypassControlFactory);
}
- @Test
- public void
testGetUserGroupsReturnsRawGroupsEvenWhenRolesInterceptorRewritesMemberOf()
throws Exception {
- GatewayConfig mockConfig =
EasyMock.createNiceMock(GatewayConfig.class);
-
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
- expect(mockConfig.getLDAPPort()).andReturn(port).anyTimes();
-
expect(mockConfig.getLDAPBaseDN()).andReturn("dc=test,dc=com").anyTimes();
-
expect(mockConfig.getLDAPInterceptorNames()).andReturn(List.of()).anyTimes();
- replay(mockConfig);
-
- serverManager.initialize(mockConfig);
- serverManager.start();
-
- SchemaManager schemaManager =
serverManager.directoryService.getSchemaManager();
- Entry userEntry = new DefaultEntry(schemaManager);
- userEntry.setDn("uid=admin,ou=people,dc=test,dc=com");
- userEntry.add("uid", "admin");
- userEntry.add("memberOf",
"cn=me-test-group-a,ou=groups,dc=test,dc=com");
- userEntry.add("memberOf",
"cn=me-test-group-b,ou=groups,dc=test,dc=com");
- ConfigurableEntriesTestInterceptor entriesInterceptor = new
ConfigurableEntriesTestInterceptor("testEntries");
- entriesInterceptor.setEntries(List.of(userEntry));
- entriesInterceptor.init(serverManager.directoryService);
-
- LDAPRolesLookupService mockRolesService =
EasyMock.createNiceMock(LDAPRolesLookupService.class);
- expect(mockRolesService.lookupRoles(anyString(), anyObject()))
- .andReturn(Arrays.asList("console:admin", "ws-1:viewer",
"ws-2:user")).anyTimes();
- replay(mockRolesService);
- LDAPRolesLookupInterceptor rolesInterceptor = new
LDAPRolesLookupInterceptor(mockRolesService);
- rolesInterceptor.init(serverManager.directoryService);
-
- List<Interceptor> chain = new
ArrayList<>(serverManager.directoryService.getInterceptors());
- chain.add(0, rolesInterceptor);
- chain.add(1, entriesInterceptor);
- serverManager.directoryService.setInterceptors(chain);
-
- List<String> groups = serverManager.getUserGroups("admin");
-
- assertEquals(Arrays.asList("me-test-group-a", "me-test-group-b"),
groups);
- }
-
@Test(expected = LdapException.class)
public void testBindRequiredRejectsAnonymous() throws Exception {
useBindPassword(BIND_PASSWORD);
diff --git
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/interceptor/ConfigurableEntriesTestInterceptor.java
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/interceptor/ConfigurableEntriesTestInterceptor.java
index a8507c614..27ac17f86 100644
---
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/interceptor/ConfigurableEntriesTestInterceptor.java
+++
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/interceptor/ConfigurableEntriesTestInterceptor.java
@@ -35,7 +35,7 @@ public class ConfigurableEntriesTestInterceptor extends
BaseInterceptor {
private List<Entry> entries;
private EntryFilteringCursor cursor;
- public ConfigurableEntriesTestInterceptor(String name) {
+ ConfigurableEntriesTestInterceptor(String name) {
super(name);
}
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 4e844d643..8ed3aa660 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
@@ -17,6 +17,7 @@
*/
package org.apache.knox.gateway.service.auth;
+import org.apache.knox.gateway.filter.security.AbstractIdentityAssertionBase;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.security.SubjectUtils;
import org.apache.knox.gateway.services.GatewayServices;
@@ -26,6 +27,7 @@ import org.apache.knox.gateway.util.GroupUtils;
import javax.security.auth.Subject;
import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Response;
import java.util.Collection;
@@ -86,6 +88,8 @@ public abstract class AbstractAuthResource {
/* Abstract method that gets context instance */
abstract ServletContext getContext();
+ abstract ServletRequest getRequest();
+
String getInitParameter(String paramName, String defaultValue) {
final String initParam = getContext().getInitParameter(paramName);
return initParam == null ? defaultValue : initParam;
@@ -110,7 +114,7 @@ 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 ? authHeaderActorGroupsPrefix :
String.format(Locale.ROOT, ACTOR_GROUPS_HEADER_FORMAT,
authHeaderActorGroupsPrefix, i + 1);
+ final String headerName = useRoles || rolesLookupExecuted() ?
authHeaderActorGroupsPrefix : String.format(Locale.ROOT,
ACTOR_GROUPS_HEADER_FORMAT, authHeaderActorGroupsPrefix, i + 1);
getResponse().addHeader(headerName, groupStrings.get(i));
}
}
@@ -120,7 +124,7 @@ public abstract class AbstractAuthResource {
private Collection<String> lookupRoles(String userName, Collection<String>
groups) {
Collection<String> roles = null;
try {
- if (ldapRolesLookupService != null &&
ldapRolesLookupService.enabled()) {
+ if (!rolesLookupExecuted() && ldapRolesLookupService != null &&
ldapRolesLookupService.enabled()) {
roles = ldapRolesLookupService.lookupRoles(userName, groups);
}
} catch (Exception e) {
@@ -130,4 +134,9 @@ public abstract class AbstractAuthResource {
return roles == null ? Collections.emptySet() : roles;
}
+ private boolean rolesLookupExecuted() {
+ final Object rolesLookupExecutedReqAttribute = getRequest() == null ? null
:
getRequest().getAttribute(AbstractIdentityAssertionBase.ROLES_LOOKUP_EXECUTED);
+ return rolesLookupExecutedReqAttribute != null &&
Boolean.parseBoolean(rolesLookupExecutedReqAttribute.toString());
+ }
+
}
diff --git
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/ExtAuthzResource.java
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/ExtAuthzResource.java
index 5cd90e01e..59318d363 100644
---
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/ExtAuthzResource.java
+++
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/ExtAuthzResource.java
@@ -19,6 +19,7 @@ package org.apache.knox.gateway.service.auth;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@@ -39,6 +40,9 @@ public class ExtAuthzResource extends AbstractAuthResource {
private boolean ignoreAdditionalPath;
+ @Context
+ HttpServletRequest request;
+
@Context
HttpServletResponse response;
@@ -51,6 +55,11 @@ public class ExtAuthzResource extends AbstractAuthResource {
ignoreAdditionalPath =
Boolean.parseBoolean(getInitParameter(IGNORE_ADDITIONAL_PATH,
DEFAULT_IGNORE_ADDITIONAL_PATH));
}
+ @Override
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+
@Override
HttpServletResponse getResponse() {
return response;
diff --git
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/PreAuthResource.java
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/PreAuthResource.java
index 335a25fd7..6cd9dd98c 100644
---
a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/PreAuthResource.java
+++
b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/PreAuthResource.java
@@ -19,6 +19,7 @@ package org.apache.knox.gateway.service.auth;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.DELETE;
@@ -34,6 +35,9 @@ public class PreAuthResource extends AbstractAuthResource {
static final String RESOURCE_PATH = "auth/api/v1/pre";
+ @Context
+ HttpServletRequest request;
+
@Context
HttpServletResponse response;
@@ -44,6 +48,11 @@ public class PreAuthResource extends AbstractAuthResource {
initialize();
}
+ @Override
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+
@Override
HttpServletResponse getResponse() {
return response;
diff --git
a/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/ExtAuthzResourceTest.java
b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/ExtAuthzResourceTest.java
index 9d093973d..8e5fd90b8 100644
---
a/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/ExtAuthzResourceTest.java
+++
b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/ExtAuthzResourceTest.java
@@ -17,6 +17,7 @@
*/
package org.apache.knox.gateway.service.auth;
+import org.apache.knox.gateway.filter.security.AbstractIdentityAssertionBase;
import org.apache.knox.gateway.security.GroupPrincipal;
import org.apache.knox.gateway.security.PrimaryPrincipal;
import org.apache.knox.gateway.security.SubjectUtils;
@@ -64,6 +65,7 @@ public class ExtAuthzResourceTest {
final ExtAuthzResource extAuthzResource = new ExtAuthzResource();
extAuthzResource.context = context;
extAuthzResource.response = response;
+ extAuthzResource.request = request;
executeResourceWithAdditionalPath(extAuthzResource);
EasyMock.verify(response);
}
@@ -75,6 +77,7 @@ public class ExtAuthzResourceTest {
EasyMock.expect(context.getInitParameter(ExtAuthzResource.AUTH_ACTOR_GROUPS_HEADER_PREFIX)).andReturn(groupsHeaderPrefix).anyTimes();
EasyMock.expect(context.getInitParameter(ExtAuthzResource.IGNORE_ADDITIONAL_PATH)).andReturn("true").anyTimes();
request = EasyMock.createNiceMock(HttpServletRequest.class);
+
EasyMock.expect(request.getAttribute(AbstractIdentityAssertionBase.ROLES_LOOKUP_EXECUTED)).andReturn("false").anyTimes();
response = EasyMock.createNiceMock(HttpServletResponse.class);
if (SubjectUtils.getPrimaryPrincipalName(subject) != null) {
@@ -122,13 +125,17 @@ public class ExtAuthzResourceTest {
response.addHeader(EasyMock.eq(AbstractAuthResource.DEFAULT_AUTH_ACTOR_GROUPS_HEADER_PREFIX),
EasyMock.anyString());
EasyMock.expectLastCall().anyTimes();
- EasyMock.replay(context, response, mockRolesService, mockGatewayServices);
+ request = EasyMock.createNiceMock(HttpServletRequest.class);
+
EasyMock.expect(request.getAttribute(AbstractIdentityAssertionBase.ROLES_LOOKUP_EXECUTED)).andReturn("false").anyTimes();
+
+ EasyMock.replay(context, request, response, mockRolesService,
mockGatewayServices);
groups.forEach(group -> subject.getPrincipals().add(new
GroupPrincipal(group)));
final ExtAuthzResource extAuthzResource = new ExtAuthzResource();
extAuthzResource.context = context;
extAuthzResource.response = response;
+ extAuthzResource.request = request;
executeResourceWithAdditionalPath(extAuthzResource);
EasyMock.verify(response);
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 78c019d62..5e1496c83 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
@@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Response;
+import org.apache.knox.gateway.filter.security.AbstractIdentityAssertionBase;
import org.apache.knox.gateway.security.GroupPrincipal;
import org.apache.knox.gateway.security.PrimaryPrincipal;
import org.apache.knox.gateway.security.SubjectUtils;
@@ -48,6 +49,7 @@ public class PreAuthResourceTest {
private static final String USER_NAME = "test-username";
private ServletContext context;
+ private HttpServletRequest request;
private HttpServletResponse response;
private final Subject subject = new Subject();
@@ -61,14 +63,15 @@ public class PreAuthResourceTest {
}
private void configureCommonExpectations(String actorIdHeaderName, String
groupsHeaderPrefix, Collection<String> groups) throws Exception {
- configureCommonExpectations(actorIdHeaderName, groupsHeaderPrefix, groups,
null);
+ configureCommonExpectations(actorIdHeaderName, groupsHeaderPrefix, groups,
null, false);
}
- private void configureCommonExpectations(String actorIdHeaderName, String
groupsHeaderPrefix, Collection<String> groups, GatewayServices gatewayServices)
throws Exception {
+ private void configureCommonExpectations(String actorIdHeaderName, String
groupsHeaderPrefix, Collection<String> groups, GatewayServices gatewayServices,
boolean rolesLookupExecuted) throws Exception {
context = EasyMock.createNiceMock(ServletContext.class);
EasyMock.expect(context.getInitParameter(PreAuthResource.AUTH_ACTOR_ID_HEADER_NAME)).andReturn(actorIdHeaderName).anyTimes();
EasyMock.expect(context.getInitParameter(PreAuthResource.AUTH_ACTOR_GROUPS_HEADER_PREFIX)).andReturn(groupsHeaderPrefix).anyTimes();
- final HttpServletRequest request =
EasyMock.createNiceMock(HttpServletRequest.class);
+ request = EasyMock.createNiceMock(HttpServletRequest.class);
+
EasyMock.expect(request.getAttribute(AbstractIdentityAssertionBase.ROLES_LOOKUP_EXECUTED)).andReturn(rolesLookupExecuted).anyTimes();
response = EasyMock.createNiceMock(HttpServletResponse.class);
if (SubjectUtils.getPrimaryPrincipalName(subject) != null) {
@@ -81,12 +84,12 @@ public class PreAuthResourceTest {
EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(gatewayServices);
final LDAPRolesLookupService rolesLookupService =
gatewayServices.getService(ServiceType.LDAP_ROLES_LOOKUP_SERVICE);
if (rolesLookupService != null && rolesLookupService.enabled()) {
- Collection<String> roles = rolesLookupService.lookupRoles(USER_NAME,
groups);
- if (roles != null && !roles.isEmpty()) {
final String expectedGroupsHeaderPrefix = (groupsHeaderPrefix ==
null ? PreAuthResource.DEFAULT_AUTH_ACTOR_GROUPS_HEADER_PREFIX :
groupsHeaderPrefix);
response.addHeader(EasyMock.eq(expectedGroupsHeaderPrefix),
EasyMock.anyString());
- EasyMock.expectLastCall().anyTimes();
- }
+ EasyMock.expectLastCall().times(1);
+ }
+ if (rolesLookupExecuted) {
+ groups.forEach(group -> subject.getPrincipals().add(new
GroupPrincipal(group)));
}
} else if (!groups.isEmpty()) {
groups.forEach(group -> subject.getPrincipals().add(new
GroupPrincipal(group)));
@@ -117,6 +120,7 @@ public class PreAuthResourceTest {
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
final Response response = executeResourceWithSubject(preAuthResource);
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus());
}
@@ -127,6 +131,7 @@ public class PreAuthResourceTest {
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
executeResourceWithSubject(preAuthResource);
EasyMock.verify(response);
}
@@ -137,6 +142,7 @@ public class PreAuthResourceTest {
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
executeResourceWithSubject(preAuthResource);
EasyMock.verify(response);
}
@@ -147,6 +153,7 @@ public class PreAuthResourceTest {
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
executeResourceWithSubject(preAuthResource);
EasyMock.verify(response);
}
@@ -157,29 +164,47 @@ public class PreAuthResourceTest {
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 GatewayServices gatewayServices =
configureLdapRolesLookupExpectations();
-
configureCommonExpectations(PreAuthResource.DEFAULT_AUTH_ACTOR_ID_HEADER_NAME,
null, Collections.singleton("engineering"), gatewayServices);
+ final String rolesHeader = "X-Knox-Roles";
+ final GatewayServices gatewayServices =
configureLdapRolesLookupExpectations(false);
+
configureCommonExpectations(PreAuthResource.DEFAULT_AUTH_ACTOR_ID_HEADER_NAME,
rolesHeader, Collections.singleton("engineering"), gatewayServices, false);
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
Response preAuthResponse = executeResourceWithSubject(preAuthResource);
assertEquals(HttpServletResponse.SC_OK, preAuthResponse.getStatus());
EasyMock.verify(response);
}
- private GatewayServices configureLdapRolesLookupExpectations() throws
Exception {
+ @Test
+ public void testRolesAreNotPopulatedTwice() throws Exception {
+ final String rolesHeader = "X-Knox-Roles";
+ final GatewayServices gatewayServices =
configureLdapRolesLookupExpectations(true);
+
configureCommonExpectations(PreAuthResource.DEFAULT_AUTH_ACTOR_ID_HEADER_NAME,
rolesHeader, Collections.singleton("engineering"), gatewayServices, true);
+ final PreAuthResource preAuthResource = new PreAuthResource();
+ preAuthResource.context = context;
+ preAuthResource.response = response;
+ preAuthResource.request = request;
+ Response preAuthResponse = executeResourceWithSubject(preAuthResource);
+ assertEquals(HttpServletResponse.SC_OK, preAuthResponse.getStatus());
+ EasyMock.verify(response);
+ }
+
+ private GatewayServices configureLdapRolesLookupExpectations(boolean
roleLookupExecuted) throws Exception {
final String role1 = "platform:admin";
final String role2 = "ml-workspace:viewer";
- final Set<String> groups = Collections.singleton("engineering");
- final LDAPRolesLookupService rolesLookupService =
EasyMock.createNiceMock(LDAPRolesLookupService.class);
+ final LDAPRolesLookupService rolesLookupService =
EasyMock.createMock(LDAPRolesLookupService.class);
EasyMock.expect(rolesLookupService.enabled()).andReturn(true).anyTimes();
- EasyMock.expect(rolesLookupService.lookupRoles(EasyMock.eq(USER_NAME),
EasyMock.anyObject())).andReturn(Arrays.asList(role1, role2)).anyTimes();
+ if (!roleLookupExecuted) {
+ EasyMock.expect(rolesLookupService.lookupRoles(EasyMock.eq(USER_NAME),
EasyMock.anyObject())).andReturn(Arrays.asList(role1, role2)).anyTimes();
+ }
final GatewayServices gatewayServices =
EasyMock.createNiceMock(GatewayServices.class);
EasyMock.expect(gatewayServices.getService(ServiceType.LDAP_ROLES_LOOKUP_SERVICE)).andReturn(rolesLookupService).anyTimes();
@@ -203,6 +228,7 @@ public class PreAuthResourceTest {
final PreAuthResource preAuthResource = new PreAuthResource();
preAuthResource.context = context;
preAuthResource.response = response;
+ preAuthResource.request = request;
executeResourceWithSubject(preAuthResource);
EasyMock.verify(response);
}
diff --git
a/gateway-spi/src/main/java/org/apache/knox/gateway/filter/security/AbstractIdentityAssertionBase.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/filter/security/AbstractIdentityAssertionBase.java
index 0ee186395..25909aff7 100644
---
a/gateway-spi/src/main/java/org/apache/knox/gateway/filter/security/AbstractIdentityAssertionBase.java
+++
b/gateway-spi/src/main/java/org/apache/knox/gateway/filter/security/AbstractIdentityAssertionBase.java
@@ -23,6 +23,8 @@ import javax.security.auth.Subject;
public class AbstractIdentityAssertionBase {
+ public static final String ROLES_LOOKUP_EXECUTED = "ROLES_LOOKUP_EXECUTED";
+
/**
* Retrieve the principal to represent the asserted identity from
* the provided Subject.