Skip to content

Commit

Permalink
Fix tsh aws ecr Internal Server Error (#10475) (#11108)
Browse files Browse the repository at this point in the history
  • Loading branch information
greedy52 authored Mar 15, 2022
1 parent 2aa5741 commit ffbc535
Show file tree
Hide file tree
Showing 5 changed files with 530 additions and 24 deletions.
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/alicebob/miniredis/v2 v2.17.0
github.com/aquasecurity/libbpfgo v0.1.0
github.com/armon/go-radix v1.0.0
github.com/aws/aws-sdk-go v1.37.17
github.com/aws/aws-sdk-go v1.43.15
github.com/aws/aws-sdk-go-v2 v1.9.0
github.com/aws/aws-sdk-go-v2/config v1.8.0
github.com/aws/aws-sdk-go-v2/credentials v1.4.0
Expand Down Expand Up @@ -170,11 +170,10 @@ require (
github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect
github.com/jstemmer/go-junit-report v0.9.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531
github.com/klauspost/compress v1.9.5 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/pretty v0.3.0
github.com/kr/text v0.2.0 // indirect
github.com/mailgun/metrics v0.0.0-20150124003306-2b3c4565aafd // indirect
github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect
Expand Down Expand Up @@ -223,7 +222,7 @@ require (
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
Expand Down Expand Up @@ -253,7 +252,7 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
Expand Down
10 changes: 6 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.37.17 h1:Ga33kM38f58l7X+Z2B6JNdz9dFqxjR8AXHBbK3bXYc0=
github.com/aws/aws-sdk-go v1.37.17/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.43.15 h1:zAOUdqgNgJrkivRZi93NTjPNvuIQ5EcqNHSk0A1jrk8=
github.com/aws/aws-sdk-go v1.43.15/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v1.9.0 h1:+S+dSqQCN3MSU5vJRu1HqHrq00cJn6heIMU7X9hcsoo=
github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/config v1.8.0 h1:O8EMFBOl6tue5gdJJV6U3Ikyl3lqgx6WrulCYrcy2SQ=
Expand Down Expand Up @@ -578,10 +578,12 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4=
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4=
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg=
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d h1:J8tJzRyiddAFF65YVgxli+TyWBi0f79Sld6rJP6CBcY=
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d/go.mod h1:b+Q3v8Yrg5o15d71PSUraUzYb+jWl6wQMSBXSGS/hv0=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
Expand Down
160 changes: 160 additions & 0 deletions lib/srv/app/aws/endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
Copyright 2022 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package aws

import (
"net/http"
"strings"

"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/service/appstream"
"github.com/aws/aws-sdk-go/service/detective"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go/service/ecrpublic"
"github.com/aws/aws-sdk-go/service/elasticinference"
"github.com/aws/aws-sdk-go/service/iot1clickdevicesservice"
"github.com/aws/aws-sdk-go/service/iotdataplane"
"github.com/aws/aws-sdk-go/service/iotdeviceadvisor"
"github.com/aws/aws-sdk-go/service/ioteventsdata"
"github.com/aws/aws-sdk-go/service/iotfleethub"
"github.com/aws/aws-sdk-go/service/iotjobsdataplane"
"github.com/aws/aws-sdk-go/service/iotsecuretunneling"
"github.com/aws/aws-sdk-go/service/iottwinmaker"
"github.com/aws/aws-sdk-go/service/iotwireless"
"github.com/aws/aws-sdk-go/service/lexmodelsv2"
"github.com/aws/aws-sdk-go/service/marketplacecatalog"
"github.com/aws/aws-sdk-go/service/mediatailor"
"github.com/aws/aws-sdk-go/service/memorydb"
"github.com/aws/aws-sdk-go/service/migrationhubstrategyrecommendations"
"github.com/aws/aws-sdk-go/service/mobile"
"github.com/aws/aws-sdk-go/service/pinpoint"
"github.com/aws/aws-sdk-go/service/pinpointsmsvoice"
"github.com/aws/aws-sdk-go/service/pricing"
"github.com/aws/aws-sdk-go/service/proton"
"github.com/aws/aws-sdk-go/service/sagemaker"
"github.com/aws/aws-sdk-go/service/ses"
"github.com/aws/aws-sdk-go/service/sso"
"github.com/aws/aws-sdk-go/service/ssooidc"
"github.com/aws/aws-sdk-go/service/timestreamquery"

awsutils "github.com/gravitational/teleport/lib/utils/aws"

"github.com/gravitational/trace"
)

// resolveEndpoint extracts the aws-service on and aws-region from the request
// authorization header and resolves the aws-service and aws-region to AWS
// endpoint.
func resolveEndpoint(r *http.Request) (*endpoints.ResolvedEndpoint, error) {
awsAuthHeader, err := awsutils.ParseSigV4(r.Header.Get(awsutils.AuthorizationHeader))
if err != nil {
return nil, trace.Wrap(err)
}

// aws-sdk-go maintains a mapping of service endpoints which can be looked
// up by calling `endpoints.DefaultResolver().EndpointFor`. This mapping
// can be found at:
// https://github.com/aws/aws-sdk-go/blob/main/aws/endpoints/defaults.go
//
// The json equivalent can be found in botocore source code at:
// https://github.com/boto/botocore/blob/develop/botocore/data/endpoints.json
//
// The keys used for lookups are endpoints IDs, which can be different from
// the signing names. We have to translate the signing name received from
// the header back to the endpoints ID.
//
// In addition, many services are NOT found in aws-sdk-go's endpoints
// mapping. How aws-sdk-go resolves endpoints for these services is to
// allow ResolveUnknownService when creating the client sessions, which in
// turn generates the endpoint by using the endpoints ID and some default
// suffixes. We allow ResolveUnknownService here for the same purpose.
endpointsID := endpointsIDFromSigningName(awsAuthHeader.Service)
opts := func(opts *endpoints.Options) {
opts.ResolveUnknownService = true
}

resolvedEndpoint, err := endpoints.DefaultResolver().EndpointFor(endpointsID, awsAuthHeader.Region, opts)
if err != nil {
return nil, trace.Wrap(err)
}

// SigningName can be derived from the endpoint ID which may not be the
// correct signing name. Set it back to what is received from the header.
resolvedEndpoint.SigningName = awsAuthHeader.Service
return &resolvedEndpoint, nil
}

// endpointsIDFromSigningName returns the endpoints ID used for endpoint
// lookups when calling endpoints.DefaultResolver().EndpointFor.
func endpointsIDFromSigningName(signingName string) string {
// Some clients may sign some services with upper case letters. We use all
// lower cases in our mapping.
signingName = strings.ToLower(signingName)

if endpointsID, ok := signingNameToEndpointsID[signingName]; ok {
return endpointsID
}

// If not found in the mapping, endpoints ID is expected to be the same as
// the signing name.
return signingName
}

// signingNameToEndpointsID is a map of AWS services' signing names to their
// endpoints IDs.
//
// This mapping was created by the following process:
// 1. Compiled a mapping of all signing names to their hostnames (e.g. grep/awk
// keywords in "aws-sdk-go-v2/services/")
// 2. Created unit test "TestResolveEndpoints" to test each signing name.
// 3. Investigated the test failures, and updated this mapping to fix them.
//
// TODO Many services may sign with same names but use different hostnames.
// Will need a way to differentiate them. For now, either make the best guess
// in this mapping or use the default signing names. See signingNameToHostname
// in endpoints_test.go for conflicting services.
var signingNameToEndpointsID = map[string]string{
"appstream": appstream.EndpointsID,
"aws-marketplace": marketplacecatalog.EndpointsID,
"awsiottwinmaker": iottwinmaker.EndpointsID,
"awsmigrationhubstrategyrecommendation": migrationhubstrategyrecommendations.EndpointsID,
"awsmobilehubservice": mobile.EndpointsID,
"awsproton20200720": proton.EndpointsID,
"awsssooidc": ssooidc.EndpointsID,
"awsssoportal": sso.EndpointsID,
"detective": detective.EndpointsID,
"ecr": ecr.EndpointsID,
"ecr-public": ecrpublic.EndpointsID,
"elastic-inference": elasticinference.EndpointsID,
"iot-jobs-data": iotjobsdataplane.EndpointsID,
"iot1click": iot1clickdevicesservice.EndpointsID,
"iotdata": iotdataplane.EndpointsID,
"iotdeviceadvisor": iotdeviceadvisor.EndpointsID,
"ioteventsdata": ioteventsdata.EndpointsID,
"iotfleethub": iotfleethub.EndpointsID,
"iotsecuredtunneling": iotsecuretunneling.EndpointsID,
"iotwireless": iotwireless.EndpointsID,
"lex": lexmodelsv2.EndpointsID,
"mediatailor": mediatailor.EndpointsID,
"memorydb": memorydb.EndpointsID,
"mobiletargeting": pinpoint.EndpointsID,
"pricing": pricing.EndpointsID,
"sagemaker": sagemaker.EndpointsID,
"ses": ses.EndpointsID,
"sms-voice": pinpointsmsvoice.EndpointsID,
"timestream": timestreamquery.EndpointsID,
}
Loading

0 comments on commit ffbc535

Please sign in to comment.