Skip to content

Latest commit

 

History

History
184 lines (116 loc) · 11.8 KB

0002-no-root-in-containers.md

File metadata and controls

184 lines (116 loc) · 11.8 KB

CBPP-0002: Container should execute process(es) as non-root user

Release Signoff Checklist

Items marked with (R) are required for the proposed best practice to be included in a release.

  • (R) CBPP approvers have approved the CBPP status as implementable
  • (R) CBPP summary, motivation and best practice details are appropriately documented
  • (R) Test plan is in place, giving consideration to CNF Test Suite input
  • (R) Scoring has been determined
  • "Implementation History" section is up-to-date
  • Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes

Summary

Containers have a list of their own users independent of the host system, one of which is UID 0, the root user. Containers should run processes as a user other than root which makes it easier to run the container images securely.

Motivation

This best practice benefits the CNF developer, improving the quality of the CNF and reducing the developer's likelihood of having to diagnose problems with the CNF. Validation of the best practice is the responsibility of the CNF developer.

Indirectly, improved CNF quality benefits CNF operators. The proposed tests are runnable by CNF operators as acceptance tests.

SE-Linux based environments will require dropping root privileges. Example: OpenShift

Goals

Avoiding root in containers can help to:

  • Improve the security and behaviour of applications.
  • Add to the defense in depth strategy against external compromises.
  • Avoid compromised apps from causing more damage.

Non-Goals

This BP recommends that the application not use the UID that can override all protections. This means that file read and write protections can be established.

It does not consider what filesystem write permissions should be in order to benefit from those protections. CNF developers will additionally want to ensure filesystem permissions are tightened up appropriately so that non-root users are prevented from doing damage. This is outside the BP scope.

Proposal

When building a container, the container should be built to run its processes as a non-root user. setsid processes should not be required to do the work inside a container.

A container's root user has fewer Linux Kernel capabilities and may be distinct from the platform's root (if the container runtime enables user namespaces remap feature).

However, the container's root user does have full read/write access to the container's filesystem. It can read or modify any file. No secrets can be kept from it; it cannot be prevented from changing the content of all executable files on the system.

On a basic level, avoiding the root user means that the container filesystem permissions are enforceable against all processes running in the system. Those processes can be prevented from doing critical things like:

  • viewing secrets they should not be viewing
  • modifying binaries within the filesystem that will later be executed

Obviously, a well-written CNF would not be attempting to do things it should not do. But all software has bugs. Also, executing processes can be compromised by outside forces, and if this happens filesystem protection is a part of a "Defense in depth" strategy to ensure the compromise does not escalate.

User/group access enforcement will be respected. As an added advantage, fine-grained access enforcement, such as in SELinux, will also hold

Workload Context

All pod types should implement this best practice.

User Stories (Optional)

Supply chain attack user stories

Supply chain attacks are a risk at any point in the supply chain. ‘Defence in depth’ says that we should (a) defend against supply chain attacks but also (b) add mitigations in the case that supply chain attacks happen.

Examples include

In all of these examples, the CNFs using a non-root user for their container processes, have limited the scope of damage a compromised process may cause.

See main defense in depth for supply chain attacks document for more information.

Notes/Constraints/Caveats (Optional)

Container images are frequently built from upstream image versions made from OS deployments. These will include things like setsid binaries as a part of their base configuration. If CNF developers follow this best practice they will have to audit and clean up any upstream images to respect this rule (removing files, removing packages or changing permissions as appropriate).

By default, the first process starting in a container runs as root - you have to actively take steps to shed the permissions (Dockerfile USER line, plus installing files with appropriate ownership within the Dockerfile).

We specifically want the process to run as a non-root user so that its access is limited. Of course, if access is limited then the CNF developer must ensure that access is still available to the things the CNF is going to need to access. This will involve changing permissions on data files and on working directories when the container image is constructed (they cannot be changed on startup because the application does not have the right to do that). This may also affect the use of shared volume mounts or host mounts - ownership of and rights on the root directory must permit access to the container users.

References

Alternatives (Optional)

These are not strictly alternatives as they can be used with non-root, but can be applied to a container running as root.

  • Disable all capabilities or limit them
  • Do not run the container in privileged mode

Related items include

Testing Objectives

An application which follows this best practice will not have any containers with processes running as root

This CBPP will be tested by the CNF Test Suite.

Static analysis

A container image can be tested for compliance:

  • The container metadata should indicate that the first process started is started as a non-root user
  • The container filesystem will not have setsid-root binaries.

If available, the Dockerfile can be checked to see if a non-root user is used. (Dockerfiles are not the only way to build containers, and the Dockerfile may not be a part of the CNF deliverable.)

  • See USER and RUN commands, both of which allow the Dockerfile author to express which user is to be used when launching the container.

The above static analysis definitively confirms that a container cannot elevate privileges to local root as it removes all avenues for doing so.

Runtime analysis

One can check for processes launched as, or running as container root.

We offer the following applications as examples that operators might wish to evaluate for this purpose:

  • Cnitch periodically checks the list of running containers in a Docker environment to see if any are running as container root.
  • Falco checks for processes running as container root if the non-root container policy is set.

Scanning systems that periodically check running processes or may not identify all root-owned processes, as it must conduct a scan at the moment a process is running. Similarly, process monitoring will not identify a problem if behaviour requiring a root process is not triggered. This cannot be used as a definitive guarantee of safety but is useful as a secondary check.

Scoring

This best practice results in a pass/fail on two counts, depending on role.

Static analysis (all items checked for a pass) - CNF developers (testing before delivery) or CNF operators (testing what is delivered):

  • Container images indicate their processes should be started as a user other than 0
  • Container images should not contain setsid-root binaries (user 0, u+s)

Runtime analysis - CNF operators:

  • Operators may use runtime verification, from outside the application, to confirm that containers in processes are not owned by container root

Implementation History

First version: July 2021