7

This question is about best practices. I'm running a deployment script with Fabric. My deployment user 'deploy' needs sudo to restart services. So I am using the sudo function from fabric to run these commands in my script. This works fine but prompts for password during script execution. I DON'T want to type a password during deployments. What's the best practice here. The only solution I can think of is changing the sudo permissions to not require password for the commands my deployment user runs. This doesn't seem right to me.

4

7 回答 7

6

理想的解决方案是在您的服务器上创建一个仅用于部署的用户(例如,deploy)。然后,env.user=deploy在您的 fabfile 中设置。然后在您的服务器上,您可以在 sudoers 文件中逐个命令地授予用户必要的权限:

重要提示:始终用于sudo visudo修改 sudoers 文件

Cmnd_Alias RELOAD_SITE = /bin/bash -l -c supervisorctl*, /usr/bin/supervisorctl*
deploy ALL = NOPASSWD: RELOAD_SITE

您可以Cmnd_Alias根据部署用户的需要添加任意数量的指令,然后授予NOPASSWD每个命令的访问权限。有关man sudoers更多详细信息,请参阅。

我喜欢保留我的特定于部署的 sudoers 配置,并通过在最后添加:来/etc/sudoers.d/deploy包含该文件。/etc/sudoersincludedir /etc/suoders.d

于 2014-08-25T22:54:33.833 回答
2

您可以使用:

fabric.api import env
# [...]
env.password = 'yourpassword'
于 2013-05-13T11:41:56.557 回答
2

最好的方法是使用子任务。您可以在 fabfile中提示输入密码,并且永远不要公开任何密码,也不要对远程系统上的 sudo 进行鲁莽的配置更改。

import getpass

from fabric.api import env, parallel, run, task
from fabric.decorators import roles
from fabric.tasks import execute


env.roledefs = {'my_role': ['host1', 'host2']}


@task
# @parallel -- uncomment if you need parallel execution, it'll work!
@roles('my_role')
def deploy(*args, **kwargs):
    print 'deploy args:', args, kwargs
    print 'password:', env.password
    run('echo hello')


@task
def prompt(task_name, *args, **kwargs):
    env.password = getpass.getpass('sudo password: ')
    execute(task_name, *args, role='my_role', **kwargs)

请注意,您甚至可以将其与并行执行结合起来,并且该prompt任务仍然只运行一次,而该deploy任务为角色中的每个主机并行运行。

最后,一个如何调用它的示例:

$ fab prompt:deploy,some_arg,another_arg,key=value
于 2016-04-23T14:41:00.773 回答
1

似乎sudo毕竟可能不是那么糟糕的选择。您可以指定用户可以运行哪些命令以及该命令可能采用的参数 ( man sudoers)。如果问题只是必须输入密码,一个选项将涉及使用pexpect模块自动登录,也许使用可以加密存储的密码:

import pexpect, sys

pwd = getEncryptedPassword()
cmd = "yourcommand" 

sCmd = pexpect.spawn('sudo {0}'.format(cmd))
sCmd.logfile_read = sys.stdout
sCmd.expect('Password:')
sCmd.sendline(pwd)
sCmd.expect(pexpect.EOF)
于 2012-12-19T01:57:31.457 回答
1

使用密钥环模块安全地存储和访问密码。

这是我使用 Fabric 2 的方法:

from fabric import task
import keyring

@task
def restart_apache(connection):
    # set the password with keyring.set_password('some-host', 'some-user', 'passwd')
    connection.config.sudo.password = keyring.get_password(connection.host, 'some-user')
    connection.sudo('service apache2 restart')

您还可以使用 GPG 或任何其他命令行密码工具。例如:

connection.config.sudo.password = connection.local('gpg --quiet -d /path/to/secret.gpg', hide=True).strip()

secret.gpg文件可以用echo "mypassword" | gpg -e > secret.gpg. 该hide参数避免将密码回显到控制台。

要保留对 的支持--prompt-for-sudo-password,请添加条件:

if not connection.config.sudo.password:
    connection.config.sudo.password = keyring.get_password(connection.host, 'some-user')
于 2018-12-28T21:55:56.440 回答
-1

您还可以为多台机器使用密码:

from fabric import env
env.hosts = ['user1@host1:port1', 'user2@host2.port2']
env.passwords = {'user1@host1:port1': 'password1', 'user2@host2.port2': 'password2'}

看到这个答案:https ://stackoverflow.com/a/5568219/552671

于 2013-09-28T12:37:14.723 回答
-2

正如 Bartek 还建议的那样,在 sudoers 文件中为部署“用户”启用无密码 sudo。

就像是:

run('echo "{0} ALL=(ALL) ALL" >> /etc/sudoers'.format(env.user))
于 2012-12-19T13:30:09.690 回答