[
https://issues.apache.org/jira/browse/KNOX-3048?focusedWorklogId=969994&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-969994
]
ASF GitHub Bot logged work on KNOX-3048:
----------------------------------------
Author: ASF GitHub Bot
Created on: 20/May/25 12:38
Start Date: 20/May/25 12:38
Worklog Time Spent: 10m
Work Description: zeroflag commented on code in PR #1043:
URL: https://github.com/apache/knox/pull/1043#discussion_r2097847028
##########
gateway-spi/src/main/java/org/apache/knox/gateway/util/GroupBasedImpersonationProvider.java:
##########
@@ -0,0 +1,252 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.util;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authorize.AccessControlList;
+import org.apache.hadoop.security.authorize.AuthorizationException;
+import org.apache.hadoop.security.authorize.DefaultImpersonationProvider;
+import org.apache.hadoop.util.MachineList;
+import org.apache.knox.gateway.i18n.GatewaySpiMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+
+import java.net.InetAddress;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import static
org.apache.knox.gateway.util.AuthFilterUtils.DEFAULT_IMPERSONATION_MODE;
+import static org.apache.knox.gateway.util.AuthFilterUtils.IMPERSONATION_MODE;
+
+/**
+ * An extension of Hadoop's DefaultImpersonationProvider that adds support for
group-based impersonation.
+ * This provider allows users who belong to specific groups to impersonate
other users.
+ */
+public class GroupBasedImpersonationProvider extends
DefaultImpersonationProvider {
+ private static final GatewaySpiMessages LOG =
MessagesFactory.get(GatewaySpiMessages.class);
+ private static final String CONF_HOSTS = ".hosts";
+ private static final String CONF_USERS = ".users";
+ private static final String CONF_GROUPS = ".groups";
+ private final Map<String, AccessControlList> proxyGroupsAcls = new
HashMap<>();
+ /* is the proxy user configuration enabled */
+ boolean isProxyUserEnabled = true;
+ /* is the proxy group configuration enabled, defaulting it to false for
backwards compatibility */
+ boolean isProxyGroupEnabled;
+ private Map<String, MachineList> groupProxyHosts = new HashMap<>();
+ private String groupConfigPrefix;
+ private String impersonationMode = DEFAULT_IMPERSONATION_MODE;
+
+ public GroupBasedImpersonationProvider() {
+ super();
+ }
+
+ public GroupBasedImpersonationProvider(boolean isProxyUserEnabled, boolean
isProxyGroupEnabled) {
+ super();
+ this.isProxyUserEnabled = isProxyUserEnabled;
+ this.isProxyGroupEnabled = isProxyGroupEnabled;
+ }
+
+ @Override
+ public Configuration getConf() {
+ return super.getConf();
+ }
+
+ @Override
+ public void setConf(Configuration conf) {
+ super.setConf(conf);
+ }
+
+ public void init(String configurationPrefix, String proxyGroupPrefix) {
+ super.init(configurationPrefix);
+ initGroupBasedProvider(proxyGroupPrefix);
+ }
+
+ private void initGroupBasedProvider(String proxyGroupPrefix) {
+ impersonationMode = getConf().get(IMPERSONATION_MODE,
DEFAULT_IMPERSONATION_MODE);
+ groupConfigPrefix = proxyGroupPrefix +
+ (proxyGroupPrefix.endsWith(".") ? "" : ".");
+
+ // constructing regex to match the following patterns:
+ // $configPrefix.[ANY].users
+ // $configPrefix.[ANY].groups
+ // $configPrefix.[ANY].hosts
+ //
+ String prefixRegEx = groupConfigPrefix.replace(".", "\\.");
+ String usersGroupsRegEx = prefixRegEx + "[\\S]*(" +
+ Pattern.quote(CONF_USERS) + "|" + Pattern.quote(CONF_GROUPS) +
")";
+ String hostsRegEx = prefixRegEx + "[\\S]*" + Pattern.quote(CONF_HOSTS);
+
+ // get list of users and groups per proxygroup
+ // Map of <hadoop.proxygroup.[VIRTUAL_GROUP].users|groups,
group1,group2>
+ Map<String, String> allMatchKeys =
+ getConf().getValByRegex(usersGroupsRegEx);
+
+ for (Map.Entry<String, String> entry : allMatchKeys.entrySet()) {
+ //aclKey = hadoop.proxygroup.[VIRTUAL_GROUP]
+ String aclKey = getAclKey(entry.getKey());
+
+ if (!proxyGroupsAcls.containsKey(aclKey)) {
+ proxyGroupsAcls.put(aclKey, new AccessControlList(
+ allMatchKeys.get(aclKey + CONF_USERS),
+ allMatchKeys.get(aclKey + CONF_GROUPS)));
+ }
+ }
+
+ // get hosts per proxygroup
+ allMatchKeys = getConf().getValByRegex(hostsRegEx);
+ for (Map.Entry<String, String> entry : allMatchKeys.entrySet()) {
+ groupProxyHosts.put(entry.getKey(),
+ new MachineList(entry.getValue()));
+ }
+ }
+
+ private String getAclKey(String key) {
+ int endIndex = key.lastIndexOf('.');
+ if (endIndex != -1) {
+ return key.substring(0, endIndex);
+ }
+ return key;
+ }
+
+ @Override
+ public void authorize(UserGroupInformation user, InetAddress
remoteAddress) throws AuthorizationException {
+ // If both authorization methods are disabled, allow the operation to
proceed
+ if (!isProxyUserEnabled && !isProxyGroupEnabled) {
+ LOG.successfulImpersonation(user.getRealUser().getUserName(),
user.getUserName());
+ return;
+ }
+
+ boolean isProxyUserAuthorized = false;
+ boolean isProxyGroupAuthorized = false;
+ if (isProxyUserEnabled) {
+ /* authorize proxy user */
+ isProxyUserAuthorized = checkProxyUserAuthorization(user,
remoteAddress);
+ /* In case of AND no reason to check for proxy groups if
isProxyUserAuthorized=false */
+ if("AND".equalsIgnoreCase(impersonationMode) &&
!isProxyUserAuthorized) {
Review Comment:
I would either extract this (`"AND"`) to a string constant, or introduce an
enum.
Issue Time Tracking
-------------------
Worklog Id: (was: 969994)
Time Spent: 1.5h (was: 1h 20m)
> 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: 1.5h
> 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)