From 4515a7ae88dcc36feab51a00cc54ca703bfee4c7 Mon Sep 17 00:00:00 2001
From: Denis Kirillov <d.kirillov@yadro.com>
Date: Wed, 4 Dec 2024 16:10:28 +0300
Subject: [PATCH] [#339] Don't explicitly use smithy-go

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
---
 api/auth/center_test.go                       |  4 +-
 api/auth/presign.go                           | 23 ++----------
 api/auth/presign_test.go                      |  4 +-
 .../encoding/httpbinding/path_replace.go      | 37 +++++++++++++++++++
 api/auth/signer/v4asdk2/v4a.go                | 18 +++++----
 api/auth/signer/v4asdk2/v4a_test.go           | 14 ++-----
 api/auth/signer/v4sdk2/signer/v4/v4.go        | 16 +++++---
 go.mod                                        |  2 +-
 8 files changed, 68 insertions(+), 50 deletions(-)
 create mode 100644 api/auth/signer/smithy/encoding/httpbinding/path_replace.go

diff --git a/api/auth/center_test.go b/api/auth/center_test.go
index 23e7d1c8..807bdd17 100644
--- a/api/auth/center_test.go
+++ b/api/auth/center_test.go
@@ -8,7 +8,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
-	"os"
 	"strings"
 	"testing"
 	"time"
@@ -27,7 +26,6 @@ import (
 	oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
 	"github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/credentials"
-	"github.com/aws/smithy-go/logging"
 	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/stretchr/testify/require"
 	"go.uber.org/zap/zaptest"
@@ -101,7 +99,7 @@ func TestSignatureV4A(t *testing.T) {
 
 	signer := v4a.NewSigner(func(options *v4a.SignerOptions) {
 		options.DisableURIPathEscaping = true
-		options.Logger = logging.NewStandardLogger(os.Stdout)
+		options.Logger = zaptest.NewLogger(t)
 		options.LogSigning = true
 	})
 
diff --git a/api/auth/presign.go b/api/auth/presign.go
index fa712558..f24b02f1 100644
--- a/api/auth/presign.go
+++ b/api/auth/presign.go
@@ -9,12 +9,11 @@ import (
 	"strings"
 	"time"
 
+	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/smithy/encoding/httpbinding"
 	v4a "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4asdk2"
 	v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4sdk2/signer/v4"
 	"github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/credentials"
-	"github.com/aws/smithy-go/encoding/httpbinding"
-	"github.com/aws/smithy-go/logging"
 	"go.uber.org/zap"
 )
 
@@ -50,7 +49,7 @@ func PresignRequest(ctx context.Context, creds aws.Credentials, reqData RequestD
 	signer := v4.NewSigner(func(options *v4.SignerOptions) {
 		options.DisableURIPathEscaping = true
 		options.LogSigning = true
-		options.Logger = &logWrapper{log: log}
+		options.Logger = log
 	})
 
 	signedURI, _, err := signer.PresignHTTP(ctx, creds, req, presignData.Headers[AmzContentSHA256], presignData.Service, presignData.Region, presignData.SignTime)
@@ -83,7 +82,7 @@ func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData Pr
 	signer := v4a.NewSigner(func(options *v4a.SignerOptions) {
 		options.DisableURIPathEscaping = true
 		options.LogSigning = true
-		options.Logger = &logWrapper{log: log}
+		options.Logger = log
 	})
 
 	credAdapter := v4a.SymmetricCredentialAdaptor{
@@ -101,19 +100,3 @@ func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData Pr
 
 	return http.NewRequest(reqData.Method, presignedURL, nil)
 }
-
-type logWrapper struct {
-	log *zap.Logger
-}
-
-func (l *logWrapper) Logf(classification logging.Classification, format string, args ...interface{}) {
-	msg := fmt.Sprintf(format, args...)
-	switch classification {
-	case logging.Warn:
-		l.log.Warn(msg)
-	case logging.Debug:
-		l.log.Debug(msg)
-	default:
-		l.log.Info(msg)
-	}
-}
diff --git a/api/auth/presign_test.go b/api/auth/presign_test.go
index bc2bf34c..7b70dbf4 100644
--- a/api/auth/presign_test.go
+++ b/api/auth/presign_test.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"fmt"
 	"net/http"
-	"os"
 	"strings"
 	"testing"
 	"time"
@@ -18,7 +17,6 @@ import (
 	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
 	"github.com/aws/aws-sdk-go-v2/aws"
 	credentialsv2 "github.com/aws/aws-sdk-go-v2/credentials"
-	"github.com/aws/smithy-go/logging"
 	"github.com/stretchr/testify/require"
 	"go.uber.org/zap/zaptest"
 )
@@ -167,7 +165,7 @@ func TestPresignRequestV4a(t *testing.T) {
 	signer := v4a.NewSigner(func(options *v4a.SignerOptions) {
 		options.DisableURIPathEscaping = true
 		options.LogSigning = true
-		options.Logger = logging.NewStandardLogger(os.Stdout)
+		options.Logger = zaptest.NewLogger(t)
 	})
 
 	credAdapter := v4a.SymmetricCredentialAdaptor{
diff --git a/api/auth/signer/smithy/encoding/httpbinding/path_replace.go b/api/auth/signer/smithy/encoding/httpbinding/path_replace.go
new file mode 100644
index 00000000..2da24eea
--- /dev/null
+++ b/api/auth/signer/smithy/encoding/httpbinding/path_replace.go
@@ -0,0 +1,37 @@
+// This file is part of https://github.com/aws/smithy-go/blob/f0c6adfdec6e40bb8bb2920a40d016943b4ad762/encoding/httpbinding/path_replace.go
+
+package httpbinding
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// EscapePath escapes part of a URL path in Amazon style.
+func EscapePath(path string, encodeSep bool) string {
+	var buf bytes.Buffer
+	for i := 0; i < len(path); i++ {
+		c := path[i]
+		if noEscape[c] || (c == '/' && !encodeSep) {
+			buf.WriteByte(c)
+		} else {
+			fmt.Fprintf(&buf, "%%%02X", c)
+		}
+	}
+	return buf.String()
+}
+
+var noEscape [256]bool
+
+func init() {
+	for i := 0; i < len(noEscape); i++ {
+		// AWS expects every character except these to be escaped
+		noEscape[i] = (i >= 'A' && i <= 'Z') ||
+			(i >= 'a' && i <= 'z') ||
+			(i >= '0' && i <= '9') ||
+			i == '-' ||
+			i == '.' ||
+			i == '_' ||
+			i == '~'
+	}
+}
diff --git a/api/auth/signer/v4asdk2/v4a.go b/api/auth/signer/v4asdk2/v4a.go
index 5eaf72db..15b29f00 100644
--- a/api/auth/signer/v4asdk2/v4a.go
+++ b/api/auth/signer/v4asdk2/v4a.go
@@ -3,6 +3,8 @@
 //   * adding exported VerifySignature methods
 //   * using different ignore headers for sing/presign requests
 //   * don't duplicate content-length as signed header
+//   * use copy of smithy-go encoding/httpbinding package
+//   * use zap.Logger instead of smithy-go/logging
 
 package v4a
 
@@ -25,10 +27,10 @@ import (
 	"strings"
 	"time"
 
+	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/smithy/encoding/httpbinding"
 	signerCrypto "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4asdk2/internal/crypto"
 	v4Internal "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4asdk2/internal/v4"
-	"github.com/aws/smithy-go/encoding/httpbinding"
-	"github.com/aws/smithy-go/logging"
+	"go.uber.org/zap"
 )
 
 const (
@@ -70,7 +72,7 @@ func init() {
 
 // SignerOptions is the SigV4a signing options for constructing a Signer.
 type SignerOptions struct {
-	Logger     logging.Logger
+	Logger     *zap.Logger
 	LogSigning bool
 
 	// Disables the Signer's moving HTTP header key/value pairs from the HTTP
@@ -164,7 +166,7 @@ type httpSigner struct {
 	Credentials Credentials
 	IsPreSign   bool
 
-	Logger logging.Logger
+	Logger *zap.Logger
 	Debug  bool
 
 	// PayloadHash is the hex encoded SHA-256 hash of the request payload
@@ -193,6 +195,7 @@ func (s *Signer) SignHTTP(ctx context.Context, credentials Credentials, r *http.
 		Time:                   signingTime.UTC(),
 		DisableHeaderHoisting:  options.DisableHeaderHoisting,
 		DisableURIPathEscaping: options.DisableURIPathEscaping,
+		Logger:                 options.Logger,
 	}
 
 	signedRequest, err := signer.Build()
@@ -566,7 +569,7 @@ const logSignedURLMsg = `
 ---[ SIGNED URL ]------------------------------------
 %s`
 
-func logHTTPSigningInfo(ctx context.Context, options SignerOptions, r signedRequest) {
+func logHTTPSigningInfo(_ context.Context, options SignerOptions, r signedRequest) {
 	if !options.LogSigning {
 		return
 	}
@@ -574,8 +577,9 @@ func logHTTPSigningInfo(ctx context.Context, options SignerOptions, r signedRequ
 	if r.PreSigned {
 		signedURLMsg = fmt.Sprintf(logSignedURLMsg, r.Request.URL.String())
 	}
-	logger := logging.WithContext(ctx, options.Logger)
-	logger.Logf(logging.Debug, logSignInfoMsg, r.CanonicalString, r.StringToSign, signedURLMsg)
+	if options.Logger != nil {
+		options.Logger.Debug(fmt.Sprintf(logSignInfoMsg, r.CanonicalString, r.StringToSign, signedURLMsg))
+	}
 }
 
 type signedRequest struct {
diff --git a/api/auth/signer/v4asdk2/v4a_test.go b/api/auth/signer/v4asdk2/v4a_test.go
index 40c68830..dfcc735c 100644
--- a/api/auth/signer/v4asdk2/v4a_test.go
+++ b/api/auth/signer/v4asdk2/v4a_test.go
@@ -1,4 +1,6 @@
 // This file is https://github.com/aws/aws-sdk-go-v2/blob/a2b751d1ba71f59175a41f9cae5f159f1044360f/internal/v4a/v4a_test.go
+// with changes:
+//   * use zap.Logger instead of smithy-go/logging
 
 package v4a
 
@@ -17,7 +19,7 @@ import (
 
 	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4asdk2/internal/crypto"
 	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/smithy-go/logging"
+	"go.uber.org/zap/zaptest"
 )
 
 const (
@@ -388,9 +390,7 @@ func buildSigner(t *testing.T, withToken bool) (*Signer, CredentialsProvider) {
 	}
 
 	return NewSigner(func(options *SignerOptions) {
-			options.Logger = loggerFunc(func(format string, v ...interface{}) {
-				t.Logf(format, v...)
-			})
+			options.Logger = zaptest.NewLogger(t)
 		}), &SymmetricCredentialAdaptor{
 			SymmetricProvider: staticCredentialsProvider{
 				Value: creds,
@@ -398,12 +398,6 @@ func buildSigner(t *testing.T, withToken bool) (*Signer, CredentialsProvider) {
 		}
 }
 
-type loggerFunc func(format string, v ...interface{})
-
-func (l loggerFunc) Logf(_ logging.Classification, format string, v ...interface{}) {
-	l(format, v...)
-}
-
 type staticCredentialsProvider struct {
 	Value aws.Credentials
 }
diff --git a/api/auth/signer/v4sdk2/signer/v4/v4.go b/api/auth/signer/v4sdk2/signer/v4/v4.go
index afcd4641..5ea9a185 100644
--- a/api/auth/signer/v4sdk2/signer/v4/v4.go
+++ b/api/auth/signer/v4sdk2/signer/v4/v4.go
@@ -1,6 +1,8 @@
 // This is https://github.com/aws/aws-sdk-go-v2/blob/a2b751d1ba71f59175a41f9cae5f159f1044360f/aws/signer/v4/v4.go
 // with changes:
 //   * using different headers for sign/presign
+//   * use copy of smithy-go encoding/httpbinding package
+//   * use zap.Logger instead of smithy-go/logging
 
 // Package v4 implements the AWS signature version 4 algorithm (commonly known
 // as SigV4).
@@ -56,10 +58,10 @@ import (
 	"strings"
 	"time"
 
+	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/smithy/encoding/httpbinding"
 	v4Internal "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4sdk2/signer/internal/v4"
 	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/smithy-go/encoding/httpbinding"
-	"github.com/aws/smithy-go/logging"
+	"go.uber.org/zap"
 )
 
 const (
@@ -97,7 +99,7 @@ type SignerOptions struct {
 	DisableURIPathEscaping bool
 
 	// The logger to send log messages to.
-	Logger logging.Logger
+	Logger *zap.Logger
 
 	// Enable logging of signed requests.
 	// This will enable logging of the canonical request, the string to sign, and for presigning the subsequent
@@ -547,7 +549,7 @@ func (s *httpSigner) setRequiredSigningFields(headers http.Header, query url.Val
 	}
 }
 
-func logSigningInfo(ctx context.Context, options SignerOptions, request *signedRequest, isPresign bool) {
+func logSigningInfo(_ context.Context, options SignerOptions, request *signedRequest, isPresign bool) {
 	if !options.LogSigning {
 		return
 	}
@@ -555,8 +557,10 @@ func logSigningInfo(ctx context.Context, options SignerOptions, request *signedR
 	if isPresign {
 		signedURLMsg = fmt.Sprintf(logSignedURLMsg, request.Request.URL.String())
 	}
-	logger := logging.WithContext(ctx, options.Logger)
-	logger.Logf(logging.Debug, logSignInfoMsg, request.CanonicalString, request.StringToSign, signedURLMsg)
+
+	if options.Logger != nil {
+		options.Logger.Debug(fmt.Sprintf(logSignInfoMsg, request.CanonicalString, request.StringToSign, signedURLMsg))
+	}
 }
 
 type signedRequest struct {
diff --git a/go.mod b/go.mod
index 68ff6c34..d654eb39 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,6 @@ require (
 	github.com/aws/aws-sdk-go-v2 v1.30.5
 	github.com/aws/aws-sdk-go-v2/config v1.27.32
 	github.com/aws/aws-sdk-go-v2/credentials v1.17.31
-	github.com/aws/smithy-go v1.20.4
 	github.com/bluele/gcache v0.0.2
 	github.com/go-chi/chi/v5 v5.0.8
 	github.com/google/uuid v1.6.0
@@ -58,6 +57,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/sso v1.22.6 // indirect
 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.6 // indirect
 	github.com/aws/aws-sdk-go-v2/service/sts v1.30.6 // indirect
+	github.com/aws/smithy-go v1.20.4 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect