#cloud-config mounts: - [ /dev/disk/by-label/config-2, /mnt/config ] write_files: - path: /root/tatu-setup-ssh.sh permissions: '0700' owner: root:root content: | #!/bin/bash # Name: tatu-setup-ssh.sh # # Purpose: Fetch a SSH host cert from Tatu and configure SSH to use certs. metadata=$(cat /mnt/config/openstack/latest/meta_data.json) auth_id=$(echo $metadata | grep -Po 'project_id": "\K[^"]*') if [ -z $auth_id ]; then echo Failed to extract the project ID from metadata exit 1 fi echo auth_id=$auth_id host_id=$(echo $metadata | grep -Po 'uuid": "\K[^"]*') echo host_id=$host_id vendordata=$(cat /mnt/config/openstack/latest/vendor_data2.json) pam_sudo=$(echo $vendordata | grep -Po '"pam_sudo": \K[^,]*' | tr '[:upper:]' '[:lower:]') pam_sudo=${pam_sudo:-false} echo pam_sudo=$pam_sudo token=$(echo $vendordata | grep -Po '"token": "\K[^"]*') if [ -z $token ]; then echo Failed to extract the Tatu token ID from vendordata exit 1 fi echo token=$token ca_user=$(echo $vendordata | grep -Po '"auth_pub_key_user": "\K[^"]*') echo ca_user=$ca_user echo $ca_user > /etc/ssh/ca_user.pub #root_principals=$(echo $vendordata | grep -Po '"root_principals": "\K[^"]*') #echo root_principals=$root_principals users=$(echo $vendordata | grep -Po '"users": "\K[^"]*') echo users=$users sudoers=$(echo $vendordata | grep -Po '"sudoers": "\K[^"]*') echo sudoers=$sudoers ssh_port=$(echo $vendordata | grep -Po '"ssh_port": \K[^,]*') echo ssh_port=$ssh_port host_pub_key=$(cat /etc/ssh/ssh_host_rsa_key.pub) echo host public key is $host_pub_key data=$(echo {\"token_id\": \"$token\", \"host_id\": \"$host_id\", \"pub_key\": \"$host_pub_key\"}) echo $data > /tmp/tatu_cert_request.json api=$(echo $vendordata | grep -Po '"api_endpoint": "\K[^"]*') url=$api/noauth/hostcerts echo Posting Host Certificate request to Tatu API at $url response=$(curl -s -w "%{http_code}" -d "@/tmp/tatu_cert_request.json" -X POST $url) code=${response##*\}} if [ "$code" != "200" ]; then echo Curl to Tatu API failed with code $code exit 1 fi echo Tatu response is $response cert=$(echo $response | grep -Po 'cert": "\K[^"]*') cert=${cert%%\\n} # TODO: fix the trailing \n on the server side. echo $cert > /etc/ssh/ssh_host_rsa_key-cert.pub mkdir -p /etc/ssh/auth_principals #root_principals_file=/etc/ssh/auth_principals/root #> $root_principals_file #for i in ${root_principals//,/ } #do # echo $i >> $root_principals_file #done for i in ${users//,/ }; do id -u $i > /dev/null 2>&1 if [ $? == 1 ]; then #adduser --disabled-password --gecos '' $i adduser $i fi done x=0 for i in ${sudoers//,/ }; do prefix=$((130 + x++)) if [ "$pam_sudo" = true ]; then echo $i ALL= ALL > /etc/sudoers.d/$prefix-$i echo Defaults:$i timestamp_timeout=1 >> /etc/sudoers.d/$prefix-$i else echo $i ALL= NOPASSWD: ALL > /etc/sudoers.d/$prefix-$i fi done if [ "$pam_sudo" = true ]; then (crontab -l; echo "* * * * * /root/tatu-setup-pam.sh >> /var/log/tatu-setup-pam.log") | crontab - fi sed -i -e '$aTrustedUserCAKeys /etc/ssh/ca_user.pub' /etc/ssh/sshd_config # man sshd_config, under AuthorizedPrincipalsFile: The default is none, i.e. not to use a principals file # – in this case, the username of the user must appear in a certificate's principals list for it to be accepted. #sed -i -e '$aAuthorizedPrincipalsFile /etc/ssh/auth_principals/%u' /etc/ssh/sshd_config sed -i -e '$aHostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub' /etc/ssh/sshd_config sed -i -e '/^PasswordAuthentication /d' /etc/ssh/sshd_config sed -i -e '$aPasswordAuthentication no' /etc/ssh/sshd_config > /etc/ssh/revoked-keys sed -i -e '$aRevokedKeys /etc/ssh/revoked-keys' /etc/ssh/sshd_config sed -i -e '$aPort '"$ssh_port" /etc/ssh/sshd_config sed -i -e '$aPort 22' /etc/ssh/sshd_config setenforce permissive systemctl restart sshd echo Completed! - path: /root/tatu-setup-pam.sh permissions: '0700' owner: root:root content: | #!/bin/bash # Name: tatu-setup-pam.sh # # Purpose: Install uber/pam-ussh so that every sudo call authenticates the user's certificate in the background. # If the user's certificate expires or is revoked, sudo authentication will fail. They lose sudo privileges even if # they are still logged in. crontab -l | grep -v 'tatu-setup-pam' | crontab - cd /root rm -rf /root/pam-ussh inst=`which dnf` inst=${inst:-`which yum`} inst=${inst:-`which apt-get`} $inst install -y pam-devel golang git git clone https://github.com/pinodeca/pam-ussh cd pam-ussh git checkout -b krl origin/krl export GOPATH=/root/pam-ussh/.go go get golang.org/x/crypto/ssh go get github.com/stretchr/testify/require go get github.com/stripe/krl make mv pam_ussh.so /lib64/security/ vendordata=$(cat /mnt/config/openstack/latest/vendor_data2.json) sudoers=$(echo $vendordata | grep -Po '"sudoers": "\K[^"]*') echo setting up pam-ussh sudo authentication for $sudoers sed -i -e '/auth.*include.*system-auth/i \ auth sufficient /lib64/security/pam_ussh.so ca_file=/etc/ssh/ca_user.pub authorized_principals='"$sudoers"' revoked_keys_file=/etc/ssh/revoked-keys' /etc/pam.d/sudo - path: /root/tatu-manage-revoked-keys.sh permissions: '0700' owner: root:root content: | #!/bin/bash # Name: tatu-manage-revoked-keys.sh # # Purpose: Fetch the revoked keys data from Tatu and write it to /etc/ssh # !/usr/bin/env python metadata=$(cat /mnt/config/openstack/latest/meta_data.json) auth_id=$(echo $metadata | grep -Po 'project_id": "\K[^"]*') echo auth_id=$auth_id vendordata=$(cat /mnt/config/openstack/latest/vendor_data2.json) api=$(echo $vendordata | grep -Po '"api_endpoint": "\K[^"]*') url=$api/noauth/revokeduserkeys/$auth_id echo Fetching revoked user keys from Tatu API at $url response=$(curl -s -w "%{http_code}" $url) code=${response##*\}} if [ "$code" != "200" ]; then echo Curl to Tatu API failed with code $code exit 1 fi echo Tatu response is $response b64revoked=$(echo $response | grep -Po 'revoked_keys_data": "\K[^"]*') echo $b64revoked | base64 -d > /etc/ssh/revoked-keys runcmd: - /root/tatu-setup-ssh.sh > /var/log/tatu-setup-ssh.log 2>&1 - /root/tatu-manage-revoked-keys.sh > /var/log/tatu-revoked-keys.log - crontab -l | { cat; echo "* * * * * /root/tatu-manage-revoked-keys.sh >> /var/log/tatu-revoked-keys.log"; } | crontab -