วิธีที่ดีที่สุดในการเปลี่ยนรหัสผ่านรูทบนเซิร์ฟเวอร์ Solaris, AIX และ Linux มากกว่า 3000+


12

เรื่องสั้นสั้น: บริษัท เก่าขนาดใหญ่จำนวนมากเซิร์ฟเวอร์ UNIX / Linux

ฉันรับช่วงความรับผิดชอบของสคริปต์จำนวนมากที่เหลืออยู่เมื่อไม่กี่ปีก่อน หนึ่งในนั้นคือสคริปต์ที่จะทำงานทุก ๆ เดือนจำนวน $ X เพื่ออัปเดตรหัสผ่านทั่วโลกในเซิร์ฟเวอร์ของเราทั้งหมด

สคริปต์เป็นระเบียบของ Shell Script และคาดหวังและทำงานบนความไว้วางใจ SSH ที่ตั้งค่าระหว่างเซิร์ฟเวอร์ทั้งหมดของเราและเซิร์ฟเวอร์คำสั่งและควบคุมกลาง

ปัญหาคือสคริปต์เป็นระเบียบขนาดใหญ่ คำสั่งคาดหวังกำลังพยายามบัญชีสำหรับ "passwd" ทุกรุ่นที่เป็นไปได้ที่มีอยู่ในกล่อง UNIX / Linux ใด ๆ ออกมา - และพวกมันต่างกันเล็กน้อย

ในขณะที่เรากำลังขยายและอัพเกรดโครงสร้างพื้นฐานจำนวนมากสคริปต์ก็เริ่มไม่สามารถจัดการได้จริงๆ

คำถามของฉันคือ: มีวิธีที่ดีกว่าในการทำเช่นนี้? สมมติว่ามีความไว้วางใจ SSH ที่สร้างไว้แล้ววิธีที่ดีที่สุดในการเปลี่ยนรหัสผ่านรูทบนเซิร์ฟเวอร์มากกว่า 3000+ ในเวลาเดียวกันคืออะไร?


2
การใช้sudoและกำจัดรหัสผ่านรูททั้งหมดนั้นไม่ใช่ตัวเลือกใช่ไหม?
Dmitri Chubarov

5
จ้างฝึกงาน? :)
EEAA

1
@DmitriChubarov โดยใช้ "sudo" จะหมายความว่ามีบัญชีที่แตกต่างกันในการรักษา (และเปลี่ยน) รหัสผ่าน - ดังนั้นจุดที่อยู่ที่ไหน
the-wabbit

1
@ syneticon-dj บัญชีอื่น ๆ อาจถูกสร้างขึ้นใหม่และเก็บไว้ในฐานข้อมูลบางส่วนที่ได้รับการดูแลจากส่วนกลางเช่น LDAP หรือ NIS สิ่งที่ได้รับการสนับสนุนที่ดีกว่า มันไม่เหมือนกับการฉีกรากในเครื่องและแทนที่ด้วยการแทนที่จาก ldap
Dmitri Chubarov

2
หากคุณมีเครื่อง> 3k คุณต้องมีเครื่องมือจัดการ ... เมื่อวานนี้!
วอร์เรน

คำตอบ:


17

ใช้หุ่นกระบอก

Puppet นั้นยืดหยุ่นและง่ายต่อการบำรุงรักษาและใช้ SSL อาจฟังดูเกินกำลังเล็กน้อยและคุณจะต้องใช้ความพยายามพิเศษในการสร้างระบบ Puppet

แต่. อาจเป็นไปได้ว่านี่ไม่ใช่การอัปเดตจำนวนมากครั้งล่าสุดที่คุณทำกับเครื่องเหล่านี้ Puppet จะช่วยคุณประหยัดเวลาได้มากเมื่อเริ่มกระบวนการอัพเดทมวลและสคริปต์นั้นสามารถอ่าน / นำมาใช้ซ้ำได้

