Il modo migliore per cambiare una password di root su 3000+ server Solaris, AIX e Linux?


12

Per farla breve: grande vecchia società, molti server UNIX / Linux.

Ho ereditato la responsabilità di un mucchio di sceneggiature che è partito qualche anno fa. Uno di questi era uno script che sarebbe stato eseguito ogni $ X mesi per aggiornare globalmente la password di root su tutti i nostri server.

Lo script è un casino di Shell Script e Expect e funziona sulla fiducia SSH che è impostata tra tutti i nostri server e un server centrale di comando e controllo.

Il problema è che la sceneggiatura è un casino enorme. I comandi Expect stanno cercando di tenere conto di ogni possibile versione di "passwd" che esiste su qualsiasi box UNIX / Linux là fuori - e variano abbastanza.

Mentre stiamo espandendo e aggiornando gran parte della nostra infrastruttura, lo script sta diventando davvero ingestibile.

La mia domanda è: esiste un modo migliore per farlo? Supponendo che ci sia un trust SSH già stabilito, qual è il modo migliore per cambiare la password di root su più di 3000 server contemporaneamente?


2
L'uso sudoe l'eliminazione totale delle password di root non è un'opzione, vero?
Dmitri Chubarov,

5
Assumere un tirocinante? :)
EEAA

1
@DmitriChubarov usando "sudo" implicherebbe avere un account diverso per mantenere (e cambiare) una password - quindi qual è il punto?
the-wabbit

1
@ syneticon-dj gli altri account possono essere creati di nuovo e archiviati in un database gestito centralmente, ad esempio LDAP o NIS, qualunque cosa sia meglio supportata. Non è la stessa cosa strappare via la radice locale e sostituirla con quella proveniente da LDAP.
Dmitri Chubarov,

2
Se hai> macchine 3k, hai bisogno di strumenti di gestione ... ieri!
warren,

Risposte:


17

Usa marionetta .

Puppet è molto flessibile, facile da mantenere e utilizza SSL. Potrebbe sembrare un po 'eccessivo e dovrai fare uno sforzo extra per costruire il sistema Puppet.

Ma. Molto probabilmente questo non è l'ultimo aggiornamento di massa che eseguirai su queste macchine. Puppet ti farà risparmiare molto tempo quando inizia qualsiasi procedura di aggiornamento di massa e gli script sono molto leggibili / riutilizzabili.

Almeno questo ha funzionato per me alcuni anni fa e sono ancora in grado di riutilizzare alcune di quelle ricette di marionette (aka script). L'ho usato anche in ambienti un po 'più piccoli, assicurandomi che ogni macchina abbia effettivamente uno stato noto .

Ho dimostrato molte volte (in molte aziende) che tutti gli script di distribuzione personalizzati diventano dolore nel culo dopo un po 'o quando interviene il ragazzo successivo. E finché porti un cellulare, i vecchi script lo perseguiteranno e ti perseguiteranno.

Se pensi che questo suona davvero bene, ecco un ottimo tutorial Puppet con ambiente virtuale incluso per iniziare.


4
Agred, ma non utilizzare a user{"root":}per impostare la password. Invece, usa un exec{"chpasswd -e ..."}, che è molto più sicuro.
Dennis Kaarsemaker,

7
Correggi la tua risposta, il burattino utilizza SSL, non SSH. Concordo con il resto, anche se Ansible sembra un'alternativa leggera molto più adatta a questo caso d'uso. Solo pip install ansiblein una scatola GNU / Linux, crea un elenco di host e ansible -m user -a "password=$crpyt". Nessun agente necessario. Gestisce immediatamente GNU / Linux, AIX e Solaris.
dawud,

È vero che utilizza SSL, non SSH. Uso come manutentore in un sistema in cui Puppet veniva utilizzato tramite SSH eseguendo un client - per farla breve. Risposta corretta Grazie dawud sottolineandolo!
Tomi,

Di seguito ho fornito la mia risposta , ma sto accettando la tua, poiché è probabilmente la soluzione più "corretta" e gestibile a lungo termine al problema. Tuttavia, richiede un investimento significativo in termini di infrastruttura, pianificazione, licenze e tempo per distribuire Puppet in un ambiente delle nostre dimensioni. Un giorno ci arriveremo ...
Ricapar

1
@DennisKaarsemaker: dovresti segnalarlo come un bug a Puppet Labs. Sarebbero molto interessati a sentirlo.
Bill Weiss,

3

Ho usato il modulo Perl Authen :: PAM su Solaris con grande successo. Ecco uno script di esempio:

#!/usr/bin/perl

use Authen::PAM;

my $username = 'root';
my $password = '1234567';

die qq{Error: Unknown user\n} unless getpwnam($username);

die qq{Error: You must run this as root.\n} unless ($> == 0);

