From 20afe41bee7ca2f7cda5dd0cb498fd21385b00d4 Mon Sep 17 00:00:00 2001 From: Patrick East Date: Wed, 22 Jul 2020 14:43:10 -0700 Subject: [PATCH] plugins/rest/aws: Include port in Host header The AWS v4 signing feature for bundle requests would automatically add a `Host` header by using the URL hostname. This would break for URLs that specified a port number (eg: https://127.0.0.1:9000/). That causes issues with sending a valid request. This commit changes to use the `URL.Host` which will have the full `host:port` string, when a port was specified. Fixes: #2568 Signed-off-by: Patrick East --- plugins/rest/aws.go | 6 +++--- plugins/rest/aws_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/plugins/rest/aws.go b/plugins/rest/aws.go index b294074cad..d0291b64f1 100644 --- a/plugins/rest/aws.go +++ b/plugins/rest/aws.go @@ -286,11 +286,11 @@ func signV4(req *http.Request, credService awsCredentialService, theTime time.Ti dateNow := now.Format("20060102") iso8601Now := now.Format("20060102T150405Z") - // certain mandatory headers for V4 signing awsHeaders := map[string]string{ - "host": req.URL.Hostname(), + "host": req.URL.Host, "x-amz-content-sha256": bodyHexHash, - "x-amz-date": iso8601Now} + "x-amz-date": iso8601Now, + } // the security token header is necessary for ephemeral credentials, e.g. from // the EC2 metadata service diff --git a/plugins/rest/aws_test.go b/plugins/rest/aws_test.go index b8f8743d55..5066e6a4ac 100644 --- a/plugins/rest/aws_test.go +++ b/plugins/rest/aws_test.go @@ -282,6 +282,41 @@ func TestV4Signing(t *testing.T) { assertEq(req.Header.Get("X-Amz-Security-Token"), "MYAWSSECURITYTOKENGOESHERE", t) } +func TestV4SigningCustomPort(t *testing.T) { + ts := credTestServer{} + ts.start() + defer ts.stop() + + cs := &awsMetadataCredentialService{ + RoleName: "my_iam_role", // not present + RegionName: "us-east-1", + credServicePath: ts.server.URL + "/latest/meta-data/iam/security-credentials/", + tokenPath: ts.server.URL + "/latest/api/token"} + ts.payload = metadataPayload{ + AccessKeyID: "MYAWSACCESSKEYGOESHERE", + SecretAccessKey: "MYAWSSECRETACCESSKEYGOESHERE", + Code: "Success", + Token: "MYAWSSECURITYTOKENGOESHERE", + Expiration: time.Now().UTC().Add(time.Minute * 2)} + req, _ := http.NewRequest("GET", "https://custom.s3.server:9000/bundle.tar.gz", strings.NewReader("")) + err := signV4(req, cs, time.Unix(1556129697, 0)) + + if err != nil { + t.Error("unexpected error during signing") + } + + // expect mandatory headers + assertEq(req.Header.Get("Host"), "custom.s3.server:9000", t) + assertEq(req.Header.Get("Authorization"), + "AWS4-HMAC-SHA256 Credential=MYAWSACCESSKEYGOESHERE/20190424/us-east-1/s3/aws4_request,"+ + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token,"+ + "Signature=765b67c6b136f99d9b769171c9939fc444021f7d17e4fbe6e1ab8b1926713c2b", t) + assertEq(req.Header.Get("X-Amz-Content-Sha256"), + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", t) + assertEq(req.Header.Get("X-Amz-Date"), "20190424T181457Z", t) + assertEq(req.Header.Get("X-Amz-Security-Token"), "MYAWSSECURITYTOKENGOESHERE", t) +} + // simulate EC2 metadata service type credTestServer struct { t *testing.T