88package org .elasticsearch .xpack .core .security .authc ;
99
1010import org .elasticsearch .Version ;
11+ import org .elasticsearch .common .Strings ;
1112import org .elasticsearch .common .bytes .BytesArray ;
1213import org .elasticsearch .common .bytes .BytesReference ;
14+ import org .elasticsearch .common .settings .Settings ;
15+ import org .elasticsearch .common .util .ArrayUtils ;
1316import org .elasticsearch .test .ESTestCase ;
1417import org .elasticsearch .test .VersionUtils ;
18+ import org .elasticsearch .xpack .core .security .authc .service .ServiceAccountSettings ;
1519import org .elasticsearch .xpack .core .security .authz .store .RoleReference ;
1620import org .elasticsearch .xpack .core .security .authz .store .RoleReference .ApiKeyRoleReference ;
1721import 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 ;
1825import org .elasticsearch .xpack .core .security .user .User ;
1926
2027import java .util .Arrays ;
2734import static org .elasticsearch .xpack .core .security .authc .AuthenticationField .API_KEY_REALM_NAME ;
2835import static org .elasticsearch .xpack .core .security .authc .AuthenticationField .API_KEY_REALM_TYPE ;
2936import 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 ;
3039import static org .hamcrest .Matchers .contains ;
3140import static org .hamcrest .Matchers .equalTo ;
41+ import static org .hamcrest .Matchers .hasSize ;
42+ import static org .hamcrest .Matchers .instanceOf ;
3243import static org .hamcrest .Matchers .isA ;
3344
3445public 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}
0 commit comments