1414
1515import org .apache .logging .log4j .LogManager ;
1616import org .apache .logging .log4j .Logger ;
17+ import org .elasticsearch .client .internal .node .NodeClient ;
1718import org .elasticsearch .cluster .metadata .RepositoryMetadata ;
1819import org .elasticsearch .cluster .service .ClusterService ;
1920import org .elasticsearch .common .settings .MockSecureSettings ;
2021import org .elasticsearch .common .settings .Settings ;
22+ import org .elasticsearch .common .settings .SettingsFilter ;
2123import org .elasticsearch .common .util .BigArrays ;
24+ import org .elasticsearch .core .SuppressForbidden ;
2225import org .elasticsearch .env .Environment ;
2326import org .elasticsearch .indices .recovery .RecoverySettings ;
2427import org .elasticsearch .plugins .Plugin ;
2528import org .elasticsearch .plugins .PluginsService ;
2629import org .elasticsearch .repositories .RepositoriesService ;
30+ import org .elasticsearch .rest .AbstractRestChannel ;
31+ import org .elasticsearch .rest .RestRequest ;
32+ import org .elasticsearch .rest .RestResponse ;
33+ import org .elasticsearch .rest .action .admin .cluster .RestGetRepositoriesAction ;
2734import org .elasticsearch .test .ESSingleNodeTestCase ;
35+ import org .elasticsearch .test .rest .FakeRestRequest ;
2836import org .elasticsearch .xcontent .NamedXContentRegistry ;
2937
38+ import java .security .AccessController ;
39+ import java .security .PrivilegedAction ;
3040import java .util .Collection ;
3141import java .util .List ;
42+ import java .util .concurrent .CountDownLatch ;
43+ import java .util .concurrent .atomic .AtomicReference ;
3244
3345import static org .elasticsearch .repositories .s3 .S3ClientSettings .ACCESS_KEY_SETTING ;
3446import static org .elasticsearch .repositories .s3 .S3ClientSettings .SECRET_KEY_SETTING ;
3547import static org .elasticsearch .test .hamcrest .ElasticsearchAssertions .assertAcked ;
48+ import static org .hamcrest .Matchers .containsString ;
3649import static org .hamcrest .Matchers .instanceOf ;
3750import static org .hamcrest .Matchers .is ;
51+ import static org .hamcrest .Matchers .not ;
3852import static org .hamcrest .Matchers .notNullValue ;
3953
54+ @ SuppressForbidden (reason = "test requires to set a System property to allow insecure settings when running in IDE" )
4055public class RepositoryCredentialsTests extends ESSingleNodeTestCase {
4156
57+ static {
58+ AccessController .doPrivileged ((PrivilegedAction <Void >) () -> {
59+ // required for client settings overwriting when running in IDE
60+ System .setProperty ("es.allow_insecure_settings" , "true" );
61+ return null ;
62+ });
63+ }
64+
4265 @ Override
4366 protected Collection <Class <? extends Plugin >> getPlugins () {
4467 return List .of (ProxyS3RepositoryPlugin .class );
@@ -60,11 +83,51 @@ protected Settings nodeSettings() {
6083 return Settings .builder ().setSecureSettings (secureSettings ).put (super .nodeSettings ()).build ();
6184 }
6285
86+ public void testRepositoryCredentialsOverrideSecureCredentials () {
87+ final String repositoryName = "repo-creds-override" ;
88+ final Settings .Builder repositorySettings = Settings .builder ()
89+ // repository settings for credentials override node secure settings
90+ .put (S3Repository .ACCESS_KEY_SETTING .getKey (), "insecure_aws_key" )
91+ .put (S3Repository .SECRET_KEY_SETTING .getKey (), "insecure_aws_secret" );
92+
93+ final String clientName = randomFrom ("default" , "other" , null );
94+ if (clientName != null ) {
95+ repositorySettings .put (S3Repository .CLIENT_NAME .getKey (), clientName );
96+ }
97+ createRepository (repositoryName , repositorySettings .build ());
98+
99+ final RepositoriesService repositories = getInstanceFromNode (RepositoriesService .class );
100+ assertThat (repositories .repository (repositoryName ), notNullValue ());
101+ assertThat (repositories .repository (repositoryName ), instanceOf (S3Repository .class ));
102+
103+ final S3Repository repository = (S3Repository ) repositories .repository (repositoryName );
104+ final AmazonS3 client = repository .createBlobStore ().clientReference ().client ();
105+ assertThat (client , instanceOf (ProxyS3RepositoryPlugin .ClientAndCredentials .class ));
106+
107+ final AWSCredentials credentials = ((ProxyS3RepositoryPlugin .ClientAndCredentials ) client ).credentials .getCredentials ();
108+ assertThat (credentials .getAWSAccessKeyId (), is ("insecure_aws_key" ));
109+ assertThat (credentials .getAWSSecretKey (), is ("insecure_aws_secret" ));
110+
111+ assertCriticalWarnings (
112+ "[secret_key] setting was deprecated in Elasticsearch and will be removed in a future release." ,
113+ "Using s3 access/secret key from repository settings. Instead store these in named clients and"
114+ + " the elasticsearch keystore for secure settings." ,
115+ "[access_key] setting was deprecated in Elasticsearch and will be removed in a future release."
116+ );
117+ }
118+
63119 public void testReinitSecureCredentials () {
64120 final String clientName = randomFrom ("default" , "other" );
65121
66122 final Settings .Builder repositorySettings = Settings .builder ();
67- repositorySettings .put (S3Repository .CLIENT_NAME .getKey (), clientName );
123+ final boolean hasInsecureSettings = randomBoolean ();
124+ if (hasInsecureSettings ) {
125+ // repository settings for credentials override node secure settings
126+ repositorySettings .put (S3Repository .ACCESS_KEY_SETTING .getKey (), "insecure_aws_key" );
127+ repositorySettings .put (S3Repository .SECRET_KEY_SETTING .getKey (), "insecure_aws_secret" );
128+ } else {
129+ repositorySettings .put (S3Repository .CLIENT_NAME .getKey (), clientName );
130+ }
68131
69132 final String repositoryName = "repo-reinit-creds" ;
70133 createRepository (repositoryName , repositorySettings .build ());
@@ -79,7 +142,10 @@ public void testReinitSecureCredentials() {
79142 assertThat (client , instanceOf (ProxyS3RepositoryPlugin .ClientAndCredentials .class ));
80143
81144 final AWSCredentials credentials = ((ProxyS3RepositoryPlugin .ClientAndCredentials ) client ).credentials .getCredentials ();
82- if ("other" .equals (clientName )) {
145+ if (hasInsecureSettings ) {
146+ assertThat (credentials .getAWSAccessKeyId (), is ("insecure_aws_key" ));
147+ assertThat (credentials .getAWSSecretKey (), is ("insecure_aws_secret" ));
148+ } else if ("other" .equals (clientName )) {
83149 assertThat (credentials .getAWSAccessKeyId (), is ("secure_other_key" ));
84150 assertThat (credentials .getAWSSecretKey (), is ("secure_other_secret" ));
85151 } else {
@@ -98,7 +164,10 @@ public void testReinitSecureCredentials() {
98164 plugin .reload (newSettings );
99165
100166 // check the not-yet-closed client reference still has the same credentials
101- if ("other" .equals (clientName )) {
167+ if (hasInsecureSettings ) {
168+ assertThat (credentials .getAWSAccessKeyId (), is ("insecure_aws_key" ));
169+ assertThat (credentials .getAWSSecretKey (), is ("insecure_aws_secret" ));
170+ } else if ("other" .equals (clientName )) {
102171 assertThat (credentials .getAWSAccessKeyId (), is ("secure_other_key" ));
103172 assertThat (credentials .getAWSSecretKey (), is ("secure_other_secret" ));
104173 } else {
@@ -113,11 +182,66 @@ public void testReinitSecureCredentials() {
113182 assertThat (client , instanceOf (ProxyS3RepositoryPlugin .ClientAndCredentials .class ));
114183
115184 final AWSCredentials newCredentials = ((ProxyS3RepositoryPlugin .ClientAndCredentials ) client ).credentials .getCredentials ();
116- assertThat (newCredentials .getAWSAccessKeyId (), is ("new_secret_aws_key" ));
117- assertThat (newCredentials .getAWSSecretKey (), is ("new_secret_aws_secret" ));
185+ if (hasInsecureSettings ) {
186+ assertThat (newCredentials .getAWSAccessKeyId (), is ("insecure_aws_key" ));
187+ assertThat (newCredentials .getAWSSecretKey (), is ("insecure_aws_secret" ));
188+ } else {
189+ assertThat (newCredentials .getAWSAccessKeyId (), is ("new_secret_aws_key" ));
190+ assertThat (newCredentials .getAWSSecretKey (), is ("new_secret_aws_secret" ));
191+ }
192+ }
193+
194+ if (hasInsecureSettings ) {
195+ assertCriticalWarnings (
196+ "[secret_key] setting was deprecated in Elasticsearch and will be removed in a future release." ,
197+ "Using s3 access/secret key from repository settings. Instead store these in named clients and"
198+ + " the elasticsearch keystore for secure settings." ,
199+ "[access_key] setting was deprecated in Elasticsearch and will be removed in a future release."
200+ );
118201 }
119202 }
120203
204+ public void testInsecureRepositoryCredentials () throws Exception {
205+ final String repositoryName = "repo-insecure-creds" ;
206+ createRepository (
207+ repositoryName ,
208+ Settings .builder ()
209+ .put (S3Repository .ACCESS_KEY_SETTING .getKey (), "insecure_aws_key" )
210+ .put (S3Repository .SECRET_KEY_SETTING .getKey (), "insecure_aws_secret" )
211+ .build ()
212+ );
213+
214+ final RestRequest fakeRestRequest = new FakeRestRequest ();
215+ fakeRestRequest .params ().put ("repository" , repositoryName );
216+ final RestGetRepositoriesAction action = new RestGetRepositoriesAction (getInstanceFromNode (SettingsFilter .class ));
217+
218+ final CountDownLatch latch = new CountDownLatch (1 );
219+ final AtomicReference <AssertionError > error = new AtomicReference <>();
220+ action .handleRequest (fakeRestRequest , new AbstractRestChannel (fakeRestRequest , true ) {
221+ @ Override
222+ public void sendResponse (RestResponse response ) {
223+ try {
224+ String responseAsString = response .content ().utf8ToString ();
225+ assertThat (responseAsString , containsString (repositoryName ));
226+ assertThat (responseAsString , not (containsString ("insecure_" )));
227+ } catch (final AssertionError ex ) {
228+ error .set (ex );
229+ }
230+ latch .countDown ();
231+ }
232+ }, getInstanceFromNode (NodeClient .class ));
233+
234+ latch .await ();
235+ if (error .get () != null ) {
236+ throw error .get ();
237+ }
238+
239+ assertWarnings (
240+ "Using s3 access/secret key from repository settings. Instead store these in named clients and"
241+ + " the elasticsearch keystore for secure settings."
242+ );
243+ }
244+
121245 private void createRepository (final String name , final Settings repositorySettings ) {
122246 assertAcked (
123247 client ().admin ()
0 commit comments