github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/namespaces/namespaces.go (about)

     1  package namespaces
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/containers/storage/types"
     9  )
    10  
    11  const (
    12  	bridgeType    = "bridge"
    13  	containerType = "container"
    14  	defaultType   = "default"
    15  	hostType      = "host"
    16  	noneType      = "none"
    17  	nsType        = "ns"
    18  	podType       = "pod"
    19  	privateType   = "private"
    20  	shareableType = "shareable"
    21  	slirpType     = "slirp4netns"
    22  )
    23  
    24  // CgroupMode represents cgroup mode in the container.
    25  type CgroupMode string
    26  
    27  // IsHost indicates whether the container uses the host's cgroup.
    28  func (n CgroupMode) IsHost() bool {
    29  	return n == hostType
    30  }
    31  
    32  // IsDefaultValue indicates whether the cgroup namespace has the default value.
    33  func (n CgroupMode) IsDefaultValue() bool {
    34  	return n == "" || n == defaultType
    35  }
    36  
    37  // IsNS indicates a cgroup namespace passed in by path (ns:<path>)
    38  func (n CgroupMode) IsNS() bool {
    39  	return strings.HasPrefix(string(n), nsType)
    40  }
    41  
    42  // NS gets the path associated with a ns:<path> cgroup ns
    43  func (n CgroupMode) NS() string {
    44  	parts := strings.SplitN(string(n), ":", 2)
    45  	if len(parts) > 1 {
    46  		return parts[1]
    47  	}
    48  	return ""
    49  }
    50  
    51  // IsContainer indicates whether the container uses a new cgroup namespace.
    52  func (n CgroupMode) IsContainer() bool {
    53  	parts := strings.SplitN(string(n), ":", 2)
    54  	return len(parts) > 1 && parts[0] == containerType
    55  }
    56  
    57  // Container returns the name of the container whose cgroup namespace is going to be used.
    58  func (n CgroupMode) Container() string {
    59  	parts := strings.SplitN(string(n), ":", 2)
    60  	if len(parts) > 1 && parts[0] == containerType {
    61  		return parts[1]
    62  	}
    63  	return ""
    64  }
    65  
    66  // IsPrivate indicates whether the container uses the a private cgroup.
    67  func (n CgroupMode) IsPrivate() bool {
    68  	return n == privateType
    69  }
    70  
    71  // Valid indicates whether the Cgroup namespace is valid.
    72  func (n CgroupMode) Valid() bool {
    73  	parts := strings.Split(string(n), ":")
    74  	switch mode := parts[0]; mode {
    75  	case "", hostType, privateType, nsType:
    76  	case containerType:
    77  		if len(parts) != 2 || parts[1] == "" {
    78  			return false
    79  		}
    80  	default:
    81  		return false
    82  	}
    83  	return true
    84  }
    85  
    86  // UsernsMode represents userns mode in the container.
    87  type UsernsMode string
    88  
    89  // IsHost indicates whether the container uses the host's userns.
    90  func (n UsernsMode) IsHost() bool {
    91  	return n == hostType
    92  }
    93  
    94  // IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is kept inside of the namespace.
    95  func (n UsernsMode) IsKeepID() bool {
    96  	return n == "keep-id"
    97  }
    98  
    99  // IsNoMap indicates whether container uses a mapping where the (uid, gid) on the host is not present in the namespace.
   100  func (n UsernsMode) IsNoMap() bool {
   101  	return n == "nomap"
   102  }
   103  
   104  // IsAuto indicates whether container uses the "auto" userns mode.
   105  func (n UsernsMode) IsAuto() bool {
   106  	parts := strings.Split(string(n), ":")
   107  	return parts[0] == "auto"
   108  }
   109  
   110  // IsDefaultValue indicates whether the user namespace has the default value.
   111  func (n UsernsMode) IsDefaultValue() bool {
   112  	return n == "" || n == defaultType
   113  }
   114  
   115  // GetAutoOptions returns a AutoUserNsOptions with the settings to setup automatically
   116  // a user namespace.
   117  func (n UsernsMode) GetAutoOptions() (*types.AutoUserNsOptions, error) {
   118  	parts := strings.SplitN(string(n), ":", 2)
   119  	if parts[0] != "auto" {
   120  		return nil, fmt.Errorf("wrong user namespace mode")
   121  	}
   122  	options := types.AutoUserNsOptions{}
   123  	if len(parts) == 1 {
   124  		return &options, nil
   125  	}
   126  	for _, o := range strings.Split(parts[1], ",") {
   127  		v := strings.SplitN(o, "=", 2)
   128  		if len(v) != 2 {
   129  			return nil, fmt.Errorf("invalid option specified: %q", o)
   130  		}
   131  		switch v[0] {
   132  		case "size":
   133  			s, err := strconv.ParseUint(v[1], 10, 32)
   134  			if err != nil {
   135  				return nil, err
   136  			}
   137  			options.Size = uint32(s)
   138  		case "uidmapping":
   139  			mapping, err := types.ParseIDMapping([]string{v[1]}, nil, "", "")
   140  			if err != nil {
   141  				return nil, err
   142  			}
   143  			options.AdditionalUIDMappings = append(options.AdditionalUIDMappings, mapping.UIDMap...)
   144  		case "gidmapping":
   145  			mapping, err := types.ParseIDMapping(nil, []string{v[1]}, "", "")
   146  			if err != nil {
   147  				return nil, err
   148  			}
   149  			options.AdditionalGIDMappings = append(options.AdditionalGIDMappings, mapping.GIDMap...)
   150  		default:
   151  			return nil, fmt.Errorf("unknown option specified: %q", v[0])
   152  		}
   153  	}
   154  	return &options, nil
   155  }
   156  
   157  // IsPrivate indicates whether the container uses the a private userns.
   158  func (n UsernsMode) IsPrivate() bool {
   159  	return !(n.IsHost() || n.IsContainer())
   160  }
   161  
   162  // Valid indicates whether the userns is valid.
   163  func (n UsernsMode) Valid() bool {
   164  	parts := strings.Split(string(n), ":")
   165  	switch mode := parts[0]; mode {
   166  	case "", privateType, hostType, "keep-id", nsType, "auto", "nomap":
   167  	case containerType:
   168  		if len(parts) != 2 || parts[1] == "" {
   169  			return false
   170  		}
   171  	default:
   172  		return false
   173  	}
   174  	return true
   175  }
   176  
   177  // IsNS indicates a userns namespace passed in by path (ns:<path>)
   178  func (n UsernsMode) IsNS() bool {
   179  	return strings.HasPrefix(string(n), "ns:")
   180  }
   181  
   182  // NS gets the path associated with a ns:<path> userns ns
   183  func (n UsernsMode) NS() string {
   184  	parts := strings.SplitN(string(n), ":", 2)
   185  	if len(parts) > 1 {
   186  		return parts[1]
   187  	}
   188  	return ""
   189  }
   190  
   191  // IsContainer indicates whether container uses a container userns.
   192  func (n UsernsMode) IsContainer() bool {
   193  	parts := strings.SplitN(string(n), ":", 2)
   194  	return len(parts) > 1 && parts[0] == containerType
   195  }
   196  
   197  // Container is the id of the container which network this container is connected to.
   198  func (n UsernsMode) Container() string {
   199  	parts := strings.SplitN(string(n), ":", 2)
   200  	if len(parts) > 1 && parts[0] == containerType {
   201  		return parts[1]
   202  	}
   203  	return ""
   204  }
   205  
   206  // UTSMode represents the UTS namespace of the container.
   207  type UTSMode string
   208  
   209  // IsPrivate indicates whether the container uses its private UTS namespace.
   210  func (n UTSMode) IsPrivate() bool {
   211  	return !(n.IsHost())
   212  }
   213  
   214  // IsHost indicates whether the container uses the host's UTS namespace.
   215  func (n UTSMode) IsHost() bool {
   216  	return n == hostType
   217  }
   218  
   219  // IsContainer indicates whether the container uses a container's UTS namespace.
   220  func (n UTSMode) IsContainer() bool {
   221  	parts := strings.SplitN(string(n), ":", 2)
   222  	return len(parts) > 1 && parts[0] == containerType
   223  }
   224  
   225  // Container returns the name of the container whose uts namespace is going to be used.
   226  func (n UTSMode) Container() string {
   227  	parts := strings.SplitN(string(n), ":", 2)
   228  	if len(parts) > 1 && parts[0] == containerType {
   229  		return parts[1]
   230  	}
   231  	return ""
   232  }
   233  
   234  // Valid indicates whether the UTS namespace is valid.
   235  func (n UTSMode) Valid() bool {
   236  	parts := strings.Split(string(n), ":")
   237  	switch mode := parts[0]; mode {
   238  	case "", privateType, hostType:
   239  	case containerType:
   240  		if len(parts) != 2 || parts[1] == "" {
   241  			return false
   242  		}
   243  	default:
   244  		return false
   245  	}
   246  	return true
   247  }
   248  
   249  // IpcMode represents the container ipc stack.
   250  type IpcMode string
   251  
   252  // IsPrivate indicates whether the container uses its own private ipc namespace which cannot be shared.
   253  func (n IpcMode) IsPrivate() bool {
   254  	return n == privateType
   255  }
   256  
   257  // IsHost indicates whether the container shares the host's ipc namespace.
   258  func (n IpcMode) IsHost() bool {
   259  	return n == hostType
   260  }
   261  
   262  // IsShareable indicates whether the container uses its own shareable ipc namespace which can be shared.
   263  func (n IpcMode) IsShareable() bool {
   264  	return n == shareableType
   265  }
   266  
   267  // IsContainer indicates whether the container uses another container's ipc namespace.
   268  func (n IpcMode) IsContainer() bool {
   269  	parts := strings.SplitN(string(n), ":", 2)
   270  	return len(parts) > 1 && parts[0] == containerType
   271  }
   272  
   273  // IsNone indicates whether container IpcMode is set to "none".
   274  func (n IpcMode) IsNone() bool {
   275  	return n == noneType
   276  }
   277  
   278  // IsEmpty indicates whether container IpcMode is empty
   279  func (n IpcMode) IsEmpty() bool {
   280  	return n == ""
   281  }
   282  
   283  // Valid indicates whether the ipc mode is valid.
   284  func (n IpcMode) Valid() bool {
   285  	return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
   286  }
   287  
   288  // Container returns the name of the container ipc stack is going to be used.
   289  func (n IpcMode) Container() string {
   290  	parts := strings.SplitN(string(n), ":", 2)
   291  	if len(parts) > 1 && parts[0] == containerType {
   292  		return parts[1]
   293  	}
   294  	return ""
   295  }
   296  
   297  // PidMode represents the pid namespace of the container.
   298  type PidMode string
   299  
   300  // IsPrivate indicates whether the container uses its own new pid namespace.
   301  func (n PidMode) IsPrivate() bool {
   302  	return !(n.IsHost() || n.IsContainer())
   303  }
   304  
   305  // IsHost indicates whether the container uses the host's pid namespace.
   306  func (n PidMode) IsHost() bool {
   307  	return n == hostType
   308  }
   309  
   310  // IsContainer indicates whether the container uses a container's pid namespace.
   311  func (n PidMode) IsContainer() bool {
   312  	parts := strings.SplitN(string(n), ":", 2)
   313  	return len(parts) > 1 && parts[0] == containerType
   314  }
   315  
   316  // Valid indicates whether the pid namespace is valid.
   317  func (n PidMode) Valid() bool {
   318  	parts := strings.Split(string(n), ":")
   319  	switch mode := parts[0]; mode {
   320  	case "", privateType, hostType:
   321  	case containerType:
   322  		if len(parts) != 2 || parts[1] == "" {
   323  			return false
   324  		}
   325  	default:
   326  		return false
   327  	}
   328  	return true
   329  }
   330  
   331  // Container returns the name of the container whose pid namespace is going to be used.
   332  func (n PidMode) Container() string {
   333  	parts := strings.SplitN(string(n), ":", 2)
   334  	if len(parts) > 1 && parts[0] == containerType {
   335  		return parts[1]
   336  	}
   337  	return ""
   338  }
   339  
   340  // NetworkMode represents the container network stack.
   341  type NetworkMode string
   342  
   343  // IsNone indicates whether container isn't using a network stack.
   344  func (n NetworkMode) IsNone() bool {
   345  	return n == noneType
   346  }
   347  
   348  // IsHost indicates whether the container uses the host's network stack.
   349  func (n NetworkMode) IsHost() bool {
   350  	return n == hostType
   351  }
   352  
   353  // IsDefault indicates whether container uses the default network stack.
   354  func (n NetworkMode) IsDefault() bool {
   355  	return n == defaultType
   356  }
   357  
   358  // IsPrivate indicates whether container uses its private network stack.
   359  func (n NetworkMode) IsPrivate() bool {
   360  	return !(n.IsHost() || n.IsContainer())
   361  }
   362  
   363  // IsContainer indicates whether container uses a container network stack.
   364  func (n NetworkMode) IsContainer() bool {
   365  	parts := strings.SplitN(string(n), ":", 2)
   366  	return len(parts) > 1 && parts[0] == containerType
   367  }
   368  
   369  // Container is the id of the container which network this container is connected to.
   370  func (n NetworkMode) Container() string {
   371  	parts := strings.SplitN(string(n), ":", 2)
   372  	if len(parts) > 1 && parts[0] == containerType {
   373  		return parts[1]
   374  	}
   375  	return ""
   376  }
   377  
   378  // UserDefined indicates user-created network
   379  func (n NetworkMode) UserDefined() string {
   380  	if n.IsUserDefined() {
   381  		return string(n)
   382  	}
   383  	return ""
   384  }
   385  
   386  // IsBridge indicates whether container uses the bridge network stack
   387  func (n NetworkMode) IsBridge() bool {
   388  	return n == bridgeType
   389  }
   390  
   391  // IsSlirp4netns indicates if we are running a rootless network stack
   392  func (n NetworkMode) IsSlirp4netns() bool {
   393  	return n == slirpType || strings.HasPrefix(string(n), slirpType+":")
   394  }
   395  
   396  // IsNS indicates a network namespace passed in by path (ns:<path>)
   397  func (n NetworkMode) IsNS() bool {
   398  	return strings.HasPrefix(string(n), nsType)
   399  }
   400  
   401  // NS gets the path associated with a ns:<path> network ns
   402  func (n NetworkMode) NS() string {
   403  	parts := strings.SplitN(string(n), ":", 2)
   404  	if len(parts) > 1 {
   405  		return parts[1]
   406  	}
   407  	return ""
   408  }
   409  
   410  // IsPod returns whether the network refers to pod networking
   411  func (n NetworkMode) IsPod() bool {
   412  	return n == podType
   413  }
   414  
   415  // IsUserDefined indicates user-created network
   416  func (n NetworkMode) IsUserDefined() bool {
   417  	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() && !n.IsSlirp4netns() && !n.IsNS()
   418  }