77import ch .cyberduck .core .DisabledCancelCallback ;
88import ch .cyberduck .core .DisabledHostKeyCallback ;
99import ch .cyberduck .core .Host ;
10- import ch .cyberduck .core .HostUrlProvider ;
1110import ch .cyberduck .core .LoginCallback ;
1211import ch .cyberduck .core .PasswordCallback ;
1312import ch .cyberduck .core .Path ;
14- import ch .cyberduck .core .PathAttributes ;
1513import ch .cyberduck .core .Session ;
16- import ch .cyberduck .core .cryptomator .ContentWriter ;
17- import ch .cyberduck .core .cryptomator .UVFVault ;
14+ import ch .cyberduck .core .cryptomator .AbstractVault ;
15+ import ch .cyberduck .core .cryptomator .impl . uvf . CryptoVault ;
1816import ch .cyberduck .core .exception .BackgroundException ;
1917import ch .cyberduck .core .exception .InteroperabilityException ;
2018import ch .cyberduck .core .exception .UnsupportedException ;
21- import ch .cyberduck .core .features .AttributesFinder ;
22- import ch .cyberduck .core .features .Directory ;
23- import ch .cyberduck .core .features .Write ;
2419import ch .cyberduck .core .preferences .HostPreferencesFactory ;
25- import ch .cyberduck .core .preferences .PreferencesFactory ;
2620import ch .cyberduck .core .proxy .ProxyFactory ;
2721import ch .cyberduck .core .s3 .S3Session ;
28- import ch .cyberduck .core .transfer .TransferStatus ;
29- import ch .cyberduck .core .vault .VaultCredentials ;
22+ import ch .cyberduck .core .vault .VaultMetadataProvider ;
3023import ch .cyberduck .core .vault .VaultUnlockCancelException ;
3124
3225import org .apache .logging .log4j .LogManager ;
3528
3629import java .nio .charset .StandardCharsets ;
3730import java .util .Collections ;
38- import java .util .EnumSet ;
3931import java .util .UUID ;
4032
4133import cloud .katta .client .ApiException ;
4436import cloud .katta .client .model .VaultDto ;
4537import cloud .katta .core .DeviceSetupCallback ;
4638import cloud .katta .crypto .UserKeys ;
47- import cloud .katta .crypto .uvf .UvfMetadataPayload ;
48- import cloud .katta .crypto .uvf .UvfMetadataPayloadPasswordCallback ;
39+ import cloud .katta .crypto .uvf .VaultIdMetadataUVFProvider ;
4940import cloud .katta .protocols .hub .exceptions .HubExceptionMappingService ;
5041import cloud .katta .protocols .s3 .S3AssumeRoleProtocol ;
5142import com .fasterxml .jackson .core .JsonProcessingException ;
5445/**
5546 * Unified vault format (UVF) implementation for Katta
5647 */
57- public class HubUVFVault extends UVFVault {
48+ public class HubUVFVault extends CryptoVault {
5849 private static final Logger log = LogManager .getLogger (HubUVFVault .class );
5950
60- private final UUID vaultId ;
61- private final UvfMetadataPayload vaultMetadata ;
62-
6351 /**
6452 * Storage connection only available after loading vault
6553 */
@@ -68,17 +56,13 @@ public class HubUVFVault extends UVFVault {
6856
6957 /**
7058 *
71- * @param storage Storage connection
72- * @param vaultId Vault Id
73- * @param vaultMetadata Vault UVF metadata
74- * @param prompt Login prompt to access storage
59+ * @param storage Storage connection
60+ * @param bucket Vault UVF metadata
61+ * @param prompt Login prompt to access storage
7562 */
76- public HubUVFVault (final Session <?> storage , final UUID vaultId , final UvfMetadataPayload vaultMetadata , final LoginCallback prompt ) {
77- super (new Path (vaultMetadata .storage ().getDefaultPath (), EnumSet .of (Path .Type .directory , Path .Type .volume ),
78- new PathAttributes ().setDisplayname (vaultMetadata .storage ().getNickname ())));
63+ public HubUVFVault (final Session <?> storage , final Path bucket , final LoginCallback prompt ) {
64+ super (bucket );
7965 this .storage = storage ;
80- this .vaultId = vaultId ;
81- this .vaultMetadata = vaultMetadata ;
8266 this .login = prompt ;
8367 }
8468
@@ -115,36 +99,32 @@ public synchronized void close() {
11599 }
116100
117101 @ Override
118- public Path create (final Session <?> session , final String region , final VaultCredentials noop ) throws BackgroundException {
102+ public AbstractVault create (final Session <?> session , final String region , final VaultMetadataProvider metadata ) throws BackgroundException {
119103 try {
120104 final HubSession hub = HubSession .coerce (session );
121- log . debug ( "Created metadata JWE {}" , vaultMetadata );
122- final UvfMetadataPayload . UniversalVaultFormatJWKS jwks = UvfMetadataPayload . createKeys ();
105+ final Path home = this . getHome ( );
106+ final UUID vaultId = VaultIdMetadataUVFProvider . cast ( metadata ). getVaultId ();
123107 final VaultDto vaultDto = new VaultDto ()
124108 .id (vaultId )
125- .name (vaultMetadata . storage ().getNickname ())
109+ .name (home . attributes ().getDisplayname ())
126110 .description (null )
127111 .archived (false )
128112 .creationTime (DateTime .now ())
129- .uvfMetadataFile (vaultMetadata .encrypt (
130- String .format ("%s/api" , new HostUrlProvider (false , true ).get (session .getHost ())),
131- vaultId ,
132- jwks .toJWKSet ()
133- ))
134- .uvfKeySet (jwks .serializePublicRecoverykey ());
113+ .uvfMetadataFile (new String (VaultIdMetadataUVFProvider .cast (metadata ).getMetadata (), StandardCharsets .US_ASCII ))
114+ .uvfKeySet (VaultIdMetadataUVFProvider .cast (metadata ).getJwks ().serializePublicRecoverykey ());
135115 // Create vault in Hub
136116 final VaultResourceApi vaultResourceApi = new VaultResourceApi (hub .getClient ());
137117 log .debug ("Create vault {}" , vaultDto );
138- vaultResourceApi .apiVaultsVaultIdPut (vaultDto . getId () , vaultDto ,
118+ vaultResourceApi .apiVaultsVaultIdPut (vaultId , vaultDto ,
139119 storage .getHost ().getProtocol ().isRoleConfigurable () && !S3Session .isAwsHostname (storage .getHost ().getHostname ()),
140120 storage .getHost ().getProtocol ().isRoleConfigurable () && S3Session .isAwsHostname (storage .getHost ().getHostname ()));
141121 // Upload JWE
142122 log .debug ("Grant access to vault {}" , vaultDto );
143123 final UserDto userDto = hub .getMe ();
144124 final DeviceSetupCallback setup = login .getFeature (DeviceSetupCallback .class );
145125 final UserKeys userKeys = hub .getUserKeys (setup );
146- vaultResourceApi .apiVaultsVaultIdAccessTokensPost (vaultDto . getId () ,
147- Collections .singletonMap (userDto .getId (), jwks .toOwnerAccessToken ().encryptForUser (userKeys .ecdhKeyPair ().getPublic ())));
126+ vaultResourceApi .apiVaultsVaultIdAccessTokensPost (vaultId ,
127+ Collections .singletonMap (userDto .getId (), VaultIdMetadataUVFProvider . cast ( metadata ). getJwks () .toOwnerAccessToken ().encryptForUser (userKeys .ecdhKeyPair ().getPublic ())));
148128 // Upload vault template to storage
149129 log .debug ("Connect to {}" , storage );
150130 final Host configuration = storage .getHost ();
@@ -156,36 +136,8 @@ public Path create(final Session<?> session, final String region, final VaultCre
156136 // No role chaining when creating vault
157137 configuration .setProperty (S3AssumeRoleProtocol .S3_ASSUMEROLE_ROLEARN_TAG , null );
158138 storage .open (ProxyFactory .get (), new DisabledHostKeyCallback (), login , new DisabledCancelCallback ());
159- final Path vault ;
160- if (false ) {
161- log .debug ("Upload vault template to {}" , storage );
162- return super .create (storage ,
163- HubStorageLocationService .StorageLocation .fromIdentifier (region ).getRegion (), noop );
164- }
165- else { // Obsolete when implemented in super
166- final Directory <?> directory = (Directory <?>) storage ._getFeature (Directory .class );
167- final Path home = this .getHome ();
168- log .debug ("Create vault root directory at {}" , home );
169- final TransferStatus status = (new TransferStatus ()).setRegion (HubStorageLocationService .StorageLocation .fromIdentifier (region ).getRegion ());
170- vault = directory .mkdir (storage ._getFeature (Write .class ), home , status );
171-
172- final String hashedRootDirId = vaultMetadata .computeRootDirIdHash ();
173- final Path dataDir = new Path (vault , "d" , EnumSet .of (Path .Type .directory ));
174- final Path firstLevel = new Path (dataDir , hashedRootDirId .substring (0 , 2 ), EnumSet .of (Path .Type .directory ));
175- final Path secondLevel = new Path (firstLevel , hashedRootDirId .substring (2 ), EnumSet .of (Path .Type .directory ));
176-
177- directory .mkdir (storage ._getFeature (Write .class ), dataDir , status );
178- directory .mkdir (storage ._getFeature (Write .class ), firstLevel , status );
179- directory .mkdir (storage ._getFeature (Write .class ), secondLevel , status );
180-
181- // vault.uvf
182- new ContentWriter (storage ).write (new Path (home , PreferencesFactory .get ().getProperty ("cryptomator.vault.config.filename" ),
183- EnumSet .of (Path .Type .file , Path .Type .vault )), vaultDto .getUvfMetadataFile ().getBytes (StandardCharsets .US_ASCII ));
184- // dir.uvf
185- new ContentWriter (storage ).write (new Path (secondLevel , "dir.uvf" , EnumSet .of (Path .Type .file )),
186- vaultMetadata .computeRootDirUvf ());
187- }
188- return vault ;
139+ log .debug ("Upload vault template to {}" , storage );
140+ return super .create (storage , HubStorageLocationService .StorageLocation .fromIdentifier (region ).getRegion (), metadata );
189141 }
190142 catch (JOSEException | JsonProcessingException e ) {
191143 throw new InteroperabilityException (e .getMessage (), e );
@@ -203,34 +155,24 @@ public Path create(final Session<?> session, final String region, final VaultCre
203155 */
204156 @ Override
205157 public HubUVFVault load (final Session <?> session , final PasswordCallback prompt ) throws BackgroundException {
158+ log .debug ("Connect to {}" , storage );
206159 try {
207- log .debug ("Connect to {}" , storage );
208- try {
209- storage .open (ProxyFactory .get (), new DisabledHostKeyCallback (), login , new DisabledCancelCallback ());
210- }
211- catch (BackgroundException e ) {
212- log .warn ("Skip loading vault with failure {} connecting to storage" , e .toString ());
213- throw new VaultUnlockCancelException (this , e );
214- }
215- final Path home = this .getHome ();
216- home .setAttributes (storage .getFeature (AttributesFinder .class ).find (home )
217- .setDisplayname (vaultMetadata .storage ().getNickname ()));
218- log .debug ("Initialize vault {} with metadata {}" , this , vaultMetadata );
219- // Initialize cryptors
220- super .load (storage , new UvfMetadataPayloadPasswordCallback (vaultMetadata .toJSON ()));
221- return this ;
160+ storage .open (ProxyFactory .get (), new DisabledHostKeyCallback (), login , new DisabledCancelCallback ());
222161 }
223- catch (JsonProcessingException e ) {
224- throw new InteroperabilityException (e .getMessage (), e );
162+ catch (BackgroundException e ) {
163+ log .warn ("Skip loading vault with failure {} connecting to storage" , e .toString ());
164+ throw new VaultUnlockCancelException (this , e );
225165 }
166+ log .debug ("Initialize vault {}" , this );
167+ // Initialize cryptors
168+ super .load (storage , prompt );
169+ return this ;
226170 }
227171
228172 @ Override
229173 public String toString () {
230174 final StringBuilder sb = new StringBuilder ("HubUVFVault{" );
231- sb .append ("vaultId=" ).append (vaultId );
232- sb .append (", vaultMetadata=" ).append (vaultMetadata );
233- sb .append (", storage=" ).append (storage );
175+ sb .append ("storage=" ).append (storage );
234176 sb .append ('}' );
235177 return sb .toString ();
236178 }
0 commit comments