From f4d90dc0dd33392484591e029699dff98eb5e328 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 6 Oct 2026 05:59:53 +0000 Subject: [PATCH 1/2] Add test for iptables switching at runtime for non root user --- .github/workflows/test-all.yaml | 2 +- .github/workflows/test-pr-arm64.yaml | 2 +- .github/workflows/test-pr.yaml | 3 ++- ...cker_iptables_switch_at_runtime_non_root.sh | 12 ++++++++++++ .../Dockerfile | 3 +++ test/docker-in-docker/scenarios.json | 18 ++++++++++++++++++ 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 test/docker-in-docker/docker_iptables_switch_at_runtime_non_root.sh create mode 100644 test/docker-in-docker/docker_iptables_switch_at_runtime_non_root/Dockerfile diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 71b7bee73..7ce56f8c7 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -117,7 +117,7 @@ jobs: run: | sudo apt-get update && sudo apt-get install -y jq sed 's://.*$::' test/docker-in-docker/scenarios.json \ - | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu)' \ + | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu, .docker_iptables_switch_at_runtime_non_root)' \ > test/docker-in-docker/scenarios.json.tmp mv test/docker-in-docker/scenarios.json.tmp test/docker-in-docker/scenarios.json diff --git a/.github/workflows/test-pr-arm64.yaml b/.github/workflows/test-pr-arm64.yaml index 758586389..a22e4209e 100644 --- a/.github/workflows/test-pr-arm64.yaml +++ b/.github/workflows/test-pr-arm64.yaml @@ -80,7 +80,7 @@ jobs: run: | sudo apt-get update && sudo apt-get install -y jq sed 's://.*$::' test/docker-in-docker/scenarios.json \ - | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu)' \ + | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu, .docker_iptables_switch_at_runtime_non_root)' \ > test/docker-in-docker/scenarios.json.tmp mv test/docker-in-docker/scenarios.json.tmp test/docker-in-docker/scenarios.json diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index ecc96afbb..1c86a2265 100644 --- a/.github/workflows/test-pr.yaml +++ b/.github/workflows/test-pr.yaml @@ -96,7 +96,7 @@ jobs: run: | sudo apt-get update && sudo apt-get install -y jq sed 's://.*$::' test/docker-in-docker/scenarios.json \ - | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu)' \ + | jq 'del(.docker_with_default_iptables, .docker_with_default_iptables_ubuntu, .docker_iptables_switch_at_runtime_non_root)' \ > test/docker-in-docker/scenarios.json.tmp mv test/docker-in-docker/scenarios.json.tmp test/docker-in-docker/scenarios.json @@ -114,6 +114,7 @@ jobs: scenario: - docker_with_default_iptables - docker_with_default_iptables_ubuntu + - docker_iptables_switch_at_runtime_non_root steps: - uses: actions/checkout@v7 diff --git a/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root.sh b/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root.sh new file mode 100644 index 000000000..7a957b55d --- /dev/null +++ b/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +check "entrypoint runs as codespace" bash -c "test \"$(id -un)\" = codespace" +check "iptables uses legacy backend" bash -c "iptables --version | grep -q '(legacy)'" + +# Report result +reportResults \ No newline at end of file diff --git a/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root/Dockerfile b/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root/Dockerfile new file mode 100644 index 000000000..84a598d42 --- /dev/null +++ b/test/docker-in-docker/docker_iptables_switch_at_runtime_non_root/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:noble + +RUN if id ubuntu > /dev/null 2>&1; then userdel -f -r ubuntu; fi diff --git a/test/docker-in-docker/scenarios.json b/test/docker-in-docker/scenarios.json index af18591bf..22f64f729 100644 --- a/test/docker-in-docker/scenarios.json +++ b/test/docker-in-docker/scenarios.json @@ -36,6 +36,24 @@ }, "initializeCommand": "sudo modprobe ip_tables" }, + "docker_iptables_switch_at_runtime_non_root": { + "build": { + "dockerfile": "Dockerfile" + }, + "containerUser": "codespace", + "remoteUser": "codespace", + "features": { + "common-utils": { + "username": "codespace", + "userUid": "1000", + "userGid": "1000" + }, + "docker-in-docker": { + "moby": "false", + "iptablesSwitchAtRuntime": true + } + } + }, "docker_with_default_iptables": { "image": "mcr.microsoft.com/devcontainers/base:debian", "features": { From 963c650d68309935d2abe8ceb3043965ee770c53 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 6 Oct 2026 06:13:14 +0000 Subject: [PATCH 2/2] Fixing the permission issue with the selection of iptables at runtime. --- .../devcontainer-feature.json | 2 +- src/docker-in-docker/install.sh | 29 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/docker-in-docker/devcontainer-feature.json b/src/docker-in-docker/devcontainer-feature.json index c76df9661..b6f7d1611 100644 --- a/src/docker-in-docker/devcontainer-feature.json +++ b/src/docker-in-docker/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "docker-in-docker", - "version": "4.1.2", + "version": "4.1.3", "name": "Docker (Docker-in-Docker)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-in-docker", "description": "Create child containers *inside* a container, independent from the host's docker instance. Installs Docker extension in the container along with needed CLIs.", diff --git a/src/docker-in-docker/install.sh b/src/docker-in-docker/install.sh index cd7b9a120..ab57b5580 100755 --- a/src/docker-in-docker/install.sh +++ b/src/docker-in-docker/install.sh @@ -982,6 +982,17 @@ DOCKER_HOST_GATEWAY_IP=${DOCKER_HOST_GATEWAY_IP} DOCKER_DEFAULT_IP6_TABLES=${DOCKER_DEFAULT_IP6_TABLES} EOF +tee -a /usr/local/share/docker-init.sh > /dev/null \ +<< 'EOF' +sudo_if() { + if [ "$(id -u)" -ne 0 ]; then + sudo "$@" + else + "$@" + fi +} +EOF + # On Debian-based images, re-assert the iptables alternative at container start # (only when the user opted into runtime switching via iptablesSwitchAtRuntime=true). if [ "${IPTABLES_SWITCH_AT_RUNTIME}" = "true" ] && [ "${ADJUSTED_ID}" = "debian" ]; then @@ -995,12 +1006,12 @@ if type iptables-legacy > /dev/null 2>&1 \ && { grep -qE '^(ip_tables)\b' /proc/modules \ || [ -d /sys/module/ip_tables ]; } \ && update-alternatives --list iptables 2>/dev/null | grep -q '/usr/sbin/iptables-legacy'; then - update-alternatives --set iptables /usr/sbin/iptables-legacy || true - update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true + sudo_if update-alternatives --set iptables /usr/sbin/iptables-legacy || true + sudo_if update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true elif type iptables-nft > /dev/null 2>&1 \ && update-alternatives --list iptables 2>/dev/null | grep -q '/usr/sbin/iptables-nft'; then - update-alternatives --set iptables /usr/sbin/iptables-nft || true - update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true + sudo_if update-alternatives --set iptables /usr/sbin/iptables-nft || true + sudo_if update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true fi EOF fi @@ -1130,16 +1141,6 @@ dockerd_start="AZURE_DNS_AUTO_DETECTION=${AZURE_DNS_AUTO_DETECTION} DOCKER_DEFAU INNEREOF )" -sudo_if() { - COMMAND="$*" - - if [ "$(id -u)" -ne 0 ]; then - sudo $COMMAND - else - $COMMAND - fi -} - retry_docker_start_count=0 docker_ok="false"