[#339] Fix logging in authmate [pre]sign command

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2024-11-27 11:31:53 +03:00
parent 58b193c8d9
commit 09ffe7287a
6 changed files with 54 additions and 31 deletions

View file

@ -142,10 +142,6 @@ func (c *Center) parseAuthHeader(authHeader string, headers http.Header) (*AuthH
default:
return nil, fmt.Errorf("%w: %s", apierr.GetAPIError(apierr.ErrAuthorizationHeaderMalformed), authHeader)
}
// AWS4-ECDSA-P256-SHA256
// Credential=2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf/20240326/s3/aws4_request,
// SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;host;x-amz-content-sha256;x-amz-date;x-amz-region-set,
// Signature=3044022006a2bc760140834101d0a79667d6aa75768c1a28e9cafc8963484d0752a6c6050220629dc06d7d6505e1b1e2a5d1f974b25ba32fdffc6f3f70dc4dda31b8a6f7ea2b
return &AuthHeader{
AccessKeyID: submatches["access_key_id"],
@ -487,20 +483,19 @@ func SignStr(secret, service, region string, t time.Time, strToSign string) stri
return hex.EncodeToString(signature)
}
func SignStrV4A(cred aws.Credentials, strToSign string) (string, error) {
hash := sha256.New()
hash.Write([]byte(strToSign))
func SignStrV4A(ctx context.Context, cred aws.Credentials, strToSign string) (string, error) {
credAdapter := v4a.SymmetricCredentialAdaptor{
SymmetricProvider: credentials.NewStaticCredentialsProvider(cred.AccessKeyID, cred.SecretAccessKey, ""),
}
creds, err := credAdapter.RetrievePrivateKey(context.Background()) // because of using StaticCredentialsProvider
creds, err := credAdapter.RetrievePrivateKey(ctx)
if err != nil {
// no error is expected
panic(err)
return "", err
}
hash := sha256.New()
hash.Write([]byte(strToSign))
sig, err := creds.PrivateKey.Sign(rand.Reader, hash.Sum(nil), crypto.SHA256)
if err != nil {
return "", err

View file

@ -13,6 +13,7 @@ import (
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/aws/aws-sdk-go-v2/aws"
utils "github.com/trailofbits/go-fuzz-utils"
"go.uber.org/zap"
)
const (
@ -60,7 +61,7 @@ func DoFuzzAuthenticate(input []byte) int {
SignTime: time.Now().UTC(),
}
req, err := PresignRequest(context.Background(), awsCreds, reqData, presignData)
req, err := PresignRequest(context.Background(), awsCreds, reqData, presignData, zap.NewNop())
if req == nil {
return fuzzFailExitCode
}

View file

@ -5,7 +5,6 @@ import (
"fmt"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
@ -16,6 +15,7 @@ import (
"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"
)
type RequestData struct {
@ -34,7 +34,7 @@ type PresignData struct {
}
// PresignRequest forms pre-signed request to access objects without aws credentials.
func PresignRequest(ctx context.Context, creds aws.Credentials, reqData RequestData, presignData PresignData) (*http.Request, error) {
func PresignRequest(ctx context.Context, creds aws.Credentials, reqData RequestData, presignData PresignData, log *zap.Logger) (*http.Request, error) {
urlStr := fmt.Sprintf("%s/%s/%s", reqData.Endpoint, httpbinding.EscapePath(reqData.Bucket, false), httpbinding.EscapePath(reqData.Object, false))
req, err := http.NewRequest(strings.ToUpper(reqData.Method), urlStr, nil)
if err != nil {
@ -49,6 +49,8 @@ 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}
})
signedURI, _, err := signer.PresignHTTP(ctx, creds, req, presignData.Headers[AmzContentSHA256], presignData.Service, presignData.Region, presignData.SignTime)
@ -64,7 +66,7 @@ func PresignRequest(ctx context.Context, creds aws.Credentials, reqData RequestD
}
// PresignRequestV4a forms pre-signed request to access objects without aws credentials.
func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData PresignData) (*http.Request, error) {
func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData PresignData, log *zap.Logger) (*http.Request, error) {
urlStr := fmt.Sprintf("%s/%s/%s", reqData.Endpoint, httpbinding.EscapePath(reqData.Bucket, false), httpbinding.EscapePath(reqData.Object, false))
req, err := http.NewRequest(strings.ToUpper(reqData.Method), urlStr, nil)
if err != nil {
@ -76,12 +78,12 @@ func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData Pr
}
req.Header.Set(AmzDate, presignData.SignTime.Format("20060102T150405Z"))
req.Header.Set(AmzExpires, strconv.Itoa(int(presignData.Lifetime.Seconds())))
req.Header.Set(AmzExpires, strconv.FormatFloat(presignData.Lifetime.Round(time.Second).Seconds(), 'f', 0, 64))
signer := v4a.NewSigner(func(options *v4a.SignerOptions) {
options.DisableURIPathEscaping = true
options.LogSigning = true
options.Logger = logging.NewStandardLogger(os.Stdout)
options.Logger = &logWrapper{log: log}
})
credAdapter := v4a.SymmetricCredentialAdaptor{
@ -97,7 +99,21 @@ func PresignRequestV4a(cred aws.Credentials, reqData RequestData, presignData Pr
return nil, fmt.Errorf("presign: %w", err)
}
fmt.Println(presignedURL)
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)
}
}

View file

@ -20,6 +20,7 @@ import (
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"
)
var _ tokens.Credentials = (*credentialsMock)(nil)
@ -83,7 +84,7 @@ func TestCheckSign(t *testing.T) {
},
}
req, err := PresignRequest(ctx, awsCreds, reqData, presignData)
req, err := PresignRequest(ctx, awsCreds, reqData, presignData, zaptest.NewLogger(t))
require.NoError(t, err)
expBox := &accessbox.Box{
@ -131,7 +132,7 @@ func TestCheckSignV4a(t *testing.T) {
},
}
req, err := PresignRequestV4a(awsCreds, reqData, presignData)
req, err := PresignRequestV4a(awsCreds, reqData, presignData, zaptest.NewLogger(t))
require.NoError(t, err)
req.Header.Set(ContentTypeHdr, "text/plain")

View file

@ -1,6 +1,7 @@
package modules
import (
"context"
"encoding/json"
"fmt"
"net/http"
@ -60,6 +61,11 @@ func initGeneratePresignedURLCmd() {
}
func runGeneratePresignedURLCmd(cmd *cobra.Command, _ []string) error {
ctx, cancel := context.WithTimeout(cmd.Context(), viper.GetDuration(timeoutFlag))
defer cancel()
log := getLogger()
var (
region string
creds aws.Credentials
@ -68,16 +74,16 @@ func runGeneratePresignedURLCmd(cmd *cobra.Command, _ []string) error {
profile := viper.GetString(profileFlag)
if profile == "" {
cfg, err := config.LoadDefaultConfig(cmd.Context())
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return wrapPreparationError(err)
}
region = cfg.Region
if creds, err = cfg.Credentials.Retrieve(cmd.Context()); err != nil {
if creds, err = cfg.Credentials.Retrieve(ctx); err != nil {
return wrapPreparationError(fmt.Errorf("couldn't get default aws credentials: %w", err))
}
} else {
cfg, err := config.LoadSharedConfigProfile(cmd.Context(), viper.GetString(profileFlag))
cfg, err := config.LoadSharedConfigProfile(ctx, viper.GetString(profileFlag))
if err != nil {
return wrapPreparationError(fmt.Errorf("couldn't get '%s' aws credentials: %w", viper.GetString(profileFlag), err))
}
@ -117,9 +123,9 @@ func runGeneratePresignedURLCmd(cmd *cobra.Command, _ []string) error {
var req *http.Request
if viper.GetBool(sigV4AFlag) {
req, err = auth.PresignRequestV4a(creds, reqData, presignData)
req, err = auth.PresignRequestV4a(creds, reqData, presignData, log)
} else {
req, err = auth.PresignRequest(cmd.Context(), creds, reqData, presignData)
req, err = auth.PresignRequest(ctx, creds, reqData, presignData, log)
}
if err != nil {
return wrapBusinessLogicError(err)

View file

@ -1,6 +1,7 @@
package modules
import (
"context"
"errors"
"fmt"
"os"
@ -49,22 +50,25 @@ func initSignCmd() {
}
func runSignCmd(cmd *cobra.Command, _ []string) error {
ctx, cancel := context.WithTimeout(cmd.Context(), viper.GetDuration(timeoutFlag))
defer cancel()
var (
region string
creds aws.Credentials
)
if profile := viper.GetString(profileFlag); profile == "" {
cfg, err := config.LoadDefaultConfig(cmd.Context())
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return wrapPreparationError(err)
}
region = cfg.Region
if creds, err = cfg.Credentials.Retrieve(cmd.Context()); err != nil {
if creds, err = cfg.Credentials.Retrieve(ctx); err != nil {
return wrapPreparationError(fmt.Errorf("couldn't get default aws credentials: %w", err))
}
} else {
cfg, err := config.LoadSharedConfigProfile(cmd.Context(), profile)
cfg, err := config.LoadSharedConfigProfile(ctx, profile)
if err != nil {
return wrapPreparationError(fmt.Errorf("couldn't get '%s' aws credentials: %w", profile, err))
}
@ -106,8 +110,8 @@ func runSignCmd(cmd *cobra.Command, _ []string) error {
sigv4a := viper.GetBool(sigV4AFlag)
if sigv4a {
var err error
if signature, err = auth.SignStrV4A(creds, data); err != nil {
return wrapPreparationError(fmt.Errorf("sign v4a: %w", err))
if signature, err = auth.SignStrV4A(ctx, creds, data); err != nil {
return wrapPreparationError(fmt.Errorf("sign str v4a: %w", err))
}
} else {
signature = auth.SignStr(creds.SecretAccessKey, service, region, signTime, data)