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 }