You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ranger.apache.org by "vyommani (via GitHub)" <gi...@apache.org> on 2026/10/14 12:11:59 UTC
[PR] RANGER-5838: Add constraintDefs to RangerServiceDef and constraint po… [ranger]
vyommani opened a new pull request, #1309:
URL: https://github.com/apache/ranger/pull/1309
…licy model to RangerPolicy
## What changes were proposed in this pull request?
This adds the data model for constraint policies. It’s the first step toward constraint-policy support: conditions a plugin must enforce on top of an allow decision, such as human approval for AI agent actions (requireApproval) or row limits (maxRows). This change only adds model classes and JSON serialization.
RangerServiceDef
New constraintDefs (List<RangerConstraintDef>): the constraints a service supports.
RangerConstraintDef fields: itemId, name, label, description, rbKeyLabel, rbKeyDescription, resources (resource names), accessTypes (access-type names), parameters, options.
RangerConstraintParamDef fields: itemId, name, label, description, type, mandatory (defaults to false), defaultValue, rbKeyLabel, rbKeyDescription.
updateFrom, dedupStrings and toString include the new field. dataMaskDef and rowFilterDef are unchanged.
RangerPolicy
New POLICY_TYPE_CONSTRAINTS = 4. Like POLICY_TYPE_AUDIT, it is not added to POLICY_TYPES, so engine and Admin code that loops over policy types is unaffected until evaluation support is added.
New constraintPolicyItems (List<RangerConstraintPolicyItem>).
RangerConstraintPolicyItem extends RangerPolicyItem and carries RangerPolicyItemConstraintInfo: constraintName plus parameters (Map<String, Object>). This follows the RangerDataMaskPolicyItem / RangerPolicyItemDataMaskInfo pattern.
dedupStrings on the constraint info dedups both parameter keys and String values.
Example service-def:
"constraintDefs": [{
"itemId": 1, "name": "requireApproval", "label": "Require approval",
"resources": ["tool"], "accessTypes": ["execute"],
"parameters": [{ "itemId": 1, "name": "approver", "label": "Approver", "type": "user", "mandatory": true }]
}]
Example policy:
"policyType": 4,
"constraintPolicyItems": [{
"groups": ["finance-users"],
"accesses": [{ "type": "execute", "isAllowed": true }],
"conditions": [{ "type": "expression", "values": ["ATTR.trx_amount > 10000"] }],
"constraintInfo": { "constraintName": "requireApproval", "parameters": { "approver": "finance-approvers" } }
}]
Not in this change. These are follow-up sub-tasks:
Admin persistence and validation (DB schema for constraintDefs)
policy-engine evaluation
supported-constraint registration, and denying requests with unsupported constraints
audit
authz-api/PDP result
policy UI
plugin capability gating
Points for review:
One constraint per policy item, as with data masks, rather than a list per item.
resources / accessTypes in RangerConstraintDef are plain names, rather than full RangerResourceDef / RangerAccessTypeDef objects as in dataMaskDef.
Which parameter type values to support, e.g. string, int, boolean, user, group, role.
## How was this patch tested?
New tests in the existing model test classes:
TestRangerServiceDef.test14_ConstraintDefsJsonRoundTrip covers:
JSON parsing and round-trip of constraintDefs;
service-def JSON without constraintDefs deserializes, and the field isn’t written when empty;
null-safe setters, copy constructors, updateFrom, equals/hashCode, toString, normalize() and dedupStrings.
TestRangerPolicy.test13_ConstraintPolicyItemsAndJson covers:
POLICY_TYPE_CONSTRAINTS is not in POLICY_TYPES;
JSON parsing and round-trip of constraintPolicyItems, with unknown fields ignored;
access-policy JSON doesn’t include the new field;
updateFrom, equals/hashCode, toString, and dedup of parameter keys and values.
TestRangerPolicy.test09 is extended for the V2 null-safe supplier.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5838: Add constraintDefs to RangerServiceDef and constraint po… [ranger]
Posted by "vyommani (via GitHub)" <gi...@apache.org>.
vyommani commented on code in PR #1309:
URL: https://github.com/apache/ranger/pull/1309#discussion_r4286048173
##########
agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java:
##########
@@ -3742,4 +3782,426 @@ public String toString() {
return sb.toString();
}
}
+
+ @JsonAutoDetect(fieldVisibility = Visibility.ANY)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class RangerConstraintDef implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Long itemId;
+ private String name;
+ private String label;
+ private String description;
+ private String rbKeyLabel;
+ private String rbKeyDescription;
+ private List<String> resources;
+ private List<String> accessTypes;
+ private List<RangerConstraintParamDef> parameters;
+ private Map<String, String> options;
+
+ public RangerConstraintDef() {
+ setResources(null);
+ setAccessTypes(null);
+ setParameters(null);
+ setOptions(null);
+ }
+
+ public RangerConstraintDef(RangerConstraintDef other) {
+ setItemId(other.getItemId());
+ setName(other.getName());
+ setLabel(other.getLabel());
+ setDescription(other.getDescription());
+ setRbKeyLabel(other.getRbKeyLabel());
+ setRbKeyDescription(other.getRbKeyDescription());
+ setResources(other.getResources());
+ setAccessTypes(other.getAccessTypes());
+ setParameters(other.getParameters());
+ setOptions(other.getOptions() == null ? null : new HashMap<>(other.getOptions()));
+ }
+
+ public Long getItemId() {
+ return itemId;
+ }
+
+ public void setItemId(Long itemId) {
+ this.itemId = itemId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getRbKeyLabel() {
+ return rbKeyLabel;
+ }
+
+ public void setRbKeyLabel(String rbKeyLabel) {
+ this.rbKeyLabel = rbKeyLabel;
+ }
+
+ public String getRbKeyDescription() {
+ return rbKeyDescription;
+ }
+
+ public void setRbKeyDescription(String rbKeyDescription) {
+ this.rbKeyDescription = rbKeyDescription;
+ }
+
+ public List<String> getResources() {
+ return resources;
+ }
+
+ public void setResources(List<String> resources) {
+ if (this.resources == null) {
+ this.resources = new ArrayList<>();
+ }
+
+ if (this.resources == resources) {
+ return;
+ }
+
+ this.resources.clear();
+
+ if (resources != null) {
+ this.resources.addAll(resources);
+ }
+ }
+
+ public List<String> getAccessTypes() {
+ return accessTypes;
+ }
+
+ public void setAccessTypes(List<String> accessTypes) {
+ if (this.accessTypes == null) {
+ this.accessTypes = new ArrayList<>();
+ }
+
+ if (this.accessTypes == accessTypes) {
+ return;
+ }
+
+ this.accessTypes.clear();
+
+ if (accessTypes != null) {
+ this.accessTypes.addAll(accessTypes);
+ }
+ }
+
+ public List<RangerConstraintParamDef> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List<RangerConstraintParamDef> parameters) {
+ if (this.parameters == null) {
+ this.parameters = new ArrayList<>();
+ }
+
+ if (this.parameters == parameters) {
+ return;
+ }
+
+ this.parameters.clear();
+
+ if (parameters != null) {
+ this.parameters.addAll(parameters);
+ }
+ }
+
+ public Map<String, String> getOptions() {
+ return options;
+ }
+
+ public void setOptions(Map<String, String> options) {
+ this.options = options == null ? new HashMap<>() : options;
+ }
+
+ public void dedupStrings(Map<String, String> strTbl) {
+ name = StringUtil.dedupString(name, strTbl);
+ label = StringUtil.dedupString(label, strTbl);
+ description = StringUtil.dedupString(description, strTbl);
+ rbKeyLabel = StringUtil.dedupString(rbKeyLabel, strTbl);
+ rbKeyDescription = StringUtil.dedupString(rbKeyDescription, strTbl);
+ resources = StringUtil.dedupStringsList(resources, strTbl);
+ accessTypes = StringUtil.dedupStringsList(accessTypes, strTbl);
+ options = StringUtil.dedupStringsMap(options, strTbl);
+
+ if (parameters != null) {
+ for (RangerConstraintParamDef parameter : parameters) {
+ parameter.dedupStrings(strTbl);
+ }
+ }
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ sb.append("RangerConstraintDef={");
+ sb.append("itemId={").append(itemId).append("} ");
+ sb.append("name={").append(name).append("} ");
+ sb.append("label={").append(label).append("} ");
+ sb.append("description={").append(description).append("} ");
+ sb.append("rbKeyLabel={").append(rbKeyLabel).append("} ");
+ sb.append("rbKeyDescription={").append(rbKeyDescription).append("} ");
+
+ sb.append("resources={");
+ if (resources != null) {
+ for (String resource : resources) {
+ if (resource != null) {
+ sb.append(resource).append(" ");
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("accessTypes={");
+ if (accessTypes != null) {
+ for (String accessType : accessTypes) {
+ if (accessType != null) {
+ sb.append(accessType).append(" ");
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("parameters={");
+ if (parameters != null) {
+ for (RangerConstraintParamDef parameter : parameters) {
+ if (parameter != null) {
+ parameter.toString(sb);
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("options={").append(options).append("} ");
+ sb.append("}");
+
+ return sb;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(itemId, name, label, description, rbKeyLabel, rbKeyDescription, resources, accessTypes, parameters, options);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj == null) {
+ return false;
+ } else if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ RangerConstraintDef other = (RangerConstraintDef) obj;
+
+ return Objects.equals(itemId, other.itemId) &&
+ Objects.equals(name, other.name) &&
+ Objects.equals(label, other.label) &&
+ Objects.equals(description, other.description) &&
+ Objects.equals(rbKeyLabel, other.rbKeyLabel) &&
+ Objects.equals(rbKeyDescription, other.rbKeyDescription) &&
+ Objects.equals(resources, other.resources) &&
+ Objects.equals(accessTypes, other.accessTypes) &&
+ Objects.equals(parameters, other.parameters) &&
+ Objects.equals(options, other.options);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ toString(sb);
+
+ return sb.toString();
+ }
+ }
+
+ @JsonAutoDetect(fieldVisibility = Visibility.ANY)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class RangerConstraintParamDef implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Long itemId;
+ private String name;
+ private String label;
+ private String description;
+ private String type;
Review Comment:
Added subType to RangerConstraintParamDef, following RangerServiceConfigDef: for type = enum, subType names an enum in the service-def’s enums.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5838: Add constraintDefs to RangerServiceDef and constraint po… [ranger]
Posted by "vyommani (via GitHub)" <gi...@apache.org>.
vyommani commented on PR #1309:
URL: https://github.com/apache/ranger/pull/1309#issuecomment-6208491888
> @vyommani - I suggest including changes to `RangerAccessResult` as well in this PR. It will provide complete integration details for services planning to leverage constraints. If any changes are expected in policy engine calls (`isAccessAllowed(request)`), hopefully not, consider including those details as well in this PR. Note that implementations can come later.
Thanks Madhan. The RangerAccessResult changes are in RANGER-5842, stacked on this PR. There’s no change to isAccessAllowed(request). When access is allowed, the result includes getConstraintResults(), which the service enforces; on deny it’s empty. I’d prefer to review that API together with its implementation, but I’m happy to move it here if you’d rather.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5838: Add constraintDefs to RangerServiceDef and constraint po… [ranger]
Posted by "vyommani (via GitHub)" <gi...@apache.org>.
vyommani merged PR #1309:
URL: https://github.com/apache/ranger/pull/1309
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] RANGER-5838: Add constraintDefs to RangerServiceDef and constraint po… [ranger]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #1309:
URL: https://github.com/apache/ranger/pull/1309#discussion_r4285467671
##########
agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java:
##########
@@ -3742,4 +3782,426 @@ public String toString() {
return sb.toString();
}
}
+
+ @JsonAutoDetect(fieldVisibility = Visibility.ANY)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class RangerConstraintDef implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Long itemId;
+ private String name;
+ private String label;
+ private String description;
+ private String rbKeyLabel;
+ private String rbKeyDescription;
+ private List<String> resources;
+ private List<String> accessTypes;
+ private List<RangerConstraintParamDef> parameters;
+ private Map<String, String> options;
+
+ public RangerConstraintDef() {
+ setResources(null);
+ setAccessTypes(null);
+ setParameters(null);
+ setOptions(null);
+ }
+
+ public RangerConstraintDef(RangerConstraintDef other) {
+ setItemId(other.getItemId());
+ setName(other.getName());
+ setLabel(other.getLabel());
+ setDescription(other.getDescription());
+ setRbKeyLabel(other.getRbKeyLabel());
+ setRbKeyDescription(other.getRbKeyDescription());
+ setResources(other.getResources());
+ setAccessTypes(other.getAccessTypes());
+ setParameters(other.getParameters());
+ setOptions(other.getOptions() == null ? null : new HashMap<>(other.getOptions()));
+ }
+
+ public Long getItemId() {
+ return itemId;
+ }
+
+ public void setItemId(Long itemId) {
+ this.itemId = itemId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getRbKeyLabel() {
+ return rbKeyLabel;
+ }
+
+ public void setRbKeyLabel(String rbKeyLabel) {
+ this.rbKeyLabel = rbKeyLabel;
+ }
+
+ public String getRbKeyDescription() {
+ return rbKeyDescription;
+ }
+
+ public void setRbKeyDescription(String rbKeyDescription) {
+ this.rbKeyDescription = rbKeyDescription;
+ }
+
+ public List<String> getResources() {
+ return resources;
+ }
+
+ public void setResources(List<String> resources) {
+ if (this.resources == null) {
+ this.resources = new ArrayList<>();
+ }
+
+ if (this.resources == resources) {
+ return;
+ }
+
+ this.resources.clear();
+
+ if (resources != null) {
+ this.resources.addAll(resources);
+ }
+ }
+
+ public List<String> getAccessTypes() {
+ return accessTypes;
+ }
+
+ public void setAccessTypes(List<String> accessTypes) {
+ if (this.accessTypes == null) {
+ this.accessTypes = new ArrayList<>();
+ }
+
+ if (this.accessTypes == accessTypes) {
+ return;
+ }
+
+ this.accessTypes.clear();
+
+ if (accessTypes != null) {
+ this.accessTypes.addAll(accessTypes);
+ }
+ }
+
+ public List<RangerConstraintParamDef> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List<RangerConstraintParamDef> parameters) {
+ if (this.parameters == null) {
+ this.parameters = new ArrayList<>();
+ }
+
+ if (this.parameters == parameters) {
+ return;
+ }
+
+ this.parameters.clear();
+
+ if (parameters != null) {
+ this.parameters.addAll(parameters);
+ }
+ }
+
+ public Map<String, String> getOptions() {
+ return options;
+ }
+
+ public void setOptions(Map<String, String> options) {
+ this.options = options == null ? new HashMap<>() : options;
+ }
+
+ public void dedupStrings(Map<String, String> strTbl) {
+ name = StringUtil.dedupString(name, strTbl);
+ label = StringUtil.dedupString(label, strTbl);
+ description = StringUtil.dedupString(description, strTbl);
+ rbKeyLabel = StringUtil.dedupString(rbKeyLabel, strTbl);
+ rbKeyDescription = StringUtil.dedupString(rbKeyDescription, strTbl);
+ resources = StringUtil.dedupStringsList(resources, strTbl);
+ accessTypes = StringUtil.dedupStringsList(accessTypes, strTbl);
+ options = StringUtil.dedupStringsMap(options, strTbl);
+
+ if (parameters != null) {
+ for (RangerConstraintParamDef parameter : parameters) {
+ parameter.dedupStrings(strTbl);
+ }
+ }
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ sb.append("RangerConstraintDef={");
+ sb.append("itemId={").append(itemId).append("} ");
+ sb.append("name={").append(name).append("} ");
+ sb.append("label={").append(label).append("} ");
+ sb.append("description={").append(description).append("} ");
+ sb.append("rbKeyLabel={").append(rbKeyLabel).append("} ");
+ sb.append("rbKeyDescription={").append(rbKeyDescription).append("} ");
+
+ sb.append("resources={");
+ if (resources != null) {
+ for (String resource : resources) {
+ if (resource != null) {
+ sb.append(resource).append(" ");
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("accessTypes={");
+ if (accessTypes != null) {
+ for (String accessType : accessTypes) {
+ if (accessType != null) {
+ sb.append(accessType).append(" ");
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("parameters={");
+ if (parameters != null) {
+ for (RangerConstraintParamDef parameter : parameters) {
+ if (parameter != null) {
+ parameter.toString(sb);
+ }
+ }
+ }
+ sb.append("} ");
+
+ sb.append("options={").append(options).append("} ");
+ sb.append("}");
+
+ return sb;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(itemId, name, label, description, rbKeyLabel, rbKeyDescription, resources, accessTypes, parameters, options);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj == null) {
+ return false;
+ } else if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ RangerConstraintDef other = (RangerConstraintDef) obj;
+
+ return Objects.equals(itemId, other.itemId) &&
+ Objects.equals(name, other.name) &&
+ Objects.equals(label, other.label) &&
+ Objects.equals(description, other.description) &&
+ Objects.equals(rbKeyLabel, other.rbKeyLabel) &&
+ Objects.equals(rbKeyDescription, other.rbKeyDescription) &&
+ Objects.equals(resources, other.resources) &&
+ Objects.equals(accessTypes, other.accessTypes) &&
+ Objects.equals(parameters, other.parameters) &&
+ Objects.equals(options, other.options);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ toString(sb);
+
+ return sb.toString();
+ }
+ }
+
+ @JsonAutoDetect(fieldVisibility = Visibility.ANY)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class RangerConstraintParamDef implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Long itemId;
+ private String name;
+ private String label;
+ private String description;
+ private String type;
Review Comment:
I suggest introducing `subType` field, similar to in `RangerServiceConfigDef`. This will be necessary to support `enum` types. For example, consider modelling existing `RangerDataMaskDef` as a constraintDef. The list of mask-types can be modelled as an enum, say `MaskTypes`. The constraint parameter will be `maskExpression`, with type as `enum`, subType as `MaskTypes`. This will help UI to render the list of supported mask types for the user to pick one.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@ranger.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org