Skip to content

Commit 4136f8b

Browse files
Merge pull request #10915 from ashley-cui/backport
[3.2] Backport: Support uid,gid,mode options for secrets
2 parents 60d12f7 + 6f9d963 commit 4136f8b

File tree

17 files changed

+197
-49
lines changed

17 files changed

+197
-49
lines changed

cmd/podman/common/specgen.go

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -778,28 +778,38 @@ func parseThrottleIOPsDevices(iopsDevices []string) (map[string]specs.LinuxThrot
778778
return td, nil
779779
}
780780

781-
func parseSecrets(secrets []string) ([]string, map[string]string, error) {
781+
func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) {
782782
secretParseError := errors.New("error parsing secret")
783-
var mount []string
783+
var mount []specgen.Secret
784784
envs := make(map[string]string)
785785
for _, val := range secrets {
786+
// mount only tells if user has set an option that can only be used with mount secret type
787+
mountOnly := false
786788
source := ""
787789
secretType := ""
788790
target := ""
791+
var uid, gid uint32
792+
// default mode 444 octal = 292 decimal
793+
var mode uint32 = 292
789794
split := strings.Split(val, ",")
790795

791796
// --secret mysecret
792797
if len(split) == 1 {
793-
source = val
794-
mount = append(mount, source)
798+
mountSecret := specgen.Secret{
799+
Source: val,
800+
UID: uid,
801+
GID: gid,
802+
Mode: mode,
803+
}
804+
mount = append(mount, mountSecret)
795805
continue
796806
}
797807
// --secret mysecret,opt=opt
798808
if !strings.Contains(split[0], "=") {
799809
source = split[0]
800810
split = split[1:]
801811
}
802-
// TODO: implement other secret options
812+
803813
for _, val := range split {
804814
kv := strings.SplitN(val, "=", 2)
805815
if len(kv) < 2 {
@@ -818,6 +828,28 @@ func parseSecrets(secrets []string) ([]string, map[string]string, error) {
818828
secretType = kv[1]
819829
case "target":
820830
target = kv[1]
831+
case "mode":
832+
mountOnly = true
833+
mode64, err := strconv.ParseUint(kv[1], 8, 32)
834+
if err != nil {
835+
return nil, nil, errors.Wrapf(secretParseError, "mode %s invalid", kv[1])
836+
}
837+
mode = uint32(mode64)
838+
case "uid", "UID":
839+
mountOnly = true
840+
uid64, err := strconv.ParseUint(kv[1], 10, 32)
841+
if err != nil {
842+
return nil, nil, errors.Wrapf(secretParseError, "UID %s invalid", kv[1])
843+
}
844+
uid = uint32(uid64)
845+
case "gid", "GID":
846+
mountOnly = true
847+
gid64, err := strconv.ParseUint(kv[1], 10, 32)
848+
if err != nil {
849+
return nil, nil, errors.Wrapf(secretParseError, "GID %s invalid", kv[1])
850+
}
851+
gid = uint32(gid64)
852+
821853
default:
822854
return nil, nil, errors.Wrapf(secretParseError, "option %s invalid", val)
823855
}
@@ -833,9 +865,18 @@ func parseSecrets(secrets []string) ([]string, map[string]string, error) {
833865
if target != "" {
834866
return nil, nil, errors.Wrapf(secretParseError, "target option is invalid for mounted secrets")
835867
}
836-
mount = append(mount, source)
868+
mountSecret := specgen.Secret{
869+
Source: source,
870+
UID: uid,
871+
GID: gid,
872+
Mode: mode,
873+
}
874+
mount = append(mount, mountSecret)
837875
}
838876
if secretType == "env" {
877+
if mountOnly {
878+
return nil, nil, errors.Wrap(secretParseError, "UID, GID, Mode options cannot be set with secret type env")
879+
}
839880
if target == "" {
840881
target = source
841882
}

docs/source/markdown/podman-create.1.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,9 @@ Secret Options
859859

860860
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
861861
- `target=target` : Target of secret. Defauts to secret name.
862+
- `uid=0` : UID of secret. Defaults to 0. Mount secret type only.
863+
- `gid=0` : GID of secret. Defaults to 0. Mount secret type only.
864+
- `mode=0` : Mode of secret. Defaults to 0444. Mount secret type only.
862865

863866
#### **--security-opt**=*option*
864867

docs/source/markdown/podman-run.1.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,9 @@ Secret Options
911911

912912
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
913913
- `target=target` : Target of secret. Defauts to secret name.
914+
- `uid=0` : UID of secret. Defaults to 0. Mount secret type only.
915+
- `gid=0` : GID of secret. Defaults to 0. Mount secret type only.
916+
- `mode=0` : Mode of secret. Defaults to 0444. Mount secret type only.
914917

915918
#### **--security-opt**=*option*
916919

libpod/container.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,18 @@ type ContainerImageVolume struct {
237237
ReadWrite bool `json:"rw"`
238238
}
239239

240+
// ContainerSecret is a secret that is mounted in a container
241+
type ContainerSecret struct {
242+
// Secret is the secret
243+
*secrets.Secret
244+
// UID is tbe UID of the secret file
245+
UID uint32
246+
// GID is the GID of the secret file
247+
GID uint32
248+
// Mode is the mode of the secret file
249+
Mode uint32
250+
}
251+
240252
// ContainerNetworkDescriptions describes the relationship between the CNI
241253
// network and the ethN where N is an integer
242254
type ContainerNetworkDescriptions map[string]int
@@ -1136,7 +1148,7 @@ func (c *Container) Umask() string {
11361148
}
11371149

11381150
//Secrets return the secrets in the container
1139-
func (c *Container) Secrets() []*secrets.Secret {
1151+
func (c *Container) Secrets() []*ContainerSecret {
11401152
return c.config.Secrets
11411153
}
11421154

libpod/container_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ type ContainerRootFSConfig struct {
148148
// default, but others do not.
149149
CreateWorkingDir bool `json:"createWorkingDir,omitempty"`
150150
// Secrets lists secrets to mount into the container
151-
Secrets []*secrets.Secret `json:"secrets,omitempty"`
151+
Secrets []*ContainerSecret `json:"secrets,omitempty"`
152152
// SecretPath is the secrets location in storage
153153
SecretsPath string `json:"secretsPath"`
154154
// Volatile specifies whether the container storage can be optimized

libpod/container_inspect.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,13 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
343343
ctrConfig.CreateCommand = c.config.CreateCommand
344344

345345
ctrConfig.Timezone = c.config.Timezone
346-
347346
for _, secret := range c.config.Secrets {
348347
newSec := define.InspectSecret{}
349348
newSec.Name = secret.Name
350349
newSec.ID = secret.ID
350+
newSec.UID = secret.UID
351+
newSec.GID = secret.GID
352+
newSec.Mode = secret.Mode
351353
ctrConfig.Secrets = append(ctrConfig.Secrets, &newSec)
352354
}
353355

libpod/container_internal.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
metadata "github.com/checkpoint-restore/checkpointctl/lib"
1717
"github.com/containers/buildah/copier"
18-
"github.com/containers/common/pkg/secrets"
18+
butil "github.com/containers/buildah/util"
1919
"github.com/containers/podman/v3/libpod/define"
2020
"github.com/containers/podman/v3/libpod/events"
2121
"github.com/containers/podman/v3/pkg/cgroups"
@@ -24,6 +24,7 @@ import (
2424
"github.com/containers/podman/v3/pkg/hooks/exec"
2525
"github.com/containers/podman/v3/pkg/rootless"
2626
"github.com/containers/podman/v3/pkg/selinux"
27+
"github.com/containers/podman/v3/pkg/util"
2728
"github.com/containers/storage"
2829
"github.com/containers/storage/pkg/archive"
2930
"github.com/containers/storage/pkg/idtools"
@@ -2188,21 +2189,31 @@ func (c *Container) hasNamespace(namespace spec.LinuxNamespaceType) bool {
21882189
}
21892190

21902191
// extractSecretToStorage copies a secret's data from the secrets manager to the container's static dir
2191-
func (c *Container) extractSecretToCtrStorage(name string) error {
2192-
manager, err := secrets.NewManager(c.runtime.GetSecretsStorageDir())
2192+
func (c *Container) extractSecretToCtrStorage(secr *ContainerSecret) error {
2193+
manager, err := c.runtime.SecretsManager()
21932194
if err != nil {
21942195
return err
21952196
}
2196-
secr, data, err := manager.LookupSecretData(name)
2197+
_, data, err := manager.LookupSecretData(secr.Name)
21972198
if err != nil {
21982199
return err
21992200
}
22002201
secretFile := filepath.Join(c.config.SecretsPath, secr.Name)
22012202

2203+
hostUID, hostGID, err := butil.GetHostIDs(util.IDtoolsToRuntimeSpec(c.config.IDMappings.UIDMap), util.IDtoolsToRuntimeSpec(c.config.IDMappings.GIDMap), secr.UID, secr.GID)
2204+
if err != nil {
2205+
return errors.Wrap(err, "unable to extract secret")
2206+
}
22022207
err = ioutil.WriteFile(secretFile, data, 0644)
22032208
if err != nil {
22042209
return errors.Wrapf(err, "unable to create %s", secretFile)
22052210
}
2211+
if err := os.Lchown(secretFile, int(hostUID), int(hostGID)); err != nil {
2212+
return err
2213+
}
2214+
if err := os.Chmod(secretFile, os.FileMode(secr.Mode)); err != nil {
2215+
return err
2216+
}
22062217
if err := label.Relabel(secretFile, c.config.MountLabel, false); err != nil {
22072218
return err
22082219
}

libpod/container_internal_linux.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/containers/common/pkg/apparmor"
3030
"github.com/containers/common/pkg/chown"
3131
"github.com/containers/common/pkg/config"
32-
"github.com/containers/common/pkg/secrets"
3332
"github.com/containers/common/pkg/subscriptions"
3433
"github.com/containers/common/pkg/umask"
3534
"github.com/containers/podman/v3/libpod/define"
@@ -759,7 +758,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
759758
return nil, errors.Wrapf(err, "error setting up OCI Hooks")
760759
}
761760
if len(c.config.EnvSecrets) > 0 {
762-
manager, err := secrets.NewManager(c.runtime.GetSecretsStorageDir())
761+
manager, err := c.runtime.SecretsManager()
762+
if err != nil {
763+
return nil, err
764+
}
763765
if err != nil {
764766
return nil, err
765767
}
@@ -2413,7 +2415,7 @@ func (c *Container) createSecretMountDir() error {
24132415
oldUmask := umask.Set(0)
24142416
defer umask.Set(oldUmask)
24152417

2416-
if err := os.MkdirAll(src, 0644); err != nil {
2418+
if err := os.MkdirAll(src, 0755); err != nil {
24172419
return err
24182420
}
24192421
if err := label.Relabel(src, c.config.MountLabel, false); err != nil {

libpod/define/container_inspect.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -713,13 +713,16 @@ type DriverData struct {
713713
Data map[string]string `json:"Data"`
714714
}
715715

716-
// InspectHostPort provides information on a port on the host that a container's
717-
// port is bound to.
716+
// InspectSecret contains information on secrets mounted inside the container
718717
type InspectSecret struct {
719-
// IP on the host we are bound to. "" if not specified (binding to all
720-
// IPs).
718+
// Name is the name of the secret
721719
Name string `json:"Name"`
722-
// Port on the host we are bound to. No special formatting - just an
723-
// integer stuffed into a string.
720+
// ID is the ID of the secret
724721
ID string `json:"ID"`
722+
// ID is the UID of the mounted secret file
723+
UID uint32 `json:"UID"`
724+
// ID is the GID of the mounted secret file
725+
GID uint32 `json:"GID"`
726+
// ID is the ID of the mode of the mounted secret file
727+
Mode uint32 `json:"Mode"`
725728
}

libpod/options.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,23 +1712,12 @@ func WithUmask(umask string) CtrCreateOption {
17121712
}
17131713

17141714
// WithSecrets adds secrets to the container
1715-
func WithSecrets(secretNames []string) CtrCreateOption {
1715+
func WithSecrets(containerSecrets []*ContainerSecret) CtrCreateOption {
17161716
return func(ctr *Container) error {
17171717
if ctr.valid {
17181718
return define.ErrCtrFinalized
17191719
}
1720-
manager, err := secrets.NewManager(ctr.runtime.GetSecretsStorageDir())
1721-
if err != nil {
1722-
return err
1723-
}
1724-
for _, name := range secretNames {
1725-
secr, err := manager.Lookup(name)
1726-
if err != nil {
1727-
return err
1728-
}
1729-
ctr.config.Secrets = append(ctr.config.Secrets, secr)
1730-
}
1731-
1720+
ctr.config.Secrets = containerSecrets
17321721
return nil
17331722
}
17341723
}
@@ -1740,7 +1729,7 @@ func WithEnvSecrets(envSecrets map[string]string) CtrCreateOption {
17401729
if ctr.valid {
17411730
return define.ErrCtrFinalized
17421731
}
1743-
manager, err := secrets.NewManager(ctr.runtime.GetSecretsStorageDir())
1732+
manager, err := ctr.runtime.SecretsManager()
17441733
if err != nil {
17451734
return err
17461735
}

0 commit comments

Comments
 (0)