¿La mejor manera de cambiar una contraseña de root en más de 3000 servidores Solaris, AIX y Linux?

12

Larga historia corta: gran corporación antigua, muchos servidores UNIX / Linux.

Heredé la responsabilidad de un montón de guiones que dejaron hace unos años. Uno de ellos era un script que se ejecutaría cada $ X durante meses para actualizar globalmente la contraseña de root en todos nuestros servidores.

El script es un desastre de Shell Script and Expect, y funciona en la confianza SSH que se configura entre todos nuestros servidores y un servidor central de comando y control.

El problema es que el guión es un desastre gigante. Los comandos de Expect están tratando de dar cuenta de todas las versiones posibles de "passwd" que existen en cualquier cuadro de UNIX / Linux, y varían bastante.

A medida que estamos ampliando y actualizando gran parte de nuestra infraestructura, el script se está volviendo realmente inmanejable.

Mi pregunta es: ¿hay una mejor manera de hacer esto? Suponiendo que haya una confianza SSH ya establecida, ¿cuál es la mejor manera de cambiar la contraseña de root en más de 3000 servidores al mismo tiempo?

Ricapar
fuente
2
Usar sudoy eliminar las contraseñas raíz por completo no es una opción, ¿verdad?
Dmitri Chubarov
55
¿Contratar a un pasante? :)
EEAA
1
@DmitriChubarov usar "sudo" implicaría tener una cuenta diferente para mantener (y cambiar) una contraseña, así que, ¿dónde está el punto?
the-wabbit
1
@ syneticon-dj las otras cuentas pueden crearse nuevamente y almacenarse en alguna base de datos mantenida centralmente, por ejemplo, LDAP o NIS, lo que sea mejor soportado. No es lo mismo que arrancar la raíz local y reemplazarla con la que proviene de ldap.
Dmitri Chubarov
2
Si tienes máquinas> 3k, necesitas herramientas de administración ... ¡ayer!
Warren

Respuestas:

17

Utiliza la marioneta .

Puppet es muy flexible, fácil de mantener y utiliza SSL. Puede sonar un poco exagerado y tendrás que hacer un esfuerzo extra para construir el sistema Puppet.

Pero. Probablemente esta no sea la última actualización masiva que harás en estas máquinas. Puppet te ahorrará mucho tiempo cuando comience cualquier procedimiento de actualización masiva y los scripts sean muy legibles / reutilizables.

Al menos esto funcionó para mí hace unos años y todavía puedo reutilizar algunas de esas recetas de Puppet (también conocidos como scripts). También lo he usado en entornos un poco más pequeños, solo asegúrate de que cada máquina tenga un estado conocido .

He demostrado muchas veces (en muchas empresas) que todos los scripts de implementación personalizados se vuelven dolorosos después de un tiempo o cuando interviene el siguiente tipo. Y siempre que lleve un teléfono celular, los scripts antiguos lo perseguirán y lo harán.

Si crees que esto realmente suena bien, aquí hay un gran tutorial de Puppet con entorno virtual incluido para que comiences.

tomi
fuente
44
Envejecido, pero no use a user{"root":}para establecer la contraseña. En cambio, use un exec{"chpasswd -e ..."}, que es mucho más seguro.
Dennis Kaarsemaker
77
Corrija su respuesta, la marioneta usa SSL, no SSH. De acuerdo con el resto, aunque ansible parece una alternativa ligera mucho más adecuada para este caso de uso. Solo pip install ansibleen un cuadro de GNU / Linux, cree una lista de hosts y ansible -m user -a "password=$crpyt". No se necesitan agentes. Gestiona GNU / Linux, AIX y Solaris fuera de la caja.
Dawud
Es cierto que usa SSL, no SSH. Solía ​​ser mantenedor en un sistema en el que Puppet se usaba a través de SSH ejecutando un cliente. Respuesta corregida. Gracias Dawud señalando eso!
Tomi
A continuación proporcioné mi propia respuesta , pero acepto la suya, ya que probablemente sea la solución a largo plazo más "correcta" y manejable para el problema. Sin embargo, requiere una inversión significativa en términos de infraestructura, planificación, licencias y tiempo para implementar Puppet en un entorno de nuestro tamaño. Algún día llegaremos allí ...
Ricapar
1
@DennisKaarsemaker: debe informarlo como un error a Puppet Labs. Estarían súper interesados ​​en escucharlo.
Bill Weiss
3

