1010import org .elasticsearch .action .ActionListener ;
1111import org .elasticsearch .action .ActionResponse ;
1212import org .elasticsearch .action .support .ActionFilters ;
13+ import org .elasticsearch .common .ValidationException ;
1314import org .elasticsearch .common .settings .Settings ;
1415import org .elasticsearch .tasks .Task ;
1516import org .elasticsearch .test .ESTestCase ;
2627import org .elasticsearch .xpack .core .security .user .KibanaUser ;
2728import org .elasticsearch .xpack .core .security .user .User ;
2829import org .elasticsearch .xpack .security .authc .esnative .NativeUsersStore ;
30+ import org .elasticsearch .xpack .security .authc .file .FileUserPasswdStore ;
31+ import org .mockito .Mockito ;
2932
3033import java .util .Collections ;
3134import java .util .Locale ;
@@ -56,6 +59,7 @@ public void testAnonymousUser() {
5659 .build ();
5760 AnonymousUser anonymousUser = new AnonymousUser (settings );
5861 NativeUsersStore usersStore = mock (NativeUsersStore .class );
62+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
5963 TransportService transportService = new TransportService (
6064 Settings .EMPTY ,
6165 mock (Transport .class ),
@@ -69,7 +73,8 @@ public void testAnonymousUser() {
6973 settings ,
7074 transportService ,
7175 mock (ActionFilters .class ),
72- usersStore
76+ usersStore ,
77+ fileUserPasswdStore
7378 );
7479 // Request will fail before the request hashing algorithm is checked, but we use the same algorithm as in settings for consistency
7580 ChangePasswordRequest request = new ChangePasswordRequest ();
@@ -96,6 +101,56 @@ public void onFailure(Exception e) {
96101 verifyNoMoreInteractions (usersStore );
97102 }
98103
104+ public void testFileRealmUser () {
105+ final Hasher hasher = getFastStoredHashAlgoForTests ();
106+ Settings settings = Settings .builder ()
107+ .put (AnonymousUser .ROLES_SETTING .getKey (), "superuser" )
108+ .put (XPackSettings .PASSWORD_HASHING_ALGORITHM .getKey (), hasher .name ())
109+ .build ();
110+ ElasticUser elasticUser = new ElasticUser (true );
111+ NativeUsersStore usersStore = mock (NativeUsersStore .class );
112+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
113+ TransportService transportService = new TransportService (
114+ Settings .EMPTY ,
115+ mock (Transport .class ),
116+ mock (ThreadPool .class ),
117+ TransportService .NOOP_TRANSPORT_INTERCEPTOR ,
118+ x -> null ,
119+ null ,
120+ Collections .emptySet ()
121+ );
122+ TransportChangePasswordAction action = new TransportChangePasswordAction (
123+ settings ,
124+ transportService ,
125+ mock (ActionFilters .class ),
126+ usersStore ,
127+ fileUserPasswdStore
128+ );
129+ Mockito .when (fileUserPasswdStore .userExists (Mockito .eq (elasticUser .principal ()))).thenReturn (true );
130+ ChangePasswordRequest request = new ChangePasswordRequest ();
131+ request .username (elasticUser .principal ());
132+ request .passwordHash (hasher .hash (SecuritySettingsSourceField .TEST_PASSWORD_SECURE_STRING ));
133+
134+ final AtomicReference <Throwable > throwableRef = new AtomicReference <>();
135+ final AtomicReference <ActionResponse .Empty > responseRef = new AtomicReference <>();
136+ action .doExecute (mock (Task .class ), request , new ActionListener <>() {
137+ @ Override
138+ public void onResponse (ActionResponse .Empty changePasswordResponse ) {
139+ responseRef .set (changePasswordResponse );
140+ }
141+
142+ @ Override
143+ public void onFailure (Exception e ) {
144+ throwableRef .set (e );
145+ }
146+ });
147+
148+ assertThat (responseRef .get (), is (nullValue ()));
149+ assertThat (throwableRef .get (), instanceOf (ValidationException .class ));
150+ assertThat (throwableRef .get ().getMessage (), containsString ("is file-based and cannot be managed via this API" ));
151+ verifyNoMoreInteractions (usersStore );
152+ }
153+
99154 public void testValidUser () {
100155 testValidUser (randomFrom (new ElasticUser (true ), new KibanaUser (true ), new User ("joe" )));
101156 }
@@ -107,6 +162,7 @@ public void testValidUserWithInternalUsername() {
107162 private void testValidUser (User user ) {
108163 final Hasher hasher = getFastStoredHashAlgoForTests ();
109164 NativeUsersStore usersStore = mock (NativeUsersStore .class );
165+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
110166 ChangePasswordRequest request = new ChangePasswordRequest ();
111167 request .username (user .principal ());
112168 request .passwordHash (hasher .hash (SecuritySettingsSourceField .TEST_PASSWORD_SECURE_STRING ));
@@ -132,7 +188,8 @@ private void testValidUser(User user) {
132188 passwordHashingSettings ,
133189 transportService ,
134190 mock (ActionFilters .class ),
135- usersStore
191+ usersStore ,
192+ fileUserPasswdStore
136193 );
137194 final AtomicReference <Throwable > throwableRef = new AtomicReference <>();
138195 final AtomicReference <ActionResponse .Empty > responseRef = new AtomicReference <>();
@@ -157,6 +214,7 @@ public void onFailure(Exception e) {
157214 public void testWithPasswordThatsNotAHash () {
158215 final User user = randomFrom (new ElasticUser (true ), new KibanaUser (true ), new User ("joe" ));
159216 NativeUsersStore usersStore = mock (NativeUsersStore .class );
217+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
160218 ChangePasswordRequest request = new ChangePasswordRequest ();
161219 request .username (user .principal ());
162220 request .passwordHash (randomAlphaOfLengthBetween (14 , 20 ).toCharArray ());
@@ -177,7 +235,8 @@ public void testWithPasswordThatsNotAHash() {
177235 passwordHashingSettings ,
178236 transportService ,
179237 mock (ActionFilters .class ),
180- usersStore
238+ usersStore ,
239+ fileUserPasswdStore
181240 );
182241 action .doExecute (mock (Task .class ), request , new ActionListener <>() {
183242 @ Override
@@ -204,6 +263,7 @@ public void testWithDifferentPasswordHashingAlgorithm() {
204263 final User user = randomFrom (new ElasticUser (true ), new KibanaUser (true ), new User ("joe" ));
205264 final Hasher hasher = getFastStoredHashAlgoForTests ();
206265 NativeUsersStore usersStore = mock (NativeUsersStore .class );
266+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
207267 ChangePasswordRequest request = new ChangePasswordRequest ();
208268 request .username (user .principal ());
209269 request .passwordHash (hasher .hash (SecuritySettingsSourceField .TEST_PASSWORD_SECURE_STRING ));
@@ -235,7 +295,8 @@ public void testWithDifferentPasswordHashingAlgorithm() {
235295 passwordHashingSettings ,
236296 transportService ,
237297 mock (ActionFilters .class ),
238- usersStore
298+ usersStore ,
299+ fileUserPasswdStore
239300 );
240301 action .doExecute (mock (Task .class ), request , new ActionListener <>() {
241302 @ Override
@@ -259,6 +320,7 @@ public void testException() {
259320 final Hasher hasher = getFastStoredHashAlgoForTests ();
260321 final User user = randomFrom (new ElasticUser (true ), new KibanaUser (true ), new User ("joe" ));
261322 NativeUsersStore usersStore = mock (NativeUsersStore .class );
323+ FileUserPasswdStore fileUserPasswdStore = mock (FileUserPasswdStore .class );
262324 ChangePasswordRequest request = new ChangePasswordRequest ();
263325 request .username (user .principal ());
264326 request .passwordHash (hasher .hash (SecuritySettingsSourceField .TEST_PASSWORD_SECURE_STRING ));
@@ -285,7 +347,8 @@ public void testException() {
285347 passwordHashingSettings ,
286348 transportService ,
287349 mock (ActionFilters .class ),
288- usersStore
350+ usersStore ,
351+ fileUserPasswdStore
289352 );
290353 final AtomicReference <Throwable > throwableRef = new AtomicReference <>();
291354 final AtomicReference <ActionResponse .Empty > responseRef = new AtomicReference <>();
0 commit comments