A melhor maneira de alterar uma senha raiz em mais de 3000 servidores Solaris, AIX e Linux?

13

Longa história: grande corporação antiga, muitos servidores UNIX / Linux.

Eu herdei a responsabilidade por um monte de scripts que foram deixados há alguns anos atrás. Um deles era um script que seria executado a cada $ X meses para atualizar globalmente a senha de root em todos os nossos servidores.

O script é uma bagunça do Shell Script and Expect, e funciona na confiança SSH que é configurada entre todos os nossos servidores e um servidor central de comando e controle.

O problema é que o script é uma bagunça gigante. Os comandos Expect estão tentando explicar todas as versões possíveis de "passwd" que existem em qualquer caixa UNIX / Linux - e elas variam um pouco.

Como estamos expandindo e atualizando muito da nossa infraestrutura, o script está ficando realmente incontrolável.

Minha pergunta é: existe uma maneira melhor de fazer isso? Supondo que exista uma confiança SSH já estabelecida, qual é a melhor maneira de alterar a senha de root em mais de 3000 servidores ao mesmo tempo?

    
por Ricapar 22.05.2013 / 16:22

11 respostas

17

Use o Fantoche .

O Puppet é muito flexível, fácil de manter e usa SSL. Pode soar um pouco exagerado e você terá que fazer um esforço extra para construir o sistema Puppet.

Mas. Provavelmente, esta não é a última atualização em massa que você fará nessas máquinas. O Puppet irá poupar muito tempo quando o processo de atualização em massa começar e os scripts forem muito legíveis / reutilizáveis.

Pelo menos isso funcionou para mim há alguns anos e ainda posso reutilizar algumas dessas receitas Puppet (também conhecidas como scripts). Eu também usei em ambientes um pouco menores, apenas certifique-se de que cada máquina esteja realmente tendo um estado conhecido .

Eu provei isso muitas vezes (em muitas empresas) que todos os scripts de implantação personalizados se tornam problemáticos depois de um tempo ou quando o próximo cara entra em cena. E enquanto você carrega um celular, os scripts antigos o perseguem você.

Se você acha que isso realmente parece bom, aqui está um grande tutorial de marionetes com ambiente virtual incluído para você começar.

    
por 22.05.2013 / 21:03
3

Eu usei o módulo Perl Authen :: PAM no Solaris com grande sucesso. Aqui está um exemplo de script:

#!/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;
    
por 26.05.2013 / 21:04
2

Se você pode escrever Perl, o módulo Net :: OpenSSH :: Parallel permite escrever scripts que executam ações em paralelo em hosts remotos via SSH com bastante facilidade.

Ele contém um script de amostra para alterar as senhas que você pode usar como base. Como parece que você tem um ambiente heterogêneo, você gostaria de agrupar os hosts por tipo e usar um subcole de manipulação de diálogos diferente para cada um.

    
por 23.05.2013 / 10:37
1

Eu não sei sobre o "melhor", e se é possível para todas as máquinas não-Linux * nix em seu mix, mas você já olhou para o fantoche ou cfengine para este tipo de atividade?

Também existem ferramentas comerciais (muito caras) para gerenciamento de identidades, duas que eu vi / usei no passado são o Oracle Identity Manager e o equivalente a Novel.

    
por 22.05.2013 / 19:42
1

Depois de continuar a pesquisar isso, aprendi algumas coisas ...

Em primeiro lugar, essa é uma tarefa realmente irritante de automatizar, especialmente em muitos ambientes diferentes. A resposta mais correta para essa pergunta provavelmente é a do @ tomi: use Puppet.

Eventualmente, espero que o Puppet gerencie a infraestrutura, mas a implantação nos servidores UNIX de toda a empresa para uma alteração de senha raiz agora não é uma opção viável.

Depois de ler muitas páginas man e muito do Google-fu, consegui criar um script que percorre uma lista de servidores de destino, abre uma conexão SSH e executa um dos seguintes procedimentos:

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

Ele faz um pouco mais do que executar apenas esses comandos, mas aqueles acima são o que funciona a mágica.

Não encontrei nenhuma maneira simples de alterar a senha de maneira não iterativa no Solaris, por isso recorremos à modificação de /etc/shadow em tempo real.

    
por 23.05.2013 / 21:24
1

Recentemente, fiz isso usando o 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 $*
    
por 29.05.2013 / 05:28
1

Esta é a minha solução até agora. ainda precisa ver se funciona em vários 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 $*
    
por 20.10.2014 / 14:33
0

Você pode usar o pdsh para executar seu comando em vários hosts ao mesmo tempo.

    
por 22.05.2013 / 17:17
0

Além do fantoche: SaltStack Outra abordagem - automatize a execução usando bibliotecas SSH sequencialmente ou em paralelo usando o link , do Capistrano ou similar que não requer muito tempo / esforço para implantar.

    
por 04.06.2013 / 15:49
0

Duas opções:

Use fantoche

Use o deck de corrida. Run deck é um servidor que permite executar comandos em centenas de máquinas simultaneamente. Você pode agrupar máquinas em grupos, para executar comandos em apenas um subconjunto de máquinas.

link

    
por 04.06.2013 / 16:15
-2

Acho que o formato do arquivo /etc/shadow é bem padronizado nas distribuições Linux. Você pode simplesmente escrever um script awk simples para atualizar a senha.

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

Eu me certificaria de testá-lo para que você não se deixe enganar;)

    
por 22.05.2013 / 17:51