Handle canonical Docker capability names
This commit is contained in:
parent
2d0f10bb56
commit
d0e8286636
2 changed files with 74 additions and 3 deletions
|
|
@ -1156,10 +1156,16 @@ def _validate_starting_container(
|
||||||
"container_security",
|
"container_security",
|
||||||
"container_cap_drop_mismatch",
|
"container_cap_drop_mismatch",
|
||||||
)
|
)
|
||||||
|
cap_add = host.get("CapAdd")
|
||||||
|
normalized_cap_add = (
|
||||||
|
[item.removeprefix("CAP_") for item in cap_add]
|
||||||
|
if isinstance(cap_add, list) and all(isinstance(item, str) for item in cap_add)
|
||||||
|
else None
|
||||||
|
)
|
||||||
_verification_require(
|
_verification_require(
|
||||||
isinstance(host.get("CapAdd"), list)
|
normalized_cap_add is not None
|
||||||
and all(isinstance(item, str) for item in host["CapAdd"])
|
and len(normalized_cap_add) == len(set(normalized_cap_add))
|
||||||
and sorted(host["CapAdd"]) == ["CHOWN", "SETGID", "SETPCAP", "SETUID"],
|
and sorted(normalized_cap_add) == ["CHOWN", "SETGID", "SETPCAP", "SETUID"],
|
||||||
"container_security",
|
"container_security",
|
||||||
"container_cap_add_mismatch",
|
"container_cap_add_mismatch",
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -725,6 +725,71 @@ def test_container_contract_failures_have_field_specific_bounded_codes(
|
||||||
assert caught.value.failure_reason == failure_reason
|
assert caught.value.failure_reason == failure_reason
|
||||||
|
|
||||||
|
|
||||||
|
def test_container_cap_add_accepts_docker_28_canonical_names(tmp_path: Path) -> None:
|
||||||
|
bundle, release, image = release_bundle(tmp_path, "2")
|
||||||
|
paths = install_paths(tmp_path)
|
||||||
|
host = FakeHost(paths)
|
||||||
|
host.add_release(release, image)
|
||||||
|
installer.install_release(
|
||||||
|
bundle,
|
||||||
|
paths=paths,
|
||||||
|
source_binding=source_binding(),
|
||||||
|
runner=host,
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
execute_restart=True,
|
||||||
|
)
|
||||||
|
assert host.container is not None
|
||||||
|
host.container["HostConfig"]["CapAdd"] = [
|
||||||
|
"CAP_CHOWN",
|
||||||
|
"CAP_SETGID",
|
||||||
|
"CAP_SETPCAP",
|
||||||
|
"CAP_SETUID",
|
||||||
|
]
|
||||||
|
|
||||||
|
verification = installer.verify_running_release(
|
||||||
|
release,
|
||||||
|
runner=host,
|
||||||
|
paths=paths,
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert verification["container_id"] == host.container["Id"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_container_cap_add_rejects_mixed_duplicate_names(tmp_path: Path) -> None:
|
||||||
|
bundle, release, image = release_bundle(tmp_path, "2")
|
||||||
|
paths = install_paths(tmp_path)
|
||||||
|
host = FakeHost(paths)
|
||||||
|
host.add_release(release, image)
|
||||||
|
installer.install_release(
|
||||||
|
bundle,
|
||||||
|
paths=paths,
|
||||||
|
source_binding=source_binding(),
|
||||||
|
runner=host,
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
execute_restart=True,
|
||||||
|
)
|
||||||
|
assert host.container is not None
|
||||||
|
host.container["HostConfig"]["CapAdd"] = [
|
||||||
|
"CHOWN",
|
||||||
|
"CAP_CHOWN",
|
||||||
|
"SETGID",
|
||||||
|
"SETPCAP",
|
||||||
|
"SETUID",
|
||||||
|
]
|
||||||
|
|
||||||
|
with pytest.raises(installer.VerificationError) as caught:
|
||||||
|
installer.verify_running_release(
|
||||||
|
release,
|
||||||
|
runner=host,
|
||||||
|
paths=paths,
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert caught.value.failure_stage == "container_security"
|
||||||
|
assert caught.value.failure_reason == "container_cap_add_mismatch"
|
||||||
|
|
||||||
|
|
||||||
def test_container_inspection_shape_has_bounded_code(tmp_path: Path) -> None:
|
def test_container_inspection_shape_has_bounded_code(tmp_path: Path) -> None:
|
||||||
bundle, release, image = release_bundle(tmp_path, "2")
|
bundle, release, image = release_bundle(tmp_path, "2")
|
||||||
paths = install_paths(tmp_path)
|
paths = install_paths(tmp_path)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue