0% found this document useful (0 votes)
230 views

Containers-Best Practices PDF

Uploaded by

Rama Garcia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
230 views

Containers-Best Practices PDF

Uploaded by

Rama Garcia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

Creating non-root

containers with support


for arbitrary UIDs
Containers for
production environments

Juan Ariza Toledano

May 2020

©2020 VMware, Inc.


Agenda I. Why non-root containers?

II. Why arbitrary UIDs?

III. Main challenges

IV. Enough talking... Let’s do an example!

©2020 VMware, Inc. 2


About me
Joined Bitnami 4 years ago
(now part of VMware)

Focused on packaging open-


source applications

Juan Ariza Toledano


MTS at VMware

Helm charts maintainer &


CKAD certified

©2020 VMware, Inc. 3


Why non-root containers?

©2020 VMware, Inc. 4


What’s a non-root container?

There is no magic here!

A non-root container it’s just a container


executed with a non privileged user.

©2020 VMware, Inc. 5


Why non-root containers

Security Platform Restrictions

Non-root containers are automatically Some K8s distributions implement Pod


more secure. Security Policies that requires running
containers without privileges.

The reason: they prevent malicious code


from gaining elevated permissions on the
container host.

©2020 VMware, Inc. 6


Why arbitrary UIDs?

©2020 VMware, Inc. 7


Arbitrary UID? What do you mean?

Every container image has a default user.

However, we can execute a container with any


user we want, regardless its default one.

$ docker run --user=[ uid | uid:gid] IMAGE[:TAG]

©2020 VMware, Inc. 8


Why arbitrary UIDs?

Again, both security and platform


restrictions (mainly Openshift) are the
reasons behind this.

“In order to support running containers with volumes mounted


in a secure fashion, images should be capable of being run as
any arbitrary user ID. When OpenShift mounts volumes for a
container, it configures the volume so it can only be written to
be a particular user ID, and then runs the image using that
same user ID. This ensures the volume is only accessible to the
appropriate container, but requires the image be able to run as
an arbitrary user ID.”

Reference: https://docs.openshift.com/enterprise/3.0/creating_images/guidelines.html

©2020 VMware, Inc. 9


Main challenges

©2020 VMware, Inc. 10


Main challenges

Adapting file Privileged ports Actions that No assumptions


permissions. cannot be used require privileges about uid/gids
anymore (0-1023) permissions
cannot be
performed

©2020 VMware, Inc. 11


Enough talking… Let’s
do an example!

©2020 VMware, Inc. 12


Enough talking… Let’s do an example

Sometimes we think we understood


sth…
Let’s create a non-root NGINX
container with support for arbitrary
UIDs

But then…

©2020 VMware, Inc. 13


Let’s do an example!
NGINX Dockerfile

FROM bitnami/minideb:buster
LABEL maintaner "Juan Ariza Toledano <[email protected]>"

RUN apt-get update && \


# Install NGINX
apt-get install -y nginx && \
# Upgrade packages and clean cache
apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives

EXPOSE 80 443

ENTRYPOINT ["nginx"]
CMD ["-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]

©2020 VMware, Inc. 14


Let’s do an example!
Build and run container

$ docker build . -t my-nginx:v1


$ docker run --detach --rm --name nginx --publish 80:80 my-nginx:v1
$ curl http://127.0.0.1/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

</head>
<body>
<h1>Welcome to nginx!</h1>

</body>
</html>

©2020 VMware, Inc. 15


Let’s do an example!
Let’s make it non-root by default

FROM bitnami/minideb:buster
LABEL maintaner "Juan Ariza Toledano <[email protected]>"

RUN apt-get update && \


# Install NGINX
apt-get install -y nginx && \
# Upgrade packages and clean cache
apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives

EXPOSE 80 443

USER 1001

ENTRYPOINT ["nginx"]
CMD ["-c:", "/etc/nginx/nginx.conf", "-g", "daemon off;"]

©2020 VMware, Inc. 16


Let’s do an example!
Build and run container

$ docker build . -t my-nginx:v2


$ docker run --rm --name nginx --publish 80:80 my-nginx:v2
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2020/04/23 10:09:41 [warn] 1#1: the "user" directive makes sense only if the master process runs with super-
user privileges, ignored in /etc/nginx/nginx.conf:1
2020/04/23 10:09:41 [emerg] 1#1: mkdir() "/var/lib/nginx/body" failed (13: Permission denied)

©2020 VMware, Inc. 17


Let’s do an example File Permissions
Fixing file permissions issues

NGINX requires writing permissions in these directories/files:


• /var/lib/nginx
• /var/log/nginx/access.log
What directories should be
• /var/log/nginx/error.log
• /run (pid file) writable by the application?

Adapt them by giving writing


apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives permissions to the non-root
user.
+ RUN chown 1001 –R /var/lib/nginx /var/log/nginx && \
+ chmod 777 /run

EXPOSE 80 443
USER 1001

©2020 VMware, Inc. 18


Let’s do an example!
Build and run container

$ docker build . -t my-nginx:v3


$ docker run --rm --name nginx --publish 80:80 my-nginx:v3
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges,
ignored in /etc/nginx/nginx.conf:1
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

©2020 VMware, Inc. 19


Let’s do an example Privileged ports
Adapting ports used by the application

NGINX uses port 80/443 by default. We can change that in the


configuration files available at /etc/nginx.
We cannot use privileged
server {
listen 8080 default_server; ports (1-1023) anymore.
listen [::]:8080 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}

RUN chown 1001 –R /var/lib/nginx /var/log/nginx && \


chmod 777 /run
Alternative, use authbind
+ COPY config/default /etc/nginx/sites-available/default
http://manpages.ubuntu.com/manpages
- EXPOSE 80 443
+ EXPOSE 8080 /bionic/man1/authbind.1.html
USER 1001

©2020 VMware, Inc. 20


Let’s do an example!
Build and run container

$ docker build . -t my-nginx:v4


$ docker run --rm --name nginx -detatch --publish 8080:8080 my-nginx:v4
$ curl http://127.0.0.1:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

</head>
<body>
<h1>Welcome to nginx!</h1>

</body>
</html>

©2020 VMware, Inc. 21


Let’s do an example Privileged actions
Privileged actions

Remember that limition! You won’t be able to perform certain actions in


the container.
Actions that require
For instance, installing an editor to modify the NGINX configuration.
privileges permissions
cannot be performed

$ docker exec -it nginx bash


I have no name!@...:/$ apt-get install -y vim && vim /etc/nginx/sites-available/default
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?

©2020 VMware, Inc. 22


Let’s do an example Arbitrary UIDs (I)
Adding support for arbitrary UIDs

$ docker run --rm --name nginx --publish 8080:8080 --user 1002 my-nginx:v4
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13:
We have a non-root NGINX
Permission denied)
2020/04/23 11:25:48 [warn] 1#1: the "user" directive makes sense only if the master container, great!!
process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:1
2020/04/23 11:25:48 [emerg] 1#1: mkdir() "/var/lib/nginx/body" failed (13: Permission
denied)
But does it support arbitrary
UIDs?
apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives

