kopia lustrzana https://github.com/gaul/s3proxy
Fix EncryptedBlobStore support for s3 compatible backends without eTag suffix
Some mostly S3 REST API compatible storage backends do not return the number of multipart upload parts as a suffix to the eTag as Amazon does and as the previous code expects. An example for this is NetApp StorageGRID S3 REST API. The old code had a fallback to just assume one encrypted part, but this is actually wrong in the multipart upload case for these backends, thus this is replace in this commit. Example eTag structure from real AWS S3 for multipart uploads with 2 parts:`xyzabc-2` In this case the number of parts is also not present in the object metadata, as metadata is set on S3 API when starting the multipart upload, and not when completing it, thus the number of parts is not yet known at this earlier point in time. This change adds a third fallback option to just read the number of parts from the final part padding, which is the only place guaranteed to always be present for encrypted blobs. Only for these backends this adds an additional GET request to the backend, but only for the actual 64 bytes of the padding.pull/825/head
rodzic
17e490e775
commit
b420e92bcd
|
@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.ArrayList;
|
||||
|
@ -41,6 +42,7 @@ import com.google.common.hash.Hashing;
|
|||
import org.gaul.s3proxy.crypto.Constants;
|
||||
import org.gaul.s3proxy.crypto.Decryption;
|
||||
import org.gaul.s3proxy.crypto.Encryption;
|
||||
import org.gaul.s3proxy.crypto.PartPadding;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobAccess;
|
||||
|
@ -317,9 +319,21 @@ public final class EncryptedBlobStore extends ForwardingBlobStore {
|
|||
mbm.setSize(size);
|
||||
mbm.getContentMetadata().setContentLength(size);
|
||||
} else {
|
||||
long size = blobMeta.getSize() - Constants.PADDING_BLOCK_SIZE;
|
||||
mbm.setSize(size);
|
||||
mbm.getContentMetadata().setContentLength(size);
|
||||
// if there is also no eTag suffix then get the number of parts from last padding
|
||||
var options = new GetOptions()
|
||||
.range(blobMeta.getSize() - Constants.PADDING_BLOCK_SIZE, blobMeta.getSize());
|
||||
var name = blobNameWithSuffix(blobMeta.getName());
|
||||
var blob = delegate().getBlob(blobMeta.getContainer(), name, options);
|
||||
try {
|
||||
PartPadding lastPartPadding = PartPadding.readPartPaddingFromBlob(blob);
|
||||
int parts = lastPartPadding.getPart();
|
||||
int partPaddingSizes = Constants.PADDING_BLOCK_SIZE * parts;
|
||||
long size = blobMeta.getSize() - partPaddingSizes;
|
||||
mbm.setSize(size);
|
||||
mbm.getContentMetadata().setContentLength(size);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read part-padding from encrypted blob", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue