diff --git a/aws-es-proxy.go b/aws-es-proxy.go index ae5651cc..bab082eb 100644 --- a/aws-es-proxy.go +++ b/aws-es-proxy.go @@ -2,7 +2,9 @@ package main import ( "bytes" + "crypto/sha256" "crypto/subtle" + "encoding/hex" "encoding/json" "flag" "fmt" @@ -31,6 +33,8 @@ import ( "golang.org/x/net/publicsuffix" ) +const emptyBodySHA256 = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" + func logger(debug bool) { formatFilePath := func(path string) string { @@ -285,8 +289,25 @@ func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Start AWS session from ENV, Shared Creds or EC2Role signer := p.getSigner() + contentSha256Hash := emptyBodySHA256 + body := replaceBody(req) + + if len(body) > 0 { + hash, err := hexEncodedSha256(body) + if err != nil { + logrus.WithError(err).Errorln("failed to calculate hash of request body: %w", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + contentSha256Hash = hash + } + + // Add the "X-Amz-Content-Sha256" header as required by Amazon OpenSearch Serverless. + req.Header.Set("X-Amz-Content-Sha256", contentSha256Hash) + // Sign the request with AWSv4 - payload := bytes.NewReader(replaceBody(req)) + payload := bytes.NewReader(body) _, err := signer.Sign(req, payload, p.service, p.region, time.Now()) if err != nil { p.credentials = nil @@ -443,6 +464,15 @@ func addHeaders(src, dest http.Header) { } } +func hexEncodedSha256(b []byte) (string, error) { + hasher := sha256.New() + if _, err := hasher.Write(b); err != nil { + return "", fmt.Errorf("failed to write: %w", err) + } + digest := hasher.Sum(nil) + return hex.EncodeToString(digest), nil +} + // Signer.Sign requires a "seekable" body to sum body's sha256 func replaceBody(req *http.Request) []byte { if req.Body == nil { diff --git a/go.mod b/go.mod index 78cb65e5..de9e9dc7 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/abutaha/aws-es-proxy go 1.20 require ( - github.com/aws/aws-sdk-go v1.44.215 + github.com/aws/aws-sdk-go v1.47.4 github.com/sirupsen/logrus v1.9.0 go.mongodb.org/mongo-driver v1.11.2 - golang.org/x/net v0.8.0 + golang.org/x/net v0.17.0 ) require ( github.com/jmespath/go-jmespath v0.4.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/sys v0.13.0 // indirect ) diff --git a/go.sum b/go.sum index e57e12d5..e6204f92 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/aws/aws-sdk-go v1.44.215 h1:K3KERfO6MaV349idub2w1u1H0R0KSkED0LshPnaAn3Q= github.com/aws/aws-sdk-go v1.44.215/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.47.4 h1:IyhNbmPt+5ldi5HNzv7ZnXiqSglDMaJiZlzj4Yq3qnk= +github.com/aws/aws-sdk-go v1.47.4/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -43,6 +45,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -56,6 +60,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=