この質問は、ベストプラクティスに関するものです。Fabricでデプロイメントスクリプトを実行しています。デプロイメントユーザー「deploy」は、サービスを再起動するためにsudoが必要です。そのため、ファブリックのsudo関数を使用して、スクリプトでこれらのコマンドを実行しています。これは正常に機能しますが、スクリプトの実行中にパスワードの入力を求められます。展開中にパスワードを入力したくありません。ここでのベストプラクティスは何ですか。私が考えることができる唯一の解決策は、デプロイメントユーザーが実行するコマンドのパスワードを必要としないようにsudo権限を変更することです。これは私には正しくないようです。
7 に答える
理想的な解決策は、展開にのみ使用されるユーザーをサーバー上に作成することです(例:)deploy
。次に、env.user=deploy
fabfileを設定します。次に、サーバー上で、sudoersファイルでコマンドごとに必要な権限をユーザーに与えることができます。
重要: sudoersファイルの変更には常に使用してくださいsudo visudo
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/sudoers
includedir /etc/suoders.d
次を使用できます。
fabric.api import env
# [...]
env.password = 'yourpassword'
これを行う最良の方法は、サブタスクを使用することです。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
、タスクは1回だけ実行されることに注意してください。deploy
最後に、それを呼び出す方法の例:
$ fab prompt:deploy,some_arg,another_arg,key=value
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)
キーリングモジュールを使用して、パスワードを安全に保存およびアクセスします。
これが私がFabric2でそれを行う方法です。
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')
複数のマシンにパスワードを使用することもできます。
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
Bartekも提案しているように、sudoersファイルでデプロイメント'user'に対してパスワードなしのsudoを有効にします。
何かのようなもの:
run('echo "{0} ALL=(ALL) ALL" >> /etc/sudoers'.format(env.user))