From dc589a6e63233ccf5c78acc00d4c034ce5943f74 Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Wed, 15 Jan 2025 22:25:32 +0000 Subject: [PATCH] Add support for AWS shared credentials file Also adds a CLI flag and fields for session token, which must be passed alongside the access key and secret when using temporary credentials. Signed-off-by: Brad Davidson --- go.mod | 8 ++++---- go.sum | 14 +++++++------- pkg/cli/cmds/etcd_snapshot.go | 6 ++++++ pkg/cli/cmds/server.go | 7 +++++++ pkg/cli/server/server.go | 1 + pkg/daemons/config/types.go | 1 + pkg/etcd/s3/config_secret.go | 17 +++++++++-------- pkg/etcd/s3/s3.go | 23 +++++++++++++++-------- pkg/etcd/snapshot/types.go | 1 + 9 files changed, 51 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 027aa917b461..49037dc5c0d6 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( github.com/k3s-io/kine v0.13.5 github.com/klauspost/compress v1.17.11 github.com/libp2p/go-libp2p v0.38.2 - github.com/minio/minio-go/v7 v7.0.70 + github.com/minio/minio-go/v7 v7.0.83 github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/onsi/ginkgo/v2 v2.22.2 @@ -262,12 +262,13 @@ require ( github.com/francoispqt/gojay v1.2.13 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-json v0.10.4 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -422,7 +423,7 @@ require ( github.com/quic-go/quic-go v0.48.2 // indirect github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rs/xid v1.5.0 // indirect + github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shengdoushi/base58 v1.0.0 // indirect github.com/soheilhy/cmux v0.1.5 // indirect @@ -477,7 +478,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 7f92871205a7..aa193065546d 100644 --- a/go.sum +++ b/go.sum @@ -595,6 +595,7 @@ github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmn github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= @@ -648,8 +649,8 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -1175,8 +1176,8 @@ github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.70 h1:1u9NtMgfK1U42kUxcsl5v0yj6TEOPR497OAQxpJnn2g= -github.com/minio/minio-go/v7 v7.0.70/go.mod h1:4yBA8v80xGA30cfM3fz0DKYMXunWl/AV/6tWEs9ryzo= +github.com/minio/minio-go/v7 v7.0.83 h1:W4Kokksvlz3OKf3OqIlzDNKd4MERlC2oN8YptwJ0+GA= +github.com/minio/minio-go/v7 v7.0.83/go.mod h1:57YXpvc5l3rjPdhqNrDsvVlY0qPI6UTk1bflAe+9doY= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -1515,8 +1516,9 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rootless-containers/rootlesskit v1.0.1 h1:jepqW1txFSowKSMAEkVhWH3Oa1TCY9S400MVYe/6Iro= github.com/rootless-containers/rootlesskit v1.0.1/go.mod h1:t2UAiYagxrJ+wmpFAUIZPcqsm4k2B7ve6g7lILKbloc= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -2270,8 +2272,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= diff --git a/pkg/cli/cmds/etcd_snapshot.go b/pkg/cli/cmds/etcd_snapshot.go index fd2ae7586936..12c678d9463a 100644 --- a/pkg/cli/cmds/etcd_snapshot.go +++ b/pkg/cli/cmds/etcd_snapshot.go @@ -87,6 +87,12 @@ var EtcdSnapshotFlags = []cli.Flag{ EnvVar: "AWS_SECRET_ACCESS_KEY", Destination: &ServerConfig.EtcdS3SecretKey, }, + &cli.StringFlag{ + Name: "s3-session-token,etcd-s3-session-token", + Usage: "(db) S3 session token", + EnvVar: "AWS_SESSION_TOKEN", + Destination: &ServerConfig.EtcdS3SessionToken, + }, &cli.StringFlag{ Name: "s3-bucket,etcd-s3-bucket", Usage: "(db) S3 bucket name", diff --git a/pkg/cli/cmds/server.go b/pkg/cli/cmds/server.go index 5ad71386e432..b30cb6ff324c 100644 --- a/pkg/cli/cmds/server.go +++ b/pkg/cli/cmds/server.go @@ -101,6 +101,7 @@ type Server struct { EtcdS3SkipSSLVerify bool EtcdS3AccessKey string EtcdS3SecretKey string + EtcdS3SessionToken string EtcdS3BucketName string EtcdS3Region string EtcdS3Folder string @@ -438,6 +439,12 @@ var ServerFlags = []cli.Flag{ EnvVar: "AWS_SECRET_ACCESS_KEY", Destination: &ServerConfig.EtcdS3SecretKey, }, + &cli.StringFlag{ + Name: "etcd-s3-session-token", + Usage: "(db) S3 session token", + EnvVar: "AWS_SESSION_TOKEN", + Destination: &ServerConfig.EtcdS3SessionToken, + }, &cli.StringFlag{ Name: "etcd-s3-bucket", Usage: "(db) S3 bucket name", diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index fa8e14ee061e..ae2e7293993f 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -197,6 +197,7 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont Proxy: cfg.EtcdS3Proxy, Region: cfg.EtcdS3Region, SecretKey: cfg.EtcdS3SecretKey, + SessionToken: cfg.EtcdS3SessionToken, SkipSSLVerify: cfg.EtcdS3SkipSSLVerify, Timeout: metav1.Duration{Duration: cfg.EtcdS3Timeout}, } diff --git a/pkg/daemons/config/types.go b/pkg/daemons/config/types.go index 2de46082cefe..3b0ded467ed0 100644 --- a/pkg/daemons/config/types.go +++ b/pkg/daemons/config/types.go @@ -72,6 +72,7 @@ type EtcdS3 struct { Proxy string `json:"proxy,omitempty"` Region string `json:"region,omitempty"` SecretKey string `json:"secretKey,omitempty"` + SessionToken string `json:"sessionToken,omitempty"` Insecure bool `json:"insecure,omitempty"` SkipSSLVerify bool `json:"skipSSLVerify,omitempty"` Timeout metav1.Duration `json:"timeout,omitempty"` diff --git a/pkg/etcd/s3/config_secret.go b/pkg/etcd/s3/config_secret.go index 0b81e94b41f8..81380873cca8 100644 --- a/pkg/etcd/s3/config_secret.go +++ b/pkg/etcd/s3/config_secret.go @@ -44,14 +44,15 @@ func (c *Controller) getConfigFromSecret(secretName string) (*config.EtcdS3, err } etcdS3 := &config.EtcdS3{ - AccessKey: string(secret.Data["etcd-s3-access-key"]), - Bucket: string(secret.Data["etcd-s3-bucket"]), - Endpoint: defaultEtcdS3.Endpoint, - Folder: string(secret.Data["etcd-s3-folder"]), - Proxy: string(secret.Data["etcd-s3-proxy"]), - Region: defaultEtcdS3.Region, - SecretKey: string(secret.Data["etcd-s3-secret-key"]), - Timeout: *defaultEtcdS3.Timeout.DeepCopy(), + AccessKey: string(secret.Data["etcd-s3-access-key"]), + Bucket: string(secret.Data["etcd-s3-bucket"]), + Endpoint: defaultEtcdS3.Endpoint, + Folder: string(secret.Data["etcd-s3-folder"]), + Proxy: string(secret.Data["etcd-s3-proxy"]), + Region: defaultEtcdS3.Region, + SecretKey: string(secret.Data["etcd-s3-secret-key"]), + SessionToken: string(secret.Data["etcd-s3-session-token"]), + Timeout: *defaultEtcdS3.Timeout.DeepCopy(), } // Set endpoint from secret if set diff --git a/pkg/etcd/s3/s3.go b/pkg/etcd/s3/s3.go index 9f727b5785eb..6660da9cb211 100644 --- a/pkg/etcd/s3/s3.go +++ b/pkg/etcd/s3/s3.go @@ -205,14 +205,21 @@ func (c *Controller) GetClient(ctx context.Context, etcdS3 *config.EtcdS3) (*Cli tr.Proxy = http.ProxyURL(u) } - var creds *credentials.Credentials - if len(etcdS3.AccessKey) == 0 && len(etcdS3.SecretKey) == 0 { - creds = credentials.NewIAM("") // for running on ec2 instance - if _, err := creds.Get(); err != nil { - return nil, errors.Wrap(err, "failed to get IAM credentials") - } - } else { - creds = credentials.NewStaticV4(etcdS3.AccessKey, etcdS3.SecretKey, "") + creds := credentials.NewChainCredentials([]credentials.Provider{ + &credentials.Static{ + Value: credentials.Value{ + AccessKeyID: etcdS3.AccessKey, + SecretAccessKey: etcdS3.SecretKey, + SessionToken: etcdS3.SessionToken, + SignerType: credentials.SignatureV4, + }, + }, + &credentials.FileAWSCredentials{}, + &credentials.IAM{}, + }) + + if _, err := creds.Get(); err != nil { + return nil, errors.Wrap(err, "failed to get credentials") } opt := minio.Options{ diff --git a/pkg/etcd/snapshot/types.go b/pkg/etcd/snapshot/types.go index 00e93cc6d8ca..970fe336efdc 100644 --- a/pkg/etcd/snapshot/types.go +++ b/pkg/etcd/snapshot/types.go @@ -47,6 +47,7 @@ type S3Config struct { // Mask these fields in the embedded struct to avoid serializing their values in the snapshotFile record AccessKey string `json:"accessKey,omitempty"` ConfigSecret string `json:"configSecret,omitempty"` + SessionToken string `json:"sessionToken,omitempty"` Proxy string `json:"proxy,omitempty"` SecretKey string `json:"secretKey,omitempty"` Timeout metav1.Duration `json:"timeout,omitempty"`