更改3000+ Solaris,AIX和Linux服务器上的root密码的最佳方法?


12

长话短说:大型的老公司,很多UNIX / Linux服务器。

我继承了几年前留下的一堆脚本的责任。其中一个是脚本,该脚本将每隔$ X个月运行一次,以全局更新我们所有服务器上的root密码。

该脚本是Shell脚本和Expect的混乱之处,它可在所有服务器与中央命令和控制服务器之间建立的SSH信任下使用。

问题是,脚本太乱了。Expect命令试图解释存在于任何UNIX / Linux机器上的“ passwd”的每个可能版本-它们相差很大。

随着我们正在扩展和升级许多基础架构,该脚本变得非常难以管理。

我的问题是:还有更好的方法吗?假设已经建立了SSH信任,那么同时更改3000台以上服务器上的root密码的最佳方法是什么?


2
sudo完全不使用和完全消除root密码是不是一种选择?
Dmitri Chubarov

5
雇用实习生?:)
EEAA 2013年

1
@DmitriChubarov使用“ sudo”将意味着拥有一个用于维护(和更改)密码的其他帐户-那么重点在哪里?
the-wabbit

1
@ syneticon-dj可以重新创建其他帐户,并将其存储在一些集中维护的数据库(例如LDAP或NIS)中,而这会得到更好的支持。这与剥夺本地根目录并将其替换为来自ldap的根目录不同。
Dmitri Chubarov

2
如果您有超过3k台计算机,则需要管理工具……昨天!
沃伦

Answers:


17

使用Puppet

Puppet非常灵活,易于维护并且使用SSL。听起来可能有些矫kill过正,但您必须付出更多的努力才能构建Puppet系统。

但。这很可能不是您要对这些机器进行的最后一次大规模更新。当实际的任何大规模更新过程开始并且脚本非常易读/可重用时,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。
dawud

的确,它使用SSL,而不是SSH。我曾经是通过执行客户端通过SSH使用Puppet的系统的维护者-长话短说。答案已更正。谢谢dawud指出!
tomi

在下面提供了自己的答案,但是我接受您的回答,因为它可能是对该问题最“正确”且可管理的长期解决方案。但是,为了在我们如此规模的环境中部署Puppet,确实需要在基础架构,计划,许可和时间方面进行大量投资。有一天我们会到达那里...
Ricapar

1
@DennisKaarsemaker:您应该将其作为错误报告给Puppet Labs。他们会对听到这个消息非常感兴趣。
Bill Weiss 2013年

3

我在Solaris上使用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;

2

如果您可以编写Perl,则模块Net :: OpenSSH :: Parallel允许编写脚本,这些脚本通过SSH轻松地在远程主机上并行执行操作。

它包含用于更改密码的示例脚本,您可以将其用作基础。似乎您拥有一个异构环境,您希望按类型对主机进行分组,并对每个主机使用不同的对话处理子。


1

我不了解“最佳”,也不知道您的混合版本中所有非Linux * nix机器是否都可以使用,但是您是否研究过puppet或cfengine进行此类活动?

还有一些用于身份管理的商业(非常昂贵的)工具,我过去曾经看过/使用过的两个工具是Oracle Identity Manager和等效的Novel。


1

继续研究之后,我学到了一些东西...

首先,这是一个非常烦人的自动化任务,尤其是在许多不同的环境中。这个问题的最正确答案可能是@ tomi's:使用Puppet。

最终,我希望让Puppet能够管理基础架构,但是现在无法部署到整个企业的UNIX服务器上以更改root密码。

在阅读了许多联机帮助页和许多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
请不要在命令行上输入明文密码,因为明文密码会记录在shell历史记录中。或/dev/null在执行之前将shell历史记录设置为。
Marcin

1
是的,也不要在脚本中输入密码,请检查我的脚本以添加加密的密码
Rahul Patil,

1

最近,我已经完成了使用Bash脚本的操作。

#!/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并非总是可用....
克里斯S

我们可以很好地在所有对话框上运行命令。.问题是密码的实际更改。据我所知,passwd始终是用户交互的。
Ricapar

passwd在RHEL Linux上至少有一个--stdin参数
AngerClown 2013年


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
阴影的格式可以是,但是不能保证哈希算法在任何地方都可以用相同的算法来解释。另外,您的小脚本刚刚从阴影中完全删除了所有条目。:}
天衣

大声笑,应该固定。希望您不要随意操作;)
HaxElit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.