add oci.WithAllDevicesAllowed flag for privileged_without_host_devices
This commit adds a flag that enable all devices whitelisting when privileged_without_host_devices is already enabled. Fixes #5679 Signed-off-by: Dat Nguyen <dnguyen7@atlassian.com>
This commit is contained in:
		@@ -168,6 +168,14 @@ version = 2
 | 
				
			|||||||
      # i.e pass host devices through to privileged containers.
 | 
					      # i.e pass host devices through to privileged containers.
 | 
				
			||||||
      privileged_without_host_devices = false
 | 
					      privileged_without_host_devices = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # privileged_without_host_devices_all_devices_allowed allows the allowlisting of all devices when
 | 
				
			||||||
 | 
					      # privileged_without_host_devices is enabled.
 | 
				
			||||||
 | 
					      # In plain privileged mode all host device nodes are added to the container's spec and all devices
 | 
				
			||||||
 | 
					      # are put in the container's device allowlist. This flags is for the modification of the privileged_without_host_devices
 | 
				
			||||||
 | 
					      # option so that even when no host devices are implicitly added to the container, all devices allowlisting is still enabled.
 | 
				
			||||||
 | 
					      # Requires privileged_without_host_devices to be enabled. Defaults to false.
 | 
				
			||||||
 | 
					      privileged_without_host_devices_all_devices_allowed = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # base_runtime_spec is a file path to a JSON file with the OCI spec that will be used as the base spec that all
 | 
					      # base_runtime_spec is a file path to a JSON file with the OCI spec that will be used as the base spec that all
 | 
				
			||||||
      # container's are created from.
 | 
					      # container's are created from.
 | 
				
			||||||
      # Use containerd's `ctr oci spec > /etc/containerd/cri-base.json` to output initial spec file.
 | 
					      # Use containerd's `ctr oci spec > /etc/containerd/cri-base.json` to output initial spec file.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,10 @@ type Runtime struct {
 | 
				
			|||||||
	// PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the
 | 
						// PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the
 | 
				
			||||||
	// runtime spec when the container is privileged. Defaults to false.
 | 
						// runtime spec when the container is privileged. Defaults to false.
 | 
				
			||||||
	PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices" json:"privileged_without_host_devices"`
 | 
						PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices" json:"privileged_without_host_devices"`
 | 
				
			||||||
 | 
						// PrivilegedWithoutHostDevicesAllDevicesAllowed overloads the default behaviour device allowlisting when
 | 
				
			||||||
 | 
						// to the runtime spec when the container when PrivilegedWithoutHostDevices is already enabled. Requires
 | 
				
			||||||
 | 
						// PrivilegedWithoutHostDevices to be enabled. Defaults to false.
 | 
				
			||||||
 | 
						PrivilegedWithoutHostDevicesAllDevicesAllowed bool `toml:"privileged_without_host_devices_all_devices_allowed" json:"privileged_without_host_devices_all_devices_allowed"`
 | 
				
			||||||
	// BaseRuntimeSpec is a json file with OCI spec to use as base spec that all container's will be created from.
 | 
						// BaseRuntimeSpec is a json file with OCI spec to use as base spec that all container's will be created from.
 | 
				
			||||||
	BaseRuntimeSpec string `toml:"base_runtime_spec" json:"baseRuntimeSpec"`
 | 
						BaseRuntimeSpec string `toml:"base_runtime_spec" json:"baseRuntimeSpec"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -368,6 +372,9 @@ func ValidatePluginConfig(ctx context.Context, c *PluginConfig) error {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead")
 | 
								log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if !r.PrivilegedWithoutHostDevices && r.PrivilegedWithoutHostDevicesAllDevicesAllowed {
 | 
				
			||||||
 | 
								return errors.Errorf("`privileged_without_host_devices_all_devices_allowed` requires `privileged_without_host_devices` to be enabled")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	useConfigPath := c.Registry.ConfigPath != ""
 | 
						useConfigPath := c.Registry.ConfigPath != ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -360,6 +360,21 @@ func TestValidateConfig(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			expectedErr: "`configs.tls` cannot be set when `config_path` is provided",
 | 
								expectedErr: "`configs.tls` cannot be set when `config_path` is provided",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"privileged_without_host_devices_all_devices_allowed without privileged_without_host_devices": {
 | 
				
			||||||
 | 
								config: &PluginConfig{
 | 
				
			||||||
 | 
									ContainerdConfig: ContainerdConfig{
 | 
				
			||||||
 | 
										DefaultRuntimeName: RuntimeDefault,
 | 
				
			||||||
 | 
										Runtimes: map[string]Runtime{
 | 
				
			||||||
 | 
											RuntimeDefault: {
 | 
				
			||||||
 | 
												PrivilegedWithoutHostDevices:                  false,
 | 
				
			||||||
 | 
												PrivilegedWithoutHostDevicesAllDevicesAllowed: true,
 | 
				
			||||||
 | 
												Type: "default",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErr: "`privileged_without_host_devices_all_devices_allowed` requires `privileged_without_host_devices` to be enabled",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	} {
 | 
						} {
 | 
				
			||||||
		t.Run(desc, func(t *testing.T) {
 | 
							t.Run(desc, func(t *testing.T) {
 | 
				
			||||||
			err := ValidatePluginConfig(context.Background(), test.config)
 | 
								err := ValidatePluginConfig(context.Background(), test.config)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -223,6 +223,9 @@ func (c *criService) containerSpec(
 | 
				
			|||||||
		specOpts = append(specOpts, oci.WithPrivileged)
 | 
							specOpts = append(specOpts, oci.WithPrivileged)
 | 
				
			||||||
		if !ociRuntime.PrivilegedWithoutHostDevices {
 | 
							if !ociRuntime.PrivilegedWithoutHostDevices {
 | 
				
			||||||
			specOpts = append(specOpts, oci.WithHostDevices, oci.WithAllDevicesAllowed)
 | 
								specOpts = append(specOpts, oci.WithHostDevices, oci.WithAllDevicesAllowed)
 | 
				
			||||||
 | 
							} else if ociRuntime.PrivilegedWithoutHostDevicesAllDevicesAllowed {
 | 
				
			||||||
 | 
								// allow rwm on all devices for the container
 | 
				
			||||||
 | 
								specOpts = append(specOpts, oci.WithAllDevicesAllowed)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1382,27 +1382,44 @@ func TestPrivilegedDevices(t *testing.T) {
 | 
				
			|||||||
	for desc, test := range map[string]struct {
 | 
						for desc, test := range map[string]struct {
 | 
				
			||||||
		privileged                                    bool
 | 
							privileged                                    bool
 | 
				
			||||||
		privilegedWithoutHostDevices                  bool
 | 
							privilegedWithoutHostDevices                  bool
 | 
				
			||||||
 | 
							privilegedWithoutHostDevicesAllDevicesAllowed bool
 | 
				
			||||||
		expectHostDevices                             bool
 | 
							expectHostDevices                             bool
 | 
				
			||||||
 | 
							expectAllDevicesAllowed                       bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		"expect no host devices when privileged is false": {
 | 
							"expect no host devices when privileged is false": {
 | 
				
			||||||
			privileged:                   false,
 | 
								privileged:                   false,
 | 
				
			||||||
			privilegedWithoutHostDevices: false,
 | 
								privilegedWithoutHostDevices: false,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevicesAllDevicesAllowed: false,
 | 
				
			||||||
			expectHostDevices:       false,
 | 
								expectHostDevices:       false,
 | 
				
			||||||
 | 
								expectAllDevicesAllowed: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"expect no host devices when privileged is false and privilegedWithoutHostDevices is true": {
 | 
							"expect no host devices when privileged is false and privilegedWithoutHostDevices is true": {
 | 
				
			||||||
			privileged:                   false,
 | 
								privileged:                   false,
 | 
				
			||||||
			privilegedWithoutHostDevices: true,
 | 
								privilegedWithoutHostDevices: true,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevicesAllDevicesAllowed: false,
 | 
				
			||||||
			expectHostDevices:       false,
 | 
								expectHostDevices:       false,
 | 
				
			||||||
 | 
								expectAllDevicesAllowed: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"expect host devices when privileged is true": {
 | 
							"expect host devices and all device allowlist when privileged is true": {
 | 
				
			||||||
			privileged:                   true,
 | 
								privileged:                   true,
 | 
				
			||||||
			privilegedWithoutHostDevices: false,
 | 
								privilegedWithoutHostDevices: false,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevicesAllDevicesAllowed: false,
 | 
				
			||||||
			expectHostDevices:       true,
 | 
								expectHostDevices:       true,
 | 
				
			||||||
 | 
								expectAllDevicesAllowed: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"expect no host devices when privileged is true and privilegedWithoutHostDevices is true": {
 | 
							"expect no host devices when privileged is true and privilegedWithoutHostDevices is true": {
 | 
				
			||||||
			privileged:                   true,
 | 
								privileged:                   true,
 | 
				
			||||||
			privilegedWithoutHostDevices: true,
 | 
								privilegedWithoutHostDevices: true,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevicesAllDevicesAllowed: false,
 | 
				
			||||||
			expectHostDevices:       false,
 | 
								expectHostDevices:       false,
 | 
				
			||||||
 | 
								expectAllDevicesAllowed: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"expect host devices and all devices allowlist when privileged is true and privilegedWithoutHostDevices is true and privilegedWithoutHostDevicesAllDevicesAllowed is true": {
 | 
				
			||||||
 | 
								privileged:                   true,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevices: true,
 | 
				
			||||||
 | 
								privilegedWithoutHostDevicesAllDevicesAllowed: true,
 | 
				
			||||||
 | 
								expectHostDevices:       false,
 | 
				
			||||||
 | 
								expectAllDevicesAllowed: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	} {
 | 
						} {
 | 
				
			||||||
		t.Logf("TestCase %q", desc)
 | 
							t.Logf("TestCase %q", desc)
 | 
				
			||||||
@@ -1412,6 +1429,7 @@ func TestPrivilegedDevices(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		ociRuntime := config.Runtime{
 | 
							ociRuntime := config.Runtime{
 | 
				
			||||||
			PrivilegedWithoutHostDevices:                  test.privilegedWithoutHostDevices,
 | 
								PrivilegedWithoutHostDevices:                  test.privilegedWithoutHostDevices,
 | 
				
			||||||
 | 
								PrivilegedWithoutHostDevicesAllDevicesAllowed: test.privilegedWithoutHostDevicesAllDevicesAllowed,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		spec, err := c.containerSpec(t.Name(), testSandboxID, testPid, "", testContainerName, testImageName, containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
 | 
							spec, err := c.containerSpec(t.Name(), testSandboxID, testPid, "", testContainerName, testImageName, containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
@@ -1431,6 +1449,11 @@ func TestPrivilegedDevices(t *testing.T) {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			assert.Empty(t, spec.Linux.Devices)
 | 
								assert.Empty(t, spec.Linux.Devices)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.Len(t, spec.Linux.Resources.Devices, 1)
 | 
				
			||||||
 | 
							assert.Equal(t, spec.Linux.Resources.Devices[0].Allow, test.expectAllDevicesAllowed)
 | 
				
			||||||
 | 
							assert.Equal(t, spec.Linux.Resources.Devices[0].Access, "rwm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user