Cách tốt nhất để thay đổi mật khẩu root trên 3000+ máy chủ Solaris, AIX và Linux?


12

Câu chuyện dài: Tập đoàn lớn cũ, rất nhiều máy chủ UNIX / Linux.

Tôi được thừa hưởng trách nhiệm cho một loạt các kịch bản đã để lại một vài năm trước đây. Một trong số đó là một tập lệnh sẽ được chạy mỗi tháng $ X để cập nhật toàn cầu mật khẩu gốc trên tất cả các máy chủ của chúng tôi.

Kịch bản là một mớ hỗn độn của Shell Script và Expect, và nó hoạt động dựa trên sự tin tưởng SSH được thiết lập giữa tất cả các máy chủ của chúng tôi và một máy chủ chỉ huy và kiểm soát trung tâm.

Vấn đề là, kịch bản là một mớ hỗn độn khổng lồ. Các lệnh Expect đang cố gắng tính toán cho mọi phiên bản "passwd" có thể tồn tại trên bất kỳ hộp UNIX / Linux nào ngoài đó - và chúng thay đổi khá nhiều.

Khi chúng tôi đang mở rộng và nâng cấp rất nhiều cơ sở hạ tầng, kịch bản đang trở nên khó kiểm soát.

Câu hỏi của tôi là: Có cách nào tốt hơn để làm điều này? Giả sử đã có một ủy thác SSH đã được thiết lập, cách tốt nhất để thay đổi mật khẩu gốc trên hơn 3000 máy chủ cùng một lúc là gì?


2
Sử dụng sudovà loại bỏ mật khẩu gốc hoàn toàn không phải là một lựa chọn, phải không?
Dmitri Chubarov

5
Thuê thực tập sinh? :)
EEAA

1
@DmitriChubarov sử dụng "sudo" sẽ ngụ ý có một tài khoản khác để duy trì (và thay đổi) mật khẩu trên - vậy vấn đề nằm ở đâu?
the-wợi

1
@ syirecton-dj, các tài khoản khác có thể được tạo trước đó và được lưu trữ trên một số cơ sở dữ liệu được duy trì tập trung, ví dụ LDAP hoặc NIS bất cứ điều gì được hỗ trợ tốt hơn. Nó không giống như việc trích xuất root cục bộ và thay thế nó bằng cái đến từ ldap.
Dmitri Chubarov

2
Nếu bạn có> 3k máy, bạn cần các công cụ quản lý ... ngày hôm qua!
warren

Câu trả lời:


17

Sử dụng con rối .

Con rối rất linh hoạt, dễ bảo trì và sử dụng SSL. Có thể âm thanh hơi quá mức và bạn sẽ phải nỗ lực thêm để xây dựng hệ thống rối.

Nhưng. Rất có thể đây không phải là bản cập nhật hàng loạt cuối cùng mà bạn sẽ thực hiện với các máy này. Con rối sẽ và giúp bạn tiết kiệm rất nhiều thời gian khi thực tế bất cứ quy trình cập nhật hàng loạt nào bắt đầu và các tập lệnh rất dễ đọc / có thể sử dụng lại.

Ít nhất điều này đã làm việc cho tôi vài năm trước và tôi vẫn có thể sử dụng lại một số công thức Puppet (hay còn gọi là script). Tôi cũng đã sử dụng nó trong một môi trường nhỏ hơn một chút chỉ để đảm bảo rằng mọi máy đều thực sự có trạng thái đã biết .

Tôi đã chứng minh điều đó nhiều lần (tại nhiều công ty) rằng tất cả các tập lệnh triển khai tùy chỉnh trở nên đau đớn sau một lúc hoặc khi anh chàng tiếp theo bước vào. Và miễn là bạn mang theo điện thoại di động, các tập lệnh cũ sẽ và ám ảnh bạn.

Nếu bạn nghĩ rằng điều này thực sự nghe có vẻ tốt, thì đây là một hướng dẫn rối tuyệt vời với môi trường ảo đi kèm để giúp bạn bắt đầu.


4
Agred, nhưng không sử dụng a user{"root":}để đặt mật khẩu. Thay vào đó, sử dụng một exec{"chpasswd -e ..."}, an toàn hơn nhiều.
Dennis Kaarsemaker

7
Vui lòng sửa câu trả lời của bạn, con rối sử dụng SSL, không phải SSH. Đồng ý với phần còn lại, mặc dù ansible có vẻ như là một sự thay thế nhẹ phù hợp hơn nhiều cho trường hợp sử dụng này. Chỉ pip install ansibletrong một hộp GNU / Linux, xây dựng một danh sách các máy chủ và ansible -m user -a "password=$crpyt". Không cần đại lý. Quản lý GNU / Linux, AIX và Solaris.
dawud

Đúng là nó sử dụng SSL, không phải SSH. Tôi sử dụng để duy trì trong một hệ thống mà Puppet được sử dụng thông qua SSH bằng cách thực thi một câu chuyện dài của khách hàng. Trả lời đúng. Cảm ơn dawud chỉ ra rằng!
tomi

Tôi đã cung cấp câu trả lời của riêng mình bên dưới , nhưng tôi chấp nhận câu trả lời của bạn, vì đó có lẽ là giải pháp lâu dài "chính xác" và dễ quản lý nhất cho vấn đề. Tuy nhiên, nó đòi hỏi một sự đầu tư đáng kể về cơ sở hạ tầng, quy hoạch, cấp phép và thời gian để tung ra Con rối trong một môi trường có quy mô của chúng tôi. Một ngày nào đó chúng ta sẽ đến đó ...
Ricapar

