21
21
22
22
import org .apache .logging .log4j .message .ParameterizedMessage ;
23
23
import org .apache .logging .log4j .util .Supplier ;
24
+ import org .elasticsearch .ElasticsearchException ;
24
25
import org .elasticsearch .ExceptionsHelper ;
26
+ import org .elasticsearch .action .ActionListener ;
25
27
import org .elasticsearch .action .FailedNodeException ;
26
28
import org .elasticsearch .action .support .ActionFilters ;
27
29
import org .elasticsearch .action .support .nodes .BaseNodeRequest ;
28
30
import org .elasticsearch .action .support .nodes .TransportNodesAction ;
31
+ import org .elasticsearch .cluster .node .DiscoveryNode ;
29
32
import org .elasticsearch .cluster .service .ClusterService ;
30
33
import org .elasticsearch .common .inject .Inject ;
31
34
import org .elasticsearch .common .io .stream .StreamInput ;
32
35
import org .elasticsearch .common .io .stream .StreamOutput ;
33
36
import org .elasticsearch .common .settings .KeyStoreWrapper ;
37
+ import org .elasticsearch .common .settings .SecureString ;
34
38
import org .elasticsearch .common .settings .Settings ;
35
39
import org .elasticsearch .env .Environment ;
36
40
import org .elasticsearch .plugins .PluginsService ;
@@ -78,15 +82,39 @@ protected NodesReloadSecureSettingsResponse.NodeResponse newNodeResponse() {
78
82
return new NodesReloadSecureSettingsResponse .NodeResponse ();
79
83
}
80
84
85
+ @ Override
86
+ protected void doExecute (Task task , NodesReloadSecureSettingsRequest request ,
87
+ ActionListener <NodesReloadSecureSettingsResponse > listener ) {
88
+ if (request .hasPassword () && isNodeLocal (request ) == false && isNodeTransportTLSEnabled () == false ) {
89
+ request .closePassword ();
90
+ listener .onFailure (
91
+ new ElasticsearchException ("Secure settings cannot be updated cluster wide when TLS for the transport layer" +
92
+ " is not enabled. Enable TLS or use the API with a `_local` filter on each node." ));
93
+ } else {
94
+ super .doExecute (task , request , ActionListener .wrap (response -> {
95
+ request .closePassword ();
96
+ listener .onResponse (response );
97
+ }, e -> {
98
+ request .closePassword ();
99
+ listener .onFailure (e );
100
+ }));
101
+ }
102
+ }
103
+
81
104
@ Override
82
105
protected NodesReloadSecureSettingsResponse .NodeResponse nodeOperation (NodeRequest nodeReloadRequest , Task task ) {
106
+ final NodesReloadSecureSettingsRequest request = nodeReloadRequest .request ;
107
+ // We default to using an empty string as the keystore password so that we mimic pre 7.3 API behavior
108
+ final SecureString secureSettingsPassword = request .hasPassword () ? request .getSecureSettingsPassword () :
109
+ new SecureString (new char [0 ]);
83
110
try (KeyStoreWrapper keystore = KeyStoreWrapper .load (environment .configFile ())) {
84
111
// reread keystore from config file
85
112
if (keystore == null ) {
86
113
return new NodesReloadSecureSettingsResponse .NodeResponse (clusterService .localNode (),
87
114
new IllegalStateException ("Keystore is missing" ));
88
115
}
89
- keystore .decrypt (new char [0 ]);
116
+ // decrypt the keystore using the password from the request
117
+ keystore .decrypt (secureSettingsPassword .getChars ());
90
118
// add the keystore to the original node settings object
91
119
final Settings settingsWithKeystore = Settings .builder ()
92
120
.put (environment .settings (), false )
@@ -107,6 +135,8 @@ protected NodesReloadSecureSettingsResponse.NodeResponse nodeOperation(NodeReque
107
135
return new NodesReloadSecureSettingsResponse .NodeResponse (clusterService .localNode (), null );
108
136
} catch (final Exception e ) {
109
137
return new NodesReloadSecureSettingsResponse .NodeResponse (clusterService .localNode (), e );
138
+ } finally {
139
+ secureSettingsPassword .close ();
110
140
}
111
141
}
112
142
@@ -134,4 +164,20 @@ public void writeTo(StreamOutput out) throws IOException {
134
164
request .writeTo (out );
135
165
}
136
166
}
167
+
168
+ /**
169
+ * Returns true if the node is configured for TLS on the transport layer
170
+ */
171
+ private boolean isNodeTransportTLSEnabled () {
172
+ return transportService .isTransportSecure ();
173
+ }
174
+
175
+ private boolean isNodeLocal (NodesReloadSecureSettingsRequest request ) {
176
+ if (null == request .concreteNodes ()) {
177
+ resolveRequest (request , clusterService .state ());
178
+ assert request .concreteNodes () != null ;
179
+ }
180
+ final DiscoveryNode [] nodes = request .concreteNodes ();
181
+ return nodes .length == 1 && nodes [0 ].getId ().equals (clusterService .localNode ().getId ());
182
+ }
137
183
}
0 commit comments