Come posso implementare responsible con password per host, in modo sicuro?


108

Vorrei usare ansible per gestire un gruppo di server esistenti. Ho creato un ansible_hostsfile e testato con successo (con l' -Kopzione) con comandi rivolti solo a un singolo host

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Il mio problema ora è che le password degli utenti su ciascun host sono diverse, ma non riesco a trovare un modo per gestirle in Ansible.

Utilizzando -K, mi viene richiesta solo una singola password sudo in anticipo, che quindi sembra essere provata per tutti gli host successivi senza richiedere:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Ricerca finora:

  • una domanda StackOverflow con una risposta errata ("uso -K") e una risposta dell'autore che dice "Ho scoperto che avevo bisogno di un sudo senza password"

  • i documenti Ansible , che dicono "L'uso di sudo senza password rende le cose più facili da automatizzare, ma non è necessario ." (enfatizzare il mio)

  • questa domanda StackExchange di sicurezza che lo prende come letto NOPASSWDrichiesto

  • articolo "Provisioning scalabile e comprensibile ..." che dice:

    "L'esecuzione di sudo potrebbe richiedere la digitazione di una password, che è un modo sicuro per bloccare Ansible per sempre. Una semplice soluzione è eseguire visudo sull'host di destinazione e assicurarsi che l'utente che Ansible utilizzerà per accedere non debba digitare una password"

  • articolo "Basic Ansible Playbooks" , che dice

    "Ansible potrebbe accedere al server di destinazione come root ed evitare la necessità di sudo, o lasciare che l'utente ansible abbia sudo senza password, ma il pensiero di fare uno dei due fa minacciare la milza di saltare il mio esofago e bloccare la trachea, quindi non"

    I miei pensieri esattamente, ma come estendere oltre un singolo server?

  • rispondi al numero 1227 , "Ansible dovrebbe chiedere la password sudo per tutti gli utenti di un playbook", che è stata chiusa un anno fa da mpdehaan con il commento "Non ho visto molte richieste per questo, penso che la maggior parte delle persone stia facendo una sola domanda account utente o utilizzo delle chiavi il più delle volte. "

Quindi ... come stanno le persone che usano Ansible in situazioni come queste? Impostazione NOPASSWDin /etc/sudoers, il riutilizzo di password in host o l'abilitazione di accesso radice SSH tutti sembrano piuttosto drastiche riduzioni di sicurezza.


2
C'è un motivo per cui non stai usando le chiavi SSH?
Trondh,

22
Sto già usando le chiavi SSH; non influiscono sudo(che dovrebbe comunque richiedere una password).
supervacuo,

1
Questo potrebbe non essere esattamente quello che stai cercando, ma sulle scatole di Ubuntu uso ancora le chiavi, cioè inserendo la mia chiave pubblica in / root / authorized_keys per accedere direttamente come root. L'ovvio svantaggio è consentire accessi root su ssh ... Inoltre, non accedo accessi password su ssh ed eseguo fail2ban per una maggiore sicurezza.
senorsmile,

27
@senorsmile grazie per la risposta! Ti dispiacerebbe trasformarlo in una risposta, in modo da poterti sottovalutare per non aver letto la domanda?
supervacuo,

4
vale a dire che l' ansible_ssh_passwordimpostazione si applica solo alla password SSH (l'indizio è nel nome ...). E sto già utilizzando l'accesso SSH basato su chiave.
supervacuo,

Risposte:


53

Hai sicuramente fatto la tua ricerca ...

Da tutta la mia esperienza con ansible ciò che stai cercando di realizzare, non è supportato. Come hai detto, Ansible afferma che non richiede sudo senza password, e che hai ragione, non lo fa. Ma devo ancora vedere alcun metodo per utilizzare più password sudo all'interno di Ansible, senza ovviamente eseguire più configurazioni.

Quindi, non posso offrire la soluzione esatta che stai cercando, ma hai chiesto ...

"Quindi ... come fanno le persone a utilizzare Ansible in situazioni come queste? Impostare NOPASSWD in / etc / sudoers, riutilizzare la password tra host o abilitare il login SSH root sembra una drastica riduzione della sicurezza."

Posso darti una visione al riguardo. Il mio caso d'uso è 1k nodi in più data center a supporto di un'azienda SaaS globale in cui devo progettare / implementare alcuni controlli di sicurezza follemente rigidi a causa della natura della nostra attività. La sicurezza è sempre un equilibrio, più usabilità e meno sicurezza, questo processo non è diverso se si eseguono 10 server o 1.000 o 100.000.

Hai assolutamente ragione a non usare i login root tramite password o chiavi ssh. In effetti, l'accesso root dovrebbe essere disabilitato del tutto se i server hanno un cavo di rete collegato.

Parliamo del riutilizzo delle password, in una grande impresa, è ragionevole chiedere ai amministratori di sistema di avere password diverse su ciascun nodo? per un paio di nodi, forse, ma i miei amministratori / ingegneri si ammutinerebbero se dovessero avere password diverse su 1000 nodi. L'implementazione sarebbe anche quasi impossibile, ogni utente dovrebbe archiviare lì le proprie password da qualche parte, si spera un keypass, non un foglio di calcolo. E ogni volta che inserisci una password in una posizione in cui può essere estratta in testo semplice, hai notevolmente ridotto la tua sicurezza. Preferirei che conoscessero a memoria una o due password davvero forti che dover consultare un file keypass ogni volta che dovevano accedere o invocare sudo su una macchina.

