Skip to content

Commit 83e6ddc

Browse files
RANGER-5215: policy evaluation to apply same user/group name transformations as usersync (#751)
1 parent bcc0de6 commit 83e6ddc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+544
-107
lines changed

agents-common/pom.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,25 @@
171171
<artifactId>ranger-plugins-cred</artifactId>
172172
<version>${project.version}</version>
173173
</dependency>
174+
<dependency>
175+
<groupId>org.apache.ranger</groupId>
176+
<artifactId>ugsync-util</artifactId>
177+
<version>${project.version}</version>
178+
<exclusions>
179+
<exclusion>
180+
<groupId>log4j</groupId>
181+
<artifactId>*</artifactId>
182+
</exclusion>
183+
<exclusion>
184+
<groupId>org.apache.logging.log4j</groupId>
185+
<artifactId>*</artifactId>
186+
</exclusion>
187+
<exclusion>
188+
<groupId>org.slf4j</groupId>
189+
<artifactId>*</artifactId>
190+
</exclusion>
191+
</exclusions>
192+
</dependency>
174193
<dependency>
175194
<groupId>org.mockito</groupId>
176195
<artifactId>mockito-core</artifactId>

agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.apache.ranger.plugin.util.ServiceDefUtil;
4646
import org.apache.ranger.plugin.util.ServicePolicies;
4747
import org.apache.ranger.plugin.util.StringTokenReplacer;
48-
import org.apache.ranger.plugin.util.RangerUserStore;
4948
import org.slf4j.Logger;
5049
import org.slf4j.LoggerFactory;
5150

@@ -213,9 +212,7 @@ public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginC
213212
}
214213
}
215214

216-
RangerAuthContext currAuthContext = pluginContext.getAuthContext();
217-
RangerUserStore userStore = currAuthContext != null ? currAuthContext.getUserStoreUtil().getUserStore() : null;
218-
RangerAuthContext authContext = new RangerAuthContext(null, zoneMatcher, roles, userStore);
215+
RangerAuthContext authContext = new RangerAuthContext(pluginContext.getAuthContext(), zoneMatcher, roles);
219216

220217
this.pluginContext.setAuthContext(authContext);
221218

agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,47 @@
2525
import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
2626
import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
2727
import org.apache.ranger.plugin.policyengine.RangerSecurityZoneMatcher;
28+
import org.apache.ranger.plugin.util.RangerCommonConstants;
2829
import org.apache.ranger.plugin.util.RangerRoles;
2930
import org.apache.ranger.plugin.util.RangerRolesUtil;
3031
import org.apache.ranger.plugin.util.RangerUserStore;
3132
import org.apache.ranger.plugin.util.RangerUserStoreUtil;
33+
import org.apache.ranger.ugsyncutil.transform.Mapper;
34+
import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants.CaseConversion;
35+
import org.slf4j.Logger;
36+
import org.slf4j.LoggerFactory;
3237

38+
import java.util.ArrayList;
3339
import java.util.HashSet;
40+
import java.util.List;
3441
import java.util.Map;
3542
import java.util.Set;
3643
import java.util.concurrent.ConcurrentHashMap;
3744

