[
https://issues.apache.org/jira/browse/JCLOUDS-1571?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Filip Panovski updated JCLOUDS-1571:
------------------------------------
Description:
(Disclaimer: I'm not 100% sure whether this is a bug report or a feature
request, as I've found only scant information available)
We have the use case where we wish to provide a signed aws-s3 {{PUT}} URL to a
browser client which will be used to process a file upload (non-chunked, single
URL). We are using version {{2.3.0}} (the latest public release).
The {{jclouds}} API has support for this via {{BlobStoreContext#getSigner}} ,
i.e. {{BlobRequestSigner#signPutBlob(String containerName, Blob blob, long
timeInSeconds)}}.
However, there seems to be no support for signing custom headers as part of
the URL.
The relevant AWS Documentation (link
[here|https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html])
states that:
{code:java}
For added security, you should sign all the request headers that you plan to
include in your request.
{code}
I dug around the {{jclouds-core}} code and saw that, for pre-signed {{PUT}}
requests, a {{PhantomPayload}} is used which appears, for all intents and
purposes, as a real payload with checksum and content-length.
However, although this information is available at the time of signing, the
only headers which are part of the signed headers are those which are either
specifically annotated as such (e.g.: {{org.jclouds.s3.S3Client#putObject}},
which contains {{@Headers(keys = EXPECT, values = "100-continue"}}) or are
otherwise part of normal request flow depending on media type (i.e.
{{content-type}}, {{accept}}).
The way I access the API is as follows:
{code:java}
@Override
public URI getPreSignedPutUrl(final String blobId, final long contentLength,
final String checksum,
final String mediaType) {
BlobStoreContext context = blobStoreContextProvider.getBlobStoreContext();
BlobRequestSigner signer = context.getSigner();
Blob expectedBlob = context.getBlobStore().blobBuilder(blobId)
.forSigning()
.contentType(mediaType)
.contentMD5(HashCode.fromString(checksum))
.contentLength(contentLength)
.build();
HttpRequest request = signer.signPutBlob(this.bucket.getName(),
expectedBlob, 60);
return request.getEndpoint();
}
{code}
What I _expected_ to happen was:
# A pre-signed URL is created with the blob I pass it.
# The blob's content-md5 and content-length values are passed through as part
of the signed headers.
# The pre-signed URL includes these values so that only a specific file (or
something that has exactly that checksum and content length) can be uploaded to
said URL.
What _did_ happen was:
# A pre-signed URL is created with the blob I pass it.
# {{RestAnnotationProcessor}} and the default {{S3Client}} API both seem to
not take any of the blob metadata into account
# The pre-signed URL includes only the {{host}} header as a signed header.
As a result, I can upload any file I wish to the pre-signed {{PUT}} URL, not
just the one that I specifically intended, although metadata like content
checksum and length is available and could also be signed within the request.
For what it's worth, I did try to extend the existing {{BlogRequestSigner}} to
include {{PutOptions}} (which have an effect on signed headers, as far as I can
tell, see:
{{[RestAnnotationProcessor#apply:282|https://github.com/apache/jclouds/blob/master/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java#L282]}}),
but got lots of Guice binding errors that I was unable to resolve. I am
relatively new to Guice, so that might have been user error - as the
documentation is lacking though, I'm unsure if that's the preferred way.
Lastly, https://issues.apache.org/jira/browse/JCLOUDS-1161 exists which seems
loosely related to my issue. As I understand it though, the "workaround"
described therein should no longer be necessary (since V4 is automatically used
for {{aws-s3}} since ~{{2.2.0}}) and it does not help in my case either.
Is the current behaviour, as described above, correct? Is the lack of a support
for additional signed headers intentional? Is there another way that I'm not
quite seeing?
Any feedback would be greatly appreciated.
was:
(Disclaimer: I'm not 100% sure whether this is a bug report or a feature
request, as I've found only scant information available)
We have the use case where we wish to provide a signed aws-s3 {{PUT}} URL to a
browser client which will be used to process a file upload (non-chunked, single
URL). We are using version {{2.3.0}} (the latest public release).
The {{jclouds}} API has support for this via {{BlobStoreContext#getSigner}} ,
i.e. {{BlobRequestSigner#signPutBlob(String containerName, Blob blob, long
timeInSeconds)}}.
However, there seems to be no support for signing custom headers as part of
the URL.
The relevant AWS Documentation (link
[here|https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html])
states that:
{code:java}
For added security, you should sign all the request headers that you plan to
include in your request.
{code}
I dug around the {{jclouds-core}} code and saw that, for pre-signed {{PUT}}
requests, a {{PhantomPayload}} is used which appears, for all intents and
purposes, as a real payload with checksum and content-length.
However, although this information is available at the time of signing, the
only headers which are part of the signed headers are those which are either
specifically annotated as such (e.g.: {{org.jclouds.s3.S3Client#putObject}},
which contains {{@Headers(keys = EXPECT, values = "100-continue"}}) or are
otherwise part of normal request flow depending on media type (i.e.
{{content-type}}, {{accept}}).
The way I access the API is as follows:
{code:java}
@Override
public URI getPreSignedPutUrl(final String blobId, final long contentLength,
final String checksum,
final String mediaType) {
BlobStoreContext context = blobStoreContextProvider.getBlobStoreContext();
BlobRequestSigner signer = context.getSigner();
Blob expectedBlob = context.getBlobStore().blobBuilder(blobId)
.forSigning()
.contentType(mediaType)
.contentMD5(HashCode.fromString(checksum))
.contentLength(contentLength)
.build();
HttpRequest request = signer.signPutBlob(this.bucket.getName(),
expectedBlob, 60);
return request.getEndpoint();{code}
What I _expected_ to happen was:
# A pre-signed URL is created with the blob I pass it.
# The blob's content-md5 and content-length values are passed through as part
of the signed headers.
# The pre-signed URL includes these values so that only a specific file (or
something that has exactly that checksum and content length) can be uploaded to
said URL.
What _did_ happen was:
# A pre-signed URL is created with the blob I pass it.
# {{RestAnnotationProcessor}} and the default {{S3Client}} API both seem to
not take any of the blob metadata into account
# The pre-signed URL includes only the {{host}} header as a signed header.
As a result, I can upload any file I wish to the pre-signed {{PUT}} URL, not
just the one that I specifically intended, although metadata like content
checksum and length is available and could also be signed within the request.
For what it's worth, I did try to extend the existing {{BlogRequestSigner}} to
include {{PutOptions}} (which have an effect on signed headers, as far as I can
tell, see:
{{[RestAnnotationProcessor#apply:282|https://github.com/apache/jclouds/blob/master/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java#L282]}}),
but got lots of Guice binding errors that I was unable to resolve. I am
relatively new to Guice, so that might have been user error - as the
documentation is lacking though, I'm unsure if that's the preferred way.
Lastly, https://issues.apache.org/jira/browse/JCLOUDS-1161 exists which seems
loosely related to my issue. As I understand it though, the "workaround"
described therein should no longer be necessary (since V4 is automatically used
for {{aws-s3}} since ~{{2.2.0}}) and it does not help in my case either.
Is the current behaviour, as described above, correct? Is the lack of a support
for additional signed headers intentional? Is there another way that I'm not
quite seeing?
Any feedback would be greatly appreciated.
> Unable to provide custom signed headers using BlobRequestSigner#signPutBlob
> ---------------------------------------------------------------------------
>
> Key: JCLOUDS-1571
> URL: https://issues.apache.org/jira/browse/JCLOUDS-1571
> Project: jclouds
> Issue Type: Bug
> Components: jclouds-blobstore, jclouds-core
> Affects Versions: 2.3.0
> Environment: Debian
> Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
> Reporter: Filip Panovski
> Priority: Minor
>
> (Disclaimer: I'm not 100% sure whether this is a bug report or a feature
> request, as I've found only scant information available)
> We have the use case where we wish to provide a signed aws-s3 {{PUT}} URL to
> a browser client which will be used to process a file upload (non-chunked,
> single URL). We are using version {{2.3.0}} (the latest public release).
> The {{jclouds}} API has support for this via {{BlobStoreContext#getSigner}}
> , i.e. {{BlobRequestSigner#signPutBlob(String containerName, Blob blob, long
> timeInSeconds)}}.
> However, there seems to be no support for signing custom headers as part of
> the URL.
> The relevant AWS Documentation (link
> [here|https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html])
> states that:
> {code:java}
> For added security, you should sign all the request headers that you plan to
> include in your request.
> {code}
> I dug around the {{jclouds-core}} code and saw that, for pre-signed {{PUT}}
> requests, a {{PhantomPayload}} is used which appears, for all intents and
> purposes, as a real payload with checksum and content-length.
> However, although this information is available at the time of signing, the
> only headers which are part of the signed headers are those which are either
> specifically annotated as such (e.g.: {{org.jclouds.s3.S3Client#putObject}},
> which contains {{@Headers(keys = EXPECT, values = "100-continue"}}) or are
> otherwise part of normal request flow depending on media type (i.e.
> {{content-type}}, {{accept}}).
> The way I access the API is as follows:
> {code:java}
> @Override
> public URI getPreSignedPutUrl(final String blobId, final long contentLength,
> final String checksum,
> final String mediaType) {
> BlobStoreContext context = blobStoreContextProvider.getBlobStoreContext();
> BlobRequestSigner signer = context.getSigner();
> Blob expectedBlob = context.getBlobStore().blobBuilder(blobId)
> .forSigning()
> .contentType(mediaType)
> .contentMD5(HashCode.fromString(checksum))
> .contentLength(contentLength)
> .build();
> HttpRequest request = signer.signPutBlob(this.bucket.getName(),
> expectedBlob, 60);
> return request.getEndpoint();
> }
> {code}
> What I _expected_ to happen was:
> # A pre-signed URL is created with the blob I pass it.
> # The blob's content-md5 and content-length values are passed through as
> part of the signed headers.
> # The pre-signed URL includes these values so that only a specific file (or
> something that has exactly that checksum and content length) can be uploaded
> to said URL.
> What _did_ happen was:
> # A pre-signed URL is created with the blob I pass it.
> # {{RestAnnotationProcessor}} and the default {{S3Client}} API both seem to
> not take any of the blob metadata into account
> # The pre-signed URL includes only the {{host}} header as a signed header.
> As a result, I can upload any file I wish to the pre-signed {{PUT}} URL, not
> just the one that I specifically intended, although metadata like content
> checksum and length is available and could also be signed within the request.
> For what it's worth, I did try to extend the existing {{BlogRequestSigner}}
> to include {{PutOptions}} (which have an effect on signed headers, as far as
> I can tell, see:
> {{[RestAnnotationProcessor#apply:282|https://github.com/apache/jclouds/blob/master/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java#L282]}}),
> but got lots of Guice binding errors that I was unable to resolve. I am
> relatively new to Guice, so that might have been user error - as the
> documentation is lacking though, I'm unsure if that's the preferred way.
> Lastly, https://issues.apache.org/jira/browse/JCLOUDS-1161 exists which seems
> loosely related to my issue. As I understand it though, the "workaround"
> described therein should no longer be necessary (since V4 is automatically
> used for {{aws-s3}} since ~{{2.2.0}}) and it does not help in my case either.
> Is the current behaviour, as described above, correct? Is the lack of a
> support for additional signed headers intentional? Is there another way that
> I'm not quite seeing?
> Any feedback would be greatly appreciated.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)