1
@DennisKaarsemaker: bạn nên báo cáo đó là lỗi cho Puppet Labs. Họ sẽ rất thích thú khi nghe nó.
Bill Weiss

3

Tôi đã sử dụng mô-đun Perl Authen :: PAM trên Solaris rất thành công. Đây là một kịch bản mẫu:

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

Nếu bạn có thể viết Perl, mô-đun Net :: OpenSSH :: Parallel cho phép viết các tập lệnh thực hiện các hành động song song trên các máy chủ từ xa thông qua SSH khá dễ dàng.

Nó chứa một tập lệnh mẫu để thay đổi mật khẩu mà bạn có thể sử dụng làm cơ sở. Vì dường như bạn có một môi trường không đồng nhất, bạn muốn nhóm các máy chủ theo loại và sử dụng một phụ xử lý hội thoại khác nhau cho mỗi người.


1

Tôi không biết về "tốt nhất" và liệu có thể cho tất cả các máy không phải là Linux * nix trong hỗn hợp của bạn không, nhưng bạn đã xem rối hoặc cengine cho loại hoạt động này chưa?

Ngoài ra còn có các công cụ thương mại (rất đắt tiền) để quản lý danh tính ngoài kia, hai công cụ tôi đã thấy / sử dụng trong quá khứ là Trình quản lý danh tính Oracle và tương đương Tiểu thuyết.


1

Sau khi tiếp tục nghiên cứu điều này, tôi đã học được một vài điều ...

Đầu tiên và quan trọng nhất, đây là một nhiệm vụ thực sự khó chịu để tự động hóa, đặc biệt là trên nhiều môi trường khác nhau. Câu trả lời đúng nhất cho câu hỏi này có lẽ là @ tomi's: sử dụng Puppet.

Cuối cùng, tôi hy vọng có được Puppet để quản lý cơ sở hạ tầng, nhưng việc triển khai đến toàn bộ máy chủ UNIX của doanh nghiệp để thay đổi mật khẩu gốc ngay bây giờ không khả thi đối với một tùy chọn.

Sau khi đọc nhiều trang và nhiều Google-fu, tôi đã tìm được một tập lệnh lặp qua danh sách các máy chủ mục tiêu, mở kết nối SSH và chạy một trong các cách sau:

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

Nó thực hiện nhiều hơn một chút so với việc chỉ chạy các lệnh đó, nhưng những lệnh trên là những gì có tác dụng kỳ diệu.

Tôi không thể tìm thấy bất kỳ cách đơn giản nào để thay đổi mật khẩu không lặp lại trên Solaris - vì vậy chúng tôi đã dùng đến việc sửa đổi /etc/shadownhanh chóng.


2
Vui lòng không đặt mật khẩu Cleartext trên dòng lệnh, vì nó được ghi vào lịch sử shell. Hoặc đặt lịch sử shell thành /dev/nulltrước khi bạn làm điều đó.
Marcin

1
vâng, cũng đừng đặt mật khẩu vào tập lệnh, hãy kiểm tra tập lệnh của tôi để thêm mật mã được mã hóa
Rahul Patil

1

Gần đây tôi đã thực hiện điều này bằng cách sử dụng 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

Đây là giải pháp của tôi cho đến nay. vẫn cần phải xem nếu nó hoạt động trên nhiều hệ thống

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

Bạn có thể sử dụng pdsh để thực thi lệnh của mình trên nhiều máy chủ cùng một lúc.


Và lệnh nào bạn sẽ chạy? passwdlà khác nhau trên các phiên bản khác nhau được đề cập. pwkhông phải lúc nào cũng có sẵn ....
Chris S

Chúng tôi có một phần của các lệnh chạy trên tất cả các hộp khá tốt .. Vấn đề là sự thay đổi thực tế của mật khẩu. Theo tôi biết, passwdluôn luôn tương tác với người dùng.
Ricapar

passwdtrên RHEL Linux ít nhất có một --stdintham số
AngerClown

0

Ngoài con rối: SaltStack Một cách tiếp cận khác - tự động hóa thực thi bằng cách sử dụng SSH lib theo tuần tự hoặc song song bằng cách sử dụng Fabric http://docs.fabfile.org/en/1.6/ , Capistrano hoặc tương tự không cần nhiều thời gian / nỗ lực để triển khai.


0

Hai lựa chọn:

Sử dụng con rối

Sử dụng sàn chạy. Run Deck là một máy chủ cho phép bạn thực hiện các lệnh trên hàng trăm máy cùng một lúc. Bạn có thể nhóm các máy thành các nhóm, để thực hiện các lệnh trên chỉ một tập hợp con của các máy.

http://rundeck.org


-2

Tôi nghĩ rằng định dạng của /etc/shadowtập tin là khá chuẩn trên các bản phân phối linux. Bạn có thể chỉ cần viết một kịch bản awk đơn giản để cập nhật mật khẩu.

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

Tôi chắc chắn sẽ kiểm tra nó để bạn không tự khóa mình;)


Tôi tin rằng chỉnh sửa / etc / bóng là cách để đi. Tuy nhiên, sẽ không chuyển hướng xóa sạch / etc / bóng trước khi chỉnh sửa? Điều này trông giống như một trường hợp cho ed hoặc ex.
mpez0

3
Định dạng của bóng có thể là, nhưng các giá trị băm không được đảm bảo sẽ được giải thích bởi cùng một thuật toán ở mọi nơi. Cộng với kịch bản nhỏ của bạn vừa loại bỏ tất cả các mục từ bóng tối hoàn toàn. :}
tink

Rất tiếc, nên được sửa chữa. Tôi hy vọng bạn không sudo chạy tink đó;)
HaxElit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.