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

sts PresignGetCallerIdentity - lack of customisation options #1137

Closed
3 tasks done
RafPe opened this issue Feb 17, 2021 · 6 comments
Closed
3 tasks done

sts PresignGetCallerIdentity - lack of customisation options #1137

RafPe opened this issue Feb 17, 2021 · 6 comments
Labels
closed-for-staleness guidance Question that needs advice or information.

Comments

@RafPe
Copy link

RafPe commented Feb 17, 2021

Confirm by changing [ ] to [x] below to ensure that it's a bug:

Describe the bug
When calling sts PresignGetCallerIdentity I could not find how to customise the request to specific headers would be additionaly signed ( x-k8s-aws-id ) / certain Amazon headers would not be added to request ( X-Amz-User-Agent )

Version of AWS SDK for Go?

	github.com/aws/aws-sdk-go-v2 v1.2.0
	github.com/aws/aws-sdk-go-v2/config v1.1.1
	github.com/aws/aws-sdk-go-v2/credentials v1.1.1
	github.com/aws/aws-sdk-go-v2/service/eks v1.1.1
	github.com/aws/aws-sdk-go-v2/service/sts v1.1.1

Version of Go (go version)?
1.15.2

To Reproduce (observed behavior)

// -------- ...

stsSvc := sts.NewFromConfig(cfg)

getCallerIdentity, err := presignClient.PresignGetCallerIdentity(context.Background(), &sts.GetCallerIdentityInput{})
if err != nil {
	panic(err)
}

// -------- ...

fmt.Println(getCallerIdentity.URL)

Which in turn produces

https://sts.eu-central-1.amazonaws.com/?Action=GetCallerIdentity
&Version=2011-06-15&
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=A**********7/20210216/eu-central-1/sts/aws4_request&
X-Amz-Date=20210216T005611Z&
X-Amz-SignedHeaders=host&
X-Amz-User-Agent=aws-sdk-go-v2/1.2.0 os/other lang/go/1.15.2 md/GOOS/darwin md/GOARCH/amd64&
X-Amz-Signature=cd8****************************************ac2

Expected behavior
I would expect a easy form to provide headers to be signed / headers to be not included in the signing process.

Additional context
Idea here was generating code to create EKS token value.

@RafPe RafPe added the bug This issue is a bug. label Feb 17, 2021
@bluestealth
Copy link

bluestealth commented Feb 20, 2021

It does allow for quite a bit of customization using middleware functions... for example... https://github.com/bluestealth/aws-iam-authenticator/blob/ff550b8c35816a14c256aa064973f6d710334692/pkg/token/token.go#L333-L348

That said a removeHeader function would be nice.

@RafPe
Copy link
Author

RafPe commented Feb 20, 2021

@bluestealth You are absolutely right! Have not seen that and failed to figure out how to wire code into the middleware stack. Thanks for the pointer!

@bluestealth
Copy link

One other issue with this function is that it no longer allows creating POST method presigned requests with a message body. This currently breaks vault iam-auth, since they do not support presigned GET calls. This can't really be worked around currently, since by design presigned requests now do not have a body.

// PresignedHTTPRequest provides the URL and signed headers that are included
// in the presigned URL.
type PresignedHTTPRequest struct {
	URL          string
	Method       string
	SignedHeader http.Header
}

@jasdel
Copy link
Contributor

jasdel commented Mar 3, 2021

Thanks for reaching out, @RafPe, Like @bluestealth mentioned the SDK has helper utilities for customizing requests. Such as adding additional headers. Though the SDK doesn't have any helper/option to direclty specify headers to exclude from signing. With that said a SDK presign operation call can be customized to accomplish all of this.

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/sts"
	"github.com/aws/smithy-go/middleware"
	smithyhttp "github.com/aws/smithy-go/transport/http"
)

func main() {
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		log.Fatalf("failed to load config, %v", err)
	}

	presigner := sts.NewPresignClient(sts.NewFromConfig(cfg))

	p, err := presigner.PresignGetCallerIdentity(context.TODO(),
		&sts.GetCallerIdentityInput{},
		func(po *sts.PresignOptions) {
			po.ClientOptions = []func(*sts.Options){
				sts.WithAPIOptions(
					// Headers that should be signed should be included here.
					// Don't include headers that should NOT be signed.
					smithyhttp.AddHeaderValue("my-header", "value"),
					smithyhttp.AddHeaderValue("my-header-2", "value"),

					// Create custom serialization middleware for request to have POST method.
					func(s *middleware.Stack) error {
						return s.Serialize.Add(
							// Instead of usign closure could move this to standalone type
							// implementing the middleware.SerializeMiddeware interface
							// https://pkg.go.dev/github.com/aws/smithy-go/middleware#SerializeMiddleware
							middleware.SerializeMiddlewareFunc("use POST method",
								func(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (
									out middleware.SerializeOutput, metadata middleware.Metadata, err error,
								) {
									// Extract the SDK's request value, and update HTTP method.
									r, ok := in.Request.(*smithyhttp.Request)
									if !ok {
										return out, metadata, fmt.Errorf("expect %T request, got %T", r, in.Request)
									}
									r.Method = "POST"

									return next.HandleSerialize(ctx, in)
								}),
							middleware.After,
						)
					},
				),
			}
		},
	)
	if err != nil {
		log.Fatalf("failed to get presign request, %v", err)
	}

	log.Println("Presigned request")
	log.Println("HTTP Method:", p.Method)
	log.Println("Signed Headers", p.SignedHeader)
	log.Println("URL", p.URL)

	// Add additional headers to the `http.Request` created from the p.URL, p.Method, p.SignedHeader
	req, err := http.NewRequest(p.Method, p.URL, nil)
	if err != nil {
		log.Fatalf("failed to create request, %v", err)
	}
	for k, vs := range p.SignedHeader {
		for _, v := range vs {
			req.Header.Add(k, v)
		}
	}
	// TODO Add custom headers that should not be signed to request.

	var httpClient http.Client
	resp, err := httpClient.Do(req)
	if err != nil {
		log.Fatalf("failed to send presigned request, %v", err)
	}
	log.Println(resp.StatusCode)
}

@jasdel jasdel added guidance Question that needs advice or information. response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed bug This issue is a bug. labels Mar 3, 2021
@RafPe
Copy link
Author

RafPe commented Mar 3, 2021

I can confirm that the info provided enabled me to successfully make presigned requests :) Thanks a lot!

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Mar 4, 2021
@jasdel
Copy link
Contributor

jasdel commented Mar 4, 2021

Thanks for the update let us know if you run into any additional issues or have feedback!

@jasdel jasdel added the closing-soon This issue will automatically close in 4 days unless further comments are made. label Mar 4, 2021
@github-actions github-actions bot added closed-for-staleness and removed closing-soon This issue will automatically close in 4 days unless further comments are made. labels Mar 9, 2021
@github-actions github-actions bot closed this as completed Mar 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-for-staleness guidance Question that needs advice or information.
Projects
None yet
Development

No branches or pull requests

3 participants