Quadlet Kube: Add support for userns flag

Move the handling of userns keys from ConvertContainer to a separate method
Adjust the method according to the different supported values
Use the new method in both ConvertContainer and ConvertKube
Pass isUser to ConvertKube as well
Add tests

Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
This commit is contained in:
Ygal Blum
2022-12-05 15:32:50 +02:00
parent 68e51834a9
commit 1ea00ebda1
6 changed files with 90 additions and 45 deletions

View File

@ -336,7 +336,7 @@ func main() {
case strings.HasSuffix(name, ".volume"):
service, err = quadlet.ConvertVolume(unit, name)
case strings.HasSuffix(name, ".kube"):
service, err = quadlet.ConvertKube(unit)
service, err = quadlet.ConvertKube(unit, isUser)
default:
Logf("Unsupported file type '%s'", name)
continue

View File

@ -101,7 +101,11 @@ var supportedVolumeKeys = map[string]bool{
// Supported keys in "Kube" group
var supportedKubeKeys = map[string]bool{
KeyYaml: true,
KeyYaml: true,
KeyRemapUID: true,
KeyRemapGID: true,
KeyRemapUsers: true,
KeyRemapUIDSize: true,
}
func replaceExtension(name string, extension string, extraPrefix string, extraSuffix string) string {
@ -356,48 +360,8 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
}
}
uidMaps := container.LookupAllStrv(ContainerGroup, KeyRemapUID)
gidMaps := container.LookupAllStrv(ContainerGroup, KeyRemapGID)
remapUsers, ok := container.LookupLast(ContainerGroup, KeyRemapUsers)
if ok && remapUsers != "" {
switch remapUsers {
case "":
if len(uidMaps) > 0 {
return nil, fmt.Errorf("UidMap set without RemapUsers")
}
if len(gidMaps) > 0 {
return nil, fmt.Errorf("GidMap set without RemapUsers")
}
case "manual":
for _, uidMap := range uidMaps {
podman.addf("--uidmap=%s", uidMap)
}
for _, gidMap := range gidMaps {
podman.addf("--gidmap=%s", gidMap)
}
case "auto":
autoOpts := make([]string, 0)
for _, uidMap := range uidMaps {
autoOpts = append(autoOpts, "uidmapping="+uidMap)
}
for _, gidMap := range gidMaps {
autoOpts = append(autoOpts, "gidmapping="+gidMap)
}
uidSize := container.LookupUint32(ContainerGroup, KeyRemapUIDSize, 0)
if uidSize > 0 {
autoOpts = append(autoOpts, fmt.Sprintf("size=%v", uidSize))
}
podman.addf("--userns=" + usernsOpts("auto", autoOpts))
case "keep-id":
if !isUser {
return nil, fmt.Errorf("RemapUsers=keep-id is unsupported for system units")
}
podman.addf("--userns=keep-id")
default:
return nil, fmt.Errorf("unsupported RemapUsers option '%s'", remapUsers)
}
if err := handleUserRemap(container, ContainerGroup, podman, isUser, true); err != nil {
return nil, err
}
volumes := container.LookupAll(ContainerGroup, KeyVolume)
@ -598,7 +562,7 @@ func ConvertVolume(volume *parser.UnitFile, name string) (*parser.UnitFile, erro
return service, nil
}
func ConvertKube(kube *parser.UnitFile) (*parser.UnitFile, error) {
func ConvertKube(kube *parser.UnitFile, isUser bool) (*parser.UnitFile, error) {
service := kube.Dup()
service.Filename = replaceExtension(kube.Filename, ".service", "", "")
@ -665,6 +629,10 @@ func ConvertKube(kube *parser.UnitFile) (*parser.UnitFile, error) {
"--service-container=true",
)
if err := handleUserRemap(kube, KubeGroup, execStart, isUser, false); err != nil {
return nil, err
}
execStart.add(yamlPath)
service.AddCmdline(ServiceGroup, "ExecStart", execStart.Args)
@ -675,3 +643,52 @@ func ConvertKube(kube *parser.UnitFile) (*parser.UnitFile, error) {
return service, nil
}
func handleUserRemap(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline, isUser, supportManual bool) error {
uidMaps := unitFile.LookupAllStrv(groupName, KeyRemapUID)
gidMaps := unitFile.LookupAllStrv(groupName, KeyRemapGID)
remapUsers, _ := unitFile.LookupLast(groupName, KeyRemapUsers)
switch remapUsers {
case "":
if len(uidMaps) > 0 {
return fmt.Errorf("UidMap set without RemapUsers")
}
if len(gidMaps) > 0 {
return fmt.Errorf("GidMap set without RemapUsers")
}
case "manual":
if supportManual {
for _, uidMap := range uidMaps {
podman.addf("--uidmap=%s", uidMap)
}
for _, gidMap := range gidMaps {
podman.addf("--gidmap=%s", gidMap)
}
} else {
return fmt.Errorf("RemapUsers=manual is not supported")
}
case "auto":
autoOpts := make([]string, 0)
for _, uidMap := range uidMaps {
autoOpts = append(autoOpts, "uidmapping="+uidMap)
}
for _, gidMap := range gidMaps {
autoOpts = append(autoOpts, "gidmapping="+gidMap)
}
uidSize := unitFile.LookupUint32(groupName, KeyRemapUIDSize, 0)
if uidSize > 0 {
autoOpts = append(autoOpts, fmt.Sprintf("size=%v", uidSize))
}
podman.addf("--userns=" + usernsOpts("auto", autoOpts))
case "keep-id":
if !isUser {
return fmt.Errorf("RemapUsers=keep-id is unsupported for system units")
}
podman.addf("--userns=keep-id")
default:
return fmt.Errorf("unsupported RemapUsers option '%s'", remapUsers)
}
return nil
}

View File

@ -0,0 +1,5 @@
## assert-podman-args --userns=auto
[Kube]
Yaml=/opt/k8s/deployment.yml
RemapUsers=auto

View File

@ -0,0 +1,10 @@
## assert-podman-args "--userns=auto:uidmapping=0:10000:10,uidmapping=10:20000:10,gidmapping=0:10000:10,gidmapping=10:20000:10,size=20"
[Kube]
Yaml=/opt/k8s/deployment.yml
RemapUsers=auto
RemapUid=0:10000:10
RemapUid=10:20000:10
RemapGid=0:10000:10
RemapGid=10:20000:10
RemapUidSize=20

View File

@ -0,0 +1,10 @@
## assert-failed
## assert-stderr-contains "RemapUsers=manual is not supported"
[Kube]
Yaml=/opt/k8s/deployment.yml
RemapUsers=manual
RemapUid=0:10000:10
RemapUid=10:20000:10
RemapGid=0:10000:10
RemapGid=10:20000:10

View File

@ -359,6 +359,9 @@ var _ = Describe("quadlet system generator", func() {
Entry("Basic kube", "basic.kube"),
Entry("Syslog Identifier", "syslog.identifier.kube"),
Entry("Absolute Path", "absolute.path.kube"),
Entry("Kube - User Remap Manual", "remap-manual.kube"),
Entry("Kube - User Remap Auto", "remap-auto.kube"),
Entry("Kube - User Remap Auto with IDs", "remap-auto2.kube"),
)
})