[server] 3000+ Solaris, AIX 및 Linux 서버에서 루트 비밀번호를 변경하는 가장 좋은 방법은 무엇입니까?

짧은 이야기 : 큰 오래된 회사, 많은 UNIX / Linux 서버.

몇 년 전에 남은 스크립트에 대한 책임을 물려 받았습니다. 그중 하나는 모든 서버에서 루트 암호를 전체적으로 업데이트하기 위해 $ X 개월마다 실행되는 스크립트였습니다.

이 스크립트는 Shell Script and Expect의 혼란이며 모든 서버와 중앙 명령 및 제어 서버 사이에 설정된 SSH 트러스트에서 작동합니다.

문제는 스크립트가 큰 혼란입니다. Expect 명령은 UNIX / Linux 상자에 존재하는 가능한 모든 “passwd”버전을 설명하려고합니다.

많은 인프라를 확장하고 업그레이드함에 따라 스크립트는 실제로 관리하기가 어렵습니다.

내 질문은 : 더 좋은 방법이 있습니까? 이미 설정된 SSH 신뢰가 있다고 가정하면 3000 개 이상의 서버에서 동시에 루트 암호를 변경하는 가장 좋은 방법은 무엇입니까?



답변

꼭두각시를 사용하십시오 .

Puppet은 매우 유연하고 유지 관리가 쉽고 SSL을 사용합니다. 약간 과잉 소리를 낼 수 있으므로 꼭두각시 시스템을 구축하기 위해 약간의 노력을 기울여야합니다.

그러나. 아마도 이것은 당신이이 머신들에 대해 수행 할 마지막 대량 업데이트가 아닐 것입니다. 꼭두각시는 실제 대량 업데이트 절차가 시작되고 스크립트가 매우 읽기 쉽고 재사용 가능한 많은 시간을 절약 해줍니다.

적어도 이것은 몇 년 전에 저에게 효과가 있었지만 여전히 Puppet 레시피 (일명 스크립트)를 재사용 할 수 있습니다. 또한 좀 더 작은 규모의 환경에서도 사용했는데 모든 컴퓨터가 실제로 알려진 상태 인지 확인하십시오 .

나는 모든 사용자 정의 된 배포 스크립트가 잠시 후 또는 다음 사람이 들어올 때 엉덩이에 통증이되는 것으로 여러 번 입증했습니다.

이것이 실제로 좋은 것으로 생각되면 시작하기 위해 가상 환경이 포함 된 훌륭한 Puppet 자습서가 있습니다.


답변

솔라리스에서 Perl 모듈 Authen :: PAM을 성공적으로 사용했습니다. 샘플 스크립트는 다음과 같습니다.

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


답변

Perl을 작성할 수 있으면 Net :: OpenSSH :: Parallel 모듈을 사용하면 SSH를 통해 원격 호스트에서 병렬로 작업을 수행하는 스크립트를 매우 쉽게 작성할 수 있습니다.

기본으로 사용할 수있는 비밀번호 변경을위한 샘플 스크립트 가 포함되어 있습니다 . 이기종 환경이있는 것처럼 호스트를 유형별로 그룹화하고 모든 대화 처리 하위를 사용하려고합니다.


답변

나는 “최상의”에 대해 모른다. 그리고 당신의 믹스에있는 모든 비 리눅스 * nix 머신이 가능한지 아닌지, 이런 종류의 활동을 위해 꼭두각시 나 cfengine을 보았는가?

아이덴티티 관리를위한 상용 (고가의) 툴도 있습니다. 과거에 보았거나 사용했던 두 가지는 Oracle Identity Manager와 Novel에 해당합니다.


답변

이것을 계속 연구 한 후에, 나는 몇 가지를 배웠습니다 …

무엇보다도, 이것은 특히 여러 환경에서 자동화하는 정말 성가신 작업입니다. 이 질문에 대한 가장 정확한 답변은 @ tomi ‘s : use Puppet입니다.

결국 Puppet이 인프라를 관리하게하려고했지만 루트 암호 변경을 위해 전체 엔터프라이즈의 UNIX 서버에 배포하는 것은 현재로서는 불가능합니다.

많은 맨 페이지와 많은 Google-fu를 읽은 후 대상 서버 목록을 반복하고 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"

그것은 단지 그 명령을 실행하는 것보다 훨씬 더 많은 일을하지만, 위의 것들은 마술을 작동시키는 것입니다.

솔라리스에서 비밀번호를 반복적으로 변경하는 간단한 방법을 찾을 수 없었기 때문에 /etc/shadow즉시 수정 했습니다.


답변

최근에 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 $*


답변

이것은 지금까지 내 솔루션입니다. 여전히 여러 시스템에서 작동하는지 확인해야합니다.

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