diff --git a/vault-ssh-renew.sh b/vault-ssh-renew.sh new file mode 100644 index 0000000..221d3e2 --- /dev/null +++ b/vault-ssh-renew.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# vault-ssh-renew.sh — автоматическое обновление SSH-сертификата через Vault +# Вызывается из ~/.ssh/config через Match exec +# При истечении сертификата или vault token — откроет браузер для OIDC-логина + +set -euo pipefail + +CERT="${SSH_CERT_FILE:-$HOME/.ssh/id_ed25519-cert.pub}" +KEY="${SSH_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}" +export VAULT_ADDR="${VAULT_ADDR:-https://vault.lokeo.ru}" +ROLE="${VAULT_SSH_ROLE:-git-user}" +MIN_REMAINING="${MIN_REMAINING:-300}" # обновлять если < 5 мин до истечения + +# --- Проверка текущего сертификата --- + +if [[ -f "$CERT" ]]; then + EXPIRY=$(ssh-keygen -Lf "$CERT" 2>/dev/null | awk '/Valid:/{print $5}') + if [[ -n "$EXPIRY" ]]; then + EXPIRY_TS=$(date -d "$EXPIRY" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%S" "$EXPIRY" +%s 2>/dev/null || echo 0) + NOW_TS=$(date +%s) + REMAINING=$((EXPIRY_TS - NOW_TS)) + if [[ $REMAINING -gt $MIN_REMAINING ]]; then + exit 0 # сертификат ещё живой + fi + fi +fi + +# --- Проверка vault CLI --- + +if ! command -v vault &>/dev/null; then + echo "vault CLI не найден. Установи: https://developer.hashicorp.com/vault/install" >&2 + exit 1 +fi + +# --- Проверка vault token --- + +USERNAME=$(vault token lookup -format=json 2>/dev/null | jq -r '.data.display_name // empty' 2>/dev/null || true) + +if [[ -z "$USERNAME" ]]; then + echo "Vault token отсутствует или истёк. Логинимся через Authentik..." >&2 + vault login -method=oidc role=reader -no-print 2>/dev/null || { + echo "OIDC-логин не удался" >&2 + exit 1 + } + USERNAME=$(vault token lookup -format=json 2>/dev/null | jq -r '.data.display_name // empty') +fi + +if [[ -z "$USERNAME" ]]; then + echo "Не удалось определить username из vault token" >&2 + exit 1 +fi + +# --- Проверка SSH-ключа --- + +if [[ ! -f "$KEY" ]]; then + echo "SSH-ключ не найден: $KEY" >&2 + echo "Сгенерируй: ssh-keygen -t ed25519" >&2 + exit 1 +fi + +# --- Подписание --- + +vault write -field=signed_key \ + "ssh-client-signer/sign/$ROLE" \ + public_key=@"$KEY" \ + valid_principals="$USERNAME" \ + > "$CERT" 2>/dev/null || { + echo "Не удалось подписать ключ" >&2 + exit 1 +} + +echo "SSH-сертификат обновлён для $USERNAME ($(ssh-keygen -Lf "$CERT" 2>/dev/null | grep 'Valid:' | xargs))" >&2 +exit 0