Skip to content

Commit

Permalink
Merge implementations retrieving latest credentials on error response.
Browse files Browse the repository at this point in the history
  • Loading branch information
dkocher committed Aug 13, 2023
1 parent d160ce5 commit 8ea744a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import ch.cyberduck.core.Credentials;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.exception.ExpiredTokenException;
import ch.cyberduck.core.exception.LoginFailureException;
import ch.cyberduck.core.http.DisabledServiceUnavailableRetryStrategy;

import org.apache.http.HttpResponse;
Expand All @@ -31,37 +31,42 @@
import java.io.IOException;

/**
* Fetch latest temporary session token from AWS CLI configuration or instance metadata
* Update credentials on authentication failure
*/
public class S3TokenExpiredResponseInterceptor extends DisabledServiceUnavailableRetryStrategy implements S3CredentialsStrategy {
private static final Logger log = LogManager.getLogger(S3TokenExpiredResponseInterceptor.class);
public class S3AuthenticationResponseInterceptor extends DisabledServiceUnavailableRetryStrategy implements S3CredentialsStrategy {
private static final Logger log = LogManager.getLogger(S3AuthenticationResponseInterceptor.class);

private static final int MAX_RETRIES = 1;

private final S3Session session;
private final S3CredentialsStrategy configurator;
private final S3CredentialsStrategy authenticator;

public S3TokenExpiredResponseInterceptor(final S3Session session, final S3CredentialsStrategy configurator) {
public S3AuthenticationResponseInterceptor(final S3Session session, final S3CredentialsStrategy authenticator) {
this.session = session;
this.configurator = configurator;
this.authenticator = authenticator;
}

@Override
public Credentials get() throws BackgroundException {
return configurator.get();
return authenticator.get();
}

@Override
public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context) {
if(executionCount <= MAX_RETRIES) {
switch(response.getStatusLine().getStatusCode()) {
case HttpStatus.SC_FORBIDDEN:
case HttpStatus.SC_BAD_REQUEST:
try {
if(new S3ExceptionMappingService().map(response) instanceof ExpiredTokenException) {
if(new S3ExceptionMappingService().map(response) instanceof LoginFailureException) {
// 403 Forbidden (InvalidAccessKeyId) The provided token has expired
// 400 Bad Request (ExpiredToken) The provided token has expired
// 400 Bad Request (InvalidToken) The provided token is malformed or otherwise not valid
// 400 Bad Request (TokenRefreshRequired) The provided token must be refreshed.
if(log.isWarnEnabled()) {
log.warn(String.format("Handle failure %s", response));
}
final Credentials credentials = configurator.get();
final Credentials credentials = authenticator.get();
if(log.isDebugEnabled()) {
log.debug(String.format("Reconfigure client with credentials %s", credentials));
}
Expand Down
11 changes: 6 additions & 5 deletions s3/src/main/java/ch/cyberduck/core/s3/S3Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
import ch.cyberduck.core.ssl.X509KeyManager;
import ch.cyberduck.core.ssl.X509TrustManager;
import ch.cyberduck.core.sts.STSAssumeRoleCredentialsRequestInterceptor;
import ch.cyberduck.core.sts.STSAssumeRoleTokenExpiredResponseInterceptor;
import ch.cyberduck.core.threading.BackgroundExceptionCallable;
import ch.cyberduck.core.threading.CancelCallback;
import ch.cyberduck.core.transfer.TransferStatus;
Expand Down Expand Up @@ -197,20 +196,22 @@ protected RequestEntityRestStorageService connect(final Proxy proxy, final HostK
configuration.addInterceptorLast(oauth);
final STSAssumeRoleCredentialsRequestInterceptor sts = new STSAssumeRoleCredentialsRequestInterceptor(oauth, this, trust, key, prompt, cancel);
configuration.addInterceptorLast(sts);
configuration.setServiceUnavailableRetryStrategy(new STSAssumeRoleTokenExpiredResponseInterceptor(this, oauth, sts, prompt));
configuration.setServiceUnavailableRetryStrategy(new S3AuthenticationResponseInterceptor(this, sts));
authentication = sts;
}
else {
if(S3Session.isAwsHostname(host.getHostname())) {
final S3TokenExpiredResponseInterceptor interceptor;
final S3AuthenticationResponseInterceptor interceptor;
// Try auto-configure
if(Scheme.isURL(host.getProtocol().getContext())) {
interceptor = new S3TokenExpiredResponseInterceptor(this,
// Fetch temporary session token from instance metadata
interceptor = new S3AuthenticationResponseInterceptor(this,
new AWSSessionCredentialsRetriever(trust, key, this, host.getProtocol().getContext())
);
}
else {
interceptor = new S3TokenExpiredResponseInterceptor(this, new S3CredentialsStrategy() {
// Fetch temporary session token from AWS CLI configuration
interceptor = new S3AuthenticationResponseInterceptor(this, new S3CredentialsStrategy() {
@Override
public Credentials get() {
return new S3CredentialsConfigurator(
Expand Down

This file was deleted.

0 comments on commit 8ea744a

Please sign in to comment.