Skip to content

Commit 67204a9

Browse files
authored
buildFromRoleDescriptor uses application privilege look up (#91152)
Building a role from a single role descriptor previously only worked correctly for application privileges with wildcard patterns. This PR adds support for concrete name look up and ports the relevant tests. Relates: #91107 (comment)
1 parent 98aee60 commit 67204a9

File tree

5 files changed

+292
-48
lines changed

5 files changed

+292
-48
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,15 @@ static SimpleRole buildFromRoleDescriptor(
318318
final RoleDescriptor roleDescriptor,
319319
final FieldPermissionsCache fieldPermissionsCache,
320320
final RestrictedIndices restrictedIndices
321+
) {
322+
return buildFromRoleDescriptor(roleDescriptor, fieldPermissionsCache, restrictedIndices, List.of());
323+
}
324+
325+
static SimpleRole buildFromRoleDescriptor(
326+
final RoleDescriptor roleDescriptor,
327+
final FieldPermissionsCache fieldPermissionsCache,
328+
final RestrictedIndices restrictedIndices,
329+
final Collection<ApplicationPrivilegeDescriptor> storedApplicationPrivilegeDescriptors
321330
) {
322331
// TODO handle this when we introduce remote index privileges for built-in users and roles. That's the only production code
323332
// using this builder
@@ -344,14 +353,11 @@ static SimpleRole buildFromRoleDescriptor(
344353
}
345354

346355
for (RoleDescriptor.ApplicationResourcePrivileges applicationPrivilege : roleDescriptor.getApplicationPrivileges()) {
347-
builder.addApplicationPrivilege(
348-
new ApplicationPrivilege(
349-
applicationPrivilege.getApplication(),
350-
Sets.newHashSet(applicationPrivilege.getPrivileges()),
351-
applicationPrivilege.getPrivileges()
352-
),
353-
Sets.newHashSet(applicationPrivilege.getResources())
354-
);
356+
ApplicationPrivilege.get(
357+
applicationPrivilege.getApplication(),
358+
Sets.newHashSet(applicationPrivilege.getPrivileges()),
359+
storedApplicationPrivilegeDescriptors
360+
).forEach(priv -> builder.addApplicationPrivilege(priv, Sets.newHashSet(applicationPrivilege.getResources())));
355361
}
356362

357363
final String[] rdRunAs = roleDescriptor.getRunAs();

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/permission/SimpleRoleTests.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@
1111
import org.elasticsearch.test.ESTestCase;
1212
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine;
1313
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
14+
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege;
15+
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor;
1416

17+
import java.util.Arrays;
18+
import java.util.List;
1519
import java.util.Map;
20+
import java.util.Set;
1621
import java.util.concurrent.ExecutionException;
1722

1823
import static org.elasticsearch.xpack.core.security.test.TestRestrictedIndices.RESTRICTED_INDICES;
1924
import static org.hamcrest.Matchers.emptyArray;
2025
import static org.hamcrest.Matchers.equalTo;
26+
import static org.hamcrest.Matchers.is;
2127
import static org.hamcrest.Matchers.notNullValue;
2228
import static org.hamcrest.Matchers.nullValue;
2329

@@ -56,4 +62,84 @@ public void testHasPrivilegesCache() throws ExecutionException {
5662
assertThat(role.checkPrivilegesWithCache(privilegesToCheck), equalTo(privilegesCheckResult));
5763
}
5864

65+
public void testBuildFromRoleDescriptorWithApplicationPrivileges() {
66+
final boolean wildcardApplication = randomBoolean();
67+
final boolean wildcardPrivileges = randomBoolean();
68+
final boolean wildcardResources = randomBoolean();
69+
final RoleDescriptor.ApplicationResourcePrivileges applicationPrivilege = RoleDescriptor.ApplicationResourcePrivileges.builder()
70+
.application(wildcardApplication ? "*" : randomAlphaOfLengthBetween(5, 12))
71+
// concrete privileges need to be prefixed with lower case letters to be considered valid, so use "app"
72+
.privileges(wildcardPrivileges ? "*" : "app" + randomAlphaOfLengthBetween(5, 12))
73+
.resources(wildcardResources ? new String[] { "*" } : generateRandomStringArray(6, randomIntBetween(4, 8), false, false))
74+
.build();
75+
76+
final String allowedApplicationActionPattern = randomAlphaOfLengthBetween(5, 12);
77+
final SimpleRole role = Role.buildFromRoleDescriptor(
78+
new RoleDescriptor(
79+
"r1",
80+
null,
81+
null,
82+
new RoleDescriptor.ApplicationResourcePrivileges[] { applicationPrivilege },
83+
null,
84+
null,
85+
null,
86+
null
87+
),
88+
new FieldPermissionsCache(Settings.EMPTY),
89+
RESTRICTED_INDICES,
90+
wildcardPrivileges
91+
? List.of()
92+
: List.of(
93+
new ApplicationPrivilegeDescriptor(
94+
applicationPrivilege.getApplication(),
95+
Arrays.stream(applicationPrivilege.getPrivileges()).iterator().next(),
96+
Set.of(allowedApplicationActionPattern),
97+
Map.of()
98+
)
99+
)
100+
);
101+
assertThat(
102+
"expected grant for role with application privilege to be: " + applicationPrivilege,
103+
role.application()
104+
.grants(
105+
new ApplicationPrivilege(
106+
wildcardApplication ? randomAlphaOfLengthBetween(1, 10) : applicationPrivilege.getApplication(),
107+
wildcardPrivileges ? Set.of(randomAlphaOfLengthBetween(1, 10)) : Set.of(applicationPrivilege.getPrivileges()),
108+
wildcardPrivileges ? randomAlphaOfLengthBetween(1, 10) : allowedApplicationActionPattern
109+
),
110+
wildcardResources ? randomAlphaOfLengthBetween(1, 10) : randomFrom(applicationPrivilege.getResources())
111+
),
112+
is(true)
113+
);
114+
// This gives decent but not complete coverage of denial cases; for any non-wildcard field we pick a mismatched value to force a
115+
// denial
116+
assertThat(
117+
"expected grant for role with application privilege to be: " + applicationPrivilege,
118+
role.application()
119+
.grants(
120+
new ApplicationPrivilege(
121+
false == wildcardApplication
122+
? randomValueOtherThan(applicationPrivilege.getApplication(), () -> randomAlphaOfLengthBetween(1, 10))
123+
: randomAlphaOfLengthBetween(1, 10),
124+
false == wildcardPrivileges
125+
? randomValueOtherThan(
126+
Set.of(applicationPrivilege.getPrivileges()),
127+
() -> Set.of(randomAlphaOfLengthBetween(1, 10))
128+
)
129+
: Set.of(randomAlphaOfLengthBetween(1, 10)),
130+
false == wildcardPrivileges
131+
? randomValueOtherThan(allowedApplicationActionPattern, () -> randomAlphaOfLengthBetween(1, 10))
132+
: randomAlphaOfLengthBetween(1, 10)
133+
),
134+
false == wildcardResources
135+
? randomValueOtherThanMany(
136+
it -> List.of(applicationPrivilege.getResources()).contains(it),
137+
() -> randomAlphaOfLengthBetween(1, 10)
138+
)
139+
: randomAlphaOfLengthBetween(1, 10)
140+
),
141+
// If all are wildcards, then we necessarily get a grant, otherwise expect a denial
142+
is(wildcardApplication && wildcardPrivileges && wildcardResources)
143+
);
144+
}
59145
}

0 commit comments

Comments
 (0)