Quindi la reimpostazione della password e la standardizzazione sono qualcosa di completamente accettabile e standard anche in un ambiente sicuro. Altrimenti non dovrebbero esistere ldap, keystone e altri servizi di directory.

Quando passiamo agli utenti automatizzati, i tasti SSH funzionano benissimo per farti entrare, ma devi comunque superare sudo. Le tue scelte sono una password standardizzata per l'utente automatizzato (che è accettabile in molti casi) o per abilitare NOPASSWD come hai sottolineato. La maggior parte degli utenti automatici esegue solo alcuni comandi, quindi è del tutto possibile e sicuramente desiderabile abilitare NOPASSWD, ma solo per i comandi pre-approvati. Ti suggerirei di usare la tua gestione della configurazione (rispondibile in questo caso) per gestire il tuo file sudoers in modo da poter aggiornare facilmente l'elenco dei comandi senza password.

Ora, ci sono alcuni passaggi che puoi prendere una volta che inizi a ridimensionare per isolare ulteriormente il rischio. Mentre abbiamo circa 1000 nodi, non tutti sono server di "produzione", alcuni sono ambienti di test, ecc. Non tutti gli amministratori possono accedere ai server di produzione, ma quelli che possono usare il loro stesso utente SSO / pass | key come farebbero altrove . Ma gli utenti automatizzati sono un po 'più sicuri, ad esempio uno strumento automatizzato a cui gli amministratori non di produzione possono accedere ha un utente e credenziali che non possono essere utilizzate nella produzione. Se vuoi avviare ansible su tutti i nodi, dovresti farlo in due lotti, una volta per non produzione e una volta per produzione.

Tuttavia, utilizziamo anche le marionette, poiché è uno strumento di gestione della configurazione di applicazione, quindi la maggior parte delle modifiche a tutti gli ambienti verrebbero eliminate.

Ovviamente, se quella richiesta di funzionalità che hai citato viene riaperta / completata, ciò che stai cercando di fare sarebbe completamente supportato. Anche allora, la sicurezza è un processo di valutazione del rischio e di compromesso. Se hai solo pochi nodi per i quali puoi ricordare le password senza ricorrere a una nota di post-it, password separate sarebbero leggermente più sicure. Ma per la maggior parte di noi non è un'opzione fattibile.


Grazie, @Zeb - Avevo immaginato che gli utenti con dozzine di migliaia di server NOPASSWDusassero comunque per motivi di sanità mentale (probabilmente supportati da regole del firewall più strette ecc. ), Ma è bene leggere il tuo caso d'uso e pensieri sulla minaccia modello.
supervacuo,

16
Un commento, tuttavia, sul tuo suggerimento di limitare i sudocomandi "pre-approvati" (che mi è venuto in mente quando ho scoperto che NOPASSWDè praticamente necessario). Sfortunatamente, anche questo sembra completamente non supportato : non si fa alcuna promessa di chiamare direttamente eg chown o mkdirbinari e deve essere in grado di sudo /bin/shfar funzionare la maggior parte dei moduli.
supervacuo,

Mi sembra di ricordare che uno dei miei ingegneri si sia lamentato di questo tempo fa, è fastidioso.
Zeb

36

Da Ansible 1.5 in poi, è possibile utilizzare un deposito crittografato per host_vars e altre variabili. Ciò consente almeno di memorizzare in ansible_sudo_passmodo sicuro una variabile per host (o per gruppo) . Sfortunatamente, --ask-vault-passti verrà richiesta una sola password del vault per ogni chiamata, quindi sei ancora vincolato a una singola password del vault per tutti gli host che utilizzerai insieme.

Tuttavia, per alcuni usi questo potrebbe essere un miglioramento rispetto all'avere una singola password sudo su più host, poiché un attaccante senza accesso ai tuoi host_vars crittografati avrebbe comunque bisogno di una password sudo separata per ogni macchina (o gruppo di macchine) che attacca.


3
Anche l' ansible_sudo_passopzione sembra nuova e sembra fare quello che stavo chiedendo. Una sola password del Vault è ideale anche per i miei scopi. Grazie!
supervacuo,

C'è un modo per evitare di crittografare tutto host_vars usando questo metodo? (una potenziale limitazione rilevata da Alex Dupuy)
supervacuo

1
@supervacuo - Per evitare la crittografia di tutti gli host var, basta usare una directory var host contenente main.yml (non crittografato) e secret.yml (crittografato) - vedere l'ultima parte di questa sezione doc in cui si parla del gruppo "raleigh" - stessa tecnica funziona per host var e group var. Lo uso molto, l'unica variante è che se un segreto è necessario solo per alcuni playbook può essere utile memorizzarlo in un albero diverso e includerlo tramite un percorso che include l'host o il nome var.
RichVel,

