forked from TrueCloudLab/frostfs-s3-gw
[#339] Fix logging in authmate [pre]sign command
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
58b193c8d9
commit
09ffe7287a
6 changed files with 54 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue