From b56b4b53744c59cad942278ff34a0b0616a7aa60 Mon Sep 17 00:00:00 2001 From: Tino Rusch Date: Sun, 20 Jun 2021 16:11:54 +0200 Subject: read secret config from config file if no user data. feat: read secret config from config file if the user hasn't entered explicit config values feat: allow to specify `--driver-opts opt1=val1,opt2=val2` in the secret create command to allow overriding the default values fix: show driver options in `podman secret inspect` Signed-off-by: Tino Rusch --- cmd/podman/secrets/create.go | 8 +++++- docs/source/markdown/podman-secret-create.1.md | 4 +++ pkg/api/handlers/libpod/secrets.go | 16 ++++++++++-- pkg/bindings/internal/util/util.go | 4 +-- pkg/bindings/secrets/types.go | 5 ++-- pkg/bindings/secrets/types_create_options.go | 36 +++++++++++++++++++------- pkg/domain/entities/secrets.go | 1 + pkg/domain/infra/abi/secrets.go | 26 +++++++++++++++---- pkg/domain/infra/tunnel/secrets.go | 10 +++++-- test/e2e/secret_test.go | 6 ++++- 10 files changed, 91 insertions(+), 25 deletions(-) diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go index f5739e99a..8c268615c 100644 --- a/cmd/podman/secrets/create.go +++ b/cmd/podman/secrets/create.go @@ -42,8 +42,14 @@ func init() { flags := createCmd.Flags() driverFlagName := "driver" - flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver") + optsFlagName := "driver-opts" + + cfg := registry.PodmanConfig() + + flags.StringVar(&createOpts.Driver, driverFlagName, cfg.Secrets.Driver, "Specify secret driver") + flags.StringToStringVar(&createOpts.Opts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options") _ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone) + _ = createCmd.RegisterFlagCompletionFunc(optsFlagName, completion.AutocompleteNone) envFlagName := "env" flags.BoolVar(&env, envFlagName, false, "Read secret data from environment variable") diff --git a/docs/source/markdown/podman-secret-create.1.md b/docs/source/markdown/podman-secret-create.1.md index c70d80719..712ca4aaa 100644 --- a/docs/source/markdown/podman-secret-create.1.md +++ b/docs/source/markdown/podman-secret-create.1.md @@ -28,6 +28,10 @@ Read secret data from environment variable Specify the secret driver (default **file**, which is unencrypted). +#### **--driver-opts**=*key1=val1,key2=val2* + +Specify driver specific options + #### **--help** Print usage statement. diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go index e7f4397ea..867a0b957 100644 --- a/pkg/api/handlers/libpod/secrets.go +++ b/pkg/api/handlers/libpod/secrets.go @@ -1,7 +1,9 @@ package libpod import ( + "encoding/json" "net/http" + "reflect" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers/utils" @@ -16,9 +18,17 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { runtime = r.Context().Value("runtime").(*libpod.Runtime) decoder = r.Context().Value("decoder").(*schema.Decoder) ) + + decoder.RegisterConverter(map[string]string{}, func(str string) reflect.Value { + res := make(map[string]string) + json.Unmarshal([]byte(str), &res) + return reflect.ValueOf(res) + }) + query := struct { - Name string `schema:"name"` - Driver string `schema:"driver"` + Name string `schema:"name"` + Driver string `schema:"driver"` + DriverOpts map[string]string `schema:"driveropts"` }{ // override any golang type defaults } @@ -28,7 +38,9 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } + opts.Driver = query.Driver + opts.Opts = query.DriverOpts ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts) diff --git a/pkg/bindings/internal/util/util.go b/pkg/bindings/internal/util/util.go index c1961308e..ef93d6e25 100644 --- a/pkg/bindings/internal/util/util.go +++ b/pkg/bindings/internal/util/util.go @@ -85,10 +85,10 @@ func ToParams(o interface{}) (url.Values, error) { } } case f.Kind() == reflect.Map: - lowerCaseKeys := make(map[string][]string) + lowerCaseKeys := make(map[string]interface{}) iter := f.MapRange() for iter.Next() { - lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string) + lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface() } s, err := json.MarshalToString(lowerCaseKeys) if err != nil { diff --git a/pkg/bindings/secrets/types.go b/pkg/bindings/secrets/types.go index a98e894dc..a64dea1b4 100644 --- a/pkg/bindings/secrets/types.go +++ b/pkg/bindings/secrets/types.go @@ -18,6 +18,7 @@ type RemoveOptions struct { //go:generate go run ../generator/generator.go CreateOptions // CreateOptions are optional options for Creating secrets type CreateOptions struct { - Driver *string - Name *string + Name *string + Driver *string + DriverOpts map[string]string } diff --git a/pkg/bindings/secrets/types_create_options.go b/pkg/bindings/secrets/types_create_options.go index ea5bd3039..28d0c4e83 100644 --- a/pkg/bindings/secrets/types_create_options.go +++ b/pkg/bindings/secrets/types_create_options.go @@ -20,6 +20,22 @@ func (o *CreateOptions) ToParams() (url.Values, error) { return util.ToParams(o) } +// WithName +func (o *CreateOptions) WithName(value string) *CreateOptions { + v := &value + o.Name = v + return o +} + +// GetName +func (o *CreateOptions) GetName() string { + var name string + if o.Name == nil { + return name + } + return *o.Name +} + // WithDriver func (o *CreateOptions) WithDriver(value string) *CreateOptions { v := &value @@ -36,18 +52,18 @@ func (o *CreateOptions) GetDriver() string { return *o.Driver } -// WithName -func (o *CreateOptions) WithName(value string) *CreateOptions { - v := &value - o.Name = v +// WithDriverOpts +func (o *CreateOptions) WithDriverOpts(value map[string]string) *CreateOptions { + v := value + o.DriverOpts = v return o } -// GetName -func (o *CreateOptions) GetName() string { - var name string - if o.Name == nil { - return name +// GetDriverOpts +func (o *CreateOptions) GetDriverOpts() map[string]string { + var driverOpts map[string]string + if o.DriverOpts == nil { + return driverOpts } - return *o.Name + return o.DriverOpts } diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go index 8ede981da..e69b0a07c 100644 --- a/pkg/domain/entities/secrets.go +++ b/pkg/domain/entities/secrets.go @@ -12,6 +12,7 @@ type SecretCreateReport struct { type SecretCreateOptions struct { Driver string + Opts map[string]string } type SecretListRequest struct { diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go index 1e1cbc70f..fa28a9b51 100644 --- a/pkg/domain/infra/abi/secrets.go +++ b/pkg/domain/infra/abi/secrets.go @@ -17,15 +17,30 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader if err != nil { return nil, err } - driverOptions := make(map[string]string) + // set defaults from config for the case they are not set by an upper layer + // (-> i.e. tests that talk directly to the api) + cfg, err := ic.Libpod.GetConfig() + if err != nil { + return nil, err + } if options.Driver == "" { - options.Driver = "file" + options.Driver = cfg.Secrets.Driver + } + if len(options.Opts) == 0 { + options.Opts = cfg.Secrets.Opts + } + if options.Opts == nil { + options.Opts = make(map[string]string) } + if options.Driver == "file" { - driverOptions["path"] = filepath.Join(secretsPath, "filedriver") + if _, ok := options.Opts["path"]; !ok { + options.Opts["path"] = filepath.Join(secretsPath, "filedriver") + } } - secretID, err := manager.Store(name, data, options.Driver, driverOptions) + + secretID, err := manager.Store(name, data, options.Driver, options.Opts) if err != nil { return nil, err } @@ -58,7 +73,8 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string Spec: entities.SecretSpec{ Name: secret.Name, Driver: entities.SecretDriverSpec{ - Name: secret.Driver, + Name: secret.Driver, + Options: secret.DriverOptions, }, }, } diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go index 1153f490e..8cdc220a4 100644 --- a/pkg/domain/infra/tunnel/secrets.go +++ b/pkg/domain/infra/tunnel/secrets.go @@ -11,8 +11,14 @@ import ( ) func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) { - opts := new(secrets.CreateOptions).WithDriver(options.Driver).WithName(name) - created, _ := secrets.Create(ic.ClientCtx, reader, opts) + opts := new(secrets.CreateOptions). + WithDriver(options.Driver). + WithDriverOpts(options.Opts). + WithName(name) + created, err := secrets.Create(ic.ClientCtx, reader, opts) + if err != nil { + return nil, err + } return created, nil } diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go index b54b959bf..392129784 100644 --- a/test/e2e/secret_test.go +++ b/test/e2e/secret_test.go @@ -39,7 +39,7 @@ var _ = Describe("Podman secret", func() { err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) Expect(err).To(BeNil()) - session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session := podmanTest.Podman([]string{"secret", "create", "--driver-opts", "opt1=val", "a", secretFilePath}) session.WaitWithDefaultTimeout() secrID := session.OutputToString() Expect(session.ExitCode()).To(Equal(0)) @@ -48,6 +48,10 @@ var _ = Describe("Podman secret", func() { inspect.WaitWithDefaultTimeout() Expect(inspect.ExitCode()).To(Equal(0)) Expect(inspect.OutputToString()).To(Equal(secrID)) + inspect = podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Driver.Options}}", secrID}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(ContainSubstring("opt1:val")) }) It("podman secret create bad name should fail", func() { -- cgit v1.2.3-54-g00ecf From e7507fe7cf2f35e332f58ae632882f29395e4c59 Mon Sep 17 00:00:00 2001 From: Tino Rusch Date: Fri, 25 Jun 2021 08:33:15 +0200 Subject: make DriverOpts name consistent. Signed-off-by: Tino Rusch --- cmd/podman/secrets/create.go | 2 +- pkg/api/handlers/libpod/secrets.go | 2 +- pkg/domain/entities/secrets.go | 4 ++-- pkg/domain/infra/abi/secrets.go | 14 +++++++------- pkg/domain/infra/tunnel/secrets.go | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go index 8c268615c..f9846f9fb 100644 --- a/cmd/podman/secrets/create.go +++ b/cmd/podman/secrets/create.go @@ -47,7 +47,7 @@ func init() { cfg := registry.PodmanConfig() flags.StringVar(&createOpts.Driver, driverFlagName, cfg.Secrets.Driver, "Specify secret driver") - flags.StringToStringVar(&createOpts.Opts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options") + flags.StringToStringVar(&createOpts.DriverOpts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options") _ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone) _ = createCmd.RegisterFlagCompletionFunc(optsFlagName, completion.AutocompleteNone) diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go index 867a0b957..7086d9e38 100644 --- a/pkg/api/handlers/libpod/secrets.go +++ b/pkg/api/handlers/libpod/secrets.go @@ -40,7 +40,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { } opts.Driver = query.Driver - opts.Opts = query.DriverOpts + opts.DriverOpts = query.DriverOpts ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts) diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go index e69b0a07c..56a1465b7 100644 --- a/pkg/domain/entities/secrets.go +++ b/pkg/domain/entities/secrets.go @@ -11,8 +11,8 @@ type SecretCreateReport struct { } type SecretCreateOptions struct { - Driver string - Opts map[string]string + Driver string + DriverOpts map[string]string } type SecretListRequest struct { diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go index fa28a9b51..0bdb4ce60 100644 --- a/pkg/domain/infra/abi/secrets.go +++ b/pkg/domain/infra/abi/secrets.go @@ -27,20 +27,20 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader if options.Driver == "" { options.Driver = cfg.Secrets.Driver } - if len(options.Opts) == 0 { - options.Opts = cfg.Secrets.Opts + if len(options.DriverOpts) == 0 { + options.DriverOpts = cfg.Secrets.Opts } - if options.Opts == nil { - options.Opts = make(map[string]string) + if options.DriverOpts == nil { + options.DriverOpts = make(map[string]string) } if options.Driver == "file" { - if _, ok := options.Opts["path"]; !ok { - options.Opts["path"] = filepath.Join(secretsPath, "filedriver") + if _, ok := options.DriverOpts["path"]; !ok { + options.DriverOpts["path"] = filepath.Join(secretsPath, "filedriver") } } - secretID, err := manager.Store(name, data, options.Driver, options.Opts) + secretID, err := manager.Store(name, data, options.Driver, options.DriverOpts) if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go index 8cdc220a4..ecbb80931 100644 --- a/pkg/domain/infra/tunnel/secrets.go +++ b/pkg/domain/infra/tunnel/secrets.go @@ -13,7 +13,7 @@ import ( func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) { opts := new(secrets.CreateOptions). WithDriver(options.Driver). - WithDriverOpts(options.Opts). + WithDriverOpts(options.DriverOpts). WithName(name) created, err := secrets.Create(ic.ClientCtx, reader, opts) if err != nil { -- cgit v1.2.3-54-g00ecf