+ RUN chown 1001 –R /var/lib/nginx /var/log/nginx && \


+ chmod 777 /run

EXPOSE 8080
USER 1001

©2020 VMware, Inc. 23


Let’s do an example Arbitrary UIDs (II)
Adding support for arbitrary UIDs

Instead of giving permission by modifying the files/directories ownership,


we can provide those permissions to the group.

Openshift changes the


apt-get upgrade -y && \
rm -r /var/lib/apt/lists /var/cache/apt/archives
default container user with
an arbitrary UID…
- RUN chown 1001 –R /var/lib/nginx /var/log/nginx && \
- chmod 777 /run
… but it doesn’t modify the
+ RUN chown root:root -R /var/lib/nginx /var/log/nginx /run && \ GID!
chmod -R g+rwX /var/lib/nginx /var/log/nginx /run

EXPOSE 8080 It means containers are


USER 1001
executed as XXX:root (where
XXX is the arbitrary UID)

©2020 VMware, Inc. 24


Let’s do an example!
Build and run container

$ docker build . -t my-nginx:v5


$ docker run --rm --name nginx -detatch --publish 8080:8080 --user 1002 my-nginx:v5
$ curl http://127.0.0.1:8080/
<!DOCTYPE html>
<html>

<body>
<h1>Welcome to nginx!</h1>

</body>
</html>
$ docker exec nginx id –u
1002
$ docker exec nginx ls -la /var/log/nginx/access.log
-rw-rw---- 1 root root 0 Apr 23 09:39 /var/log/nginx/access.log
$ docker exec -it nginx bash
I have no name!@...:/$

©2020 VMware, Inc. 25


Let’s do an example
I noticed there’s no username associated to the UID!! What can I do?

Dynamically editing Assuming ‘I have no


Use NSS wrapper
/etc/password name!’

if ! whoami &> /dev/null; then You can use this library to Unless the application requires
if [ -w /etc/passwd ]; then
echo "${USER_NAME:-default}:x:$(id dynamically define custom a valid username, don’t do
-u):0:${USER_NAME:-default}
user:${HOME}:/bin/bash" >> /etc/passwd
passwd and group files. anything
fi
fi Pros: Pros:

• You don’t need to edit /etc/passwd • 100% compatible with arbitrary UIDs

Pros: Cons: Cons:

• 100% compatible with arbitrary UIDs • The non-root user still needs writing • An “ugly” prompt
permission in the custom passwd
Cons: and group files

• Requires /etc/passwd to be writable


by non-root user

• Very insecure

©2020 VMware, Inc. 26


Summary

• Study your application:


• What packages does it need?
• What ports does it expose?
• What directories require
read/write/execution permissions?
• How do you configure it?

• Adapt the file system permissions.

• Configure it to use non-priviliged ports.

• Avoid UID(s) assumptions.

©2020 VMware, Inc. 27


Let’s deploy to production!
re d
ire r
std ct l n n e
ou og sca
t/s s to
tde CVE
rr
reduce size
d - o n l y
re a
e sy s te m
fi l D
I/ C
C

https://github.com/juan131/dockerfile-best-practices

©2020 VMware, Inc. 28


Questions?

©2020 VMware, Inc. 29


Thank You

©2020 VMware, Inc.

You might also like