Skip to content

Conversation

@hdwhdw
Copy link
Contributor

@hdwhdw hdwhdw commented Dec 4, 2025

Why I did it

Implement container hardening for the GNMI container as per the SONiC Container Hardening HLD. This improves security by following the principle of least privilege, replacing the --privileged flag with specific Linux capabilities.

Fixes #24542

How I did it

Modified rules/docker-gnmi.mk to replace --privileged with specific Linux capabilities and security options:

Capabilities added:

  • CAP_SYS_ADMIN: For system administration operations
  • CAP_SYS_BOOT: For reboot operations via gNOI
  • CAP_SYS_MODULE: For kernel module operations
  • CAP_DAC_OVERRIDE: To bypass file permission checks
  • CAP_DAC_READ_SEARCH: To read files regardless of permissions
  • CAP_NET_ADMIN: For network administration
  • CAP_NET_BIND_SERVICE: To bind to privileged ports
  • CAP_SYS_PTRACE: To access /proc/[pid]/ns/* of other processes (required for nsenter)
  • CAP_IPC_OWNER: For IPC namespace access

Security options added:

  • --security-opt apparmor=unconfined
  • --security-opt seccomp=unconfined

These security options are required for nsenter to access host namespaces from within the container.

How to verify it

Testing performed on vlab-01:

  1. Modified the container startup script:

    # Copy and edit gnmi.sh to replace --privileged with capabilities
    scp admin@vlab-01:/usr/bin/gnmi.sh /tmp/gnmi.sh
    # Edit the file locally to add capabilities and security options
    # Copy back and restart
    scp /tmp/gnmi.sh admin@vlab-01:/tmp/gnmi_new.sh
    ssh admin@vlab-01 "sudo cp /tmp/gnmi_new.sh /usr/bin/gnmi.sh && docker rm -f gnmi && sudo systemctl restart gnmi"
  2. Verified container is running without --privileged:

    docker ps | grep gnmi
    # Output: Container running successfully with new configuration
  3. Key Test - nsenter from INSIDE the container (this is how gNOI operates):

    # Execute sonic-installer from inside the container using nsenter
    ssh admin@vlab-01 "docker exec gnmi nsenter -t 1 -m -n -p -u -i sonic-installer list"
    
    # Output:
    Current: SONiC-OS-master.982719-6ccc6065f
    Next: SONiC-OS-master.982719-6ccc6065f
    Available: 
    SONiC-OS-master.982719-6ccc6065f
    SONiC-OS-master.883725-686876262
  4. Verified capabilities inside the container:

    ssh admin@vlab-01 "docker exec gnmi capsh --print"
    # Shows all the added capabilities in the bounding set
  5. Tested reboot functionality:

    # From inside container
    ssh admin@vlab-01 "docker exec gnmi nsenter -t 1 -m -n -p -u -i reboot --help"
    # Successfully shows reboot help
    
    # Actually executed reboot to confirm full functionality
    ssh admin@vlab-01 "docker exec gnmi nsenter -t 1 -m -n -p -u -i reboot"
    # System rebooted successfully

Important: The testing confirms that gNOI can execute host commands (sonic-installer, reboot) from within the container using nsenter, which is the actual use case. Without SYS_PTRACE capability and the security options, nsenter would fail with "Permission denied" when trying to access /proc/1/ns/*.

Which release branch to backport (provide reason below if selected)

  • 202405
  • 202411

Description for the changelog

Replace --privileged flag with specific Linux capabilities and security options for GNMI container to improve security while maintaining gNOI functionality including nsenter operations from within the container.

Copilot AI review requested due to automatic review settings December 4, 2025 21:15
@mssonicbld
Copy link
Collaborator

/azp run Azure.sonic-buildimage

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copilot finished reviewing on behalf of hdwhdw December 4, 2025 21:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves container security by replacing the --privileged flag in the docker-gnmi container with specific Linux capabilities. Instead of granting all privileges, the container now receives only the capabilities needed for GNMI/GNOI operations: SYS_ADMIN, SYS_BOOT, SYS_PTRACE, NET_ADMIN, and DAC_OVERRIDE. This follows the principle of least privilege for container hardening.

Key Changes:

  • Removed --privileged flag from GNMI container runtime options
  • Added five specific Linux capabilities (SYS_ADMIN, SYS_BOOT, SYS_PTRACE, NET_ADMIN, DAC_OVERRIDE)
  • Added security options for apparmor and seccomp to enable nsenter access to host namespaces

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

$(DOCKER_GNMI)_RUN_OPT += --cap-add=DAC_OVERRIDE
# Security options needed for nsenter to access host namespaces from within container
$(DOCKER_GNMI)_RUN_OPT += --security-opt apparmor=unconfined
$(DOCKER_GNMI)_RUN_OPT += --security-opt seccomp=unconfined
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The combination of --security-opt seccomp=unconfined with multiple powerful capabilities (SYS_ADMIN, SYS_BOOT, SYS_PTRACE) significantly reduces the security benefit of removing --privileged. Disabling seccomp removes syscall filtering, which is a critical security layer.

While --security-opt apparmor=unconfined is used in other containers (e.g., docker-orchagent.mk:39, docker-platform-monitor.mk:53), seccomp=unconfined is unique to this container and should be justified. Consider:

  1. Identifying the specific syscalls needed by the GNMI container
  2. Creating a custom seccomp profile that allows only those syscalls
  3. Removing the seccomp=unconfined option if it's not strictly necessary

This would provide better defense-in-depth while maintaining functionality.

Suggested change
$(DOCKER_GNMI)_RUN_OPT += --security-opt seccomp=unconfined

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gnmi container should remove privileged mode

3 participants