He usado el módulo Perl Authen :: PAM en Solaris con gran éxito. Aquí hay un script de muestra:

#!/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;
fortezza
fuente
2

Si puede escribir Perl, el módulo Net :: OpenSSH :: Parallel permite escribir scripts que realizan acciones en paralelo en hosts remotos a través de SSH con bastante facilidad.

Contiene una secuencia de comandos de muestra para cambiar las contraseñas que puede usar como base. Como parece que tiene un entorno heterogéneo, le gustaría agrupar los hosts por tipo y usar un sub diálogo de manejo de diálogo diferente para cada uno.

salva
fuente
1

No sé sobre "mejor", y si es posible para todas las máquinas nix * que no son Linux en su mezcla, pero ¿ha mirado títeres o cfengine para este tipo de actividad?

También hay herramientas comerciales (muy caras) para la gestión de identidad, dos que he visto / usado en el pasado son Oracle Identity Manager y el equivalente de Novela.

tink
fuente
1

Después de continuar investigando esto, aprendí algunas cosas ...

En primer lugar, esta es una tarea realmente molesta para automatizar, especialmente en muchos entornos diferentes. La respuesta más correcta a esta pregunta es probablemente @ tomi's: use Puppet.

Eventualmente, espero que Puppet administre la infraestructura, pero la implementación en los servidores UNIX de toda la empresa para un cambio de contraseña de root en este momento no es una opción tan factible.

Después de leer muchas páginas de manual y un montón de Google-fu, logré crear un script que recorre una lista de servidores de destino, abre una conexión SSH y ejecuta uno de los siguientes:

# 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"

Hace bastante más que ejecutar solo esos comandos, pero los anteriores son los que funcionan la magia.

No pude encontrar ninguna manera simple de cambiar la contraseña de forma no iterativa en Solaris, por lo que recurrimos a la modificación /etc/shadowsobre la marcha.

Ricapar
fuente
2
No coloque contraseñas de texto sin cifrar en la línea de comandos, ya que se registra en el historial del shell. O configure el historial de shell /dev/nullantes de hacerlo.
Marcin
1
sí, tampoco coloque la contraseña en el script, verifique mi script para agregar passwd encriptado
Rahul Patil
1

Recientemente he hecho esto 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 [email protected]
_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 $*
Rahul Patil
fuente
1

Esta es mi solución hasta ahora. todavía necesito ver si funciona en múltiples sistemas

#!/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 $*
duez
fuente
0

Puede usar pdsh para ejecutar su comando en varios hosts al mismo tiempo.

Jack
fuente
¿Y qué comando vas a ejecutar? passwdes diferente en las diferentes versiones mencionadas. pwno siempre disponible ....
Chris S
Tenemos la parte de ejecutar comandos en todos los cuadros bastante bien. El problema es el cambio real de la contraseña. Que yo sepa, passwdsiempre es interactivo para el usuario.
Ricapar
passwden RHEL Linux al menos tiene un --stdinparámetro
AngerClown
0

Además del títere: SaltStack Otro enfoque: automatice la ejecución usando las bibliotecas SSH de forma secuencial o en paralelo usando Fabric http://docs.fabfile.org/en/1.6/ , Capistrano o similar que no requieren mucho tiempo / esfuerzo para desplegarse.

Eugene
fuente
0

Dos opciones:

Usar marioneta

Utilice la plataforma de ejecución. Run deck es un servidor que le permite ejecutar comandos en cientos de máquinas simultáneamente. Puede agrupar máquinas en grupos, para ejecutar comandos en solo un subconjunto de máquinas.

http://rundeck.org

Spuder
fuente
-2

Creo que el formato del /etc/shadowarchivo es bastante estándar en las distribuciones de Linux. ¿Puedes escribir un script awk simple para actualizar la contraseña?

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

Me aseguraría de probarlo para que no te bloquees;)

HaxElit
fuente
Creo que editar / etc / shadow es el camino a seguir. Sin embargo, ¿la redirección no borrará / etc / shadow antes de la edición? Esto parece un caso para ed o ex.
mpez0
3
El formato de sombra puede ser, pero no se garantiza que los hashes sean interpretados por el mismo algoritmo en todas partes. Además, su pequeño script acaba de eliminar todas las entradas de shadow por completo. :}
tink
lol oops, debe arreglarse. Espero que no hayas tenido ese sudo;)
HaxElit