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


12

Longa história: Grande empresa antiga, muitos servidores UNIX / Linux.

Eu herdei a responsabilidade por vários scripts deixados alguns anos atrás. Um deles era um script que seria executado a cada US $ X por meses para atualizar globalmente a senha raiz 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 contabilizar todas as versões possíveis de "passwd" que existem em qualquer caixa UNIX / Linux existente - e elas variam bastante.

Como estamos expandindo e atualizando grande parte de nossa infraestrutura, o script está ficando realmente incontrolável.

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


2
Usar sudoe eliminar completamente as senhas de raiz não é uma opção, é?
Dmitri Chubarov

5
Contratar um estagiário? :)
EEAA

1
@DmitriChubarov usando "sudo" implicaria em ter uma conta diferente para manter (e alterar) uma senha - então, qual é o sentido?
the-wabbit

1
@ syneticon-dj as outras contas podem ser criadas novamente e armazenadas em algum banco de dados mantido centralmente, por exemplo, LDAP ou NIS, o que for melhor suportado. Não é a mesma coisa que arrancar a raiz local e substituí-la pela que vem do ldap.
Dmitri Chubarov

2
Se você tem máquinas> 3k, precisa de ferramentas de gerenciamento ... ontem!
warren 28/05

Respostas:


17

Use Puppet .

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

Mas. Provavelmente, essa não é a última atualização em massa que você fará nessas máquinas. O Puppet poupa muito tempo quando real, seja qual for o procedimento de atualização em massa, e os scripts são muito legíveis / reutilizáveis.

Pelo menos isso funcionou para mim há alguns anos e ainda sou capaz de reutilizar algumas dessas receitas Puppet (também conhecidas como scripts). Também o usei em ambientes um pouco menores, apenas para garantir que todas as máquinas estejam realmente com um estado conhecido .

Eu já provei muitas vezes (em muitas empresas) que todos os scripts de implantação personalizados tornam-se problemáticos depois de um tempo ou quando o próximo cara entra em cena. E desde que você use um telefone celular, scripts antigos irão assombrá-lo.

Se você acha que isso realmente soa bem, aqui está um ótimo tutorial do Puppet com ambiente virtual incluído para você começar.


4
Agred, mas não use a user{"root":}para definir a senha. Em vez disso, use um exec{"chpasswd -e ..."}, que é muito mais seguro.
Dennis Kaarsemaker

7
Corrija sua resposta, o fantoche usa SSL, não SSH. Concorde com o resto, embora o ansible pareça uma alternativa leve muito mais adequada para este caso de uso. Apenas pip install ansibleem uma caixa GNU / Linux, construa uma lista de hosts e ansible -m user -a "password=$crpyt". Nenhum agente é necessário. Gerencia o GNU / Linux, AIX e Solaris imediatamente.
dawud

É verdade que ele usa SSL, não SSH. Eu costumava ser mantenedor de um sistema em que o Puppet era usado via SSH executando uma breve história do cliente. Resposta corrigida. Obrigado dawud apontando isso!
tomi

Forneci minha própria resposta abaixo , mas estou aceitando a sua, pois provavelmente é a solução de longo prazo mais "correta" e gerenciável para o problema. No entanto, requer um investimento significativo em termos de infraestrutura, planejamento, licenciamento e tempo para implementar o Puppet em um ambiente do nosso tamanho. Algum dia chegaremos lá ...
Ricapar

1
@DennisKaarsemaker: você deve relatar isso como um bug ao Puppet Labs. Eles estariam super interessados ​​em ouvi-lo.
Bill Weiss

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;

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 exemplo de script para alterar senhas que você pode usar como base. Como parece que você tem um ambiente heterogêneo, gostaria de agrupar os hosts por tipo e usar um submarino de manipulação de diálogo diferente para cada um.


1

Não sei o que é "melhor" e se é possível para todas as máquinas não-Linux * nix do seu mix, mas você já viu fantoches ou cfengine para esse tipo de atividade?

Existem também ferramentas comerciais (altamente caras) para gerenciamento de identidades por aí, duas que eu já vi / usei no passado são o Oracle Identity Manager e o equivalente da Novel.


1

Depois de continuar pesquisando 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 é da @ tomi: use Puppet.

Eventualmente, espero que o Puppet gerencie a infraestrutura, mas implantar nos servidores UNIX da empresa inteira uma alteração de senha raiz no momento não é uma opção viável.

Depois de ler muitas páginas de manual e muito 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"

Faz um pouco mais do que executar apenas esses comandos, mas os acima são os que funcionam com a mágica.

Não consegui encontrar uma maneira simples de alterar a senha de forma não iterativa no Solaris - por isso recorremos à modificação /etc/shadowem tempo real.


2
Por favor, não coloque senhas de texto não criptografado na linha de comando, pois ela é registrada no histórico do shell. Ou defina o histórico do shell para /dev/nullantes de fazê-lo.
Marcin

1
sim, a senha também não colocar no script, verificar o meu script para adicionar passwd criptografado
Rahul Patil

1

Recentemente eu fiz isso usando o Script Bash.

#!/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

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 $*

0

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


E qual comando você vai executar? passwdé diferente nas diferentes versões mencionadas. pwnem sempre disponível ....
Chris S

Temos a parte de executar comandos em todas as caixas muito bem. O problema é a alteração real da senha. Tanto quanto eu sei, passwdé sempre interativo.
Ricapar

passwdno RHEL Linux, pelo menos tem um --stdinparâmetro
AngerClown

0

Além do fantoche: SaltStack Outra abordagem - automatize a execução usando as bibliotecas SSH sequencialmente ou em paralelo usando o Fabric http://docs.fabfile.org/en/1.6/ , Capistrano ou similar que não exige muito tempo / esforço para implantar.


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.

http://rundeck.org


-2

Eu acho que o formato do /etc/shadowarquivo é bastante padrão nas distribuições Linux. Você pode apenas 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 bloqueie;)


Eu acredito que editar / etc / shadow é o caminho a percorrer. No entanto, o redirecionamento não apagará o / etc / shadow antes da edição? Parece um caso para ed ou ex.
mpez0

3
O formato da sombra pode ser, mas não é garantido que os hashes sejam interpretados pelo mesmo algoritmo em qualquer lugar. Além disso, seu pequeno script acabou de remover todas as entradas da sombra por completo. :}
tink

lol oops, deve ser corrigido. Eu espero que você não sudo executar esse tink;)
HaxElit
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.