Лучший способ изменить пароль root на 3000+ серверах Solaris, AIX и Linux?


12

Короче говоря: большая старая корпорация, множество серверов UNIX / Linux.

Я унаследовал ответственность за несколько сценариев, которые вышли несколько лет назад. Одним из них был скрипт, который будет запускаться каждые $ X месяцев, чтобы глобально обновить пароль root на всех наших серверах.

Этот скрипт представляет собой беспорядок в Shell Script и Expect, и он работает на уровне доверия SSH, который устанавливается между всеми нашими серверами и центральным сервером управления и контроля.

Проблема в том, что сценарий представляет собой гигантский беспорядок. Команды Expect пытаются учесть каждую возможную версию «passwd», которая существует на любом компьютере под управлением UNIX / Linux, - и они сильно различаются.

Поскольку мы расширяем и модернизируем большую часть нашей инфраструктуры, сценарий становится действительно неуправляемым.

Мой вопрос: есть ли лучший способ сделать это? Предполагая, что уже установлено доверие SSH, каков наилучший способ изменить пароль root на 3000+ серверах одновременно?


2
Использование sudoи удаление корневых паролей вообще не вариант, не так ли?
Дмитрий Чубаров

5
Нанять стажера? :)
EEAA

1
@DmitriChubarov с использованием «sudo» подразумевает наличие другой учетной записи для сохранения (и изменения) пароля - так в чем же смысл?
the wabbit

1
@ syneticon-dj другие учетные записи могут быть созданы заново и сохранены в некоторой централизованно поддерживаемой базе данных, например, LDAP или NIS, что лучше поддерживается. Это не то же самое, что оторвать локальный корень и заменить его тем, что пришел из ldap.
Дмитрий Чубаров

2
Если у вас есть> 3k машин, вам нужны инструменты управления ... вчера!
Уоррен

Ответы:


17

Используйте Кукольный .

Puppet очень гибок, прост в обслуживании и использует SSL. Возможно, это звучит немного излишне, и вам придется приложить дополнительные усилия для создания системы Puppet.

Но. Скорее всего, это не последнее массовое обновление, которое вы будете делать с этими машинами. Puppet сэкономит вам много времени, когда начнется любая процедура массового обновления, и сценарии будут очень удобочитаемыми / многократно используемыми.

По крайней мере, это сработало для меня несколько лет назад, и все же я могу повторно использовать некоторые из этих рецептов Кукол (так называемые сценарии). Я также использовал его в немного меньших средах, просто чтобы убедиться, что у каждой машины есть известное состояние .

Я много раз доказывал (во многих компаниях), что все настраиваемые сценарии развертывания становятся болью в заднице через некоторое время или когда вмешивается следующий парень. И пока вы носите мобильный телефон, старые сценарии будут преследовать вас.

Если вы думаете, что это действительно звучит хорошо, вот отличный учебник Puppet с виртуальной средой, включенной, чтобы вы начали.


4
Согласен, но не используйте user{"root":}пароль для установки пароля. Вместо этого используйте exec{"chpasswd -e ..."}, что намного безопаснее.
Деннис Каарсемакер

7
Пожалуйста, исправьте свой ответ, марионетка использует SSL, а не SSH. Согласитесь с остальными, хотя ansible кажется легкой альтернативой, гораздо лучше подходящей для этого варианта использования. Просто pip install ansibleв окне GNU / Linux создайте список хостов и ansible -m user -a "password=$crpyt". Агенты не нужны. Управляет GNU / Linux, AIX и Solaris из коробки.
Дауд

Правда он использует SSL, а не SSH. Я использую для сопровождения в системе, где Puppet был использован через SSH, выполняя клиент - короткая история. Ответ исправлен. Спасибо, Дауд, указал на это!
Томи

Я предоставил свой собственный ответ ниже , но я принимаю ваш, поскольку это, вероятно, самое «правильное» и управляемое долгосрочное решение проблемы. Тем не менее, для развертывания Puppet в условиях нашего размера требуются значительные инвестиции в инфраструктуру, планирование, лицензирование и время. Когда-нибудь мы туда доберемся ...
Ricapar

