Skip to content

Commit fdee575

Browse files
committed
Inject reference to Hub connection/Oauth explicitly. Load storage session without factory.
1 parent 815b5fb commit fdee575

File tree

10 files changed

+105
-110
lines changed

10 files changed

+105
-110
lines changed

hub/src/main/java/cloud/katta/protocols/hub/HubAwareProfile.java

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import ch.cyberduck.core.Profile;
88
import ch.cyberduck.core.Protocol;
9-
import ch.cyberduck.core.oauth.OAuth2RequestInterceptor;
109

1110
import cloud.katta.client.model.ConfigDto;
1211
import cloud.katta.model.StorageProfileDtoWrapper;
@@ -15,24 +14,7 @@
1514

1615
public final class HubAwareProfile extends Profile {
1716

18-
private final HubSession hub;
19-
private final OAuth2RequestInterceptor oauth;
20-
21-
public HubAwareProfile(final HubSession hub, final OAuth2RequestInterceptor oauth, final Protocol parent, final ConfigDto configDto, final StorageProfileDtoWrapper storageProfile) {
17+
public HubAwareProfile(final Protocol parent, final ConfigDto configDto, final StorageProfileDtoWrapper storageProfile) {
2218
super(parent, new HubConfigDtoDeserializer(configDto, new StorageProfileDtoWrapperDeserializer(storageProfile)));
23-
this.hub = hub;
24-
this.oauth = oauth;
25-
}
26-
27-
@SuppressWarnings("unchecked")
28-
@Override
29-
public <T> T getFeature(final Class<T> type) {
30-
if(type == HubSession.class) {
31-
return (T) hub;
32-
}
33-
if(type == OAuth2RequestInterceptor.class) {
34-
return (T) oauth;
35-
}
36-
return super.getFeature(type);
3719
}
3820
}

hub/src/main/java/cloud/katta/protocols/hub/HubSession.java

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,18 @@
4444
import org.apache.logging.log4j.Logger;
4545

4646
import java.io.InputStream;
47-
import java.util.List;
4847
import java.util.Map;
4948
import java.util.Optional;
5049

5150
import cloud.katta.client.ApiException;
5251
import cloud.katta.client.HubApiClient;
5352
import cloud.katta.client.api.ConfigResourceApi;
54-
import cloud.katta.client.api.StorageProfileResourceApi;
5553
import cloud.katta.client.api.UsersResourceApi;
5654
import cloud.katta.client.model.ConfigDto;
57-
import cloud.katta.client.model.StorageProfileDto;
5855
import cloud.katta.client.model.UserDto;
5956
import cloud.katta.core.DeviceSetupCallback;
6057
import cloud.katta.crypto.DeviceKeys;
6158
import cloud.katta.crypto.UserKeys;
62-
import cloud.katta.model.StorageProfileDtoWrapper;
6359
import cloud.katta.protocols.hub.exceptions.HubExceptionMappingService;
6460
import cloud.katta.protocols.hub.serializer.HubConfigDtoDeserializer;
6561
import cloud.katta.workflows.DeviceKeysServiceImpl;
@@ -82,11 +78,6 @@ public class HubSession extends HttpSession<HubApiClient> {
8278
*/
8379
private final Scheduler<?> access = new HubGrantAccessSchedulerService(this, keychain);
8480

85-
/**
86-
* Registered storage profiles
87-
*/
88-
private final ProtocolFactory storage = new ProtocolFactory();
89-
9081
/**
9182
* Interceptor for OpenID connect flow
9283
*/
@@ -171,36 +162,14 @@ public void login(final LoginCallback prompt, final CancelCallback cancel) throw
171162
log.warn("Failure {} decoding JWT {}", e, credentials.getOauth().getIdToken());
172163
throw new LoginCanceledException(e);
173164
}
174-
try {
175-
final UserDto me = this.getMe();
176-
log.debug("Retrieved user {}", me);
177-
// Ensure device key is available
178-
final DeviceSetupCallback setup = prompt.getFeature(DeviceSetupCallback.class);
179-
log.debug("Configured with setup prompt {}", setup);
180-
final UserKeys userKeys = this.getUserKeys(setup);
181-
log.debug("Retrieved user keys {}", userKeys);
182-
final List<StorageProfileDto> storageProfileDtos = new StorageProfileResourceApi(client).apiStorageprofileGet(false);
183-
for(StorageProfileDto storageProfileDto : storageProfileDtos) {
184-
final StorageProfileDtoWrapper storageProfile = StorageProfileDtoWrapper.coerce(storageProfileDto);
185-
log.debug("Read storage profile {}", storageProfile);
186-
switch(storageProfile.getProtocol()) {
187-
case S3:
188-
case S3_STS:
189-
final Profile profile = new HubAwareProfile(this, authorizationService,
190-
ProtocolFactory.get().forType(ProtocolFactory.get().find(ProtocolFactory.BUNDLED_PROFILE_PREDICATE), Protocol.Type.s3),
191-
config, storageProfile);
192-
log.debug("Register profile {}", profile);
193-
storage.register(profile);
194-
break;
195-
default:
196-
throw new InteroperabilityException(String.format("Unsupported storage configuration %s", storageProfile.getProtocol().name()));
197-
}
198-
}
199-
vaults = new HubVaultListService(storage, this, prompt);
200-
}
201-
catch(ApiException e) {
202-
throw new HubExceptionMappingService().map(e);
203-
}
165+
final UserDto me = this.getMe();
166+
log.debug("Retrieved user {}", me);
167+
// Ensure device key is available
168+
final DeviceSetupCallback setup = prompt.getFeature(DeviceSetupCallback.class);
169+
log.debug("Configured with setup prompt {}", setup);
170+
final UserKeys userKeys = this.getUserKeys(setup);
171+
log.debug("Retrieved user keys {}", userKeys);
172+
vaults = new HubVaultListService(this, prompt);
204173
}
205174

