La meilleure façon de changer un mot de passe root sur plus de 3000 serveurs Solaris, AIX et Linux?


12

Pour faire court: Big old corporation, beaucoup de serveurs UNIX / Linux.

J'ai hérité de la responsabilité d'un tas de scripts qui sont partis il y a quelques années. L'un d'eux était un script qui serait exécuté tous les X $ mois pour mettre à jour globalement le mot de passe root sur tous nos serveurs.

Le script est un gâchis de Shell Script et Expect, et il fonctionne sur la confiance SSH qui est configurée entre tous nos serveurs et un serveur central de commande et de contrôle.

Le problème est que le script est un gâchis géant. Les commandes Expect essaient de prendre en compte toutes les versions possibles de "passwd" qui existent sur n'importe quelle boîte UNIX / Linux - et elles varient beaucoup.

Alors que nous développons et mettons à niveau une grande partie de notre infrastructure, le script devient vraiment ingérable.

Ma question est: existe-t-il une meilleure façon de procéder? En supposant qu'il existe une confiance SSH déjà établie, quelle est la meilleure façon de changer le mot de passe root sur plus de 3000 serveurs en même temps?


2
Utiliser sudoet éliminer complètement les mots de passe root n'est pas une option, n'est-ce pas?
Dmitri Chubarov

5
Embaucher un stagiaire? :)
EEAA

1
@DmitriChubarov utilisant "sudo" impliquerait d'avoir un compte différent pour maintenir (et changer) un mot de passe - alors où est le point?
le-wabbit

1
@ syneticon-dj les autres comptes peuvent être créés à nouveau et stockés sur une base de données maintenue de manière centralisée, par exemple LDAP ou NIS, tout ce qui est mieux pris en charge. Ce n'est pas la même chose que d'extraire la racine locale et de la remplacer par celle provenant de ldap.
Dmitri Chubarov

2
Si vous avez> 3 000 machines, vous avez besoin d'outils de gestion ... hier!
warren

Réponses:


17

Utilisez Puppet .

Puppet est très flexible, facile à entretenir et utilise SSL. Cela peut sembler un peu exagéré et vous devrez faire un effort supplémentaire pour construire le système Puppet.

Mais. Ce n'est probablement pas la dernière mise à jour de masse que vous ferez sur ces machines. Puppet vous fera gagner du temps lorsque la procédure de mise à jour en masse commencera et que les scripts seront très lisibles / réutilisables.

Au moins, cela a fonctionné pour moi il y a quelques années et je suis toujours en mesure de réutiliser certaines de ces recettes de marionnettes (alias scripts). Je l'ai également utilisé dans des environnements un peu plus petits, assurez-vous simplement que chaque machine a un état connu .

J'ai prouvé à plusieurs reprises (dans de nombreuses entreprises) que tous les scripts de déploiement personnalisés deviennent douloureux après un certain temps ou lorsque ce prochain gars intervient. Et tant que vous portez un téléphone portable, les anciens scripts vous hanteront et vous hanteront.

Si vous pensez que cela semble vraiment bon, voici un excellent tutoriel Puppet avec un environnement virtuel inclus pour vous aider à démarrer.


4
AGRED, mais ne pas utiliser user{"root":}pour définir le mot de passe. Utilisez plutôt un exec{"chpasswd -e ..."}, qui est beaucoup plus sûr.
Dennis Kaarsemaker

7
Veuillez corriger votre réponse, la marionnette utilise SSL, pas SSH. D'accord avec le reste, bien qu'ansible semble être une alternative légère bien mieux adaptée à ce cas d'utilisation. Juste pip install ansibledans une boîte GNU / Linux, construisez une liste d'hôtes et ansible -m user -a "password=$crpyt". Aucun agent nécessaire. Gère GNU / Linux, AIX et Solaris prêts à l'emploi.
dawud

Certes, il utilise SSL, pas SSH. J'utilise pour être mainteneur dans un système où Puppet a été utilisé via SSH en exécutant un client - histoire courte. Réponse corrigée. Merci dawud de l'avoir signalé!
tomi

J'ai fourni ma propre réponse ci - dessous , mais j'accepte la vôtre, car c'est probablement la solution à long terme la plus «correcte» et la plus gérable au problème. Cependant, cela nécessite un investissement important en termes d'infrastructure, de planification, de licence et de temps pour déployer Puppet dans un environnement de notre taille. Un jour nous y arriverons ...
Ricapar

1
@DennisKaarsemaker: vous devez signaler cela comme un bug à Puppet Labs. Ils seraient super intéressés de l'entendre.
Bill Weiss