1
@DennisKaarsemaker: вы должны сообщить об этом в Puppet Labs как об ошибке. Им было бы очень интересно услышать это.
Билл Вайс

3

Я использовал модуль Perl Authen :: PAM в Solaris с большим успехом. Вот пример сценария:

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

Если вы можете написать Perl, модуль Net :: OpenSSH :: Parallel позволяет писать сценарии, которые выполняют действия параллельно на удаленных хостах через SSH довольно легко.

Он содержит пример скрипта для смены паролей, который вы можете использовать в качестве базы. Поскольку кажется, что у вас гетерогенная среда, вы хотели бы сгруппировать хосты по типу и использовать разные подпрограммы обработки диалога для каждого.


1

Я не знаю, что такое «лучший», и возможно ли это для всех машин, отличных от Linux * nix, в вашем миксе, но вы рассматривали puppet или cfengine для этого вида деятельности?

Существуют также коммерческие (очень дорогие) инструменты для управления идентификацией, два из которых я видел / использовал в прошлом: Oracle Identity Manager и эквивалент Novel.


1

Продолжив исследовать это, я узнал несколько вещей ...

Прежде всего, это действительно раздражающая задача для автоматизации, особенно в разных средах. Самый правильный ответ на этот вопрос, вероятно, @ tomi's: используйте Puppet.

В конце концов, я надеюсь, что Puppet сможет управлять инфраструктурой, но развертывание на всех серверах UNIX всего предприятия для смены пароля root сейчас не представляется возможным.

Прочитав много man-страниц и множество Google-фу, мне удалось придумать скрипт, который просматривает список целевых серверов, открывает SSH-соединение и выполняет одно из следующих действий:

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

Это намного больше, чем выполнение только этих команд, но те, что выше, работают с магией.

Я не мог найти простой способ без итеративного изменения пароля в Solaris, поэтому мы обратились к изменению /etc/shadowна лету.


2
Пожалуйста, не вводите пароли в виде открытого текста в командной строке, так как она регистрируется в истории оболочки. Или установите историю оболочки, /dev/nullпрежде чем сделать это.
Марцин

1
да, также не вводите пароль в скрипт, проверьте мой скрипт, чтобы добавить зашифрованный пароль
Рахул Патил

1

Недавно я сделал это, используя 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

Это мое решение до сих пор. еще нужно посмотреть, работает ли он на нескольких системах

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

Вы можете использовать pdsh для выполнения вашей команды на нескольких хостах одновременно.


И какую команду ты собираешься выполнить? passwdотличается на разных упомянутых версиях. pwне всегда доступно ....
Крис С

У нас есть часть запуска команд на всех блоках довольно хорошо .. Проблема заключается в реальной смене пароля. Насколько я знаю, passwdвсегда интерактивно для пользователя.
Ricapar

passwdна RHEL Linux, по крайней мере, имеет --stdinпараметр
AngerClown

0

В дополнение к puppet: SaltStack Другой подход - автоматизировать выполнение с использованием библиотек SSH либо последовательно, либо параллельно, используя Fabric http://docs.fabfile.org/en/1.6/ , Capistrano или аналогичные, которые не требуют много времени / усилий для развертывания.


0

Два варианта:

Используйте марионетку

Используйте беговую колоду. Run deck - это сервер, который позволяет вам одновременно выполнять команды на сотнях машин. Вы можете сгруппировать машины в группы, чтобы выполнять команды только на подмножестве машин.

http://rundeck.org


-2

Я думаю, что формат /etc/shadowфайла довольно стандартный в дистрибутивах Linux. Можете ли вы просто написать простой сценарий awk для обновления пароля.

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

Я бы проверил это, чтобы вы не закрылись;)


Я считаю, что редактирование / etc / shadow - это путь. Однако не будет ли редирект стереть / etc / shadow перед редактированием? Это похоже на случай для ed или ex.
mpez0

3
Формат тени может быть, но хеш-функции не гарантированы, чтобы интерпретировать один и тот же алгоритм везде. Плюс твой маленький сценарий просто удалил все записи из тени. :}
Тинк

LOL ой, должны быть исправлены. Я надеюсь, что вы не sudo запустить этот тинк;)
HaxElit
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.