package auth import ( "fmt" "net/http" "strings" "time" v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/private/protocol/rest" ) type RequestData struct { Method string Endpoint string Bucket string Object string } type PresignData struct { Service string Region string Lifetime time.Duration SignTime time.Time Headers map[string]string } // PresignRequest forms pre-signed request to access objects without aws credentials. func PresignRequest(creds *credentials.Credentials, reqData RequestData, presignData PresignData) (*http.Request, error) { urlStr := fmt.Sprintf("%s/%s/%s", reqData.Endpoint, rest.EscapePath(reqData.Bucket, false), rest.EscapePath(reqData.Object, false)) req, err := http.NewRequest(strings.ToUpper(reqData.Method), urlStr, nil) if err != nil { return nil, fmt.Errorf("failed to create new request: %w", err) } req.Header.Set(AmzDate, presignData.SignTime.Format("20060102T150405Z")) for k, v := range presignData.Headers { req.Header.Set(k, v) } signer := v4.NewSigner(creds) signer.DisableURIPathEscaping = true if _, err = signer.Presign(req, nil, presignData.Service, presignData.Region, presignData.Lifetime, presignData.SignTime); err != nil { return nil, fmt.Errorf("presign: %w", err) } return req, nil }