my $pamh;

sub my_conv_func
{
    my @res;
    while ( @_ )
    {
        my $code = shift;
        my $msg = shift;
        my $ans = "";

        if ($code == PAM_PROMPT_ECHO_OFF() )
        {
            if (($msg =~ /^New Password:/i) or ($msg =~ /^Re-enter new Password:/i))
            {
                $ans = $password;
            }
            else
            {
                die qq{Unknown message: $msg\n};
            }
        }
        else
        {
            print qq{$msg\n};
        }

        push @res, (PAM_SUCCESS(), $ans);
    }
    push @res, PAM_SUCCESS();

    return @res;
}

ref($pamh = new Authen::PAM("passwd", $username, \&my_conv_func)) || die "Error code $pamh during PAM init!";

my $res = $pamh->pam_chauthtok;

print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS();

exit 0;

2

Se riesci a scrivere Perl, il modulo Net :: OpenSSH :: Parallel consente di scrivere script che eseguono azioni in parallelo su host remoti tramite SSH abbastanza facilmente.

Contiene uno script di esempio per modificare le password che è possibile utilizzare come base. Siccome sembra che tu abbia un ambiente eterogeneo, ti piacerebbe raggruppare gli host per tipo e usare un dialogo diverso per gestire i sottotitoli di ognuno.


1

Non conosco il "migliore", e se sia possibile per tutte le macchine non Linux * nix nel tuo mix, ma hai guardato il pupazzo o il cfengine per questo tipo di attività?

Esistono anche strumenti commerciali (molto costosi) per la gestione delle identità, due che ho visto / usato in passato sono Oracle Identity Manager e l'equivalente Novel.


1

Dopo aver continuato a ricercare questo, ho imparato alcune cose ...

Innanzitutto, questo è un compito davvero fastidioso da automatizzare, specialmente in molti ambienti diversi. La risposta più corretta a questa domanda è probabilmente @ tomi: usa Puppet.

Alla fine spero di ottenere Puppet per gestire l'infrastruttura, ma la distribuzione su server UNIX dell'intera azienda per una modifica della password di root in questo momento non è così fattibile di un'opzione.

Dopo aver letto molte manpage e molti Google-fu, sono riuscito a trovare uno script che scorre in un elenco di server di destinazione, apre una connessione SSH ed esegue una delle seguenti operazioni:

# Solaris
# Generate new pass via crypt(newpass,salt) and insert it into /etc/shadow

# AIX
$ echo "root:newpass" | chpasswd -f NOCHECK

# Linux
$ echo "newpass" | passwd root --stdin

# IBM VIO (Virtual I/O)
$ echo "echo \"padmin:newpass\" | chpasswd -f NOCHECK" | oem_setup_env

# IBM HMCs (Hardware Management Consoles)
$ chhmcusr -u hscroot -t passwd -v "newpass"

Fa un po 'di più che eseguire solo quei comandi, ma quelli sopra sono ciò che funziona la magia.

Non sono riuscito a trovare un modo semplice per modificare in modo non iterativo la password su Solaris, quindi abbiamo fatto ricorso alla modifica /etc/shadowal volo.


2
Non inserire password in chiaro nella riga di comando, poiché viene registrato nella cronologia della shell. Oppure imposta la cronologia della shell su /dev/nullprima di farlo.
Marcin,

1
sì, inoltre, non inserire la password nello script, controlla il mio script per aggiungere passwd crittografato
Rahul Patil,

1

Di recente l'ho fatto usando Bash Script ..

#!/usr/bin/env bash

# Change Password of Remote Server Using SSH

#--------------------------------------------
# Define User which you want to
# Change Password in remote server
#--------------------------------------------
Uname="root"
# Create Password in Encrpyted Form Using below command,
# and store in this script
# perl -e'print crypt("YourPassword", "salt")' ; echo -e
# then copy and past in following varible,
# password should be single qouted*

Password='safv8d8ESMmWk'

Update_Pass() {
  ssh $ruser@$Server_ip  -p $port "echo ${Uname}:${Password} | chpasswd -e"
}

Show_Help(){
cat <<_EOF
Usage $0        [OPTION]..
Mandatory arguments to long options are mandatory for short options too.
  -i, --ip     <IP_ADDR_OF_SREVER> IP Address Of Remote Server
  -u, --user   <Username>          Username Of Remote Server    <Default User is root>
  -p, --port   <port>              Port Of Remote Server        <Default is 22>

Note:- For Security Reason Do Not Provide Password to the script, because
       it will get save in history, so do not provide it,
       script will prompt for password

Report $0 bugs to loginrahul90@gmail.com
_EOF
}



Main() {

        case $1 in
           -i|--ip) Server_ip=$2;
                    ruser="$4"; [[ -z $ruser ]] && ruser=root
                    port="$6";  [[ -z $port  ]]  && port=22
                    Update_Pass ;;
                *)  Show_Help ;;
        esac
}

