Last active
August 18, 2025 09:59
-
-
Save delannoy/9512a180dea2a3436b13d860bcaf4296 to your computer and use it in GitHub Desktop.
Setup for CERN lxplus keytab file (creates kerberos tokens for password-less SSH access)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # References: | |
| # [https://linux.web.cern.ch/docs/kerberos-access/] | |
| # [https://twiki.cern.ch/twiki/bin/view/Main/Kerberos] | |
| # [https://uz.sns.it/~enrico/site/posts/kerberos/password-less-ssh-login-with-kerberos.html] | |
| # Requirements: | |
| # [MIT Kerberos V5. Kerberos is a network authentication protocol.](https://github.com/krb5/krb5) | |
| # Kerberos is usually installed in most systems (run `command -v kinit` to verify) | |
| # [k5start and krenew are modified versions of kinit which add support for running as a daemon](https://github.com/rra/kstart) | |
| # kstart will most probably need to be installed (e.g. `command -v k5start || sudo apt install kstart`) | |
| # [If you have MacOS Sierra or later, it comes with an updated version of OpenSSH that drops some options that support Kerberos authentication [...] The best way to obtain an SSH binary with GSSAPITrustDNS support is using Homebrew](https://frankenthal.dev/post/ssh_kerberos_keytabs_macos/) | |
| export XDG_DATA_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}" # [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/#variables) | |
| export KRB5_CONFIG="${XDG_DATA_HOME}/krb5/conf" # [Main Kerberos configuration file.](https://web.mit.edu/kerberos/krb5-1.12/doc/admin/env_variables.html#environment-variables) | |
| export KRB5_KTNAME="${XDG_DATA_HOME}/krb5/keytab" # [Default keytab file name.](https://web.mit.edu/kerberos/krb5-1.12/doc/admin/env_variables.html#environment-variables) | |
| krb5_principal(){ | |
| # based on user input, define $KRB5_PRINCIPAL as an environment variable | |
| local principal="$1" | |
| local user="${principal%@*}" | |
| local realm="${principal#*@}" | |
| export KRB5_PRINCIPAL="${user,,}@${realm^^}" | |
| } | |
| krb5_config(){ | |
| # unless it already exists, download a Kerberos configuration file for lxplus | |
| [[ -f "${KRB5_CONFIG}" ]] && return 0 | |
| local url='https://linux.web.cern.ch/docs/krb5.conf' | |
| mkdir --parents "${KRB5_CONFIG%/*}" | |
| curl --progress-bar --create-dirs --location --url "${url}" --output "${KRB5_CONFIG}" --write-out '%{filename_effective}\n' | |
| } | |
| krb5_keytab(){ | |
| # unless a keytab file exists containing a key corresponding to $KRB5_PRINCIPAL, ssh into lxplus and execute `cern-get-keytab` to create a keytab file and transfer it to local machine via `scp` | |
| (( "$(klist -k "${KRB5_KTNAME}" 2>/dev/null | grep --ignore-case --count "${KRB5_PRINCIPAL}")" > 0 )) && return 0 | |
| local user="${KRB5_PRINCIPAL%@*}" | |
| ssh "${user}@lxplus.cern.ch" '/usr/sbin/cern-get-keytab --user --keytab ~/private/keytab || echo "error creating keytab file!"' # [https://gitlab.cern.ch/linuxsupport/rpms/cern-get-keytab] | |
| scp "${user}@lxplus.cern.ch:~/private/keytab" "${KRB5_KTNAME}" | |
| krb5_kinit(){ | |
| # unless $KRB5_KTNAME doesn't exist, list the keys in the keytab file (`klist -k`), obtain and cache Kerberos ticket (`kinit`), and list cached Kerberos tickets (`klist -c`) | |
| [[ -f "${KRB5_KTNAME}" ]] || return 1 | |
| klist -k -t -e -K "${KRB5_KTNAME}" | |
| kinit -f -p -k -t "${KRB5_KTNAME}" "${KRB5_PRINCIPAL}" | |
| klist -c -e -f | |
| } | |
| krb5_daemon(){ | |
| # unless already running, run `k5start` in the background to check (every 60 minutes) for an active kerberod tivcket and renew it if needed | |
| command -v k5start || return 1 | |
| (( "$(pgrep --list-full k5start | grep --ignore-case --count "${KRB5_PRINCIPAL}")" > 0 )) && return 0 | |
| k5start -v -b -K 60 -u "${KRB5_PRINCIPAL}" -f "${KRB5_KTNAME}" | |
| } | |
| krb5(){ | |
| krb5_principal "$1" | |
| krb5_config | |
| krb5_keytab | |
| krb5_kinit | |
| krb5_daemon | |
| } | |
| # Modify or update your "${HOME}/.ssh/config" as below, change <CERNUSERNAME> and <CMSUSERNAME> to your username, and execute the `krb5` function, and enjoy password-less ssh access to lxplus! | |
| krb5 <CERNUSERNAME>@cern.ch | |
| ssh lxplus |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This example ssh config simplifies ssh tunneling through lxplus (when needed) to reach machines within the CMS network. For example: | |
| # ssh cmsusr ssh -tCXY brildev1 'xsudo --user=brilpro --login' | |
| Host lxplus | |
| User <CERNUSERNAME> | |
| Hostname lxplus.cern.ch | |
| GSSAPIAuthentication yes | |
| GSSAPIDelegateCredentials yes | |
| ForwardX11 yes | |
| RequestTTY yes | |
| StrictHostKeyChecking no | |
| UserKnownHostsFile /dev/null | |
| # [Tunneling an SSH connection only when necessary using Match](https://mike.place/2017/ssh-match) | |
| # The `Match` statement below will tunnel through lxplus only when needed (if cmsusr.cern.ch is not directly accessible). Requires OpenSSH version > 7.2. | |
| Match host cmsusr !exec "ping -c1 -W1 cmsusr.cern.ch &>/dev/null" | |
| ProxyJump lxplus | |
| Host cmsusr | |
| User <CMSUSERNAME> | |
| Hostname cmsusr.cern.ch | |
| ForwardX11 yes | |
| RequestTTY force | |
| StrictHostKeyChecking no | |
| UserKnownHostsFile /dev/null | |
| Host cmstunnel | |
| User <CMSUSERNAME> | |
| Hostname cmsusr.cern.ch | |
| DynamicForward 10880 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment