Skip to content

Commit

Permalink
Report better error for GCS credentials load failure (#89336)
Browse files Browse the repository at this point in the history
Today if the GCS credentials file setting is invalid we report some kind
of JSON parsing error but it's not clear what JSON is being parsed so
the error is hard to track down. This commit adds the problematic
setting name to the exception message.
  • Loading branch information
DaveCTurner committed Aug 15, 2022
1 parent 51f89f4 commit 621c38c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/89336.yaml
@@ -0,0 +1,5 @@
pr: 89336
summary: Report better error for GCS credentials load failure
area: Snapshot/Restore
type: bug
issues: []
Expand Up @@ -18,9 +18,7 @@
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.TimeValue;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
Expand Down Expand Up @@ -246,13 +244,14 @@ static GoogleCloudStorageClientSettings getClientSettings(final Settings setting
* {@code null} if no service account is defined.
*/
static ServiceAccountCredentials loadCredential(final Settings settings, final String clientName) {
final var credentialsFileSetting = CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace(clientName);
try {
if (CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace(clientName).exists(settings) == false) {
if (credentialsFileSetting.exists(settings) == false) {
// explicitly returning null here so that the default credential
// can be loaded later when creating the Storage client
return null;
}
try (InputStream credStream = CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace(clientName).get(settings)) {
try (InputStream credStream = credentialsFileSetting.get(settings)) {
final Collection<String> scopes = Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL);
return SocketAccess.doPrivilegedIOException(() -> {
final ServiceAccountCredentials credentials = ServiceAccountCredentials.fromStream(credStream);
Expand All @@ -262,8 +261,8 @@ static ServiceAccountCredentials loadCredential(final Settings settings, final S
return credentials;
});
}
} catch (final IOException e) {
throw new UncheckedIOException(e);
} catch (final Exception e) {
throw new IllegalArgumentException("failed to load GCS client credentials from [" + credentialsFileSetting.getKey() + "]", e);
}
}

Expand Down
Expand Up @@ -43,6 +43,7 @@
import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.READ_TIMEOUT_SETTING;
import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.getClientSettings;
import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.loadCredential;
import static org.hamcrest.Matchers.equalTo;

public class GoogleCloudStorageClientSettingsTests extends ESTestCase {

Expand Down Expand Up @@ -89,6 +90,25 @@ public void testLoadCredential() throws Exception {
assertGoogleCredential(expectedClientSettings.getCredential(), loadCredential(randomClient.v2(), clientName));
}

public void testLoadInvalidCredential() throws Exception {
final List<Setting<?>> deprecationWarnings = new ArrayList<>();
final Settings.Builder settings = Settings.builder();
final MockSecureSettings secureSettings = new MockSecureSettings();
final String clientName = randomBoolean() ? "default" : randomAlphaOfLength(5).toLowerCase(Locale.ROOT);
randomClient(clientName, settings, secureSettings, deprecationWarnings);
secureSettings.setFile(
CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace(clientName).getKey(),
"invalid".getBytes(StandardCharsets.UTF_8)
);
assertThat(
expectThrows(
IllegalArgumentException.class,
() -> loadCredential(settings.setSecureSettings(secureSettings).build(), clientName)
).getMessage(),
equalTo("failed to load GCS client credentials from [gcs.client." + clientName + ".credentials_file]")
);
}

public void testProjectIdDefaultsToCredentials() throws Exception {
final String clientName = randomAlphaOfLength(5);
final Tuple<ServiceAccountCredentials, byte[]> credentials = randomCredential(clientName);
Expand Down

0 comments on commit 621c38c

Please sign in to comment.