1
Se ho crittografato il valore 'ansible_ssh_pass' nel Vault, quindi devo duplicare anche il valore 'ansible_sudo_pass'? C'è un modo per il secondo valore sudo_pass per fare riferimento al primo valore 'ssh_pass'?
emeraldjava,

Buona copertura sull'uso della password a volta può essere trovato qui: stackoverflow.com/a/37300030/5025060
CODE-leggere

22

Con Ansible 1.5, è possibile impostare la variabile ansible_sudo_pass usando lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Trovo questo più conveniente rispetto all'utilizzo dei file host_vars/per diversi motivi:

  • In realtà utilizzo with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" per eseguire il provisioning delle password per l' utente remoto deploy (che è quindi necessario per sudo ), quindi sono già presenti nei file (anche se fare queste ricerche in testo semplice perde il valore salt memorizzato nel file quando viene generato il valore con hash) .

  • Ciò mantiene solo le password nel file (nessun ansible_sudo_pass:testo in chiaro noto) per un aumento epsilon della sicurezza crittografica. Più significativamente, significa che non stai crittografando tutte le altre variabili specifiche dell'host, quindi possono essere lette senza la password del vault.

  • Mettere le password in una directory separata rende più facile tenere i file fuori dal controllo del codice sorgente o usare uno strumento come git-crypt per archiviarli in forma crittografata (puoi usarlo con Ansible precedente che non ha la funzionalità del vault). Uso git-crypt e poiché controllo il repository solo in forma decifrata su filesystem crittografati, non mi preoccupo del vault e quindi non ho bisogno di digitare una password del vault. (L'uso di entrambi sarebbe ovviamente più sicuro.)

Puoi anche usare la funzione di ricerca con ansible_ssh_pass ; questo potrebbe anche essere possibile con versioni precedenti di Ansible che non hanno ansible_sudo_pass .


2
Ho finalmente avuto tempo di provare questo, ma non riesco a vedere come avrebbe funzionato senza (grazie!) git-crypt; per quanto posso vedere. Sembra che Ansible non abbia ancora il supporto per l'utilizzo lookupsu un deposito crittografato. I passworddocumenti del modulo affermano che esiste un supporto ancora non documentato per l'archiviazione crittografata, ma devo ancora trovare i dettagli. Qualche indizio?
supervacuo,

19

L'uso di pass è un metodo semplice per fornire risposte con password sudo. pass memorizza una password per file che semplifica la condivisione di password tramite git o altri metodi. È anche sicuro (usando GnuPG) e se stai usando gpg-agent, ti permette di usare ansible senza inserire una password ad ogni utilizzo.

Per fornire la password memorizzata come servers/fooserver foodi risposta, utilizzarla in un file di inventario come questo:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Dato che hai sbloccato la chiave per gpg-agent in precedenza, questo verrà eseguito senza la necessità di inserire alcuna password.


3

Questo è un thread piuttosto vecchio, tuttavia:

  • Usiamo internamente due diversi sistemi di autenticazione, la gestione delle macchine viene eseguita da stazioni di lavoro locali nel mio team.
  • Ho scritto a vars_pluginfor Ansible (un'implementazione piuttosto completa può essere trovata su https://gist.github.com/mfriedenhagen/e488235d732b7becda81 ) che differenzia diversi sistemi di autenticazione:
  • Il nome del sistema di autenticazione è specifico del gruppo.
  • L'utente login / sudo utilizzato è specifico del gruppo e dell'amministratore.
  • Quindi estraggo l'utente dall'ambiente di amministrazione e la password corrispondente tramite la libreria di portachiavi in ​​pitone da una password sicura (utilizziamo il portachiavi di Mac OS X, ma anche dalla documentazione kwallet Gnome e _win_crypto sono supportati).
  • Ho impostato le autorizzazioni sulle password nel portachiavi di Mac OS X per avvisarmi del fatto, che la sicurezza del programma della riga di comando richiede l'accesso a una password per ogni sistema di autenticazione utilizzato dagli host, quindi eseguo "ansible -s all -m ping" e ottenere due prompt (uno per ciascun sistema di autenticazione) in cui premo la barra spaziatrice e Ansible raccoglie le password.

Sembra molto pulito, grazie - mi piace l'idea di non dover memorizzare le password in due posti. Al momento sono bloccato usando KeepassX (perché il portachiavi GNOME non sembra molto portatile) ma forse posso far python-keepassfunzionare?
supervacuo

A quanto ho capito, il portachiavi in ​​pitone è un'astrazione per questo, quindi i tuoi colleghi potrebbero usare altri sistemi operativi. O memorizzi il tuo keepassx db su una chiavetta USB e devi amministrare da workstation con diversi sistemi operativi?
Mirko Friedenhagen,

inteso; Volevo dire che devo già usare KeepassX per avere accesso alle password su sistemi non GNOME, quindi memorizzarle gnome-keyringsignificherebbe conservare record duplicati. Comunque molto più bello dell'uso NOPASSWD, però ...
supervacuo

0

Un modo possibile per farlo è utilizzare le variabili ambientali.

per esempio

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Quindi nei giochi, puoi cercare la password sudo usando:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.