อย่างน้อยมันก็ใช้ได้กับฉันเมื่อสองสามปีก่อนและฉันก็ยังสามารถใช้สูตร Puppet เหล่านั้น (สคริปต์ที่รู้จักกัน) อีกครั้ง ฉันยังได้ใช้มันในบิตสภาพแวดล้อมที่มีขนาดเล็กเพียงให้แน่ใจว่าทุกเครื่องที่เป็นจริงที่มีรัฐเป็นที่รู้จักกัน

ฉันได้พิสูจน์แล้วหลายครั้ง (ในหลาย ๆ บริษัท ) ว่าสคริปต์การปรับใช้ที่กำหนดเองทั้งหมดนั้นได้รับความเจ็บปวดหลังจากผ่านไประยะหนึ่งหรือเมื่อผู้ชายคนถัดไปเข้ามาและตราบใดที่คุณพกโทรศัพท์มือถือสคริปต์เก่าจะหลอกหลอนคุณ

หากคุณคิดว่ามันฟังดูดีจริง ๆ นี่คือการสอนหุ่นเชิดที่ยอดเยี่ยมพร้อมสภาพแวดล้อมเสมือนจริงเพื่อให้คุณเริ่มต้นได้


4
แต่ไม่ได้ใช้user{"root":}เพื่อตั้งรหัสผ่าน ให้ใช้อันexec{"chpasswd -e ..."}ที่ปลอดภัยกว่าแทน
Dennis Kaarsemaker

7
โปรดแก้ไขคำตอบของคุณหุ่นเชิดใช้ SSL ไม่ใช่ SSH เห็นด้วยกับส่วนที่เหลือแม้ว่าansibleดูเหมือนว่าเป็นทางเลือกที่มีน้ำหนักเบาเหมาะสำหรับกรณีการใช้งาน เพียงแค่pip install ansibleในกล่อง GNU / Linux, ansible -m user -a "password=$crpyt"สร้างรายชื่อของเจ้าภาพและ ไม่ต้องการตัวแทน จัดการ GNU / Linux, AIX และ Solaris นอกกรอบ
dawud

True ใช้ SSL ไม่ใช่ SSH ฉันใช้เป็นผู้ดูแลในระบบที่ Puppet ใช้งานผ่าน SSH โดยดำเนินเรื่องสั้น ๆ แก้ไขคำตอบแล้ว ขอบคุณdawudชี้ให้เห็นว่า!
tomi

ฉันให้คำตอบของฉันเองด้านล่างแต่ฉันยอมรับคุณเนื่องจากอาจเป็นวิธีการแก้ไขปัญหาระยะยาวที่ถูกที่สุดและจัดการได้ อย่างไรก็ตามมันต้องมีการลงทุนที่สำคัญในแง่ของโครงสร้างพื้นฐานการวางแผนการออกใบอนุญาตและเวลาเพื่อที่จะแผ่ออกหุ่นในสภาพแวดล้อมขนาดของเรา บางวันที่เราจะได้รับมี ...
Ricapar

1
@DennisKaarsemaker: คุณควรรายงานว่าเป็นข้อบกพร่องของ Puppet Labs พวกเขาจะสนใจเป็นพิเศษในการได้ยิน
Bill Weiss

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 * ทุกเครื่องในการผสมของคุณ แต่คุณเคยดูหุ่นเชิดหรือ cfengine สำหรับกิจกรรมประเภทนี้หรือไม่?

นอกจากนี้ยังมีเครื่องมือทางการค้า (ราคาแพง) สำหรับการจัดการข้อมูลผู้ใช้อีกสองคนที่ฉันเคยเห็น / เคยใช้ในอดีตคือ Oracle Identity Manager และนวนิยายเทียบเท่า


1

หลังจากค้นคว้าข้อมูลนี้ต่อไปฉันได้เรียนรู้บางสิ่ง ...

