Skip to content

Commit c5457b3

Browse files
Clearer error on modifying read-only role mappings (#115951) (#115962)
Copy of: #115509 also due to temporary repo unavailability. That PR is already approved. (cherry picked from commit e543e82) Co-authored-by: Elastic Machine <[email protected]>
1 parent 48d40dc commit c5457b3

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/rolemapping/PutRoleMappingRequest.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Objects;
2727

2828
import static org.elasticsearch.action.ValidateActions.addValidationError;
29+
import static org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG;
2930

3031
/**
3132
* Request object for adding/updating a role-mapping to the native store
@@ -77,10 +78,19 @@ public ActionRequestValidationException validate(boolean validateMetadata) {
7778
validationException = addValidationError("role-mapping rules are missing", validationException);
7879
}
7980
if (validateMetadata && MetadataUtils.containsReservedMetadata(metadata)) {
80-
validationException = addValidationError(
81-
"metadata keys may not start with [" + MetadataUtils.RESERVED_PREFIX + "]",
82-
validationException
83-
);
81+
if (metadata.containsKey(READ_ONLY_ROLE_MAPPING_METADATA_FLAG)) {
82+
validationException = addValidationError(
83+
"metadata contains ["
84+
+ READ_ONLY_ROLE_MAPPING_METADATA_FLAG
85+
+ "] flag. You cannot create or update role-mappings with a read-only flag",
86+
validationException
87+
);
88+
} else {
89+
validationException = addValidationError(
90+
"metadata keys may not start with [" + MetadataUtils.RESERVED_PREFIX + "]",
91+
validationException
92+
);
93+
}
8494
}
8595
return validationException;
8696
}

x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/rolemapping/RoleMappingRestIT.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,32 @@ public void testPutAndDeleteRoleMappings() throws IOException {
150150
);
151151
}
152152

153+
// simulate attempt to update a CS role mapping (the request will include a _read_only metadata flag
154+
{
155+
var ex = expectThrows(
156+
ResponseException.class,
157+
() -> putMapping(expressionRoleMapping("role-mapping-1-read-only-operator-mapping", Map.of("_read_only", true)))
158+
);
159+
assertThat(
160+
ex.getMessage(),
161+
containsString("metadata contains [_read_only] flag. You cannot create or update role-mappings with a read-only flag")
162+
);
163+
}
164+
165+
{
166+
var ex = expectThrows(
167+
ResponseException.class,
168+
() -> putMapping(expressionRoleMapping("role-mapping-1-read-only-operator-mapping"))
169+
);
170+
assertThat(
171+
ex.getMessage(),
172+
containsString(
173+
"Invalid mapping name [role-mapping-1-read-only-operator-mapping]. "
174+
+ "[-read-only-operator-mapping] is not an allowed suffix"
175+
)
176+
);
177+
}
178+
153179
// Also fails even if a CS role mapping with that name does not exist
154180
{
155181
var ex = expectThrows(
@@ -209,12 +235,16 @@ private static Response deleteMapping(String name, @Nullable String warning) thr
209235
}
210236

211237
private static ExpressionRoleMapping expressionRoleMapping(String name) {
238+
return expressionRoleMapping(name, Map.of());
239+
}
240+
241+
private static ExpressionRoleMapping expressionRoleMapping(String name, Map<String, Object> metadata) {
212242
return new ExpressionRoleMapping(
213243
name,
214244
new FieldExpression("username", List.of(new FieldExpression.FieldValue(randomAlphaOfLength(10)))),
215245
List.of(randomAlphaOfLength(5)),
216246
null,
217-
Map.of(),
247+
metadata,
218248
true
219249
);
220250
}

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/rolemapping/PutRoleMappingRequestTests.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,19 @@
1111
import org.elasticsearch.test.ESTestCase;
1212
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRequest;
1313
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRequestBuilder;
14+
import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping;
1415
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.RoleMapperExpression;
1516
import org.junit.Before;
1617
import org.mockito.Mockito;
1718

1819
import java.util.Collections;
20+
import java.util.Map;
1921

22+
import static org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG;
2023
import static org.hamcrest.Matchers.containsString;
24+
import static org.hamcrest.Matchers.is;
2125
import static org.hamcrest.Matchers.notNullValue;
26+
import static org.hamcrest.Matchers.nullValue;
2227

2328
public class PutRoleMappingRequestTests extends ESTestCase {
2429

@@ -54,6 +59,62 @@ public void testValidateMetadataKeys() throws Exception {
5459
assertValidationFailure(request, "metadata key");
5560
}
5661

62+
public void testValidateReadyOnlyMetadataKey() {
63+
assertValidationFailure(
64+
builder.name("test")
65+
.roles("superuser")
66+
.expression(Mockito.mock(RoleMapperExpression.class))
67+
.metadata(Map.of("_secret", false, ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG, true))
68+
.request(),
69+
"metadata contains ["
70+
+ READ_ONLY_ROLE_MAPPING_METADATA_FLAG
71+
+ "] flag. You cannot create or update role-mappings with a read-only flag"
72+
);
73+
74+
assertValidationFailure(
75+
builder.name("test")
76+
.roles("superuser")
77+
.expression(Mockito.mock(RoleMapperExpression.class))
78+
.metadata(Map.of(ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG, true))
79+
.request(),
80+
"metadata contains ["
81+
+ READ_ONLY_ROLE_MAPPING_METADATA_FLAG
82+
+ "] flag. You cannot create or update role-mappings with a read-only flag"
83+
);
84+
}
85+
86+
public void testValidateMetadataKeySkipped() {
87+
assertThat(
88+
builder.name("test")
89+
.roles("superuser")
90+
.expression(Mockito.mock(RoleMapperExpression.class))
91+
.metadata(Map.of("_secret", false, ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG, true))
92+
.request()
93+
.validate(false),
94+
is(nullValue())
95+
);
96+
97+
assertThat(
98+
builder.name("test")
99+
.roles("superuser")
100+
.expression(Mockito.mock(RoleMapperExpression.class))
101+
.metadata(Map.of(ExpressionRoleMapping.READ_ONLY_ROLE_MAPPING_METADATA_FLAG, true))
102+
.request()
103+
.validate(false),
104+
is(nullValue())
105+
);
106+
107+
assertThat(
108+
builder.name("test")
109+
.roles("superuser")
110+
.expression(Mockito.mock(RoleMapperExpression.class))
111+
.metadata(Map.of("_secret", false))
112+
.request()
113+
.validate(false),
114+
is(nullValue())
115+
);
116+
}
117+
57118
private void assertValidationFailure(PutRoleMappingRequest request, String expectedMessage) {
58119
final ValidationException ve = request.validate();
59120
assertThat(ve, notNullValue());

0 commit comments

Comments
 (0)