Читать книгу Cloud Native Security - Chris Binnie - Страница 27

Setting Up Podman

Оглавление

We are going to use the Ubuntu 20.04 Long Term Support (LTS) release to run Podman as rootless. This is because according to the docs (github.com/containers/podman/blob/master/docs/tutorials/rootless_tutorial.md), if you read this important note about the fuse-overlayfs package, you need at least version 0.7.6: “This especially needs to be checked on Ubuntu distributions as fuse-overlayfs is not generally installed by default and the 0.7.6 version is not available natively on Ubuntu releases prior to 20.04.”

To install Podman, notably this time as the root user, we will first add a source to the apt package manager this way as one long command which should go on one line:

$ echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu _20.04/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list

If you're not using Ubuntu 20.04, then alter the 20.04 string in the previous command. If you want to try other Linux distributions, then you can use this page: podman.io/getting-started/installation.

Next, we need to add the repository's key to our keyring as a trusted source (changing 20.04 if required again) which is one line command:

$ curl -L

https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/Release.key | sudo apt-key add -

A successful response is OK.

Now, refresh your packages and upgrade any that require upgrading:

$ sudo apt-get update; sudo apt-get upgrade -y

We should now be able to install Podman as follows:

$ apt-get -y install podman

Note the output from that command, shown here, so you can get an idea of the underlying components used:

Recommended packages: crun slirp4netns varlink The following NEW packages will be installed catatonit conmon containernetworking-plugins containers-common containers-golang containers-image crun libyajl2 podman podman-plugins runc slirp4netns uidmap varlink

Check that Podman has installed correctly:

$ podman -v podman version 2.0.4

We need to check our UID and GID mapping settings files to run rootless containers next. Run these commands and delete any entries (only on a development system!) to check that they are empty:

$ cat /etc/subuid $ cat /etc/subgid

This is the point where you might want to create a specific user for running rootless containers. Simply use the adduser command with a username of your choice, such as poduser, and follow the prompts:

$ sudo adduser poduser

We will stick with user chris, however, for continuity.

Now we want to populate the subuid and subgid files in the /etc directory. Use this command to set the ranges of UIDs and GIDS that you want to use, changing the name of the user at the end to suit your requirements:

$ sudo usermod --add-subuids 200000-201000 --add-subgids 200000-201000 chris

Without any more tweaking or fiddling, we are ready to run Podman in rootless mode. It has been a particularly painless process so far.

First, however, remember that Podman is not running as a daemon. Take a look with this command (to be really sure, run this as the root user to see any hidden processes in the process table, and not only as the chris user):

$ ps -ef | grep podman

The only output you should see is the grep command that you've just run. But, if we run this Podman command, we should see a service ready and waiting:

$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

It looks remarkably familiar, just as Docker Engine would output. Using the chris user we can start up a container using another familiar command for Apache:

$ podman run -it -p 8000:80 httpd:latest

We have not added the -d switch to that command, and Listing 2.4 shows the STDOUT logging (output straight to the terminal).

Listing 2.4: Podman Running Rootless with Little Effort

AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.2.100. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.2.100. Set the 'ServerName' directive globally to suppress this message [Tue Aug 29 14:09:20.303062 2020] [mpm_event:notice] [pid 1:tid 140532155102336] AH00489: Apache/2.4.46 (Unix) configured -- resuming normal operations [Tue Aug 29 14:09:20.304849 2020] [core:notice] [pid 1:tid 140532155102336] AH00094: Command line: 'httpd -D FOREGROUND'

Just as we did before with Docker in rootless mode, let's see how our networking is set up. We will open up another terminal (as the chris user) and try this command:

$ podman ps CONTAINER ID IMAGE COMMAND CREATED e09883662c2b docker.io/library/httpd:latest httpd-foreground

The abbreviated output proves we have httpd running as hoped. It is worth noting that other standard users will not have visibility of Podman container processes, but the user chris certainly does. We can see the container is definitely running, and not as the root user:

$ ps -ef | grep podman

The abbreviated output from that command shows, among other entries:

chris 6069 6035 podman run -it -p 8000:80 httpd:latest

Do we need to access the container via the host's network, as we did with Docker? We can test with this command:

$ curl localhost 8000 <html><body><h1>It works!</h1></body></html>

The answer is yes, we've exposed a nonprivileged port (TCP port 8000) and can access the container via the localhost. If you get stuck, check firewalling rules or other container runtimes that are still installed.

One difference between Docker and Podman in rootless mode is that Podman does not allocate an IP address by default. Using the previous podman ps command, we can see our container's hash ID is e09883662c2b. The next command should offer us internal IP addresses, but not in Podman containers:

$ podman inspect e098 | grep IP "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0,

The top line in the output demonstrates that an IP address doesn't appear to be allocated, even though from a container's perspective an IP address is actually allocated via slirp4netns (the component that provides userspace networking functionality that was installed earlier). The container can apparently only communicate over the network with the host and beyond (and not other containers). There is more information at github.com/rootless-containers/slirp4netns. Thanks to the fact that Podman provides no default networking bridge, this is a limitation when using slirp4netns, which is part and parcel or using rootless mode.

If you need to run the ping command from a rootless container for any reason, you might need to tweak the kernel. You can temporarily adjust the tunable kernel setting with this syntax:

$ sysctl -w "net.ipv4.ping_group_range=0 2000000"

To make sure this setting survives reboots, you should add the following command to copy it to a file:

$ echo "net.ipv4.ping_group_range=0 2000000" >> /etc/sysctl.conf

The documentation encourages you to delve into the /usr/share/containers directory. As a low-privileged user, you should be able to read the files but not necessarily edit them, as these are for the sysadmin to edit. The files are as follows:

containers.conf seccomp.json

If you look inside the directory /etc/containers, then you can apparently override the settings in the previous directory. The file listing looks like this:

containers.conf policy.json registries.conf registries.d/ storage.conf

Note that Podman reads these configuration files in this order, with the last overriding the previous file's settings potentially:

/usr/share/containers/containers.conf /etc/containers/containers.conf $HOME/.config/containers/containers.conf

The containers.conf file contains a number of user-tunable settings. You can configure cgroups (control groups) and resource quotas such as RAM and CPU, and you can also define which kernel capabilities are included. In Listing 2.5 we can see many default capabilities have been commented out, which means they are not in use but are instead replaced by Podman's corresponding default settings.

Listing 2.5: Some Additional Kernel Capabilities That Can Be Uncommented for Containers to Use

# List of default capabilities for containers. # If it is empty or commented out, # the default capabilities defined in the container engine will # be added. # # default_capabilities = [ # "AUDIT_WRITE", # "CHOWN", # "DAC_OVERRIDE", # "FOWNER", # "FSETID", # "KILL", # "MKNOD", # "NET_BIND_SERVICE", # "NET_RAW", # "SETGID", # "SETPCAP", # "SETUID", # "SYS_CHROOT", # ]

The storage.conf file is a comprehensive way of tweaking your rootless container storage options. You can remap UIDs and GIDs if required so they appear differently inside and outside your containers to suit your volume mounting needs.

There are also settings for the devicemapper logging levels, which can help debug storage driver issues if required.

Inside the registries.conf file it is also possible to set up your image registry settings. In that file you can see the following:

[registries.search] registries = ['docker.io', 'quay.io']

And, in the registries.d/ directory you can configure the settings required to access those container image registries with authentication, for example.

Cloud Native Security

Подняться наверх