Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
* Always install demo certs if configured with demo certs ([#5517](https://github.com/opensearch-project/security/pull/5517))
* [Resource Sharing] Restores client accessor pattern to fix compilation issues when security plugin is not installed ([#5541](https://github.com/opensearch-project/security/pull/5541))
* Add serialized user custom attributes to the the thread context ([#5491](https://github.com/opensearch-project/security/pull/5491))
* Fix NullPointerExceptions for "missing values" term aggregations and sorting on geo points ([#5537](https://github.com/opensearch-project/security/pull/5537))

### Refactoring

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ public void wildcard_inclusive() throws Exception {
assertEquals("FLS:*", flsRule.toString());
}

@Test
public void nullFieldName() throws Exception {
FieldPrivileges.FlsRule flsRule = FieldPrivileges.FlsRule.of("a");
assertFalse("null field value is rejected", flsRule.isAllowedAssumingParentsAreAllowed(null));
}

}

public static class FlsPattern {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public static class SimpleRule extends FieldMaskingRule {
}

public Field get(String field) {
return internalGet(stripKeywordSuffix(field));
return internalGet(FieldPrivileges.normalizeFieldName(field));
}

private Field internalGet(String field) {
Expand Down Expand Up @@ -193,7 +193,7 @@ public static class MultiRole extends FieldMaskingRule {
}

public Field get(String field) {
field = stripKeywordSuffix(field);
field = FieldPrivileges.normalizeFieldName(field);

for (SimpleRule part : parts) {
Field masking = part.get(field);
Expand Down Expand Up @@ -319,14 +319,6 @@ private byte[] blake2bHash(byte[] in, boolean useLegacyDefaultAlgorithm) {
return Hex.encode(out);
}
}

static String stripKeywordSuffix(String field) {
if (field.endsWith(".keyword")) {
return field.substring(0, field.length() - ".keyword".length());
} else {
return field;
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public boolean isAllowedAssumingParentsAreAllowed(String field) {
return true;
}

return isAllowedNonRecursive(stripKeywordSuffix(field));
return isAllowedNonRecursive(normalizeFieldName(field));
}

/**
Expand Down Expand Up @@ -231,7 +231,7 @@ public boolean isAllowedRecursive(String field) {
return true;
}

field = stripKeywordSuffix(field);
field = normalizeFieldName(field);

if (excluding) {
// search for rules that explicitly forbid this field
Expand Down Expand Up @@ -309,17 +309,6 @@ public List<String> getSource() {
public boolean isUnrestricted() {
return this.isAllowAll();
}

/**
* See https://github.com/opensearch-project/security/pull/2375
*/
static String stripKeywordSuffix(String field) {
if (field.endsWith(".keyword")) {
return field.substring(0, field.length() - ".keyword".length());
} else {
return field;
}
}
}

/**
Expand Down Expand Up @@ -435,4 +424,27 @@ public static List<FlsPattern> parse(List<String> flsPatternStrings) throws Priv

}

/**
* Processes a field name as received from wrapping leaf readers and normalizes it into a form that can
* be processed by this class.
*/
static String normalizeFieldName(String field) {
if (field == null) {
// This is a weird case; sometimes, OpenSearch code calls diverse LeafReader methods will a null field
// param. The semantics are not quite clear; most often, the underlying LeafReader will return null.
// But it is unclear if that can be relied on. Thus, in order to be safe here, we just use a NPE safe
// replacement value for privilege evaluation. Thus, the normal semantics continue to be applied. If a
// user has only access to a selected group of fields, any call for null will also be blocked. If a user
// has full access, we let the reading proceed as normal.
// See https://github.com/opensearch-project/OpenSearch-Dashboards/issues/9873 and
// https://github.com/opensearch-project/security/pull/5504#issuecomment-3114304553
return "__null__";
} else if (field.endsWith(".keyword")) {
// See https://github.com/opensearch-project/security/pull/2375
return field.substring(0, field.length() - ".keyword".length());
} else {
return field;
}
}

}
Loading