102 lines
3.6 KiB
Go
102 lines
3.6 KiB
Go
package types
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/containers/storage/pkg/idtools"
|
|
)
|
|
|
|
// AutoUserNsOptions defines how to automatically create a user namespace.
|
|
type AutoUserNsOptions struct {
|
|
// Size defines the size for the user namespace. If it is set to a
|
|
// value bigger than 0, the user namespace will have exactly this size.
|
|
// If it is not set, some heuristics will be used to find its size.
|
|
Size uint32
|
|
// InitialSize defines the minimum size for the user namespace.
|
|
// The created user namespace will have at least this size.
|
|
InitialSize uint32
|
|
// PasswdFile to use if the container uses a volume.
|
|
PasswdFile string
|
|
// GroupFile to use if the container uses a volume.
|
|
GroupFile string
|
|
// AdditionalUIDMappings specified additional UID mappings to include in
|
|
// the generated user namespace.
|
|
AdditionalUIDMappings []idtools.IDMap
|
|
// AdditionalGIDMappings specified additional GID mappings to include in
|
|
// the generated user namespace.
|
|
AdditionalGIDMappings []idtools.IDMap
|
|
}
|
|
|
|
// IDMappingOptions are used for specifying how ID mapping should be set up for
|
|
// a layer or container.
|
|
type IDMappingOptions struct {
|
|
// UIDMap and GIDMap are used for setting up a layer's root filesystem
|
|
// for use inside of a user namespace where ID mapping is being used.
|
|
// If HostUIDMapping/HostGIDMapping is true, no mapping of the
|
|
// respective type will be used. Otherwise, if UIDMap and/or GIDMap
|
|
// contain at least one mapping, one or both will be used. By default,
|
|
// if neither of those conditions apply, if the layer has a parent
|
|
// layer, the parent layer's mapping will be used, and if it does not
|
|
// have a parent layer, the mapping which was passed to the Store
|
|
// object when it was initialized will be used.
|
|
HostUIDMapping bool
|
|
HostGIDMapping bool
|
|
UIDMap []idtools.IDMap
|
|
GIDMap []idtools.IDMap
|
|
AutoUserNs bool
|
|
AutoUserNsOpts AutoUserNsOptions
|
|
}
|
|
|
|
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
|
|
func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*IDMappingOptions, error) {
|
|
options := IDMappingOptions{
|
|
HostUIDMapping: true,
|
|
HostGIDMapping: true,
|
|
}
|
|
if subGIDMap == "" && subUIDMap != "" {
|
|
subGIDMap = subUIDMap
|
|
}
|
|
if subUIDMap == "" && subGIDMap != "" {
|
|
subUIDMap = subGIDMap
|
|
}
|
|
if len(GIDMapSlice) == 0 && len(UIDMapSlice) != 0 {
|
|
GIDMapSlice = UIDMapSlice
|
|
}
|
|
if len(UIDMapSlice) == 0 && len(GIDMapSlice) != 0 {
|
|
UIDMapSlice = GIDMapSlice
|
|
}
|
|
if len(UIDMapSlice) == 0 && subUIDMap == "" && os.Getuid() != 0 {
|
|
UIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getuid())}
|
|
}
|
|
if len(GIDMapSlice) == 0 && subGIDMap == "" && os.Getuid() != 0 {
|
|
GIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getgid())}
|
|
}
|
|
|
|
if subUIDMap != "" && subGIDMap != "" {
|
|
mappings, err := idtools.NewIDMappings(subUIDMap, subGIDMap)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create NewIDMappings for uidmap=%s gidmap=%s: %w", subUIDMap, subGIDMap, err)
|
|
}
|
|
options.UIDMap = mappings.UIDs()
|
|
options.GIDMap = mappings.GIDs()
|
|
}
|
|
parsedUIDMap, err := idtools.ParseIDMap(UIDMapSlice, "UID")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create ParseUIDMap UID=%s: %w", UIDMapSlice, err)
|
|
}
|
|
parsedGIDMap, err := idtools.ParseIDMap(GIDMapSlice, "GID")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create ParseGIDMap GID=%s: %w", UIDMapSlice, err)
|
|
}
|
|
options.UIDMap = append(options.UIDMap, parsedUIDMap...)
|
|
options.GIDMap = append(options.GIDMap, parsedGIDMap...)
|
|
if len(options.UIDMap) > 0 {
|
|
options.HostUIDMapping = false
|
|
}
|
|
if len(options.GIDMap) > 0 {
|
|
options.HostGIDMapping = false
|
|
}
|
|
return &options, nil
|
|
}
|