Reopening this issue based on issue #370 . The AWS SDK for GO is currently missing a browser based PresignedPost()feature.
This feature should mirror the PresignedPost() feature provided by the AWS SDK for Ruby:
http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/PresignedPost.html
Thanks for contacting us @eriklott and creating this feature request. We'd be glad to take a look at adding this feature into the SDK. If you're interested we're always eager to review PRs and discuss implementation ideas.
Initially it looks like we should limit this feature to S3 and create it as a customization for the S3 service client similar to the SDK's s3manager's Uploader and Downloader.
any update on adding a presigned post directly?
HI @sdalezman We've not done any work on this feature request, but we'd be happy to review a PR if anyone is interested in submitting one.
This method is still missing after four years. I can create a PR but the documentation is cryptic as ever. After a lot of digging, I found out that as apposed to a signed PUT request where you sign a request, you need to sign a policy document(base64 version of it) in this case. You can then use the base64 encoded policy document and it's signature in your HTML form or POST request.
But the github.com/aws/aws-sdk-go/aws/signer/v4 does not a have method for signing strings. So, to implement this, you just need to implement a method in signer to sign strings and use that method in something like
func (c *Client) PresignedPost(policyDocument string) (policyDocumentBase64 string, signature string)
I managed to create a SignString method for github.com/aws/aws-sdk-go/aws/signer/v4
func (v4 Signer) SignString(awsContext aws.Context, stringToSign string, service, region string, exp time.Duration, signTime time.Time) (string, error) {
currentTimeFn := v4.currentTimeFn
if currentTimeFn == nil {
currentTimeFn = time.Now
}
ctx := &signingCtx{
Time: signTime,
ExpireTime: exp,
ServiceName: service,
Region: region,
DisableURIPathEscaping: v4.DisableURIPathEscaping,
unsignedPayload: v4.UnsignedPayload,
}
var err error
ctx.credValues, err = v4.Credentials.GetWithContext(awsContext)
if err != nil {
return "", err
}
ctx.stringToSign = stringToSign
ctx.buildSignature()
return ctx.signature, err
}
It is used like so:
sgn := signer.NewSigner(cfg.Credentials)
signature, err := sgn.SignString(aws.BackgroundContext(), documentEncoded, svc.ServiceName, svc.SigningRegion, expiresIn, time.Now())
if err != nil {
return nil, err
}
But it's panicking with runtime error: invalid memory address or nil pointer dereference on
ctx.credValues, err = v4.Credentials.GetWithContext(awsContext)
for some reason I can't figure out. Can I not use aws.BackgroundContext() for this?
It turns out I was providing the "wrong kind" of credentials to signer.NewSigner. Now I'm doing the following and it works:
var svc = s3.New(session.New(), cfg)
sgn := signer.NewSigner(svc.Config.Credentials)
I've created a PR that add signer/v4.SignString method which should be enough for people to manually sign their policies. Creating a convenience method in s3 will require a lot of parameter validation that I don't have time to implement.
I'm very interested in this feature too 馃憤
It's supported by other SDKs (e.g. JavaScript, Python, Ruby) since 5+ years. Go is clearly lagging behind.
@RaeesBhatti did you fork this library or how did you manage to extend v4.Signer?
I tried:
type MySigner struct {
v4.Signer
}
func (signer MySigner) SignString(awsContext aws.Context, stringToSign string, service, region string, exp time.Duration, signTime time.Time) (string, error) {
currentTimeFn := signer.currentTimeFn
// ...
}
But that does not work as most fields of v4.Signer and v4.signingCtx are not exported.
Could you share more code? I don't quite understand how it all works together
@asterikx The PR I opened has all of the changes needed to make this work: https://github.com/aws/aws-sdk-go/pull/3287
Most helpful comment
I've created a PR that add
signer/v4.SignStringmethod which should be enough for people to manually sign their policies. Creating a convenience method ins3will require a lot of parameter validation that I don't have time to implement.PR: https://github.com/aws/aws-sdk-go/pull/3287