[
https://issues.apache.org/jira/browse/KNOX-3048?focusedWorklogId=970005&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-970005
]
ASF GitHub Bot logged work on KNOX-3048:
----------------------------------------
Author: ASF GitHub Bot
Created on: 20/May/25 13:15
Start Date: 20/May/25 13:15
Worklog Time Spent: 10m
Work Description: moresandeep commented on code in PR #1043:
URL: https://github.com/apache/knox/pull/1043#discussion_r2097948923
##########
gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java:
##########
@@ -62,286 +35,318 @@
import org.apache.knox.gateway.util.AuthorizationException;
import org.apache.knox.gateway.util.HttpExceptionUtils;
+import javax.security.auth.Subject;
+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;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.stream.Collectors;
+
+import static
org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor.IMPERSONATION_PARAMS;
+import static
org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor.ROLE;
+import static
org.apache.knox.gateway.identityasserter.common.filter.VirtualGroupMapper.addRequestFunctions;
+
public class CommonIdentityAssertionFilter extends
AbstractIdentityAssertionFilter {
- private static final IdentityAsserterMessages LOG =
MessagesFactory.get(IdentityAsserterMessages.class);
-
- public static final String VIRTUAL_GROUP_MAPPING_PREFIX = "group.mapping.";
- public static final String GROUP_PRINCIPAL_MAPPING =
"group.principal.mapping";
- public static final String PRINCIPAL_MAPPING = "principal.mapping";
- public static final String ADVANCED_PRINCIPAL_MAPPING =
"expression.principal.mapping";
- private static final String PRINCIPAL_PARAM = "user.name";
- private static final String DOAS_PRINCIPAL_PARAM = "doAs";
- static final String IMPERSONATION_ENABLED_PARAM =
AuthFilterUtils.PROXYUSER_PREFIX + ".impersonation.enabled";
-
- private SimplePrincipalMapper mapper = new SimplePrincipalMapper();
- private final Parser parser = new Parser();
- private VirtualGroupMapper virtualGroupMapper;
- /* List of all default and configured impersonation params */
- protected final List<String> impersonationParamsList = new ArrayList<>();
- protected boolean impersonationEnabled;
- private AbstractSyntaxTree expressionPrincipalMapping;
- private String topologyName;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- topologyName = (String)
filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE);
- String principalMapping = filterConfig.getInitParameter(PRINCIPAL_MAPPING);
- if (principalMapping == null || principalMapping.isEmpty()) {
- principalMapping =
filterConfig.getServletContext().getInitParameter(PRINCIPAL_MAPPING);
+ public static final String VIRTUAL_GROUP_MAPPING_PREFIX = "group.mapping.";
+ public static final String GROUP_PRINCIPAL_MAPPING =
"group.principal.mapping";
+ public static final String PRINCIPAL_MAPPING = "principal.mapping";
+ public static final String ADVANCED_PRINCIPAL_MAPPING =
"expression.principal.mapping";
+ private static final IdentityAsserterMessages LOG =
MessagesFactory.get(IdentityAsserterMessages.class);
+ private static final String PRINCIPAL_PARAM = "user.name";
+ private static final String DOAS_PRINCIPAL_PARAM = "doAs";
+ /* List of all default and configured impersonation params */
+ protected final List<String> impersonationParamsList = new ArrayList<>();
+ private final Parser parser = new Parser();
+ protected boolean impersonationEnabled;
+ private SimplePrincipalMapper mapper = new SimplePrincipalMapper();
+ private VirtualGroupMapper virtualGroupMapper;
+ private AbstractSyntaxTree expressionPrincipalMapping;
+ private String topologyName;
+
+ private static List<String> virtualGroupParameterNames(List<String>
initParameterNames) {
+ return initParameterNames == null ? new ArrayList<>()
+ : initParameterNames.stream().filter(name ->
name.startsWith(VIRTUAL_GROUP_MAPPING_PREFIX)).collect(Collectors.toList());
}
- String groupPrincipalMapping =
filterConfig.getInitParameter(GROUP_PRINCIPAL_MAPPING);
- if (groupPrincipalMapping == null || groupPrincipalMapping.isEmpty()) {
- groupPrincipalMapping =
filterConfig.getServletContext().getInitParameter(GROUP_PRINCIPAL_MAPPING);
- }
- if (principalMapping != null && !principalMapping.isEmpty() ||
groupPrincipalMapping != null && !groupPrincipalMapping.isEmpty()) {
- try {
- mapper.loadMappingTable(principalMapping, groupPrincipalMapping);
- } catch (PrincipalMappingException e) {
- throw new ServletException("Unable to load principal mapping table.",
e);
- }
+
+ private static String[] unique(String[] groups) {
+ return new HashSet<>(Arrays.asList(groups)).toArray(new String[0]);
}
- expressionPrincipalMapping = parseAdvancedPrincipalMapping(filterConfig);
- final List<String> initParameterNames =
AuthFilterUtils.getInitParameterNamesAsList(filterConfig);
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ topologyName = (String)
filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE);
+ String principalMapping =
filterConfig.getInitParameter(PRINCIPAL_MAPPING);
+ if (principalMapping == null || principalMapping.isEmpty()) {
+ principalMapping =
filterConfig.getServletContext().getInitParameter(PRINCIPAL_MAPPING);
+ }
+ String groupPrincipalMapping =
filterConfig.getInitParameter(GROUP_PRINCIPAL_MAPPING);
+ if (groupPrincipalMapping == null || groupPrincipalMapping.isEmpty()) {
+ groupPrincipalMapping =
filterConfig.getServletContext().getInitParameter(GROUP_PRINCIPAL_MAPPING);
+ }
+ if (principalMapping != null && !principalMapping.isEmpty() ||
groupPrincipalMapping != null && !groupPrincipalMapping.isEmpty()) {
+ try {
+ mapper.loadMappingTable(principalMapping,
groupPrincipalMapping);
+ } catch (PrincipalMappingException e) {
+ throw new ServletException("Unable to load principal mapping
table.", e);
+ }
+ }
+ expressionPrincipalMapping =
parseAdvancedPrincipalMapping(filterConfig);
- virtualGroupMapper = new
VirtualGroupMapper(loadVirtualGroups(filterConfig, initParameterNames));
+ final List<String> initParameterNames =
AuthFilterUtils.getInitParameterNamesAsList(filterConfig);
- initImpersonationParamsList(filterConfig);
- initProxyUserConfiguration(filterConfig, initParameterNames);
- }
+ virtualGroupMapper = new
VirtualGroupMapper(loadVirtualGroups(filterConfig, initParameterNames));
- private AbstractSyntaxTree parseAdvancedPrincipalMapping(FilterConfig
filterConfig) {
- String expression =
filterConfig.getInitParameter(ADVANCED_PRINCIPAL_MAPPING);
- if (StringUtils.isBlank(expression)) {
- expression =
filterConfig.getServletContext().getInitParameter(ADVANCED_PRINCIPAL_MAPPING);
+ initImpersonationParamsList(filterConfig);
+ initProxyUserConfiguration(filterConfig, initParameterNames);
}
- return StringUtils.isBlank(expression) ? null : parser.parse(expression);
- }
-
- /*
- * Initialize the impersonation params list.
- * This list contains query params that needs to be scrubbed
- * from the outgoing request.
- */
- private void initImpersonationParamsList(FilterConfig filterConfig) {
- String impersonationListFromConfig =
filterConfig.getInitParameter(IMPERSONATION_PARAMS);
- if (impersonationListFromConfig == null ||
impersonationListFromConfig.isEmpty()) {
- impersonationListFromConfig =
filterConfig.getServletContext().getInitParameter(IMPERSONATION_PARAMS);
+
+ private AbstractSyntaxTree parseAdvancedPrincipalMapping(FilterConfig
filterConfig) {
+ String expression =
filterConfig.getInitParameter(ADVANCED_PRINCIPAL_MAPPING);
+ if (StringUtils.isBlank(expression)) {
+ expression =
filterConfig.getServletContext().getInitParameter(ADVANCED_PRINCIPAL_MAPPING);
+ }
+ return StringUtils.isBlank(expression) ? null :
parser.parse(expression);
}
- /* Add default impersonation params */
- impersonationParamsList.add(DOAS_PRINCIPAL_PARAM);
- impersonationParamsList.add(PRINCIPAL_PARAM);
-
- if (impersonationListFromConfig != null &&
!impersonationListFromConfig.isEmpty()) {
- /* Add configured impersonation params */
- LOG.impersonationConfig(impersonationListFromConfig);
- final StringTokenizer t = new
StringTokenizer(impersonationListFromConfig, ",");
- while (t.hasMoreElements()) {
- final String token = t.nextToken().trim();
- if (!impersonationParamsList.contains(token)) {
- impersonationParamsList.add(token);
+ /*
+ * Initialize the impersonation params list.
+ * This list contains query params that needs to be scrubbed
+ * from the outgoing request.
+ */
+ private void initImpersonationParamsList(FilterConfig filterConfig) {
+ String impersonationListFromConfig =
filterConfig.getInitParameter(IMPERSONATION_PARAMS);
+ if (impersonationListFromConfig == null ||
impersonationListFromConfig.isEmpty()) {
+ impersonationListFromConfig =
filterConfig.getServletContext().getInitParameter(IMPERSONATION_PARAMS);
+ }
+
+ /* Add default impersonation params */
+ impersonationParamsList.add(DOAS_PRINCIPAL_PARAM);
+ impersonationParamsList.add(PRINCIPAL_PARAM);
+
+ if (impersonationListFromConfig != null &&
!impersonationListFromConfig.isEmpty()) {
+ /* Add configured impersonation params */
+ LOG.impersonationConfig(impersonationListFromConfig);
+ final StringTokenizer t = new
StringTokenizer(impersonationListFromConfig, ",");
+ while (t.hasMoreElements()) {
+ final String token = t.nextToken().trim();
+ if (!impersonationParamsList.contains(token)) {
+ impersonationParamsList.add(token);
+ }
+ }
}
- }
}
- }
-
- private void initProxyUserConfiguration(FilterConfig filterConfig,
List<String> initParameterNames) {
- final String impersonationEnabledValue =
filterConfig.getInitParameter(IMPERSONATION_ENABLED_PARAM);
- impersonationEnabled = impersonationEnabledValue == null ? Boolean.FALSE :
Boolean.parseBoolean(impersonationEnabledValue);
-
- if (impersonationEnabled) {
- if (AuthFilterUtils.hasProxyConfig(topologyName, "HadoopAuth")) {
- LOG.ignoreProxyuserConfig();
- impersonationEnabled = false; //explicitly set to false to avoid
redundant authorization attempts at request processing time
- } else {
- AuthFilterUtils.refreshSuperUserGroupsConfiguration(filterConfig,
initParameterNames, topologyName, ROLE);
-
filterConfig.getServletContext().setAttribute(ContextAttributes.IMPERSONATION_ENABLED_ATTRIBUTE,
Boolean.TRUE);
- }
- } else {
-
filterConfig.getServletContext().setAttribute(ContextAttributes.IMPERSONATION_ENABLED_ATTRIBUTE,
Boolean.FALSE);
+
+ private void initProxyUserConfiguration(FilterConfig filterConfig,
List<String> initParameterNames) {
+ impersonationEnabled = shouldAddImpersonationProvider(filterConfig);
+ if (impersonationEnabled) {
+ if (AuthFilterUtils.hasProxyConfig(topologyName, "HadoopAuth")) {
+ LOG.ignoreProxyuserConfig();
+ impersonationEnabled = false; //explicitly set to false to
avoid redundant authorization attempts at request processing time
+ } else {
+
AuthFilterUtils.refreshSuperUserGroupsConfiguration(filterConfig,
initParameterNames, topologyName, ROLE);
+
filterConfig.getServletContext().setAttribute(ContextAttributes.IMPERSONATION_ENABLED_ATTRIBUTE,
Boolean.TRUE);
+ }
+ } else {
+
filterConfig.getServletContext().setAttribute(ContextAttributes.IMPERSONATION_ENABLED_ATTRIBUTE,
Boolean.FALSE);
+ }
}
- }
- boolean isImpersonationEnabled() {
- return impersonationEnabled;
- }
+ /**
+ * Check if the impersonation provider should be added to the filter chain
based on
+ * user and group impersonation settings.
+ *
+ * @param filterConfig
+ * @return
+ */
+ boolean shouldAddImpersonationProvider(final FilterConfig filterConfig) {
Review Comment:
@zeroflag yup!
Issue Time Tracking
-------------------
Worklog Id: (was: 970005)
Time Spent: 1h 40m (was: 1.5h)
> Surrogate proxy user configuration for user groups
> --------------------------------------------------
>
> Key: KNOX-3048
> URL: https://issues.apache.org/jira/browse/KNOX-3048
> Project: Apache Knox
> Issue Type: Improvement
> Components: Server
> Affects Versions: 2.0.0
> Reporter: Philip Zampino
> Assignee: Sandeep More
> Priority: Major
> Fix For: 2.1.0
>
> Time Spent: 1h 40m
> Remaining Estimate: 0h
>
> *Problem Statement:*
> Currently Knox has the ability for specific users (say for e.g. {{sp_user}})
> to impersonate other users (say for e.g.{{ot_user}}). This is driven by
> configs defined in a topology. Currently these configs are needed for each
> user that impersonates other users (i.e. {{sp_user}}), this can get out of
> hand quickly and can be difficult to maintain.
> To solve this problem the proposed solution uses a group level impersonation
> configuration. This configuration will be based on the virtual groups feature
> that is already available in Knox. With this new configuration we can have
> specific users who belong to a virtual group/s (based on conditions such as
> {{(match groups 'analyst|scientist') }}) impersonate other users. This will
> significantly cut down on the config properties and keep them readable and
> maintainable.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)