-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Deprecated credentials overwrite client settings in all configured repository clients #33769
Description
Elasticsearch version (bin/elasticsearch --version): 6.4.x
Plugins installed: [discovery-file, found-elasticsearch, repository-s3]
JVM version (java -version): 1.8.0_144; 25.144-b01;
OS version (uname -a if on a Unix-like system):Linux 4.4.0-1048-aws #57-Ubuntu SMP
Description of the problem including expected versus actual behavior:
Configuring a s3 repository that uses deprecated credentials specified directly in the repository client settings overwrites the credentials in all repository clients.
Expected behaviour would be that the legacy credentials are only used to populate the settings object that corresponds to the repository/client that actually specified them.
Steps to reproduce:
- configure a s3 repository (
repository 1) that uses secure credentials and a non-default client name - verify that this repository works
- configure a second repository using the default client name and deprecated credentials specified directly in the request creating the repository e.g.
"repository-2": {
"type": "s3",
"settings": {
"bucket": "bucket-name",
"access_key": "your-access-key",
"secret_key": "your-secret-key"
}
}
- verify that the
repository 2works - find that access to
repository 1is now denied
Additional information:
POST _nodes/reload_secure_settings is a workaround which restores the secure credentials for repository 1 but "breaks" repository 2 in the process.
Screenshot of a heap dump I took from the cluster, see the legacy credentials being propagated into both settings objects

Looking at the s3 repository plugin code the deprecated credentials seem to be propagated into every S3ClientSettings object when the S3 repository object holding the legacy credentials is constructed:
Lines 163 to 174 in 4108722
| static Map<String, S3ClientSettings> overrideCredentials(Map<String, S3ClientSettings> clientsSettings, | |
| BasicAWSCredentials credentials) { | |
| final MapBuilder<String, S3ClientSettings> mapBuilder = new MapBuilder<>(); | |
| for (final Map.Entry<String, S3ClientSettings> entry : clientsSettings.entrySet()) { | |
| final S3ClientSettings s3ClientSettings = new S3ClientSettings(credentials, entry.getValue().endpoint, | |
| entry.getValue().protocol, entry.getValue().proxyHost, entry.getValue().proxyPort, entry.getValue().proxyUsername, | |
| entry.getValue().proxyPassword, entry.getValue().readTimeoutMillis, entry.getValue().maxRetries, | |
| entry.getValue().throttleRetries); | |
| mapBuilder.put(entry.getKey(), s3ClientSettings); | |
| } | |
| return mapBuilder.immutableMap(); | |
| } |
Called here with on settings retrieved from the S3Service object:
Lines 251 to 254 in b1bf643
| // hack, but that's ok because the whole if branch should be axed | |
| final Map<String, S3ClientSettings> prevSettings = s3Service.refreshAndClearCache(S3ClientSettings.load(Settings.EMPTY)); | |
| final Map<String, S3ClientSettings> newSettings = S3ClientSettings.overrideCredentials(prevSettings, insecureCredentials); | |
| s3Service.refreshAndClearCache(newSettings); |