What does it take to make a call to a Kerberized service from a container running in podman? Here are the steps I am going through to debug and troubleshoot.
UPDATE: Now in a rootless container.
I have an IPA server set up. If I call $HOSTNAME/ipa/ui and I am not authenticated, I can see the response:
Unable to verify your Kerberos credentials.
If I am authenticated I get:
Bad Habit alert: you can do
echo $PASSWORD | kinit
Don’t do something like that. Instead, for process inside of containers, you want to use a mechanism to automate the fetching of a TGT. Typically, you want to use a keytab. I wrote this up years ago.
Instead, I bindmount the directory with the keytab in it into the container at run time, and automate the fetching of the TGT.
- Create a directory structure on your workstation like this: ~/user/1001
- go to an ipa client machine and generate a keytab. Note that IPA will disable your password once you do this. You hacve been warned.
- scp the keytab onto the workstation in the 0 subdirectory from the first step.machine
- Make sure the keytab is readable by the desired end user. Yes, this is a security risk. You have been warned.
- test that the keytab can be used to geta tgt: kinit -t /home/ayoung/user/1001/client.keytab ayoung@EXAMPLE.COM
Here is my Dockerfile:
FROM centos:latest MAINTAINER Adam Young RUN yum -y install krb5-workstation strace curl sssd-client RUN chmod a+rwx /var/kerberos/krb5/user COPY krb5.conf /etc/krb5.conf # Note: I added the following and can run this all in a # non-root Container USER 1001 CMD KRB5_TRACE=/dev/stderr curl -k --negotiate -u : https://idm.example.com/ipa #CMD kinit -V testuser@REDHATFSI.COM -t /var/kerberos/krb5/user/0/client.keytab ; curl -k --negotiate -u : https://idm.example.com/ipa #CMD echo $EUID #CMD cat /var/kerberos/krb5/user/0/client.keytab #CMD curl -k --negotiate -u : https://idm.example.com/ipa #CMD cat /etc/krb5.conf
Note that I left in many of my debugging lines. Each of these have been useful for troubleshooting.
The top, uncommented, CMD line is the one that I actually use. The KRB5_TRACE env var is useful for debugging, although you will want to remove it for production.
The line below it shows an explicit kinit. You can do something like this if you want to put the keytab in some other location, or to check a permissions problem.
The 0 in the directory structure reflects the effective user ID (EUID) that will be run in the container. The echo $EUID line was for confirming that the EUID was correct.
I use a slightly modified krb5.conf file from the IPA server. I removed two lines from the top that looked like this:
- includedir /etc/krb5.conf.d/
- includedir /var/lib/sss/pubconf/krb5.include.d/
I do not have anything in those directories that I need for this use case, and if I include those lines, I either need to create those subdirs, or I get the error:
“kinit: Included profile directory could not be read while initializing Kerberos 5 library”
I put the build command into a file named build.sh. It looks like this:
podman build --tag admiyo:curlkrb -f Dockerfile
I put the run command into a file called run.sh. It looks like this:
podman run -P --name krbocp --mount type=bind,source=/home/ayoung/user,destination=/var/kerberos/krb5/user --rm admiyo:curlkrb
Note the bindmount. When I move this to Kubernetes, this will be done by a secret instead.
EDIT: Note that the SELinux context for the TGT must be set properly for the user to be able to access the keytab. I have been able to use the following command to set it:
sudo chcon -R -t httpd_sys_content_t ~/user/1001/client.keytablient