@@ -39,9 +39,46 @@ public final class PutUserRequest implements Validatable, ToXContentObject {
3939
4040 private final User user ;
4141 private final @ Nullable char [] password ;
42+ private final @ Nullable char [] passwordHash ;
4243 private final boolean enabled ;
4344 private final RefreshPolicy refreshPolicy ;
4445
46+ /**
47+ * Create or update a user in the native realm, with the user's new or updated password specified in plaintext.
48+ * @param user the user to be created or updated
49+ * @param password the password of the user. The password array is not modified by this class.
50+ * It is the responsibility of the caller to clear the password after receiving
51+ * a response.
52+ * @param enabled true if the user is enabled and allowed to access elasticsearch
53+ * @param refreshPolicy the refresh policy for the request.
54+ */
55+ public static PutUserRequest withPassword (User user , char [] password , boolean enabled , RefreshPolicy refreshPolicy ) {
56+ return new PutUserRequest (user , password , null , enabled , refreshPolicy );
57+ }
58+
59+ /**
60+ * Create or update a user in the native realm, with the user's new or updated password specified as a cryptographic hash.
61+ * @param user the user to be created or updated
62+ * @param passwordHash the hash of the password of the user. It must be in the correct format for the password hashing algorithm in
63+ * use on this elasticsearch cluster. The array is not modified by this class.
64+ * It is the responsibility of the caller to clear the hash after receiving a response.
65+ * @param enabled true if the user is enabled and allowed to access elasticsearch
66+ * @param refreshPolicy the refresh policy for the request.
67+ */
68+ public static PutUserRequest withPasswordHash (User user , char [] passwordHash , boolean enabled , RefreshPolicy refreshPolicy ) {
69+ return new PutUserRequest (user , null , passwordHash , enabled , refreshPolicy );
70+ }
71+
72+ /**
73+ * Update an existing user in the native realm without modifying their password.
74+ * @param user the user to be created or updated
75+ * @param enabled true if the user is enabled and allowed to access elasticsearch
76+ * @param refreshPolicy the refresh policy for the request.
77+ */
78+ public static PutUserRequest updateUser (User user , boolean enabled , RefreshPolicy refreshPolicy ) {
79+ return new PutUserRequest (user , null , null , enabled , refreshPolicy );
80+ }
81+
4582 /**
4683 * Creates a new request that is used to create or update a user in the native realm.
4784 *
@@ -51,10 +88,33 @@ public final class PutUserRequest implements Validatable, ToXContentObject {
5188 * a response.
5289 * @param enabled true if the user is enabled and allowed to access elasticsearch
5390 * @param refreshPolicy the refresh policy for the request.
91+ * @deprecated Use {@link #withPassword(User, char[], boolean, RefreshPolicy)} or
92+ * {@link #updateUser(User, boolean, RefreshPolicy)} instead.
5493 */
94+ @ Deprecated
5595 public PutUserRequest (User user , @ Nullable char [] password , boolean enabled , @ Nullable RefreshPolicy refreshPolicy ) {
96+ this (user , password , null , enabled , refreshPolicy );
97+ }
98+
99+ /**
100+ * Creates a new request that is used to create or update a user in the native realm.
101+ * @param user the user to be created or updated
102+ * @param password the password of the user. The password array is not modified by this class.
103+ * It is the responsibility of the caller to clear the password after receiving
104+ * a response.
105+ * @param passwordHash the hash of the password. Only one of "password" or "passwordHash" may be populated.
106+ * The other parameter must be {@code null}.
107+ * @param enabled true if the user is enabled and allowed to access elasticsearch
108+ * @param refreshPolicy the refresh policy for the request.
109+ */
110+ private PutUserRequest (User user , @ Nullable char [] password , @ Nullable char [] passwordHash , boolean enabled ,
111+ RefreshPolicy refreshPolicy ) {
56112 this .user = Objects .requireNonNull (user , "user is required, cannot be null" );
113+ if (password != null && passwordHash != null ) {
114+ throw new IllegalArgumentException ("cannot specify both password and passwordHash" );
115+ }
57116 this .password = password ;
117+ this .passwordHash = passwordHash ;
58118 this .enabled = enabled ;
59119 this .refreshPolicy = refreshPolicy == null ? RefreshPolicy .getDefault () : refreshPolicy ;
60120 }
@@ -82,6 +142,7 @@ public boolean equals(Object o) {
82142 final PutUserRequest that = (PutUserRequest ) o ;
83143 return Objects .equals (user , that .user )
84144 && Arrays .equals (password , that .password )
145+ && Arrays .equals (passwordHash , that .passwordHash )
85146 && enabled == that .enabled
86147 && refreshPolicy == that .refreshPolicy ;
87148 }
@@ -90,6 +151,7 @@ public boolean equals(Object o) {
90151 public int hashCode () {
91152 int result = Objects .hash (user , enabled , refreshPolicy );
92153 result = 31 * result + Arrays .hashCode (password );
154+ result = 31 * result + Arrays .hashCode (passwordHash );
93155 return result ;
94156 }
95157
@@ -108,12 +170,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
108170 builder .startObject ();
109171 builder .field ("username" , user .getUsername ());
110172 if (password != null ) {
111- byte [] charBytes = CharArrays .toUtf8Bytes (password );
112- try {
113- builder .field ("password" ).utf8Value (charBytes , 0 , charBytes .length );
114- } finally {
115- Arrays .fill (charBytes , (byte ) 0 );
116- }
173+ charField (builder , "password" , password );
174+ }
175+ if (passwordHash != null ) {
176+ charField (builder , "password_hash" , passwordHash );
117177 }
118178 builder .field ("roles" , user .getRoles ());
119179 if (user .getFullName () != null ) {
@@ -126,4 +186,13 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
126186 builder .field ("enabled" , enabled );
127187 return builder .endObject ();
128188 }
189+
190+ private void charField (XContentBuilder builder , String fieldName , char [] chars ) throws IOException {
191+ byte [] charBytes = CharArrays .toUtf8Bytes (chars );
192+ try {
193+ builder .field (fieldName ).utf8Value (charBytes , 0 , charBytes .length );
194+ } finally {
195+ Arrays .fill (charBytes , (byte ) 0 );
196+ }
197+ }
129198}
0 commit comments