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.conf
file:
$ 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, theprecreate
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 firstpodman
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 thesudo podman (...)
command. - The
$LAST_USER
variable is set to the user that initially startedpodman
. - Finally, add the
ran_by
annotation to the container configuration by usingjq
.
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.
Sobre el autor
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.
Navegar por canal
Automatización
Las últimas novedades en la automatización de la TI para los equipos, la tecnología y los entornos
Inteligencia artificial
Descubra las actualizaciones en las plataformas que permiten a los clientes ejecutar cargas de trabajo de inteligecia artificial en cualquier lugar
Nube híbrida abierta
Vea como construimos un futuro flexible con la nube híbrida
Seguridad
Vea las últimas novedades sobre cómo reducimos los riesgos en entornos y tecnologías
Edge computing
Conozca las actualizaciones en las plataformas que simplifican las operaciones en el edge
Infraestructura
Vea las últimas novedades sobre la plataforma Linux empresarial líder en el mundo
Aplicaciones
Conozca nuestras soluciones para abordar los desafíos más complejos de las aplicaciones
Programas originales
Vea historias divertidas de creadores y líderes en tecnología empresarial
Productos
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- Servicios de nube
- Ver todos los productos
Herramientas
- Training y Certificación
- Mi cuenta
- Soporte al cliente
- Recursos para desarrolladores
- Busque un partner
- Red Hat Ecosystem Catalog
- Calculador de valor Red Hat
- Documentación
Realice pruebas, compras y ventas
Comunicarse
- Comuníquese con la oficina de ventas
- Comuníquese con el servicio al cliente
- Comuníquese con Red Hat Training
- Redes sociales
Acerca de Red Hat
Somos el proveedor líder a nivel mundial de soluciones empresariales de código abierto, incluyendo Linux, cloud, contenedores y Kubernetes. Ofrecemos soluciones reforzadas, las cuales permiten que las empresas trabajen en distintas plataformas y entornos con facilidad, desde el centro de datos principal hasta el extremo de la red.
Seleccionar idioma
Red Hat legal and privacy links
- Acerca de Red Hat
- Oportunidades de empleo
- Eventos
- Sedes
- Póngase en contacto con Red Hat
- Blog de Red Hat
- Diversidad, igualdad e inclusión
- Cool Stuff Store
- Red Hat Summit