From 82d7622c4588924d276c682d608ac82f149a8e56 Mon Sep 17 00:00:00 2001 From: Jaroslav Henner <1187265+jarovo@users.noreply.github.com> Date: Mon, 19 May 2025 00:16:04 +0200 Subject: [PATCH] Add relabel option to secrets On selinux enabled system, the secrets cannot be read without proper relabeling or correct policy being set. This patch enables user to instruc podman-copose to use :z or :Z podman volume options to make podman relabel the file under bind-mount. More info here: https://unix.stackexchange.com/questions/728801/host-wide-consequences-of-setting-selinux-z-z-option-on-container-bind-mounts?rq=1 Signed-off-by: Jaroslav Henner <1187265+jarovo@users.noreply.github.com> --- docs/Extensions.md | 16 ++++++++++++++++ .../secret-selinux-relabel-option.feature | 1 + podman_compose.py | 14 +++++++++++++- tests/unit/test_container_to_args_secrets.py | 12 ++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 newsfragments/secret-selinux-relabel-option.feature diff --git a/docs/Extensions.md b/docs/Extensions.md index 11f01c3..c4adf80 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -27,6 +27,22 @@ services: For explanations of these extensions, please refer to the [Podman Documentation](https://docs.podman.io/). +## Secrets +The following extension keys are available under `secret` configuration: + + x-podman.relabel - Configure SELinux relabeling + +For example, the following configures custom-secret to use mount with private and unshared content. +Only the current container can use a private volume. + +```yml +secrets: + custom-secret: + x-podman.relabel: Z +``` + +For explanations of these extensions, please refer to the [podman-run --volume documentation](https://docs.podman.io/en/latest/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options)). + ## Network management The following extension keys are available under network configuration: diff --git a/newsfragments/secret-selinux-relabel-option.feature b/newsfragments/secret-selinux-relabel-option.feature new file mode 100644 index 0000000..6cf6b5f --- /dev/null +++ b/newsfragments/secret-selinux-relabel-option.feature @@ -0,0 +1 @@ +- Add relabel option to secret to make possible to read the secret file by the contained process. \ No newline at end of file diff --git a/podman_compose.py b/podman_compose.py index f0841d5..759cca8 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -577,6 +577,7 @@ def get_secret_args(compose, cnt, secret, podman_is_building=False): declared_secret = compose.declared_secrets[secret_name] source_file = declared_secret.get("file") + x_podman_relabel = declared_secret.get("x-podman.relabel") dest_file = "" secret_opts = "" @@ -618,7 +619,18 @@ def get_secret_args(compose, cnt, secret, podman_is_building=False): dest_file = f"/run/secrets/{sec}" else: dest_file = secret_target - volume_ref = ["--volume", f"{source_file}:{dest_file}:ro,rprivate,rbind"] + + mount_options = 'ro,rprivate,rbind' + + selinux_relabel_to_mount_option_map = {None: "", "z": ",z", "Z": ",Z"} + try: + mount_options += selinux_relabel_to_mount_option_map[x_podman_relabel] + except KeyError as exc: + raise ValueError( + f'ERROR: Run secret "{secret_name} has invalid "relabel" option related ' + + f' to SELinux "{x_podman_relabel}". Expected "z" "Z" or nothing.' + ) from exc + volume_ref = ["--volume", f"{source_file}:{dest_file}:{mount_options}"] if secret_uid or secret_gid or secret_mode: sec = secret_target if secret_target else secret_name diff --git a/tests/unit/test_container_to_args_secrets.py b/tests/unit/test_container_to_args_secrets.py index 084839b..85906a0 100644 --- a/tests/unit/test_container_to_args_secrets.py +++ b/tests/unit/test_container_to_args_secrets.py @@ -302,6 +302,18 @@ class TestContainerToArgsSecrets(unittest.IsolatedAsyncioTestCase): "file_secret", repo_root() + "/test_dirname/my_secret:/run/secrets/file_secret:ro,rprivate,rbind", ), + ( + "relabel", + {"file_secret": {"file": "./my_secret", "x-podman.relabel": "Z"}}, + "file_secret", + repo_root() + "/test_dirname/my_secret:/run/secrets/file_secret:ro,rprivate,rbind,Z", + ), + ( + "relabel", + {"file_secret": {"file": "./my_secret", "x-podman.relabel": "z"}}, + "file_secret", + repo_root() + "/test_dirname/my_secret:/run/secrets/file_secret:ro,rprivate,rbind,z", + ), ( "custom_target_name", {