|
4 | 4 |
|
5 | 5 | package cloud.katta.protocols.s3; |
6 | 6 |
|
7 | | -import ch.cyberduck.core.AsciiRandomStringService; |
| 7 | +import ch.cyberduck.core.Credentials; |
8 | 8 | import ch.cyberduck.core.Host; |
9 | 9 | import ch.cyberduck.core.LoginCallback; |
10 | | -import ch.cyberduck.core.OAuthTokens; |
| 10 | +import ch.cyberduck.core.Profile; |
11 | 11 | import ch.cyberduck.core.TemporaryAccessTokens; |
12 | 12 | import ch.cyberduck.core.exception.BackgroundException; |
13 | | -import ch.cyberduck.core.exception.LoginFailureException; |
14 | 13 | import ch.cyberduck.core.oauth.OAuth2RequestInterceptor; |
15 | | -import ch.cyberduck.core.preferences.HostPreferences; |
16 | 14 | import ch.cyberduck.core.preferences.PreferencesReader; |
17 | | -import ch.cyberduck.core.s3.S3Session; |
18 | | -import ch.cyberduck.core.sts.STSAssumeRoleCredentialsRequestInterceptor; |
19 | | -import ch.cyberduck.core.sts.STSExceptionMappingService; |
| 15 | +import ch.cyberduck.core.preferences.ProxyPreferencesReader; |
| 16 | +import ch.cyberduck.core.ssl.X509KeyManager; |
| 17 | +import ch.cyberduck.core.ssl.X509TrustManager; |
| 18 | +import ch.cyberduck.core.sts.STSAssumeRoleWithWebIdentityRequestInterceptor; |
20 | 19 |
|
21 | 20 | import org.apache.commons.lang3.StringUtils; |
22 | 21 | import org.apache.logging.log4j.LogManager; |
23 | 22 | import org.apache.logging.log4j.Logger; |
24 | 23 |
|
25 | | -import java.util.Collections; |
26 | | - |
27 | | -import com.amazonaws.auth.AWSSessionCredentials; |
28 | | -import com.amazonaws.auth.AWSSessionCredentialsProvider; |
29 | | -import com.amazonaws.auth.BasicSessionCredentials; |
30 | | -import com.amazonaws.services.securitytoken.AWSSecurityTokenService; |
31 | | -import com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException; |
32 | | -import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; |
33 | | -import com.amazonaws.services.securitytoken.model.AssumeRoleResult; |
34 | | -import com.amazonaws.services.securitytoken.model.Tag; |
35 | | -import com.auth0.jwt.JWT; |
36 | | -import com.auth0.jwt.exceptions.JWTDecodeException; |
37 | | - |
38 | 24 | /** |
39 | 25 | * Assume role with temporary credentials obtained using OIDC token from security token service (STS) |
40 | 26 | */ |
41 | | -public class STSChainedAssumeRoleRequestInterceptor extends STSAssumeRoleCredentialsRequestInterceptor { |
| 27 | +public class STSChainedAssumeRoleRequestInterceptor extends STSAssumeRoleWithWebIdentityRequestInterceptor { |
42 | 28 | private static final Logger log = LogManager.getLogger(STSChainedAssumeRoleRequestInterceptor.class); |
43 | 29 |
|
44 | 30 | private final Host bookmark; |
45 | | - private final AWSSecurityTokenService service; |
46 | | - |
47 | | - public STSChainedAssumeRoleRequestInterceptor(final OAuth2RequestInterceptor oauth, final S3Session session, |
48 | | - final AWSSecurityTokenService service, final LoginCallback prompt) { |
49 | | - super(oauth, session, service, prompt); |
50 | | - this.service = service; |
51 | | - this.bookmark = session.getHost(); |
52 | | - } |
53 | 31 |
|
54 | | - @Override |
55 | | - public TemporaryAccessTokens authorize(final OAuthTokens oauth) throws BackgroundException { |
56 | | - return this.authorize(oauth, super.authorize(oauth)); |
| 32 | + public STSChainedAssumeRoleRequestInterceptor(final OAuth2RequestInterceptor oauth, final Host host, |
| 33 | + final X509TrustManager trust, final X509KeyManager key, |
| 34 | + final LoginCallback prompt) { |
| 35 | + super(oauth, host, trust, key, prompt); |
| 36 | + this.bookmark = host; |
57 | 37 | } |
58 | 38 |
|
59 | 39 | /** |
60 | 40 | * Assume role with previously obtained temporary access token |
61 | 41 | * |
62 | | - * @param tokens Session credentials |
| 42 | + * @param credentials Session credentials |
63 | 43 | * @return Temporary scoped access tokens |
64 | 44 | * @throws ch.cyberduck.core.exception.ExpiredTokenException Expired identity |
65 | 45 | * @throws ch.cyberduck.core.exception.LoginFailureException Authorization failure |
66 | 46 | */ |
67 | | - public TemporaryAccessTokens authorize(final OAuthTokens oauth, final TemporaryAccessTokens tokens) throws BackgroundException { |
68 | | - final AssumeRoleRequest request = new AssumeRoleRequest() |
69 | | - .withRequestCredentialsProvider(new AWSSessionCredentialsProvider() { |
70 | | - @Override |
71 | | - public AWSSessionCredentials getCredentials() { |
72 | | - return new BasicSessionCredentials( |
73 | | - tokens.getAccessKeyId(), |
74 | | - tokens.getSecretAccessKey(), |
75 | | - tokens.getSessionToken()); |
76 | | - } |
77 | | - |
78 | | - @Override |
79 | | - public void refresh() { |
80 | | - // nothing to do |
81 | | - } |
82 | | - }); |
83 | | - log.debug("Chained assume role for {}", bookmark); |
84 | | - log.debug("Assume role with temporary credentials {}", tokens); |
85 | | - final PreferencesReader preferences = new HostPreferences(bookmark); |
86 | | - if(preferences.getInteger(S3AssumeRoleProtocol.S3_ASSUMEROLE_DURATIONSECONDS) != -1) { |
87 | | - request.setDurationSeconds(preferences.getInteger(S3AssumeRoleProtocol.S3_ASSUMEROLE_DURATIONSECONDS)); |
88 | | - } |
89 | | - if(StringUtils.isNotBlank(preferences.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_POLICY))) { |
90 | | - request.setPolicy(preferences.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_POLICY)); |
91 | | - } |
92 | | - request.setRoleArn(preferences.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLEARN_2)); |
93 | | - final String sub; |
94 | | - final String identityToken = this.getWebIdentityToken(oauth); |
95 | | - try { |
96 | | - sub = JWT.decode(identityToken).getSubject(); |
97 | | - } |
98 | | - catch(JWTDecodeException e) { |
99 | | - log.warn("Failure {} decoding JWT {}", e, identityToken); |
100 | | - throw new LoginFailureException("Invalid JWT or JSON format in authentication token", e); |
101 | | - } |
102 | | - if(StringUtils.isNotBlank(preferences.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLESESSIONNAME))) { |
103 | | - request.setRoleSessionName(preferences.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLESESSIONNAME)); |
104 | | - } |
105 | | - else { |
106 | | - if(StringUtils.isNotBlank(sub)) { |
107 | | - request.setRoleSessionName(sub); |
108 | | - } |
109 | | - else { |
110 | | - log.warn("Missing subject in decoding JWT {}", identityToken); |
111 | | - request.setRoleSessionName(new AsciiRandomStringService().random()); |
112 | | - } |
113 | | - } |
114 | | - if(StringUtils.isNotBlank(preferences.getProperty("s3.assumerole.tag"))) { |
115 | | - request.setTags(Collections.singletonList(new Tag() |
116 | | - .withKey(preferences.getProperty("s3.assumerole.tag")) |
117 | | - .withValue(preferences.getProperty(S3AssumeRoleProtocol.OAUTH_TOKENEXCHANGE_VAULT)))); |
118 | | - } |
119 | | - try { |
120 | | - log.debug("Use request {}", request); |
121 | | - final AssumeRoleResult result = service.assumeRole(request); |
122 | | - log.debug("Received assume role result {} for host {}", result, bookmark); |
123 | | - return new TemporaryAccessTokens(result.getCredentials().getAccessKeyId(), |
124 | | - result.getCredentials().getSecretAccessKey(), |
125 | | - result.getCredentials().getSessionToken(), |
126 | | - result.getCredentials().getExpiration().getTime()); |
127 | | - } |
128 | | - catch(AWSSecurityTokenServiceException e) { |
129 | | - throw new STSExceptionMappingService().map(e); |
130 | | - } |
| 47 | + @Override |
| 48 | + public TemporaryAccessTokens assumeRoleWithWebIdentity(final Credentials credentials) throws BackgroundException { |
| 49 | + final PreferencesReader settings = new ProxyPreferencesReader(bookmark, credentials); |
| 50 | + final TemporaryAccessTokens tokens = super.assumeRoleWithWebIdentity(credentials |
| 51 | + .withProperty(Profile.STS_ROLE_ARN_PROPERTY_KEY, settings.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLEARN))); |
| 52 | + if(StringUtils.isNotBlank(settings.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLEARN_2))) { |
| 53 | + log.debug("Assume role with temporary credentials {}", tokens); |
| 54 | + // Assume role with previously obtained temporary access token |
| 55 | + return super.assumeRole(credentials.withTokens(tokens) |
| 56 | + .withProperty(Profile.STS_ROLE_ARN_PROPERTY_KEY, settings.getProperty(S3AssumeRoleProtocol.S3_ASSUMEROLE_ROLEARN_2)) |
| 57 | + .withProperty(Profile.STS_TAGS_PROPERTY_KEY, String.format("%s=%s", "VaultRequested", settings.getProperty(S3AssumeRoleProtocol.OAUTH_TOKENEXCHANGE_VAULT))) |
| 58 | + ); |
| 59 | + } |
| 60 | + return tokens; |
131 | 61 | } |
132 | 62 | } |
0 commit comments