Skip to content

Commit 31dc580

Browse files
committed
address feedback to add more tests
1 parent 5203df0 commit 31dc580

File tree

3 files changed

+170
-3
lines changed

3 files changed

+170
-3
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/Subject.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ private Map<String, Object> getRoleDescriptorMap(String key) {
175175

176176
// This following fixed role descriptor is for fleet-server BWC on and before 7.14.
177177
// It is fixed and must NOT be updated when the fleet-server service account updates.
178-
private static final BytesArray FLEET_SERVER_ROLE_DESCRIPTOR_BYTES_V_7_14 = new BytesArray(
178+
// Package private for testing
179+
static final BytesArray FLEET_SERVER_ROLE_DESCRIPTOR_BYTES_V_7_14 = new BytesArray(
179180
"{\"elastic/fleet-server\":{\"cluster\":[\"monitor\",\"manage_own_api_key\"],"
180181
+ "\"indices\":[{\"names\":[\"logs-*\",\"metrics-*\",\"traces-*\",\"synthetics-*\","
181182
+ "\".logs-endpoint.diagnostic.collection-*\"],"

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authc/SubjectTests.java

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@
88
package org.elasticsearch.xpack.core.security.authc;
99

1010
import org.elasticsearch.Version;
11+
import org.elasticsearch.common.Strings;
1112
import org.elasticsearch.common.bytes.BytesArray;
1213
import org.elasticsearch.common.bytes.BytesReference;
14+
import org.elasticsearch.common.settings.Settings;
15+
import org.elasticsearch.common.util.ArrayUtils;
1316
import org.elasticsearch.test.ESTestCase;
1417
import org.elasticsearch.test.VersionUtils;
18+
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccountSettings;
1519
import org.elasticsearch.xpack.core.security.authz.store.RoleReference;
1620
import org.elasticsearch.xpack.core.security.authz.store.RoleReference.ApiKeyRoleReference;
1721
import org.elasticsearch.xpack.core.security.authz.store.RoleReference.BwcApiKeyRoleReference;
22+
import org.elasticsearch.xpack.core.security.authz.store.RoleReference.NamedRoleReference;
23+
import org.elasticsearch.xpack.core.security.authz.store.RoleReference.ServiceAccountRoleReference;
24+
import org.elasticsearch.xpack.core.security.user.AnonymousUser;
1825
import org.elasticsearch.xpack.core.security.user.User;
1926

2027
import java.util.Arrays;
@@ -27,12 +34,71 @@
2734
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_REALM_NAME;
2835
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_REALM_TYPE;
2936
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY;
37+
import static org.elasticsearch.xpack.core.security.authc.Subject.FLEET_SERVER_ROLE_DESCRIPTOR_BYTES_V_7_14;
38+
import static org.hamcrest.Matchers.arrayContaining;
3039
import static org.hamcrest.Matchers.contains;
3140
import static org.hamcrest.Matchers.equalTo;
41+
import static org.hamcrest.Matchers.hasSize;
42+
import static org.hamcrest.Matchers.instanceOf;
3243
import static org.hamcrest.Matchers.isA;
3344

3445
public class SubjectTests extends ESTestCase {
3546

47+
public void testGetRoleReferencesForRegularUser() {
48+
final User user = new User("joe", "role_a", "role_b");
49+
final Subject subject = new Subject(
50+
user,
51+
new Authentication.RealmRef(randomAlphaOfLength(5), randomAlphaOfLength(5), "node"),
52+
Version.CURRENT,
53+
Map.of()
54+
);
55+
56+
final AnonymousUser anonymousUser = randomFrom(getAnonymousUser(), null);
57+
58+
final List<RoleReference> roleReferences = subject.getRoleReferences(anonymousUser);
59+
assertThat(roleReferences, hasSize(1));
60+
assertThat(roleReferences.get(0), instanceOf(NamedRoleReference.class));
61+
final NamedRoleReference namedRoleReference = (NamedRoleReference) roleReferences.get(0);
62+
assertThat(
63+
namedRoleReference.getRoleNames(),
64+
arrayContaining(ArrayUtils.concat(user.roles(), anonymousUser == null ? Strings.EMPTY_ARRAY : anonymousUser.roles()))
65+
);
66+
}
67+
68+
public void testGetRoleReferencesForAnonymousUser() {
69+
final AnonymousUser anonymousUser = getAnonymousUser();
70+
71+
final Subject subject = new Subject(
72+
anonymousUser,
73+
new Authentication.RealmRef(randomAlphaOfLength(5), randomAlphaOfLength(5), "node"),
74+
Version.CURRENT,
75+
Map.of()
76+
);
77+
78+
final List<RoleReference> roleReferences = subject.getRoleReferences(anonymousUser);
79+
assertThat(roleReferences, hasSize(1));
80+
assertThat(roleReferences.get(0), instanceOf(NamedRoleReference.class));
81+
final NamedRoleReference namedRoleReference = (NamedRoleReference) roleReferences.get(0);
82+
// Anonymous roles do not get applied again
83+
assertThat(namedRoleReference.getRoleNames(), equalTo(anonymousUser.roles()));
84+
}
85+
86+
public void testGetRoleReferencesForServiceAccount() {
87+
final User serviceUser = new User(randomAlphaOfLength(5) + "/" + randomAlphaOfLength(5));
88+
final Subject subject = new Subject(
89+
serviceUser,
90+
new Authentication.RealmRef(ServiceAccountSettings.REALM_NAME, ServiceAccountSettings.REALM_TYPE, "node"),
91+
Version.CURRENT,
92+
Map.of()
93+
);
94+
95+
final List<RoleReference> roleReferences = subject.getRoleReferences(getAnonymousUser());
96+
assertThat(roleReferences, hasSize(1));
97+
assertThat(roleReferences.get(0), instanceOf(ServiceAccountRoleReference.class));
98+
final ServiceAccountRoleReference serviceAccountRoleReference = (ServiceAccountRoleReference) roleReferences.get(0);
99+
assertThat(serviceAccountRoleReference.getPrincipal(), equalTo(serviceUser.principal()));
100+
}
101+
36102
public void testGetRoleReferencesForApiKey() {
37103
Map<String, Object> authMetadata = new HashMap<>();
38104
final String apiKeyId = randomAlphaOfLength(12);
@@ -56,7 +122,7 @@ public void testGetRoleReferencesForApiKey() {
56122
authMetadata
57123
);
58124

59-
final List<RoleReference> roleReferences = subject.getRoleReferences(null);
125+
final List<RoleReference> roleReferences = subject.getRoleReferences(getAnonymousUser());
60126
if (emptyRoleBytes) {
61127
assertThat(roleReferences, contains(isA(ApiKeyRoleReference.class)));
62128
final ApiKeyRoleReference roleReference = (ApiKeyRoleReference) roleReferences.get(0);
@@ -98,7 +164,7 @@ public void testGetRoleReferencesForApiKeyBwc() {
98164
authMetadata
99165
);
100166

101-
final List<RoleReference> roleReferences = subject.getRoleReferences(null);
167+
final List<RoleReference> roleReferences = subject.getRoleReferences(getAnonymousUser());
102168

103169
if (emptyApiKeyRoleDescriptor) {
104170
assertThat(roleReferences, contains(isA(BwcApiKeyRoleReference.class)));
@@ -117,4 +183,35 @@ public void testGetRoleReferencesForApiKeyBwc() {
117183
}
118184
}
119185

186+
public void testGetFleetApiKeyRoleReferenceBwcBugFix() {
187+
final BytesReference roleBytes = new BytesArray("{\"a role\": {\"cluster\": [\"all\"]}}");
188+
final BytesReference limitedByRoleBytes = new BytesArray("{}");
189+
final Subject subject = new Subject(
190+
new User("elastic/fleet-server"),
191+
new Authentication.RealmRef(API_KEY_REALM_NAME, API_KEY_REALM_TYPE, "node"),
192+
Version.CURRENT,
193+
Map.of(
194+
AuthenticationField.API_KEY_CREATOR_REALM_NAME,
195+
ServiceAccountSettings.REALM_NAME,
196+
AuthenticationField.API_KEY_ID_KEY,
197+
randomAlphaOfLength(20),
198+
AuthenticationField.API_KEY_NAME_KEY,
199+
randomAlphaOfLength(12),
200+
AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY,
201+
roleBytes,
202+
AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY,
203+
limitedByRoleBytes
204+
)
205+
);
206+
207+
final List<RoleReference> roleReferences = subject.getRoleReferences(getAnonymousUser());
208+
assertThat(roleReferences, contains(isA(ApiKeyRoleReference.class), isA(ApiKeyRoleReference.class)));
209+
final ApiKeyRoleReference limitedByRoleReference = (ApiKeyRoleReference) roleReferences.get(1);
210+
assertThat(limitedByRoleReference.getRoleDescriptorsBytes(), equalTo(FLEET_SERVER_ROLE_DESCRIPTOR_BYTES_V_7_14));
211+
}
212+
213+
private AnonymousUser getAnonymousUser() {
214+
final List<String> anonymousRoles = randomList(0, 2, () -> "role_anonymous_" + randomAlphaOfLength(8));
215+
return new AnonymousUser(Settings.builder().putList("xpack.security.authc.anonymous.roles", anonymousRoles).build());
216+
}
120217
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.core.security.authz.store;
9+
10+
import org.elasticsearch.common.bytes.BytesArray;
11+
import org.elasticsearch.common.hash.MessageDigests;
12+
import org.elasticsearch.test.ESTestCase;
13+
14+
import java.util.Set;
15+
16+
import static org.hamcrest.Matchers.equalTo;
17+
import static org.hamcrest.Matchers.hasItem;
18+
import static org.hamcrest.Matchers.is;
19+
20+
public class RoleReferenceTests extends ESTestCase {
21+
22+
public void testNamedRoleReference() {
23+
final String[] roleNames = randomArray(0, 2, String[]::new, () -> randomAlphaOfLength(8));
24+
25+
final boolean hasSuperUserRole = roleNames.length > 0 && randomBoolean();
26+
if (hasSuperUserRole) {
27+
roleNames[randomIntBetween(0, roleNames.length - 1)] = "superuser";
28+
}
29+
final RoleReference.NamedRoleReference namedRoleReference = new RoleReference.NamedRoleReference(roleNames);
30+
31+
if (hasSuperUserRole) {
32+
assertThat(namedRoleReference.id(), is(RoleKey.ROLE_KEY_SUPERUSER));
33+
} else if (roleNames.length == 0) {
34+
assertThat(namedRoleReference.id(), is(RoleKey.ROLE_KEY_EMPTY));
35+
} else {
36+
final RoleKey roleKey = namedRoleReference.id();
37+
assertThat(roleKey.getNames(), equalTo(Set.of(roleNames)));
38+
assertThat(roleKey.getSource(), equalTo(RoleKey.ROLES_STORE_SOURCE));
39+
}
40+
}
41+
42+
public void testApiKeyRoleReference() {
43+
final String apiKeyId = randomAlphaOfLength(20);
44+
final BytesArray roleDescriptorsBytes = new BytesArray(randomAlphaOfLength(50));
45+
final String roleKeySource = randomAlphaOfLength(8);
46+
final RoleReference.ApiKeyRoleReference apiKeyRoleReference = new RoleReference.ApiKeyRoleReference(
47+
apiKeyId,
48+
roleDescriptorsBytes,
49+
roleKeySource
50+
);
51+
52+
final RoleKey roleKey = apiKeyRoleReference.id();
53+
assertThat(
54+
roleKey.getNames(),
55+
hasItem("apikey:" + MessageDigests.toHexString(MessageDigests.digest(roleDescriptorsBytes, MessageDigests.sha256())))
56+
);
57+
assertThat(roleKey.getSource(), equalTo(roleKeySource));
58+
}
59+
60+
public void testServiceAccountRoleReference() {
61+
final String principal = randomAlphaOfLength(8) + "/" + randomAlphaOfLength(8);
62+
final RoleReference.ServiceAccountRoleReference serviceAccountRoleReference = new RoleReference.ServiceAccountRoleReference(
63+
principal
64+
);
65+
final RoleKey roleKey = serviceAccountRoleReference.id();
66+
assertThat(roleKey.getNames(), hasItem(principal));
67+
assertThat(roleKey.getSource(), equalTo("service_account"));
68+
}
69+
}

0 commit comments

Comments
 (0)