[#131] authmate: Add generate-presigned-url cobra cmd

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2023-06-23 16:11:57 +03:00
parent eba85b50b6
commit 3927223bb0
2 changed files with 111 additions and 0 deletions

View file

@ -0,0 +1,108 @@
package modules
import (
"encoding/json"
"fmt"
"os"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var generatePresignedURLCmd = &cobra.Command{
Use: "generate-presigned-url",
Short: "Generate presigned url using AWS credentials",
Long: `Generate presigned url using AWS credentials.Credentials must be placed in ~/.aws/credentials.
You provide profile to load using --profile flag or explicitly provide credentials and region using
--aws-access-key-id, --aws-secret-access-key, --region.
Note to override credentials you must provide both access key and secret key.`,
Example: `frostfs-s3-authmate generate-presigned-url --method put --bucket my-bucket --object my-object --endpoint http://localhost:8084 --lifetime 12h --region ru --aws-access-key-id ETaA2CadPcA7bAkLsML2PbTudXY8uRt2PDjCCwkvRv9s0FDCxWDXYc1SA1vKv8KbyCNsLY2AmAjJ92Vz5rgvsFCy --aws-secret-access-key c2d65ef2980f03f4f495bdebedeeae760496697880d61d106bb9a4e5cd2e0607`,
RunE: runGeneratePresignedURLCmd,
}
const defaultPresignedLifetime = 12 * time.Hour
const (
endpointFlag = "endpoint"
bucketFlag = "bucket"
objectFlag = "object"
methodFlag = "method"
profileFlag = "profile"
regionFlag = "region"
awsAccessKeyIDFlag = "aws-access-key-id"
awsSecretAccessKeyFlag = "aws-secret-access-key"
)
func initGeneratePresignedURLCmd() {
generatePresignedURLCmd.Flags().Duration(lifetimeFlag, defaultPresignedLifetime, "Lifetime of presigned URL. For example 50h30m (note: max time unit is an hour so to set a day you should use 24h).\nIt will be ceil rounded to the nearest amount of epoch.")
generatePresignedURLCmd.Flags().String(endpointFlag, "", "S3 gateway endpoint")
generatePresignedURLCmd.Flags().String(bucketFlag, "", "Bucket name to perform action")
generatePresignedURLCmd.Flags().String(objectFlag, "", "Object name to perform action")
generatePresignedURLCmd.Flags().String(methodFlag, "", "HTTP method to perform action")
generatePresignedURLCmd.Flags().String(profileFlag, "", "AWS profile to load")
generatePresignedURLCmd.Flags().String(regionFlag, "", "AWS region to use in signature (default is taken from ~/.aws/config)")
generatePresignedURLCmd.Flags().String(awsAccessKeyIDFlag, "", "AWS access key id to sign the URL (default is taken from ~/.aws/credentials)")
generatePresignedURLCmd.Flags().String(awsSecretAccessKeyFlag, "", "AWS secret access key to sign the URL (default is taken from ~/.aws/credentials)")
_ = generatePresignedURLCmd.MarkFlagRequired(endpointFlag)
_ = generatePresignedURLCmd.MarkFlagRequired(bucketFlag)
_ = generatePresignedURLCmd.MarkFlagRequired(objectFlag)
}
func runGeneratePresignedURLCmd(*cobra.Command, []string) error {
var cfg aws.Config
if region := viper.GetString(regionFlag); region != "" {
cfg.Region = &region
}
accessKeyID := viper.GetString(awsAccessKeyIDFlag)
secretAccessKey := viper.GetString(awsSecretAccessKeyFlag)
if accessKeyID != "" && secretAccessKey != "" {
cfg.Credentials = credentials.NewStaticCredentialsFromCreds(credentials.Value{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
})
}
sess, err := session.NewSessionWithOptions(session.Options{
Config: cfg,
Profile: viper.GetString(profileFlag),
SharedConfigState: session.SharedConfigEnable,
})
if err != nil {
return fmt.Errorf("couldn't get aws credentials: %w", err)
}
reqData := auth.RequestData{
Method: viper.GetString(methodFlag),
Endpoint: viper.GetString(endpointFlag),
Bucket: viper.GetString(bucketFlag),
Object: viper.GetString(objectFlag),
}
presignData := auth.PresignData{
Service: "s3",
Region: *sess.Config.Region,
Lifetime: viper.GetDuration(lifetimeFlag),
SignTime: time.Now().UTC(),
}
req, err := auth.PresignRequest(sess.Config.Credentials, reqData, presignData)
if err != nil {
return err
}
res := &struct{ URL string }{
URL: req.URL.String(),
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.SetEscapeHTML(false)
return enc.Encode(res)
}

View file

@ -59,4 +59,7 @@ GoVersion: {{ runtimeVersion }}
rootCmd.AddCommand(obtainSecretCmd) rootCmd.AddCommand(obtainSecretCmd)
initObtainSecretCmd() initObtainSecretCmd()
rootCmd.AddCommand(generatePresignedURLCmd)
initGeneratePresignedURLCmd()
} }