Iscriviti al feed

An admission controller is a key component in Red Hat OpenShift and Kubernetes. Admission controllers are used to enforce policies and rules that control the admission of pods (containers) and other resources into a Kubernetes cluster. They allow administrators to define and implement custom checks and validations that determine whether a new resource is allowed to be created or modified within the cluster. But what about podman?

Let’s imagine a scenario where developers are given a Red Hat Enterprise Linux (RHEL) system and are allowed to run containerized workloads directly via podman. Let’s also imagine users have sudo privileges on the podman command. Without extensive investigation, how could a sysadmin see at a glance which user started one of the many containers currently running on the host as root?

Of course, this is quite easy by walking up the process tree and seeing which user started the sudo (or reading audit logs or other classic methods), but what if you want to embed this information into the container itself? Open Container Initiative (OCI) hooks can help with modifying the container configuration file in various stages of the container lifecycle.

What are OCI hooks?

Container hooks are a feature of the OCI specification that allow users to define and execute actions at various points in the lifecycle of a container. These hooks are scripts or commands that are executed at specific events, such as before or after the container is created, started, stopped or deleted. Container hooks provide a way to extend the behavior of containers and can be used for various purposes, including setup, configuration and cleanup tasks.

OCI container hooks include the following types:

  • precreate: This hook is executed after the container configuration is generated, but before the actual start of the container.
  • prestart: This hook is executed before the container's primary process is started. It can be used to perform tasks like setting up environment variables, configuring network settings or preparing the container's filesystem.
  • poststart: This hook is executed after the container's primary process is started. It can be used for tasks that need to be performed after the container has started running, such as registering the container with a service discovery system or monitoring tools.
  • poststop: This hook is executed after the container's primary process has exited or the container has been stopped. It can be used for cleanup tasks, logging or any actions that should be taken after the container has stopped running.

Container hooks can be defined in the OCI configuration for a container, which is typically stored in a JSON file. The configuration specifies the path to the hook script or command, as well as any required arguments or environment variables.

Adding an annotation automatically when a container is created

We will be using the precreate hook in order to change the container configuration before it is created and started.

The first step required is actually configuring the hooks definition location by editing the /etc/containers/containers.conffile:

$ cat /etc/containers/containers.conf
[engine]
hooks_dir = ["/etc/containers/oci/hooks.d"]

Then we add our hook definition in JSON format:

$ cat /etc/containers/oci/hooks.d/names.json
{
 "version": "1.0.0",
 "hook": {
"path": "/usr/local/bin/annotate-sudo-user"
 },
 "when": {
     "always": true
 },
 "stages": ["precreate"]
}

There are a couple of observations to make on the above.

First,  you should create the hooks directory:

$ mkdir -p /etc/containers/oci/hooks.d

Second, the script referenced in hook.path needs to be executable:

$ chmod +x /usr/local/bin/check-container-name

The when section can be further customized to only apply the hook when certain conditions are met. For this simple case, always: true means for every container created, this hook will run. More complex options are detailed in the documentation.

For the precreate stage, the script defined in hook.path will take input on stdin in the form of the container configuration JSON and the container runtime expects a (potentially modified) valid configuration JSON on stdout.

The final configuration is the script itself:

$ cat /usr/local/bin/annotate-sudo-user
#!/bin/bash
input="-"
CONTAINER_CONFIG=$(cat "$input")
PSTREE=$(pstree -AacTlSucp -s "$$")
LAST_PODMAN_PPID=$(echo "${PSTREE}" | grep -C 1 podman | head -n 1 | awk -F, '{print $2}' | awk '{print $1}')
if [ -z "$LAST_PODMAN_PPID" ]
then
   LAST_USER="?"
else
   LAST_USER=$(ps -o user= -p "${LAST_PODMAN_PPID}")
fi
echo "$CONTAINER_CONFIG" | jq ".annotations += {\"ran_by\": \"${LAST_USER}\"}"

In the above script, note:

  • Read the standard input and save it to the $CONTAINER_CONFIG variable. As previously stated, the precreate hook runs your script with stdin as the generated container configuration and expects a valid JSON container configuration as the standard out of the script
  • At run time, the script still runs in the host namespace, as root and with access to the whole process tree.
  • The long series of pipes in the building of $LAST_PODMAN_PPID is simply getting the parent PID of the first podman process encountered in the process tree above the running script. As the focus of this article is not on the discovery of the parent user, this step might include bugs, but the key takeaway is $LAST_PODMAN_PPID should contain the immediate parent of the sudo podman (...) command.
  • The $LAST_USER variable is set to the user that initially started podman.
  • Finally, add the ran_by annotation to the container configuration by using jq.

Results

Let’s see how it behaves in real life. After adding the three files described above, notice that any newly started container should have the actual username as an annotation even if run with sudo:

$ whoami
kwozyman
$ sudo podman run --name foobar --detach --rm -ti fedora
1fd5f86ab5065158d135c8a4b8e28059b0e8b61fb0ef4e46f39eb88c43c5ef47
$ sudo podman inspect foobar | jq '.[].Config.Annotations'
{
 "io.container.manager": "libpod",
 "io.podman.annotations.autoremove": "TRUE",
 "org.opencontainers.image.stopSignal": "15",
 "ran_by": "kwozyman"
}

In conclusion, the use of OCI container hooks offers a powerful and flexible mechanism for enhancing the capabilities of containerized applications. By enabling developers and administrators to inject custom logic at various stages of a container's lifecycle, OCI hooks provide a valuable tool for automating tasks, enforcing security policies and optimizing performance.

Please note, however, that it's essential to exercise caution when implementing scripted hooks, as they can introduce complexity and potential security risks. Proper documentation, thorough testing and adherence to best practices are crucial to using hooks effectively without increasing your security risks.


Sull'autore

An old school Linux enthusiast, I joined Red Hat in 2021 and I've been helping our customers and partners integrate with Red Hat software ever since. Besides Linux and open source, I'm passionate about science and I've been occasionally known to cycle and hike around Switzerland.

Read full bio
UI_Icon-Red_Hat-Close-A-Black-RGB

Ricerca per canale

automation icon

Automazione

Novità sull'automazione IT di tecnologie, team e ambienti

AI icon

Intelligenza artificiale

Aggiornamenti sulle piattaforme che consentono alle aziende di eseguire carichi di lavoro IA ovunque

open hybrid cloud icon

Hybrid cloud open source

Scopri come affrontare il futuro in modo più agile grazie al cloud ibrido

security icon

Sicurezza

Le ultime novità sulle nostre soluzioni per ridurre i rischi nelle tecnologie e negli ambienti

edge icon

Edge computing

Aggiornamenti sulle piattaforme che semplificano l'operatività edge

Infrastructure icon

Infrastruttura

Le ultime novità sulla piattaforma Linux aziendale leader a livello mondiale

application development icon

Applicazioni

Approfondimenti sulle nostre soluzioni alle sfide applicative più difficili

Original series icon

Serie originali

Raccontiamo le interessanti storie di leader e creatori di tecnologie pensate per le aziende