Main $*

1

Questa è la mia soluzione finora. Devo ancora vedere se funziona su più sistemi

#!/usr/bin/env bash

ChangePassword()
{
    echo "changing password for server $ServerIp"
    ssh root@$ServerIp "echo root:${NewPassword} | chpasswd" < /dev/null
}

CreatePassword()
{
    while true;
    do
        echo "Please enter the new password :"
        read -s NewPassword <&0
        echo "Confirm the password :"
        read -s ConfirmPassword <&0 
        # /proc/${PPID}/fd/0

        if [ "$NewPassword" == "$ConfirmPassword" ]
        then
            break
        else
            echo "Passwords do not match"
            echo "Try again..."
        fi
    done
    ChangePassword
    echo "end of createpassword"
}

SetUpPasswordlessSSH()
{   
    echo "enter the old password from server $ServerIp when asked"
    ssh root@$ServerIp mkdir -p .ssh
    cat .ssh/id_rsa.pub | ssh root@$ServerIp 'cat >> .ssh/authorized_keys'

    echo "Passwordless SSH is now available"
    echo "Now you can change the password"
    CreatePassword
}

NoSSH()
{
    echo "Passwordless SSH for this server with ip $ServerIp is not yet set up."
    read -p "Do you want to set it up now? " -n 1 -r <&0
    echo "" 
    if [[ ! $REPLY =~ ^[Yy]$ ]]
    then
        break
    else
        SetUpPasswordlessSSH
    fi
}

AcceptHostKey()
{
    read -p "Do you trust the server? " -n 1 -r <&1 
    echo ""
    if [[ ! $REPLY =~ ^[Yy]$ ]]
    then
        break
    else
        SetUpPasswordlessSSH
    fi
}

Main()
{
    while read -r ServerIp <&9
    do
        echo  "Server $ServerIp ..."
        status=$(ssh -o BatchMode=yes -o ConnectTimeout=5 $ServerIp echo ok 2>&1)
        if [[ $status == ok ]]
        then
            echo "creating password"
            CreatePassword
            echo "password changed"
        elif [[ $status == "Permission denied"* ]]
        then
            NoSSH
        elif [[ $status == "Host key verification failed"* ]]
        then
            echo "Error: $status"
            AcceptHostKey
        else
            echo "ERROR OCCURED FOR SERVER WITH IP: $ServerIp"
            echo "Error: $status"
        fi
    done 9< servers.txt
    history -cw
    clear
}

Main $*

0

È possibile utilizzare pdsh per eseguire il comando su più host contemporaneamente.


E quale comando eseguirai? passwdè diverso nelle diverse versioni menzionate. pwnon sempre disponibile ....
Chris S,

Abbiamo abbastanza bene l'esecuzione dei comandi su tutte le caselle. Il problema è l'effettiva modifica della password. Per quanto ne so, passwdè sempre interattivo per l'utente.
Ricapar,

passwdsu RHEL Linux almeno ha un --stdinparametro
AngerClown

0

Oltre al pupazzo: SaltStack Un altro approccio: automatizza l'esecuzione usando le librerie SSH in modo sequenziale o in parallelo usando Fabric http://docs.fabfile.org/en/1.6/ , Capistrano o simili che non richiedono molto tempo / impegno per la distribuzione.


0

Due opzioni:

Usa il burattino

Usa il mazzo run. Run deck è un server che consente di eseguire comandi su centinaia di macchine contemporaneamente. È possibile raggruppare le macchine in gruppi, al fine di eseguire comandi su un solo sottoinsieme di macchine.

http://rundeck.org


-2

Penso che il formato del /etc/shadowfile sia abbastanza standard tra le distribuzioni di Linux. Puoi semplicemente scrivere un semplice script awk per aggiornare la password.

cat /etc/shadow| awk -v pass='NEWPASSHASH' -v now=`date '+%s'` 'BEGIN{ OFS=FS=":"} /^root/ {$2=pass; $3=now} {print}' > /tmp/shadow && mv /tmp/shadow /etc/shadow

Mi assicurerei di testarlo in modo da non bloccare te stesso;)


Credo che la modifica di / etc / shadow sia la strada da percorrere. Tuttavia, il reindirizzamento non cancellerà / etc / shadow prima della modifica? Sembra un caso per ed o ex.
mpez0

3
Il formato di ombra può essere, ma non è garantito che gli hash siano interpretati dallo stesso algoritmo ovunque. Inoltre la tua piccola sceneggiatura ha appena rimosso tutte le voci dall'ombra. :}
tink

lol oops, dovrebbe essere riparato. Spero che tu non abbia corso su quel tink;)
HaxElit
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.