Automatizzare l'accesso ai server tramite certificati
Per prima cosa automatizziamo l'accesso al server remoto tramite ssh e i certificati per evitare di inserire la password ogni volta. Dovremo generare una coppia di chiavi asimmetriche. Utilizzeremo il comando ssh-keygen per crearle:
luca@ulisse:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/luca/.ssh/id_rsa):
Created directory '/home/luca/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/luca/.ssh/id_rsa.
Your public key has been saved in /home/luca/.ssh/id_rsa.pub.
The key fingerprint is: SHA256:hAAc2bKex+4uRblXSOgV+FN/7af+YfNdNG1u3bHNheA luca@ulisse
The key's randomart image is:
+---[RSA 2048]----+
| .o=.o.. |
| + +.o.. |
| + =.o.. .. |
| . + +.. .......|
| . + . oS .E..o=|
| o = . .=X|
| + . BO|
| . . o.*|
| +o ...+|
+----[SHA256]-----+
luca@ulisse:~$ ls .ssh
id_rsa id_rsa.pub
luca@ulisse:~$
Il programma ssh-keygen, come si vede, salverà una coppia di chiavi asimmetriche del tipo RSA. È possibile proteggere la coppia tramite password (SUGGERITO) ma per ora ci limiteremo a dare invio alla richiesta di passphrase.
Il file id_rsa.pub
contiene la nostra chiave pubblica mentre il file id_rsa
contiene la chiave privata. Il prossimo passo sarà quello di copiare la chiave pubblica sul server remoto.
Nella sua configurazione di default (che si trova in /etc/ssh/sshd_config
) possiamo vedere che il server remoto può utilizzare le chiavi pubbliche che trova nella cartella ~/.ssh
dell'utente che cerca di collegarsi. Le chiavi devono trovarsi in un file chiamato authorized_keys
. Ciò premesso iniziamo a copiare la chiave pubblica sul server remoto:
luca@ulisse:~$ scp .ssh/id_rsa.pub server-remoto:/home/luca/
Trasferiamoci sul server remoto e facciamo qualche verifica:
luca@server-remoto:~$ grep PubkeyAuthentication /etc/ssh/sshd_config
PubkeyAuthentication yes
luca@server-remoto:~$ grep AuthorizedKeysFile /etc/ssh/sshd_config
AuthorizedKeysFile %h/.ssh/authorized_keys
luca@server-remoto:~$
La prima voce (PubkeyAuthentication
) ci dice che il server ssh accetta l'autenticazione tramite chiave pubblica. La seconda voce (AuthorizedKeysFile
) ci conferma che, per l'autenticazione, la chiave pubblica sarà cercata nella cartella .ssh contenuta nella home dell'utente all'interno del file authorized_keys
.
Fatte queste verifiche, creiamo, se già non esiste, la cartella ssh nella nostra home remota:
luca@server-remoto:~$ mkdir .ssh
luca@server-remoto:~$ chmod 700 .ssh
luca@server-remoto:~$ mv id_rsa.pub .ssh/authorized_keys
E questo è tutto. Verifichiamo che il sistema funzioni, ri-connettendoci al server remoto. La password non dovrebbe essere più richiesta.
Permettere l'uso privilegiato di apt-get
Il secondo punto, prevede di permettere all'utente di lanciare il comando apt-get upgrade con privilegi di root ma senza che la password venga richiesta. SUDO è lo strumento!
Il file di configurazione di default di sudo (/etc/sudoers) riporta, tra le altre, le seguenti righe:
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
Il primo parametro indica l'utente o il gruppo a cui la configurazione si riferisce. Il segno di % indica un gruppo. Il restante ALL=(ALL) ALL
, dice che gli utenti che vengono da qualsiasi host `ALL=
` possono impersonare chiunque `(ALL)
` e come tale eseguire qualsiasi comando `ALL
`.
In tutti questi casi, viene richiesta la password al primo lancio di sudo
. Per i nostri scopi è necessario aggiunge il parametro NOPASSWD
. Con questo parametro, non sarà necessario dare alcuna password. Per rendere un po più sicura questa configurazione, restringiamo i permessi ad un singolo programma: /usr/bin/apt-get
aggiungendo la seguente riga in /etc/sudoers
:
%adm ALL=(ROOT)NOPASSWD:/usr/bin/apt-get
Fatto questo non ci rimane che provare il tutto dal nostro host locale con il seguente comando:
ssh server-remoto -t "sudo apt-get update"
Se tutto è correttamente configurato, nessuna password dovrebbe venire richiesta e apt-get effettuerà l'aggiornamento delle informazione dei pacchetti.
Non rimane che ripetere tutte le operazioni precedenti per tutti i server remoti.
L'ultimo aspetto (in realtà il penultimo essendo ancora necessario aggiungere un po di sicurezza) è la scrittura di uno script che gestisca l'aggiornamento di gruppi di server. Potete vedere il mio script su gist di github. La maggior parte dello script serve per gestire gruppi predefiniti di server (quelli richiamati con il flag -l) oppure per gestirei nomi dei server da passare come parametro. In pratica è possibile chiamare lo script sia con remote-upgrade -l
che con remote-upgrade 192.168.1.23 192.168.1.27
. Nel primo caso il comando verrà eseguito su tutti i server definiti alla riga 27. Nel secondo caso, solo in quelli passati come argomento.
Sicurezza
A questo punto, chiunque possieda il nostro certificato privato potrebbe fare pericolose operazioni sui nostri server remoti. Per proteggere meglio il certificato, possiamo proteggerlo con passphrase. Una volta protetto tramite passphrase, sarà necessario fornire la password del certificato per sbloccare la coppia delle chiavi. Questo, grazie al portachiavi del nostro computer, dovrà essere fatto solo una volta.
La seconda parte è assicurarci che l'utilizzo di apt-get non venga...usato per creare insicurezze nel nostro sistema. La soluzione è creare un apposito script per l'aggiornamento, che chiameremo apt-get-update.sh
:
#!/bin/bash
sudo apt-get update && sudo apt-get upgrade -y
Salviamo lo script in /usr/local/bin
e lo rendiamo eseguibile tramite il comando chmod +x /usr/local/bin/apt-get-update.sh
.
Fatto questo, non ci rimane che aggiornare /etc/sudoers
per far si che l'utente possa eseguire solo questo script:
Modifichiamo la precedente riga da %adm ALL=(ROOT)NOPASSWD:/usr/bin/apt-get
a %adm ALL=(ROOT)NOPASSWD:/usr/local/bin/apt-get-update.sh.