问题
- 是否有更安全/更好的方式通过 Python 脚本以非交互方式设置用户密码?我当前的解决方案使用
chpasswd
Fabric脚本。另一种选择是在Fabric脚本中使用Pexpect 。 - 我当前设置密码的方法是否存在安全问题?我看到的潜在安全问题是密码在我的本地终端上显示为明文,如下所示
[xxx.xx.xx.xxx] run: echo "johnsmith:supersecretpassw0rd" | chpasswd
:
由于我只在笔记本电脑上运行Fabric脚本,我认为这不是安全问题,但我对其他人的输入感兴趣。
背景
我使用Fabric创建了一个 Python 脚本来配置一个新构建的Slicehost Ubuntu 切片。如果您不熟悉 Fabric,它使用Python SSH2 客户端Paramiko来提供“用于应用程序部署或系统管理任务”的远程访问。
我让Fabric脚本做的第一件事就是创建一个新的管理员用户并设置他们的密码。与Pexpect不同,Fabric 无法处理远程系统上的交互命令,因此我需要以非交互方式设置用户密码。目前,我正在使用chpasswd
命令,它将用户名和密码读取为明文。
当前代码
# Fabric imports and host configuration excluded for brevity
root_password = getpass.getpass("Root's password given by SliceManager: ")
admin_username = prompt("Enter a username for the admin user to create: ")
admin_password = getpass.getpass("Enter a password for the admin user: ")
env.user = 'root'
env.password = root_password
# Create the admin group and add it to the sudoers file
admin_group = 'admin'
run('addgroup {group}'.format(group=admin_group))
run('echo "%{group} ALL=(ALL) ALL" >> /etc/sudoers'.format(
group=admin_group)
)
# Create the new admin user (default group=username); add to admin group
run('adduser {username} --disabled-password --gecos ""'.format(
username=admin_username)
)
run('adduser {username} {group}'.format(
username=admin_username,
group=admin_group)
)
# Set the password for the new admin user
run('echo "{username}:{password}" | chpasswd'.format(
username=admin_username,
password=admin_password)
)
本地系统终端 I/O
$ fab config_rebuilt_slice
Root's password given by SliceManager:
Enter a username for the admin user to create: johnsmith
Enter a password for the admin user:
[xxx.xx.xx.xxx] run: addgroup admin
[xxx.xx.xx.xxx] out: Adding group `admin' (GID 1000) ...
[xxx.xx.xx.xxx] out: Done.
[xxx.xx.xx.xxx] run: echo "%admin ALL=(ALL) ALL" >> /etc/sudoers
[xxx.xx.xx.xxx] run: adduser johnsmith --disabled-password --gecos ""
[xxx.xx.xx.xxx] out: Adding user `johnsmith' ...
[xxx.xx.xx.xxx] out: Adding new group `johnsmith' (1001) ...
[xxx.xx.xx.xxx] out: Adding new user `johnsmith' (1000) with group `johnsmith' ...
[xxx.xx.xx.xxx] out: Creating home directory `/home/johnsmith' ...
[xxx.xx.xx.xxx] out: Copying files from `/etc/skel' ...
[xxx.xx.xx.xxx] run: adduser johnsmith admin
[xxx.xx.xx.xxx] out: Adding user `johnsmith' to group `admin' ...
[xxx.xx.xx.xxx] out: Adding user johnsmith to group admin
[xxx.xx.xx.xxx] out: Done.
[xxx.xx.xx.xxx] run: echo "johnsmith:supersecretpassw0rd" | chpasswd
[xxx.xx.xx.xxx] run: passwd --lock root
[xxx.xx.xx.xxx] out: passwd: password expiry information changed.
Done.
Disconnecting from [email protected]... done.
您在正在执行的命令行中传递密码。这些可能不仅在您的终端中可见,而且在其他用户发出“ps”命令时也可见(这可能取决于系统配置)。并且密码是纯文本。
我不知道 Fabric,但如果它让你有可能通过他们的标准输入/标准输出(如
subprocess.Popen()
)与执行的命令进行通信,那么使用它而不是 'echo username:password|... 可能是一个更好的选择。 '。此外,您可以选择在 Python 脚本中创建密码哈希(使用
crypt
模块和“$1$XXXXXXXX$”(“X”是随机字符)盐)并将其传递给chpasswd -e
. 那时将永远不会显示或记录纯文本密码。您使用模块生成密码哈希,
crypt
如下所示:您可以将输出传递给
chpasswd -e
这样的:对于非交互式密码设置,我通常会生成一个随机密码并将其设置为一个变量,然后将该变量传递给我的命令。我不必对密码有创意,也不必在纯文本文件中留下标准密码。
这是生成随机密码的活动状态配方。
就安全性而言,我认为在您自己的终端上打印密码并不是什么大问题(使用随机密码,无论如何您都需要这样,因此您可以记下创建的密码) .
Fabric 与 ssh 有什么不同吗?-- 大多数通过 ssh 传输的东西无论如何都应该被加密。
如果您在结构中使用 chpasswd,请确保不要使用命令行中的纯文本密码。不仅是显示密码的标准输出,它还将被写入 /var/log/secure。在 Fabric 中,您可以使用
并确保将哈希字符串与 chpasswd 命令一起使用,这样即使在安全日志中,您也不会看到纯文本密码。首先决定要使用的密码,并生成哈希字符串。您可以为此使用 openssl。
这将提示您输入密码并生成 MD5 哈希。你可以在你的脚本中使用它,如下所示。
上述命令中的 -e 标志告诉 chpasswd 密码已加密。
即将发布的 Fabric 1.0 版本(现在可从 git 分支获得)将允许与远程端进行交互会话。
您可以自动配置您的新切片,然后立即登录并更改密码吗?有时最简单的方法是最好的。
但或者,您可以在本地生成加密密码,然后继续将加密密码写入 /etc/shadow 文件。这样,您根本不使用纯文本。
请注意,最初提供初始密码时,您必须信任您的本地系统。
顺便说一句,您能否制作一份您的自动配置副本,以便我使用它而不是从头开始编写所有内容?目前我正在通过 bash 做所有事情。
像这样的东西?