สิ่งแรกคือสิ่งนี้เป็นงานที่น่ารำคาญมากที่จะทำให้เป็นอัตโนมัติโดยเฉพาะอย่างยิ่งในสภาพแวดล้อมที่แตกต่างกัน คำตอบที่ถูกต้องที่สุดสำหรับคำถามนี้น่าจะเป็น @ tomi's: ใช้ Puppet

ในที่สุดฉันก็หวังว่าจะได้รับ Puppet เพื่อจัดการโครงสร้างพื้นฐาน แต่การปรับใช้กับเซิร์ฟเวอร์ UNIX ขององค์กรทั้งหมดเพื่อเปลี่ยนรหัสผ่านของ root ในตอนนี้ไม่ได้เป็นไปได้ของตัวเลือก

หลังจากอ่าน manpages จำนวนมากและ 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"

มันไม่ได้ทำงานอะไรมากไปกว่าการรันคำสั่งเหล่านั้น แต่สิ่งที่กล่าวมาข้างต้นนั้นเป็นสิ่งที่ใช้เวทย์มนตร์ได้

ฉันไม่สามารถหาวิธีง่ายๆในการเปลี่ยนรหัสผ่านบน Solaris ได้โดยไม่ต้องทำซ้ำดังนั้นเราจึงใช้วิธีการปรับเปลี่ยนแบบ/etc/shadowทันที


2
กรุณาอย่าใส่รหัสผ่าน cleartext ใน commandline เนื่องจากมันจะถูกบันทึกไว้ในประวัติเชลล์ หรือตั้งค่าประวัติเชลล์เป็น/dev/nullก่อนที่คุณจะทำ
Marcin

1
ใช่ยังไม่ใส่รหัสผ่านในสคริปต์ตรวจสอบสคริปต์ของฉันเพื่อเพิ่ม passwd ที่เข้ารหัส
Rahul Patil

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ไม่สามารถใช้งานได้ตลอดเวลา ....
Chris S

เรามีส่วนหนึ่งของการเรียกใช้คำสั่งในทุกช่องลงค่อนข้างดี .. ปัญหาคือการเปลี่ยนรหัสผ่านจริง เท่าที่ฉันรู้passwdผู้ใช้แบบโต้ตอบเสมอ
Ricapar

passwdบน RHEL Linux อย่างน้อยมี--stdinพารามิเตอร์
AngerClown

0

นอกจากหุ่นกระบอก: SaltStack อีกวิธีหนึ่ง - ดำเนินการโดยอัตโนมัติโดยใช้ SSH libs ตามลำดับหรือขนานโดยใช้ Fabric http://docs.fabfile.org/en/1.6/ , Capistrano หรือสิ่งที่คล้ายกันซึ่งไม่ต้องใช้เวลามากในการปรับใช้


0

สองตัวเลือก:

ใช้หุ่นเชิด

ใช้สำรับเรียกใช้ Run deck เป็นเซิร์ฟเวอร์ที่ให้คุณรันคำสั่งบนเครื่องหลายร้อยเครื่องพร้อมกัน คุณสามารถจัดกลุ่มเครื่องเป็นกลุ่มเพื่อดำเนินการคำสั่งบนชุดย่อยของเครื่อง

http://rundeck.org


-2

ฉันคิดว่ารูปแบบของ/etc/shadowไฟล์ค่อนข้างมาตรฐานใน linux distros คุณสามารถเขียนสคริปต์ 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
รูปแบบของเงาอาจเป็นได้ แต่แฮชไม่รับประกันว่าจะถูกตีความโดยอัลกอริทึมเดียวกันทุกที่ บวกกับสคริปต์ตัวน้อยของคุณที่เพิ่งลบรายการทั้งหมดจากเงาทั้งหมด :}
tink

ฮ่า ๆ ๆ ควรได้รับการแก้ไข ฉันหวังว่าคุณไม่ได้ sudo เรียกใช้ทิงก์);
HaxElit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.