45+
import static org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants.toCaseConversion;
46+
3847
public class RangerAuthContext {
48+
private static final Logger LOG = LoggerFactory.getLogger(RangerAuthContext.class);
49+
3950
private final Map<RangerContextEnricher, Object> requestContextEnrichers;
4051
private final RangerSecurityZoneMatcher zoneMatcher;
4152
private RangerRolesUtil rolesUtil;
4253
private RangerUserStoreUtil userStoreUtil;
54+
private Mapper userNameTransformer;
55+
private Mapper groupNameTransformer;
56+
private CaseConversion userNameCaseConversion;
57+
private CaseConversion groupNameCaseConversion;
58+
59+
public RangerAuthContext(RangerAuthContext prevContext, RangerSecurityZoneMatcher zoneMatcher, RangerRoles roles) {
60+
this(null, zoneMatcher, roles, prevContext != null ? prevContext.getUserStoreUtil().getUserStore() : null);
61+
62+
if (prevContext != null) {
63+
this.userNameTransformer = prevContext.userNameTransformer;
64+
this.groupNameTransformer = prevContext.groupNameTransformer;
65+
this.userNameCaseConversion = prevContext.userNameCaseConversion;
66+
this.groupNameCaseConversion = prevContext.groupNameCaseConversion;
67+
}
68+
}
4369

4470
public RangerAuthContext(Map<RangerContextEnricher, Object> requestContextEnrichers, RangerSecurityZoneMatcher zoneMatcher, RangerRoles roles, RangerUserStore userStore) {
4571
this.requestContextEnrichers = requestContextEnrichers != null ? requestContextEnrichers : new ConcurrentHashMap<>();
@@ -127,4 +153,118 @@ public RangerUserStoreUtil getUserStoreUtil() {
127153
public void setUserStore(RangerUserStore userStore) {
128154
this.userStoreUtil = new RangerUserStoreUtil(userStore);
129155
}
156+
157+
public Mapper getUserNameTransformer() {
158+
return userNameTransformer;
159+
}
160+
161+
public Mapper getGroupNameTransformer() {
162+
return groupNameTransformer;
163+
}
164+
165+
public CaseConversion getUserNameCaseConversion() {
166+
return userNameCaseConversion;
167+
}
168+
169+
public CaseConversion getGroupNameCaseConversion() {
170+
return groupNameCaseConversion;
171+
}
172+
173+
public void onServiceConfigsUpdate(Map<String, String> serviceConfigs) {
174+
String userNameCaseConversion = null;
175+
String groupNameCaseConversion = null;
176+
Mapper userNameTransformer = null;
177+
Mapper groupNameTransformer = null;
178+
179+
if (MapUtils.isNotEmpty(serviceConfigs)) {
180+
LOG.debug("==> onServiceConfigsUpdate({})", serviceConfigs.keySet());
181+
182+
userNameCaseConversion = serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_USERNAME_CASE_CONVERSION_PARAM);
183+
groupNameCaseConversion = serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_GROUPNAME_CASE_CONVERSION_PARAM);
184+
185+
String mappingUserNameHandler = serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_MAPPING_USERNAME_HANDLER);
186+
187+
if (mappingUserNameHandler != null) {
188+
try {
189+
Class<Mapper> regExClass = (Class<Mapper>) Class.forName(mappingUserNameHandler);
190+
191+
userNameTransformer = regExClass.newInstance();
192+
193+
String baseProperty = RangerCommonConstants.PLUGINS_CONF_MAPPING_USERNAME;
194+
195+
userNameTransformer.init(baseProperty, getAllRegexPatterns(baseProperty, serviceConfigs), serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_MAPPING_SEPARATOR));
196+
} catch (ClassNotFoundException cne) {
197+
LOG.error("Failed to load {}", mappingUserNameHandler, cne);
198+
} catch (Throwable te) {
199+
LOG.error("Failed to instantiate {}", mappingUserNameHandler, te);
200+
}
201+
}
202+
203+
String mappingGroupNameHandler = serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME_HANDLER);
204+
205+
if (mappingGroupNameHandler != null) {
206+
try {
207+
Class<Mapper> regExClass = (Class<Mapper>) Class.forName(mappingGroupNameHandler);
208+
209+
groupNameTransformer = regExClass.newInstance();
210+
211+
String baseProperty = RangerCommonConstants.PLUGINS_CONF_MAPPING_GROUPNAME;
212+
213+
groupNameTransformer.init(baseProperty, getAllRegexPatterns(baseProperty, serviceConfigs), serviceConfigs.get(RangerCommonConstants.PLUGINS_CONF_MAPPING_SEPARATOR));
214+
} catch (ClassNotFoundException cne) {
215+
LOG.error("Failed to load {}", mappingGroupNameHandler, cne);
216+
} catch (Throwable te) {
217+
LOG.error("Failed to instantiate {}", mappingGroupNameHandler, te);
218+
}
219+
}
220+
}
221+
222+
setUserNameCaseConversion(userNameCaseConversion);
223+
setGroupNameCaseConversion(groupNameCaseConversion);
224+
setUserNameTransformer(userNameTransformer);
225+
setGroupNameTransformer(groupNameTransformer);
226+
}
227+
228+
private void setUserNameTransformer(Mapper userNameTransformer) {
229+
this.userNameTransformer = userNameTransformer;
230+
}
231+
232+
private void setGroupNameTransformer(Mapper groupNameTransformer) {
233+
this.groupNameTransformer = groupNameTransformer;
234+
}
235+
236+
private void setUserNameCaseConversion(String userNameCaseConversion) {
237+
this.userNameCaseConversion = toCaseConversion(userNameCaseConversion);
238+
}
239+
240+
private void setGroupNameCaseConversion(String groupNameCaseConversion) {
241+
this.groupNameCaseConversion = toCaseConversion(groupNameCaseConversion);
242+
}
243+
244+
private List<String> getAllRegexPatterns(String baseProperty, Map<String, String> serviceConfig) {
245+
LOG.debug("==> getAllRegexPatterns({})", baseProperty);
246+
247+
List<String> regexPatterns = new ArrayList<>();
248+
String baseRegex = serviceConfig != null ? serviceConfig.get(baseProperty) : null;
249+
250+
LOG.debug("baseRegex = {}, pluginConfig = {}", baseRegex, serviceConfig == null ? null : serviceConfig.keySet());
251+
252+
if (baseRegex != null) {
253+
regexPatterns.add(baseRegex);
254+
255+
for (int i = 1; true; i++) {
256+
String nextRegex = serviceConfig.get(baseProperty + "." + i);
257+
258+
if (nextRegex == null) {
259+
break;
260+
}
261+
262+
regexPatterns.add(nextRegex);
263+
}
264+
}
265+
266+
LOG.debug("<== getAllRegexPatterns({}): ret={}", baseProperty, regexPatterns);
267+
268+
return regexPatterns;
269+
}
130270
}

agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,6 @@ public void setPolicies(ServicePolicies policies) {
356356
if (LOG.isDebugEnabled()) {
357357
LOG.debug("==> setPolicies(" + policies + ")");
358358
}
359-
this.serviceConfigs = (policies != null && policies.getServiceConfig() != null) ? policies.getServiceConfig() : new HashMap<>();
360359
if (pluginConfig.isEnableImplicitUserStoreEnricher() && policies != null && !ServiceDefUtil.isUserStoreEnricherPresent(policies)) {
361360
String retrieverClassName = pluginConfig.get(RangerUserStoreEnricher.USERSTORE_RETRIEVER_CLASSNAME_OPTION, RangerAdminUserStoreRetriever.class.getCanonicalName());
362361
String retrieverPollIntMs = pluginConfig.get(RangerUserStoreEnricher.USERSTORE_REFRESHER_POLLINGINTERVAL_OPTION, Integer.toString(60 * 1000));
@@ -370,8 +369,8 @@ public void setPolicies(ServicePolicies policies) {
370369
isUserStoreEnricherAddedImplcitly = ServiceDefUtil.addUserStoreEnricherIfNeeded(policies, retrieverClassName, retrieverPollIntMs);
371370
}
372371
}
373-
374-
String isSyncPolicyRefresh = this.pluginConfig == null ? null : this.serviceConfigs.get(this.pluginConfig.getPropertyPrefix() + ".policy.refresh.synchronous");
372+
// String isSyncPolicyRefresh = this.pluginConfig == null ? null : this.serviceConfigs.get(this.pluginConfig.getPropertyPrefix() + ".policy.refresh.synchronous");
373+
String isSyncPolicyRefresh = this.pluginConfig == null ? null : (this.serviceConfigs == null ? null : this.serviceConfigs.get(this.pluginConfig.getPropertyPrefix() + ".policy.refresh.synchronous"));
375374
this.synchronousPolicyRefresh = Boolean.parseBoolean(isSyncPolicyRefresh);
376375
if (this.synchronousPolicyRefresh) {
377376
LOG.info("synchronousPolicyRefresh = {}", this.synchronousPolicyRefresh);
@@ -500,6 +499,8 @@ public void setPolicies(ServicePolicies policies) {
500499
newPolicyEngine.setTrustedProxyAddresses(pluginConfig.getTrustedProxyAddresses());
501500
}
502501

502+
setServiceConfigs(policies.getServiceConfig());
503+
503504
LOG.info("Switching policy engine from [" + getPolicyVersion() + "]");
504505
this.policyEngine = newPolicyEngine;
505506
LOG.info("Switched policy engine to [" + getPolicyVersion() + "]");
@@ -1422,6 +1423,18 @@ private static void overrideACLs(final RangerResourceACLs chainedResourceACLs, R
14221423
}
14231424
}
14241425

1426+
private void setServiceConfigs(Map<String, String> serviceConfigs) {
1427+
Map<String, String> oldServiceConfigs = this.serviceConfigs;
1428+
1429+
this.serviceConfigs = serviceConfigs != null ? serviceConfigs : new HashMap<>();
1430+
1431+
RangerAuthContext authContext = this.pluginContext.getAuthContext();
1432+
1433+
if (authContext != null && !Objects.equals(oldServiceConfigs, this.serviceConfigs)) {
1434+
authContext.onServiceConfigsUpdate(this.serviceConfigs);
1435+
}
1436+
}
1437+
14251438
private static AuditProviderFactory getAuditProviderFactory(String serviceName) {
14261439
AuditProviderFactory ret = AuditProviderFactory.getInstance();
14271440

agents-common/src/main/java/org/apache/ranger/plugin/service/RangerDefaultRequestProcessor.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,20 @@
3131
import org.apache.ranger.plugin.policyengine.RangerMutableResource;
3232
import org.apache.ranger.plugin.policyengine.RangerPluginContext;
3333
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
34+
import org.apache.ranger.plugin.util.RangerCommonConstants;
3435
import org.apache.ranger.plugin.util.RangerPerfTracer;
3536
import org.apache.ranger.plugin.util.RangerUserStoreUtil;
37+
import org.apache.ranger.ugsyncutil.transform.Mapper;
38+
import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants;
3639
import org.slf4j.Logger;
3740
import org.slf4j.LoggerFactory;
3841

3942
import java.util.Collections;
4043
import java.util.HashSet;
4144
import java.util.List;
45+
import java.util.Objects;
4246
import java.util.Set;
47+
import java.util.stream.Collectors;
4348

4449
public class RangerDefaultRequestProcessor implements RangerAccessRequestProcessor {
4550

@@ -103,6 +108,17 @@ public void preProcess(RangerAccessRequest request) {
103108
reqImpl.setClusterType(pluginContext.getClusterType());
104109
}
105110

111+
RangerPluginConfig config = policyEngine.getPluginContext().getConfig();
112+
113+
boolean isNameTransformationSupported = config.getBoolean(config.getPropertyPrefix() + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_NAME_TRANSFORMATION, false);
114+
115+
LOG.debug("isNameTransformationSupported = {}", isNameTransformationSupported);
116+
117+
if (isNameTransformationSupported) {
118+
reqImpl.setUser(getTransformedUser(policyEngine, request));
119+
reqImpl.setUserGroups(getTransformedGroups(policyEngine, request));
120+
}
121+
106122
convertEmailToUsername(reqImpl);
107123

108124
updateUserGroups(reqImpl);
@@ -166,6 +182,65 @@ public void enrich(RangerAccessRequest request) {
166182
}
167183
}
168184

185+
private String getTransformedUser(PolicyEngine policyEngine, RangerAccessRequest request) {
186+
RangerAuthContext authContext = policyEngine.getPluginContext().getAuthContext();
187+
boolean toLowerCase = authContext.getUserNameCaseConversion() == UgsyncCommonConstants.CaseConversion.TO_LOWER;
188+
boolean toUpperCase = authContext.getUserNameCaseConversion() == UgsyncCommonConstants.CaseConversion.TO_UPPER;
189+
Mapper nameTransformer = authContext.getUserNameTransformer();
190+
191+
if (toLowerCase || toUpperCase || nameTransformer != null) {
192+
String user = request.getUser();
193+
194+
if (toLowerCase) {
195+
user = user.toLowerCase();
196+
} else if (toUpperCase) {
197+
user = user.toUpperCase();
198+
}
199+
200+
if (nameTransformer != null) {
201+
user = nameTransformer.transform(user);
202+
}
203+
204+
LOG.debug("Original username = {}, Transformed username = {}", request.getUser(), user);
205+
206+
return user;
207+
}
208+
209+
return request.getUser();
210+
}
211+
212+
private Set<String> getTransformedGroups(PolicyEngine policyEngine, RangerAccessRequest request) {
213+
if (CollectionUtils.isNotEmpty(request.getUserGroups())) {
214+
RangerAuthContext authContext = policyEngine.getPluginContext().getAuthContext();
215+
boolean toLowerCase = authContext.getGroupNameCaseConversion() == UgsyncCommonConstants.CaseConversion.TO_LOWER;
216+
boolean toUpperCase = authContext.getGroupNameCaseConversion() == UgsyncCommonConstants.CaseConversion.TO_UPPER;
217+
Mapper nameTransformer = authContext.getGroupNameTransformer();
218+
219+
if (toLowerCase || toUpperCase || nameTransformer != null) {
220+
return request.getUserGroups().stream()
221+
.filter(Objects::nonNull)
222+
.map(group -> {
223+
String originalGroup = group;
224+
225+
if (toLowerCase) {
226+
group = group.toLowerCase();
227+
} else if (toUpperCase) {
228+
group = group.toUpperCase();
229+
}
230+
231+
String transformedGroup = nameTransformer.transform(group);
232+
233+
LOG.debug("Original group name = {}, Transformed group name = {}", originalGroup, transformedGroup);
234+
235+
return transformedGroup;
236+
})
237+
.collect(Collectors.toSet());
238+
}
239+
}
240+
241+
return request.getUserGroups();
242+
}
243+
169244
private void setResourceServiceDef(RangerAccessRequest request) {
170245
RangerAccessResource resource = request.getResource();
171246

agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ private RangerCommonConstants() {
3939

4040
public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES = ".supports.in.place.tag.updates";
4141
public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES = ".supports.in.place.tag.updates";
42+
public static final String PLUGIN_CONFIG_SUFFIX_NAME_TRANSFORMATION = ".supports.name.transformation";
43+
44+
public static final String PLUGINS_CONF_USERNAME_CASE_CONVERSION_PARAM = "ranger.plugins.conf.ldap.username.caseconversion";
45+
public static final String PLUGINS_CONF_GROUPNAME_CASE_CONVERSION_PARAM = "ranger.plugins.conf.ldap.groupname.caseconversion";
46+
public static final String PLUGINS_CONF_MAPPING_USERNAME = "ranger.plugins.conf.mapping.username.regex";
47+
public static final String PLUGINS_CONF_MAPPING_GROUPNAME = "ranger.plugins.conf.mapping.groupname.regex";
48+
public static final String PLUGINS_CONF_MAPPING_USERNAME_HANDLER = "ranger.plugins.conf.mapping.username.handler";
49+
public static final String PLUGINS_CONF_MAPPING_GROUPNAME_HANDLER = "ranger.plugins.conf.mapping.groupname.handler";
50+
public static final String PLUGINS_CONF_MAPPING_SEPARATOR = "ranger.plugins.conf.mapping.regex.separator";
4251

4352
public static final String RANGER_SUPPORTS_TAGS_DEDUP = ".supports.tags.dedup";
4453

agents-common/src/main/java/org/apache/ranger/plugin/util/ServicePolicies.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ static public ServicePolicies copyHeader(ServicePolicies source) {
444444
ret.setPolicyVersion(source.getPolicyVersion());
445445
ret.setAuditMode(source.getAuditMode());
446446
ret.setServiceDef(source.getServiceDef());
447+
ret.setServiceConfig(source.getServiceConfig() != null ? new HashMap<>(source.getServiceConfig()) : null);
447448
ret.setPolicyUpdateTime(source.getPolicyUpdateTime());
448449
ret.setSecurityZones(source.getSecurityZones());
449450
ret.setPolicies(Collections.emptyList());

distro/src/main/assembly/admin-web.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@
237237
<include>org.eclipse.jdt.core.compiler:ecj:jar:P20140317-1600</include>
238238
<include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
239239
<include>org.apache.ranger:ranger-plugins-common</include>
240+
<include>org.apache.ranger:ugsync-util</include>
240241
<include>org.slf4j:slf4j-api:jar:${slf4j.version}</include>
241242
<include>org.apache.hadoop:hadoop-common</include>
242243
<include>commons-logging:commons-logging</include>

0 commit comments

Comments
 (0)