Configurare ssh-agent su CentOS permette di utilizzare Git tramite SSH senza dover inserire la passphrase della chiave privata a ogni pull o push, mantenendo comunque la protezione offerta dalla passphrase.
Ovviamente tutto ciò che vi dico qui si può applicare allo stesso modo a Ubuntu o a un’altra distribuzione, ma oggi questo è il server con cui mi trovo a lavorare.
La soluzione non è eliminare la passphrase dalla chiave, ma utilizzare correttamente ssh-agent in modo da non dover riudigitare la password ogni volta che ci si riconnette alla consolle con una nuova sessione.
In questo HOWTO vediamo come configurarlo su CentOS Linux 7, facendo in modo che lo stesso agent venga riutilizzato anche nelle successive sessioni SSH.
Sommario
Il problema
Supponiamo di avere una chiave Ed25519:
~/.ssh/id_ed25519
e di accedere a un repository Git attraverso SSH.
Un normale:
git pull
può quindi produrre:
Enter passphrase for key '/home/marcob/.ssh/id_ed25519':
La chiave è correttamente protetta, ma non vogliamo digitare continuamente la passphrase.
Due parole su Ed25519
Ed25519 è un algoritmo di firma digitale basato sulla crittografia a curve ellittiche, comunemente utilizzato da SSH per l’autenticazione: la chiave privata rimane sul client, mentre la corrispondente chiave pubblica viene registrata sul server. La passphrase non fa parte dell’algoritmo Ed25519: serve invece a proteggere il file contenente la chiave privata, che ssh-agent può sbloccare una volta e mantenere disponibile in memoria.
A cosa serve ssh-agent su CentOS
ssh-agent è un processo che mantiene in memoria le chiavi private sbloccate.
La sequenza classica è:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519
Il primo comando avvia l’agent; il secondo gli consegna la chiave, chiedendoci la passphrase.
Possiamo verificare le chiavi presenti nell’agent con:
ssh-add -l
Da quel momento i programmi che utilizzano SSH, compreso Git, possono chiedere all’agent di effettuare le operazioni crittografiche senza doverci chiedere nuovamente la passphrase.
C’è però un problema: aprendo una nuova sessione SSH, la nuova shell deve sapere come trovare l’agent già esistente.
Il socket di ssh-agent
Quando viene avviato, ssh-agent espone principalmente due variabili:
SSH_AUTH_SOCK SSH_AGENT_PID
Possiamo visualizzarle con:
echo "$SSH_AUTH_SOCK" echo "$SSH_AGENT_PID"
Per esempio:
/tmp/ssh-GOMN9SlaqeyH/agent.16645 16647
SSH_AUTH_SOCK indica un Unix domain socket attraverso il quale i processi comunicano con ssh-agent (se volete qui trovate un articolo che parla del funzionamento dei socket)
Questo è un dettaglio importante: la chiave privata non viene copiata nelle applicazioni che ne hanno bisogno. È l’agent a eseguire per loro le operazioni crittografiche richieste.
Se però apriamo una nuova shell, dobbiamo fare in modo che essa recuperi SSH_AUTH_SOCK e SSH_AGENT_PID.
Rendere persistenti le informazioni sull’agent
Creiamo nel nostro .bashrc un piccolo meccanismo che salva queste informazioni:
SSH_ENV="$HOME/.ssh/agent-environment"
SSH_KEY="$HOME/.ssh/id_ed25519"
start_agent() {
echo "Avvio ssh-agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "$SSH_ENV"
chmod 600 "$SSH_ENV"
. "$SSH_ENV" > /dev/null
}
Il file:
~/.ssh/agent-environment
conterrà qualcosa del genere:
SSH_AUTH_SOCK=/tmp/ssh-GOMN9SlaqeyH/agent.16645; export SSH_AUTH_SOCK; SSH_AGENT_PID=16647; export SSH_AGENT_PID;
Possiamo quindi recuperare un agent già esistente oppure crearne uno nuovo:
if [ -f "$SSH_ENV" ]; then
. "$SSH_ENV" > /dev/null
# Verifica che l'agent salvato sia ancora in esecuzione
if ! kill -0 "$SSH_AGENT_PID" 2>/dev/null; then
start_agent
fi
else
start_agent
fi
kill -0 non termina il processo: viene utilizzato semplicemente per verificare se il PID indicato esiste ed è accessibile.
Caricare automaticamente la chiave
Avviare ssh-agent non significa automaticamente caricare una chiave.
Se:
ssh-add -l
risponde:
The agent has no identities.
l’agent è perfettamente funzionante, ma non contiene ancora alcuna identità.
Aggiungiamo quindi:
if ! ssh-add -l >/dev/null 2>&1; then
ssh-add "$SSH_KEY"
fi
Se l’agent non contiene identità, viene eseguito automaticamente ssh-add.
Il .bashrc completo
Il blocco completo diventa quindi:
# Riutilizzo di ssh-agent tra sessioni
SSH_ENV="$HOME/.ssh/agent-environment"
SSH_KEY="$HOME/.ssh/id_ed25519"
start_agent() {
echo "Avvio ssh-agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "$SSH_ENV"
chmod 600 "$SSH_ENV"
. "$SSH_ENV" > /dev/null
}
# Recupera l'agent esistente oppure ne avvia uno nuovo
if [ -f "$SSH_ENV" ]; then
. "$SSH_ENV" > /dev/null
if ! kill -0 "$SSH_AGENT_PID" 2>/dev/null; then
start_agent
fi
else
start_agent
fi
# Carica la chiave se l'agent non contiene identità
if ! ssh-add -l >/dev/null 2>&1; then
ssh-add "$SSH_KEY"
fi
Cosa succede adesso
Al primo login dopo l’avvio dell’agent verrà richiesta la passphrase:
Enter passphrase for /home/marcob/.ssh/id_ed25519:
Una volta inserita, la chiave rimane caricata nell’agent.
Possiamo verificarlo con:
ssh-add -l
Ora:
git pull git push
non richiederanno più la passphrase.
Se chiudiamo la sessione SSH e successivamente ci ricolleghiamo al server, il .bashrc recupererà il PID e il socket dell’agent precedente. Se questo è ancora attivo e contiene la chiave, non verrà chiesto nulla.
In sostanza:
nuovo login
|
v
esiste agent-environment?
|
+--+--+
| |
sì no
| |
v v
agent avvia
vivo? agent
|
+-+--+
| |
sì no
| |
| avvia
| agent
|
v
chiave caricata?
|
+-+--+
| |
sì no
| |
| ssh-add
| |
+----+
|
v
Git via SSH
La passphrase viene quindi normalmente richiesta una volta sola, mentre l’agent può essere riutilizzato da più sessioni.
Dopo un reboot della macchina, naturalmente, il vecchio processo ssh-agent non esisterà più: il nostro .bashrc se ne accorgerà, ne avvierà uno nuovo e ssh-add richiederà nuovamente la passphrase.
Ed è esattamente quello che vogliamo.
Verifica e diagnostica
In caso di dubbi possiamo controllare l’intera situazione con:
echo "PID=$SSH_AGENT_PID" echo "SOCK=$SSH_AUTH_SOCK" ps -ef | grep '[s]sh-agent' ssh-add -l cat ~/.ssh/agent-environment
È utile soprattutto distinguere due situazioni molto diverse:
ssh-agent non esiste
da:
ssh-agent esiste, ma non contiene identità
Nel secondo caso non dobbiamo avviare un altro agent: basta un semplice:
ssh-add ~/.ssh/id_ed25519
Con questa configurazione manteniamo quindi la protezione offerta dalla passphrase senza trasformare ogni git pull in un piccolo esercizio di memoria.
Riferimenti
- Wiht a little hekp from my friend ChatGPT
- CentOS download
- Secure SHell


Commenti recenti