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