206175
private UserKeys pair(final DeviceSetupCallback setup) throws BackgroundException {
@@ -246,6 +215,10 @@ public UserDto getMe() throws BackgroundException {
246215
}
247216
}
248217

218+
public ConfigDto getConfig() {
219+
return config;
220+
}
221+
249222
/**
250223
*
251224
* @return Destroyed keys after login
@@ -387,8 +360,8 @@ public void preflight(final Path file) throws BackgroundException {
387360
if(type == CredentialsConfigurator.class) {
388361
return (T) new HubOAuthTokensCredentialsConfigurator(keychain, host);
389362
}
390-
if(type == ProtocolFactory.class) {
391-
return (T) storage;
363+
if(type == OAuth2RequestInterceptor.class) {
364+
return (T) authorizationService;
392365
}
393366
return super._getFeature(type);
394367
}

hub/src/main/java/cloud/katta/protocols/hub/HubUVFVault.java

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
package cloud.katta.protocols.hub;
66

7-
import ch.cyberduck.core.CredentialsConfigurator;
87
import ch.cyberduck.core.DisabledCancelCallback;
98
import ch.cyberduck.core.DisabledHostKeyCallback;
109
import ch.cyberduck.core.Host;
@@ -13,13 +12,10 @@
1312
import ch.cyberduck.core.PasswordCallback;
1413
import ch.cyberduck.core.Path;
1514
import ch.cyberduck.core.PathAttributes;
16-
import ch.cyberduck.core.Protocol;
1715
import ch.cyberduck.core.Session;
18-
import ch.cyberduck.core.SessionFactory;
1916
import ch.cyberduck.core.cryptomator.ContentWriter;
2017
import ch.cyberduck.core.cryptomator.UVFVault;
2118
import ch.cyberduck.core.exception.BackgroundException;
22-
import ch.cyberduck.core.exception.ConnectionCanceledException;
2319
import ch.cyberduck.core.exception.InteroperabilityException;
2420
import ch.cyberduck.core.exception.UnsupportedException;
2521
import ch.cyberduck.core.features.AttributesFinder;
@@ -29,8 +25,6 @@
2925
import ch.cyberduck.core.preferences.PreferencesFactory;
3026
import ch.cyberduck.core.proxy.ProxyFactory;
3127
import ch.cyberduck.core.s3.S3Session;
32-
import ch.cyberduck.core.ssl.X509KeyManager;
33-
import ch.cyberduck.core.ssl.X509TrustManager;
3428
import ch.cyberduck.core.transfer.TransferStatus;
3529
import ch.cyberduck.core.vault.VaultCredentials;
3630
import ch.cyberduck.core.vault.VaultUnlockCancelException;
@@ -52,14 +46,11 @@
5246
import cloud.katta.crypto.UserKeys;
5347
import cloud.katta.crypto.uvf.UvfMetadataPayload;
5448
import cloud.katta.crypto.uvf.UvfMetadataPayloadPasswordCallback;
55-
import cloud.katta.crypto.uvf.VaultMetadataJWEBackendDto;
5649
import cloud.katta.protocols.hub.exceptions.HubExceptionMappingService;
5750
import cloud.katta.protocols.s3.S3AssumeRoleProtocol;
5851
import com.fasterxml.jackson.core.JsonProcessingException;
5952
import com.nimbusds.jose.JOSEException;
6053

61-
import static cloud.katta.protocols.s3.S3AssumeRoleProtocol.OAUTH_TOKENEXCHANGE_VAULT;
62-
6354
/**
6455
* Unified vault format (UVF) implementation for Katta
6556
*/
@@ -77,25 +68,18 @@ public class HubUVFVault extends UVFVault {
7768

7869
/**
7970
*
80-
* @param profile Storage provider configuration
71+
* @param storage Storage connection
8172
* @param vaultId Vault Id
8273
* @param vaultMetadata Vault UVF metadata
8374
* @param prompt Login prompt to access storage
8475
*/
85-
public HubUVFVault(final Protocol profile, final UUID vaultId, final UvfMetadataPayload vaultMetadata, final LoginCallback prompt) throws ConnectionCanceledException {
76+
public HubUVFVault(final Session<?> storage, final UUID vaultId, final UvfMetadataPayload vaultMetadata, final LoginCallback prompt) {
8677
super(new Path(vaultMetadata.storage().getDefaultPath(), EnumSet.of(Path.Type.directory, Path.Type.volume),
8778
new PathAttributes().setDisplayname(vaultMetadata.storage().getNickname())));
79+
this.storage = storage;
8880
this.vaultId = vaultId;
8981
this.vaultMetadata = vaultMetadata;
9082
this.login = prompt;
91-
final VaultMetadataJWEBackendDto vaultStorageMetadata = vaultMetadata.storage();
92-
final HubSession hub = profile.getFeature(HubSession.class);
93-
log.debug("Loaded profile {} for UVF metadata {}", profile, vaultMetadata);
94-
final Host storageProvider = new Host(profile, hub.getFeature(CredentialsConfigurator.class).reload().configure(hub.getHost())
95-
.setUsername(vaultStorageMetadata.getUsername()).setPassword(vaultStorageMetadata.getPassword())).withRegion(vaultStorageMetadata.getRegion());
96-
storageProvider.setProperty(OAUTH_TOKENEXCHANGE_VAULT, vaultId.toString());
97-
log.debug("Configured {} for vault {}", storageProvider, this);
98-
this.storage = SessionFactory.create(storageProvider, hub.getFeature(X509TrustManager.class), hub.getFeature(X509KeyManager.class));
9983
}
10084

10185
/**

hub/src/main/java/cloud/katta/protocols/hub/HubVaultListService.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
import ch.cyberduck.core.LocaleFactory;
1111
import ch.cyberduck.core.LoginCallback;
1212
import ch.cyberduck.core.Path;
13-
import ch.cyberduck.core.Protocol;
14-
import ch.cyberduck.core.ProtocolFactory;
13+
import ch.cyberduck.core.Session;
1514
import ch.cyberduck.core.exception.AccessDeniedException;
1615
import ch.cyberduck.core.exception.BackgroundException;
1716
import ch.cyberduck.core.exception.NotfoundException;
@@ -37,15 +36,10 @@
3736
public class HubVaultListService implements ListService {
3837
private static final Logger log = LogManager.getLogger(HubVaultListService.class);
3938

40-
/**
41-
* Storage profiles
42-
*/
43-
private final ProtocolFactory storage;
4439
private final HubSession session;
4540
private final LoginCallback prompt;
4641

47-
public HubVaultListService(final ProtocolFactory storage, final HubSession session, final LoginCallback prompt) {
48-
this.storage = storage;
42+
public HubVaultListService(final HubSession session, final LoginCallback prompt) {
4943
this.session = session;
5044
this.prompt = prompt;
5145
}
@@ -54,6 +48,7 @@ public HubVaultListService(final ProtocolFactory storage, final HubSession sessi
5448
public AttributedList<Path> list(final Path directory, final ListProgressListener listener) throws BackgroundException {
5549
if(directory.isRoot()) {
5650
try {
51+
final VaultServiceImpl vaultService = new VaultServiceImpl(session);
5752
final VaultRegistry registry = session.getRegistry();
5853
final AttributedList<Path> vaults = new AttributedList<>();
5954
for(final VaultDto vaultDto : new VaultResourceApi(session.getClient()).apiVaultsAccessibleGet(null)) {
@@ -64,19 +59,17 @@ public AttributedList<Path> list(final Path directory, final ListProgressListene
6459
log.debug("Load vault {}", vaultDto);
6560
try {
6661
// Find storage configuration in vault metadata
67-
final VaultServiceImpl vaultService = new VaultServiceImpl(session);
6862
final DeviceSetupCallback setup = prompt.getFeature(DeviceSetupCallback.class);
6963
final UvfMetadataPayload vaultMetadata = vaultService.getVaultMetadataJWE(vaultDto.getId(), session.getUserKeys(setup));
70-
final Protocol profile = storage.forName(vaultMetadata.storage().getProvider());
71-
final HubUVFVault vault = new HubUVFVault(profile, vaultDto.getId(), vaultMetadata, prompt);
64+
final Session<?> storage = vaultService.getVaultStorageSession(session, vaultDto.getId(), vaultMetadata);
65+
final HubUVFVault vault = new HubUVFVault(storage, vaultDto.getId(), vaultMetadata, prompt);
7266
try {
7367
registry.add(vault.load(session, prompt));
7468
vaults.add(vault.getHome());
7569
listener.chunk(directory, vaults);
7670
}
7771
catch(VaultUnlockCancelException e) {
7872
log.warn("Skip vault {} with failure {} loading", vaultDto, e);
79-
continue;
8073
}
8174
}
8275
catch(ApiException e) {
@@ -86,7 +79,10 @@ public AttributedList<Path> list(final Path directory, final ListProgressListene
8679
}
8780
throw e;
8881
}
89-
catch(AccessException | SecurityFailure e) {
82+
catch(AccessException e) {
83+
log.warn("Skip vault {} with access failure {}", vaultDto, e);
84+
}
85+
catch(SecurityFailure e) {
9086
throw new AccessDeniedException(e.getMessage(), e);
9187
}
9288
}

hub/src/main/java/cloud/katta/protocols/s3/S3AssumeRoleSession.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import ch.cyberduck.core.Host;
88
import ch.cyberduck.core.LoginCallback;
9-
import ch.cyberduck.core.OAuthTokens;
109
import ch.cyberduck.core.exception.LoginCanceledException;
1110
import ch.cyberduck.core.oauth.OAuth2RequestInterceptor;
1211
import ch.cyberduck.core.s3.S3CredentialsStrategy;
@@ -19,11 +18,25 @@
1918
import org.apache.logging.log4j.LogManager;
2019
import org.apache.logging.log4j.Logger;
2120

21+
import java.util.UUID;
22+
23+
import cloud.katta.protocols.hub.HubSession;
24+
2225
public class S3AssumeRoleSession extends S3Session {
2326
private static final Logger log = LogManager.getLogger(S3AssumeRoleSession.class);
2427

25-
public S3AssumeRoleSession(final Host host, final X509TrustManager trust, final X509KeyManager key) {
26-
super(host, trust, key);
28+
private final HubSession hub;
29+
/**
30+
* Shared OAuth tokens
31+
*/
32+
private final OAuth2RequestInterceptor oauth;
33+
private final UUID vaultId;
34+
35+
public S3AssumeRoleSession(final HubSession hub, final UUID vaultId, final Host host) {
36+
super(host, hub.getFeature(X509TrustManager.class), hub.getFeature(X509KeyManager.class));
37+
this.hub = hub;
38+
this.oauth = hub.getFeature(OAuth2RequestInterceptor.class);
39+
this.vaultId = vaultId;
2740
}
2841

2942
/**
@@ -37,11 +50,9 @@ public S3AssumeRoleSession(final Host host, final X509TrustManager trust, final
3750
@Override
3851
protected S3CredentialsStrategy configureCredentialsStrategy(final HttpClientBuilder configuration, final LoginCallback prompt) throws LoginCanceledException {
3952
if(host.getProtocol().isOAuthConfigurable()) {
40-
// Shared OAuth tokens
41-
final OAuth2RequestInterceptor oauth = host.getProtocol().getFeature(OAuth2RequestInterceptor.class);
4253
log.debug("Register interceptor {}", oauth);
4354
configuration.addInterceptorLast(oauth);
44-
final STSRequestInterceptor sts = new STSChainedAssumeRoleRequestInterceptor(hub, vaultId, host, trust, key, prompt);
55+
final STSRequestInterceptor sts = new STSChainedAssumeRoleRequestInterceptor(hub, oauth, vaultId, host, trust, key, prompt);
4556
log.debug("Register interceptor {}", sts);
4657
configuration.addInterceptorLast(sts);
4758
return sts;

hub/src/main/java/cloud/katta/protocols/s3/STSChainedAssumeRoleRequestInterceptor.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import ch.cyberduck.core.Profile;
1111
import ch.cyberduck.core.TemporaryAccessTokens;
1212
import ch.cyberduck.core.exception.BackgroundException;
13+
import ch.cyberduck.core.exception.InteroperabilityException;
1314
import ch.cyberduck.core.exception.LoginFailureException;
1415
import ch.cyberduck.core.oauth.OAuth2RequestInterceptor;
1516
import ch.cyberduck.core.preferences.HostPreferencesFactory;
@@ -24,6 +25,7 @@
2425

2526
import java.util.Arrays;
2627
import java.util.List;
28+
import java.util.UUID;
2729

2830
import cloud.katta.client.ApiException;
2931
import cloud.katta.client.api.StorageResourceApi;
@@ -46,15 +48,17 @@ public class STSChainedAssumeRoleRequestInterceptor extends STSAssumeRoleWithWeb
4648
*/
4749
private static final String OIDC_AUTHORIZED_PARTY = "azp";
4850

51+
private final HubSession hub;
4952
private final Host bookmark;
50-
private final String vaultId;
53+
private final UUID vaultId;
5154

52-
public STSChainedAssumeRoleRequestInterceptor(final OAuth2RequestInterceptor oauth, final Host host,
55+
public STSChainedAssumeRoleRequestInterceptor(final HubSession hub, final OAuth2RequestInterceptor oauth, final UUID vaultId, final Host host,
5356
final X509TrustManager trust, final X509KeyManager key,
5457
final LoginCallback prompt) {
5558
super(oauth, host, trust, key, prompt);
59+
this.hub = hub;
5660
this.bookmark = host;
57-
this.vaultId = HostPreferencesFactory.get(host).getProperty(S3AssumeRoleProtocol.OAUTH_TOKENEXCHANGE_VAULT);
61+
this.vaultId = vaultId;
5862
}
5963

6064
@Override
@@ -95,18 +99,15 @@ public TemporaryAccessTokens assumeRoleWithWebIdentity(final OAuthTokens oauth,
9599
* Perform OAuth 2.0 Token Exchange
96100
*
97101
* @return New tokens
98-
* @see S3AssumeRoleProtocol#OAUTH_TOKENEXCHANGE_VAULT
99102
*/
100103
private OAuthTokens tokenExchange(final OAuthTokens tokens) throws BackgroundException {
101104
final PreferencesReader settings = HostPreferencesFactory.get(bookmark);
102105
if(settings.getBoolean(S3AssumeRoleProtocol.OAUTH_TOKENEXCHANGE)) {
103106
if(this.isTokenExchangeRequired(tokens)) {
104-
log.info("Exchange tokens for {}", bookmark);
105-
final HubSession hub = bookmark.getProtocol().getFeature(HubSession.class);
106-
log.debug("Exchange token with hub {}", hub);
107+
log.info("Exchange tokens {} for vault {}", tokens, vaultId);
107108
final StorageResourceApi api = new StorageResourceApi(hub.getClient());
108109
try {
109-
final AccessTokenResponse tokenExchangeResponse = api.apiStorageS3TokenPost(vaultId);
110+
final AccessTokenResponse tokenExchangeResponse = api.apiStorageS3TokenPost(vaultId.toString());
110111
// N.B. token exchange with Id token does not work!
111112
final OAuthTokens exchanged = new OAuthTokens(tokenExchangeResponse.getAccessToken(),
112113
tokenExchangeResponse.getRefreshToken(),

0 commit comments

Comments
 (0)