3

J'ai utilisé le module Perl Authen :: PAM sur Solaris avec beaucoup de succès. Voici un exemple 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

Si vous pouvez écrire Perl, le module Net :: OpenSSH :: Parallel permet d'écrire des scripts qui effectuent des actions en parallèle sur des hôtes distants via SSH assez facilement.

Il contient un exemple de script pour changer les mots de passe que vous pouvez utiliser comme base. Comme il semble que vous ayez un environnement hétérogène, vous souhaitez regrouper les hôtes par type et utiliser un sous-gestionnaire de dialogue différent pour chacun.


1

Je ne connais pas "le meilleur", et si c'est possible pour toutes les machines non-Linux * nix de votre mix, mais avez-vous regardé marionnette ou cfengine pour ce genre d'activité?

Il existe également des outils commerciaux (très coûteux) pour la gestion des identités, dont j'ai vu / utilisé dans le passé Oracle Identity Manager et l'équivalent Novel.


1

Après avoir poursuivi mes recherches, j'ai appris quelques choses ...

D'abord et avant tout, c'est une tâche vraiment ennuyeuse à automatiser, en particulier dans de nombreux environnements différents. La réponse la plus correcte à cette question est probablement celle de @ tomi: utilisez Puppet.

Finalement, j'espère que Puppet gérera l'infrastructure, mais le déploiement sur tous les serveurs UNIX de l'entreprise pour un changement de mot de passe racine n'est pas envisageable en ce moment.

Après avoir lu de nombreuses pages de manuel et beaucoup de Google-fu, j'ai réussi à trouver un script qui parcourt une liste de serveurs cibles, ouvre une connexion SSH et exécute l'un des éléments suivants:

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

Il fait beaucoup plus que d'exécuter uniquement ces commandes, mais celles ci-dessus sont ce qui fait la magie.

Je ne pouvais pas trouver de moyen simple de changer le mot de passe de manière non itérative sur Solaris - nous avons donc eu recours à la modification /etc/shadowà la volée.


2
Veuillez ne pas mettre de mots de passe en texte clair sur la ligne de commande, car il est enregistré dans l'historique du shell. Ou définissez l'historique du shell /dev/nullavant de le faire.
Marcin

1
oui, ne mettez pas de mot de passe dans le script, vérifiez mon script pour ajouter un mot de passe crypté
Rahul Patil

1

Récemment, je l'ai fait en utilisant 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

C'est ma solution jusqu'à présent. encore besoin de voir si cela fonctionne sur plusieurs systèmes

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

Vous pouvez utiliser pdsh pour exécuter votre commande sur plusieurs hôtes en même temps.


Et quelle commande allez-vous exécuter? passwdest différent sur les différentes versions mentionnées. pwpas toujours disponible ....
Chris S

Nous avons assez bien exécuté les commandes sur toutes les boîtes. Le problème est le changement de mot de passe. Pour autant que je sache, passwdest toujours interactif pour l'utilisateur.
Ricapar

passwdsur RHEL Linux a au moins un --stdinparamètre
AngerClown

0

En plus de la marionnette: SaltStack Une autre approche - automatiser l'exécution en utilisant les bibliothèques SSH soit séquentiellement ou en parallèle en utilisant Fabric http://docs.fabfile.org/en/1.6/ , Capistrano ou similaire qui ne nécessite pas beaucoup de temps / effort pour se déployer.


0

Deux options:

Utiliser une marionnette

Utilisez run deck. Run deck est un serveur qui vous permet d'exécuter simultanément des commandes sur des centaines de machines. Vous pouvez regrouper des machines en groupes, afin d'exécuter des commandes sur un sous-ensemble de machines uniquement.

http://rundeck.org


-2

Je pense que le format du /etc/shadowfichier est assez standard dans les distributions Linux. Pouvez-vous simplement écrire un simple script awk pour mettre à jour le mot de passe.

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

Je ferais en sorte de le tester pour ne pas vous verrouiller;)


Je crois que l'édition de / etc / shadow est la voie à suivre. Cependant, la redirection n'effacera-t-elle pas / etc / shadow avant la modification? Cela ressemble à un cas pour ed ou ex.
mpez0

3
Le format de l'ombre peut être, mais les hachages ne sont pas garantis pour être interprétés partout par le même algorithme. De plus, votre petit script vient de supprimer toutes les entrées de l'ombre. :}
tink

lol oups, devrait être réparé. J'espère que vous n'avez pas fait de
bricolage
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.