Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[S3] presigned PutObject - Enforce Content-Type #503

Closed
rayrutjes opened this issue Jan 14, 2016 · 4 comments
Closed

[S3] presigned PutObject - Enforce Content-Type #503

rayrutjes opened this issue Jan 14, 2016 · 4 comments
Assignees
Labels
bug This issue is a bug.

Comments

@rayrutjes
Copy link

This is a follow up of #467 .

Actually, it looks like that the Content-Type can not be constrained by the presigned url.
Here is a quick (untested) example that illustrates the purpose:

package main

import (
    "bytes"
    "crypto/md5"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func main() {
    buf := bytes.NewReader(make([]byte, 10*1024*1024))
    h := md5.New()
    io.Copy(h, buf)

    //
    // Generate presigned PutObject URL
    svc := s3.New(session.New())
    r, _ := svc.PutObjectRequest(&s3.PutObjectInput{
        Bucket: aws.String(os.Args[1]),
        Key:    aws.String(os.Args[2]),
        ContentType: aws.String("image/png"),
    })
    r.HTTPRequest.Header.Set("Content-MD5", fmt.Sprintf("%x", h.Sum(nil)))
    url, err := r.Presign(15 * time.Minute)
    if err != nil {
        fmt.Println("error presigning request", err)
        return
    }
    fmt.Println("URL", url)
    buf.Seek(0, 0)

    //
    // Use the presigned URL to put a object to S3
    req, err := http.NewRequest("PUT", url, buf)
    req.Header.Set("Content-Type", "image/gif")
    if err != nil {
        fmt.Println("error creating request", url)
        return
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("failed making request")
        return
    }
    defer resp.Body.Close()

    //
    // Print out the response.
    fmt.Println("Status", resp.StatusCode, resp.StatusCode)
    o := &bytes.Buffer{}
    io.Copy(o, resp.Body)
    fmt.Println(o.String())
}

This results in the file being correctly uploaded but the Content-Type would be set to image/gif.
For consistency matters, I would like to ensure that the declared Content-Type while fetching the presigned url is the same as the final real Content-Type attached to the file on S3. In that way I can ensure that any clients asking my API for presigned urls do not forget to correctly add the correct Content-Type header. Hope that makes sense.

Thank you.

@jasdel
Copy link
Contributor

jasdel commented Jan 14, 2016

This issue was incorrectly closed.

@jasdel jasdel reopened this Jan 14, 2016
jasdel added a commit that referenced this issue Jan 14, 2016
@jasdel
Copy link
Contributor

jasdel commented Jan 15, 2016

@rayrutjes Thanks for creating this issue. I think it points out a generally issue with the current way the SDK generates pre-signed URLs. Content-Type is actually being explicitly ignored when calculating the signature even though the sig v4 spec states it as a valid optional parameter to include in the signature.

I think part of the issue is the SDK's normal request signing verse rules for pre-signing are getting conflated. The ignoredHeaders in v4.go are used to excluded headers from both the query string for pre-signing, and normal signature for SDK requests.

Marking this as a bug. We should take a look at this and see how changing this method will impact backwards compatibility. Or potentially the correct solutions is the idea mentioned in #458 to not hoist any headers but auth related, and removing/trimming the blacklist down.

@jasdel jasdel added the bug This issue is a bug. label Jan 15, 2016
@jasdel
Copy link
Contributor

jasdel commented Jan 15, 2016

I think to start here we need to clarify and document which headers can and cannot be hoisted to the URL path for presigning. In addition a pass over which headers are blacklisted from (pre)signing will be helpful. Specifically we can blacklist headers that can by modified by proxies.

In this we should also include a list of headers which "could" be hoisted to the query string but probably shouldn't specifically these are some of the S3 headers around policy and encryption. Bucket policy filters do not inspect query string parameters, and only verify against headers.

@xibz
Copy link
Contributor

xibz commented Jan 28, 2016

Fixed in v1.1.0. Let us know if any other issues or feedback regarding the change.

@xibz xibz closed this as completed Jan 28, 2016
skotambkar pushed a commit to skotambkar/aws-sdk-go that referenced this issue May 20, 2021
skotambkar pushed a commit to skotambkar/aws-sdk-go that referenced this issue May 20, 2021
Breaking Change
---
* Update SDK retry behavior
  * Significant updates were made the SDK's retry behavior. The SDK will now retry all connections error. In addition, to changing what errors are retried the SDK's retry behavior not distinguish the difference between throttling errors, and regular retryable errors. All errors will be retried with the same backoff jitter delay scaling.
  * The SDK will attempt an operation request 3 times by default. This is one less than the previous initial request with 3 retires.
  * New helper functions in the new `aws/retry` package allow wrapping a `Retrier` with custom behavior, overriding the base `Retrier`, (e.g. `AddWithErrorCodes`, and `AddWithMaxAttempts`)
* Update SDK error handling
  * Updates the SDK's handling of errors to take advantage of Go 1.13's new `errors.As`, `Is`, and `Unwrap`. The SDK's errors were updated to satisfy the `Unwrap` interface, returning the underlying error.
  * With this update, you can now more easily access the SDK's layered errors, and meaningful state such as, `Timeout`, `Temporary`, and other states added to the SDK such as `CanceledError`.
* Bump SDK minimum supported version from Go 1.12 to Go 1.13
  * The SDK's minimum supported version is bumped to take advantage of Go 1.13's updated `errors` package.

Services
---
* Synced the V2 SDK with latest AWS service API definitions.

SDK Features
---
* `aws`: Add Support for additional credential providers and credential configuration chaining ([aws#488](aws/aws-sdk-go-v2#488))
  * `aws/processcreds`: Adds Support for the Process Credential Provider
    * Fixes [aws#249](aws/aws-sdk-go-v2#249)
  * `aws/stscreds`: Adds Support for the Web Identity Credential Provider
    * Fixes [aws#475](aws/aws-sdk-go-v2#475)
    * Fixes [aws#338](aws/aws-sdk-go-v2#338)
  * Adds Support for `credential_source`
    * Fixes [aws#274](aws/aws-sdk-go-v2#274)
* `aws/awserr`: Adds support for Go 1.13's `errors.Unwrap` ([aws#487](aws/aws-sdk-go-v2#487))
* `aws`: Updates SDK retry behavior ([aws#487](aws/aws-sdk-go-v2#487))
  * `aws/retry`: New package defining logic to determine if a request should be retried, and backoff.
  * `aws/ratelimit`: New package defining rate limit logic such as token bucket used by the `retry.Standard` retrier.

SDK Enhancements
---
* `aws`: Add grouping of concurrent refresh of credentials ([aws#503](aws/aws-sdk-go-v2#503))
  * Concurrent calls to `Retrieve` are now grouped in order to prevent numerous synchronous calls to refresh the credentials. Replacing the mutex with a singleflight reduces the overall amount of time request signatures need to wait while retrieving credentials. This is improvement becomes pronounced when many requests are made concurrently.
* `service/s3/s3manager`: Improve memory allocation behavior by replacing sync.Pool with custom pool implementation
  * Improves memory allocations that occur when the provided `io.Reader` to upload does not satisfy both the `io.ReaderAt` and `io.ReadSeeker` interfaces.

SDK Bugs
---
* `service/s3/s3manager`: Fix resource leaks when the following occurred:
  * Failed CreateMultipartUpload call
  * Failed UploadPart call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants