Especifique a senha do sudo para Ansible

225

Como especifico uma senha do sudo para o Ansible de maneira não interativa?

Estou executando o manual do Ansible assim:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username --ask-sudo-pass

Mas eu quero executá-lo assim:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username` **--sudo-pass=12345**

Há algum jeito? Quero automatizar o máximo possível a implantação do meu projeto.

Slava Fomin II
fonte
4
Veja também: serverfault.com/questions/560106/…
utapyngo

Respostas:

170

Você pode passar variáveis ​​na linha de comando via --extra-vars "name=value". A variável de senha do Sudo é ansible_sudo_pass. Portanto, seu comando seria semelhante a:

ansible-playbook playbook.yml -i inventory.ini --user=username \
                              --extra-vars "ansible_sudo_pass=yourPassword"

Atualização 2017 : O Ansible 2.2.1.0 agora usa var ansible_become_pass. Qualquer um parece funcionar.

Alexandr Nikitin
fonte
7
Da perspectiva da segurança, a melhor resposta, se você adicionar o seguinte: history -capós a execução do yml.
kiltek
12
@ kiltek: ou adicione um espaço extra no início da linha (no bash) que * não * escreva a linha .bash_history.
Ccpizza
44
Não é uma boa prática passar senhas na linha de comando. Ninguém será capaz de ver a senha na lista de processos, enquanto o comando está sendo executado ...
Pavel Chernikov
22
ainda assim, não faça isso. --ask-sudo-pass
JasonG 5/09
2
@scrutari É perfeitamente válido em algumas situações: Por exemplo: mude de uma senha inicial padrão, conhecida mundialmente, para injetar a chave ssh pública do usuário ... Pense na configuração inicial de um sistema com nova imagem.
Ceredig 13/06/19
236

Os documentos recomendam enfaticamente não definir a senha do sudo em texto sem formatação e usá-la --ask-sudo-passna linha de comando ao executaransible-playbook


Atualização de 2016:

Ansible 2.0 (não 100% quando) marcado --ask-sudo-passcomo obsoleto. Agora, os documentos recomendam o uso --ask-become-pass, além de trocar o uso sudopelos manuais become.

deefour
fonte
16
Sim, posso ver por que isso é recomendado. No entanto, quando usamos o Ansible como parte do processo de implantação, qual é a melhor maneira de automatizar isso? Não é muito conveniente parar no meio do processo de implantação e pedir ao usuário para inserir a senha do sudo.
Slava Fomin II
9
Nota --ask-sudo-pass pode ser abreviado para -K, no entanto, até onde eu posso ver, não há como lidar com um manual em execução em vários servidores com senhas diferentes (ele pede apenas uma vez), então acho que sem senha sudo é o caminho a percorrer.
precisa
1
Não parece funcionar. mas a próxima sugestão ("some-host ansible_sudo_pass = 'foobar'") faz
nadavkav
--ask-sudo-pass foi preterido anteriormente, em 1.9 #
Chris Betti
Gostaria de atualizar a resposta com um link de origem, se você tiver um.
deefour
106

Provavelmente, a melhor maneira de fazer isso - supondo que você não possa usar a solução NOPASSWD fornecida pela scottod é usar a solução de Mircea Vutcovici em combinação com o Ansible Vault .

Por exemplo, você pode ter um manual assim:

- hosts: all

  vars_files:
    - secret

  tasks:
    - name: Do something as sudo
      service: name=nginx state=restarted
      sudo: yes

Aqui estamos incluindo um arquivo chamado secret que conterá nossa senha sudo.

Usaremos o ansible-vault para criar uma versão criptografada deste arquivo:

ansible-vault create secret

Isso solicitará uma senha e abra seu editor padrão para editar o arquivo. Você pode colocar o seu ansible_sudo_passaqui.

por exemplo secret:

ansible_sudo_pass: mysudopassword

Salve e saia, agora você tem um secretarquivo criptografado que o Ansible pode descriptografar quando você executa o seu manual. Nota: você pode editar o arquivo com ansible-vault edit secret(e inserir a senha usada ao criar o arquivo)

A peça final do quebra-cabeça é fornecer ao Ansible um --vault-password-fileque ele usará para descriptografar seu secretarquivo.

Crie um arquivo chamado vault.txte coloque a senha que você usou ao criar seusecret arquivo. A senha deve ser uma sequência armazenada como uma única linha no arquivo.

Dos Documentos Ansible:

.. garantir que as permissões no arquivo sejam tais que ninguém mais possa acessar sua chave e não a adicione ao controle de origem

Por fim: agora você pode executar seu playbook com algo como

ansible-playbook playbook.yml -u someuser -i hosts --sudo --vault-password-file=vault.txt 

O acima está assumindo o seguinte layout de diretório:

.
|_ playbook.yml
|_ secret
|_ hosts
|_ vault.txt

Você pode ler mais sobre o Ansible Vault aqui: https://docs.ansible.com/playbooks_vault.html

toast38coza
fonte
5
Nota: a partir do ansible 1.9, parece que você não pode mais usar a variável ansible_sudo_pass (ou ansible_become_pass): "fatal: [...] => ausente na senha"
toast38coza
6
Estou usando esta solução em produção, jenkins armazena a senha do cofre como uma variável de ambiente ofuscada, grava-a em tempo de execução em um arquivo temporário e passa a chamar ansible.
21616 Simone
6
ou mais simplesmente: ansible-vault create group_vars/all/ansible.ymle adicione ansible_sudo_pass: yourpasswordlá. Não há necessidade de playbooks mudança ou inventário
Bouke Versteegh
1
Tentei isso, mas eu tenho esse erro:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
Qual a vantagem de um cofre se você armazenar a senha no cofre em texto sem formatação ao lado dele?
Erik
44

Olhando para o código ( runner/__init__.py), acho que você provavelmente pode configurá-lo no seu arquivo de inventário:

[whatever]
some-host ansible_sudo_pass='foobar'

Parece haver alguma provisão no ansible.cfgarquivo de configuração também, mas não implementada agora ( constants.py).

leucos
fonte
7
Uma ótima maneira de configurar isso de forma segura seria a de armazenar esta na host_varsou group_varsdiretório e, em seguida, criptografar o arquivo usando ansible-vault
Kyle
44

Eu não acho que o ansible permitirá que você especifique uma senha nos sinalizadores como deseja. Pode haver algum lugar nas configurações que pode ser definido, mas isso tornaria o uso do ansible menos seguro em geral e não seria recomendado.

Uma coisa que você pode fazer é criar um usuário na máquina de destino e conceder a ele privilégios sudo sem senha para todos os comandos ou uma lista restrita de comandos.

Se você executar sudo visudoe digitar uma linha como a abaixo, o usuário 'privilegedUser' não precisará digitar uma senha quando executar algo como sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
escocês
fonte
7
@bschlueter então você está endossando más práticas?
21416 Stephen
1
Não acho que seja uma boa ideia. Usar --ask-sudo-pass faz sentido para mim.
kgpdeveloper 27/09/16
@ Simone Cittadini Concordo plenamente, pois na verdade essa é a resposta que eu daria. Este é um risco de segurança.
einarc
É menos um risco de segurança se você estiver usando o sudo sem senha para implantar no armazenamento temporário / prod, mas deseja usar essas respostas para evitar ter que digitar sua senha de login do laptop local ao implantar no host local a cada 15 minutos todos os dias, todos os dias.
Jonathan Hartley
Como você adiciona esta linha usando o Ansible?
Matthias
21

A senha do sudo é armazenada como uma variável chamada ansible_sudo_pass. Você pode definir esta variável de algumas maneiras:

Por host, no arquivo de hosts do seu inventário ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Por grupo, no seu arquivo de grupos de inventário ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Por grupo, em vars de grupo ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Por grupo, criptografado ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
fonte
18

Você pode definir a senha para um grupo ou para todos os servidores de uma vez:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1
Mircea Vutcovici
fonte
14

Eu estava arrancando meu cabelo com esse, agora encontrei uma solução que faz o que eu quero:

1 arquivo criptografado por host que contém a senha do sudo

/ etc / ansible / hosts:

[all:vars]
ansible_ssh_connection=ssh ansible_ssh_user=myuser ansible_ssh_private_key_file=~/.ssh/id_rsa

[some_service_group]
node-0
node-1

então você cria para cada host um arquivo var criptografado da seguinte forma:

ansible-vault create /etc/ansible/host_vars/node-0

com conteúdo

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

como você organiza a senha do cofre (digite via --ask-vault-pass) ou por cfg é com você

com base nisso, suspeito que você pode criptografar todo o arquivo hosts ...

greenone83
fonte
Criptografar usando o cofre faz mais sentido para mim, embora eu tenha lutado para usá-los ansible-playback. Eu tive que usar -e @vault/filename.exto cofre com minha ansible-playbookligação.
Alex
9

Uma maneira mais inteligente de fazer isso é armazenar sua sudosenha em um cofre seguro, como LastPass ou KeePass, e depois passá-la para o ansible-playbookuso de, -e@mas em vez de codificar o conteúdo em um arquivo real, você pode usar a construção -e@<(...)para executar um comando em um sub-shell e redirecione sua saída (STDOUT) para um descritor de arquivo anônimo, alimentando efetivamente a senha para o -e@<(..).

Exemplo

$ ansible-playbook -i /tmp/hosts pb.yml \
   -e@<(echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)")

O acima está fazendo várias coisas, vamos dividir.

  • ansible-playbook -i /tmp/hosts pb.yml - obviamente, executando um manual via ansible-playbook
  • $(lpass show folder1/item1 --password)"- executa a CLI LastPass lpasse recupera a senha para usar
  • echo "ansible_sudo_pass: ...password..." - pega a string 'ansible_sudo_pass:' e a combina com a senha fornecida por lpass
  • -e@<(..)- reúne o que foi dito acima e conecta o subshell de <(...)como um descritor de arquivo para ansible-playbookconsumo.

Outras melhorias

Se você preferir não digitar isso toda vez, pode simplesmente coisas assim. Primeiro, crie um alias .bashrccomo você gosta:

$ cat ~/.bashrc
alias asp='echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)"'

Agora você pode executar seu playbook assim:

$ ansible-playbook -i /tmp/hosts pb.yml -e@<(asp)

Referências

slm
fonte
1
Usar um subshell é uma ideia muito inteligente! Para aqueles que se perguntam, aqui está o que parece com a CLI do 1Password:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti
1
Eu gosto disso porque, quando verifiquei o histórico do bach, a senha não foi exposta em texto não criptografado. Provavelmente também é verdade que, se a auditoria do sistema estiver ativada, o comando será registrado como leitura de um arquivo; por exemplo, /dev/fd/63a senha do descritor de arquivo temporário não será divulgada.
precisa saber é o seguinte
5

Se você se sente confortável em manter senhas em arquivos de texto sem formatação, outra opção é usar um arquivo JSON com o parâmetro --extra-vars (certifique-se de excluir o arquivo do controle de origem):

ansible-playbook --extra-vars "@private_vars.json" playbook.yml 

O Ansible suporta esta opção desde a versão 1.3 .

sidecarcat
fonte
5

você pode escrever a senha do sudo para o seu playbook no arquivo hosts assim:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'
fawadRafiq
fonte
5

O cofre Ansible foi sugerido algumas vezes aqui, mas eu prefiro o git-crypt para criptografar arquivos confidenciais nos meus playbooks. Se você estiver usando o git para manter seus playbooks ansíveis, é fácil. O problema que encontrei no cofre ansible é que, inevitavelmente, acabo encontrando cópias criptografadas do arquivo com o qual quero trabalhar e preciso descriptografá-lo antes de poder trabalhar. git-cryptoferece um melhor fluxo de trabalho IMO.

Com isso, você pode colocar suas senhas em um var no seu playbook e marcá-lo como um arquivo criptografado da .gitattributesseguinte maneira:

 my_playbook.yml filter=git-crypt diff=git-crypt

Seu manual será criptografado de forma transparente no Github. Então você só precisa instalar sua chave de criptografia no host usado para executar o ansible ou seguir as instruções na documentação para configurá-la gpg.

Há boas perguntas e respostas sobre o encaminhamento de gpgchaves como as ssh-agentchaves SSH de encaminhamento aqui: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

user2432419
fonte
3

Você pode usar o sshpassutilitário como abaixo,

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass
Sachin
fonte
3

O uso do ansible 2.4.1.0 e o seguinte devem funcionar:

[all]
17.26.131.10
17.26.131.11
17.26.131.12
17.26.131.13
17.26.131.14

[all:vars]
ansible_connection=ssh
ansible_user=per
ansible_ssh_pass=per
ansible_sudo_pass=per

E basta executar o manual com este inventário como:

ansible-playbook -i inventory copyTest.yml
Hearen
fonte
3

Meu truque para automatizar isso era usar uma variável de ambiente e acessá-la via --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Exporte uma var env, mas evite o histórico do bash / shell (inclua um espaço ou outros métodos). Por exemplo:

     export ANSIBLE_BECOME_PASS='<your password>'

Pesquise a var env ao passar a ansible_become_passvariável extra para ansible-playbook, por exemplo:

ansible-playbook playbook.yml -i inventories/dev/hosts.yml -u user --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

Boas respostas alternativas:

JPvRiel
fonte
2

Você pode usar o cofre ansible, que codificará sua senha no cofre criptografado. Depois disso, você pode usar a variável from vault nos playbooks.

Alguma documentação sobre o ansible vault:
http://docs.ansible.com/playbooks_vault.html

Estamos usando-o como cofre por ambiente. Para editar o vault, temos o comando como:
ansible-vault edit inventories/production/group_vars/all/vault

Se você quiser chamar a variável do vault, precisará usar o ansible-playbook com parâmetros como:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Sim, estamos armazenando a senha do cofre no diretório local em texto simples, mas não é mais perigoso, como armazenar a senha raiz de todos os sistemas. A senha raiz está dentro do arquivo do Vault ou você pode tê-lo como um arquivo sudoers para o seu usuário / grupo.

Eu estou recomendando usar o arquivo sudoers no servidor. Aqui está um exemplo para o administrador do grupo:
%admin ALL=(ALL) NOPASSWD:ALL

maxo
fonte
1

Depois de cinco anos, vejo que esse ainda é um assunto muito relevante. Um tanto espelhando a resposta de leucos que eu acho melhor no meu caso, usando apenas ferramentas ansible (sem autenticação centralizada, tokens ou qualquer outra coisa). Isso pressupõe que você tenha o mesmo nome de usuário e a mesma chave pública em todos os servidores. Caso contrário, é claro que você precisará ser mais específico e adicionar as variáveis ​​correspondentes ao lado dos hosts:

[all:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file=home/user/.ssh/mykey
[group]
192.168.0.50 ansible_sudo_pass='{{ myserver_sudo }}'

ansible-vault create mypasswd.yml
ansible-vault edit mypasswd.yml

Adicionar:

myserver_sudo: mysecretpassword

Então:

ansible-playbook -i inv.ini my_role.yml --ask-vault --extra-vars '@passwd.yml'

Pelo menos desta forma, você não precisa escrever mais as variáveis ​​que apontam para as senhas.

Lethargos
fonte
1

A solução acima de @ toast38coza funcionou para mim; apenas esse sudo: yes está obsoleto no Ansible agora. Use torne - se e torne - se_usuário .

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root
Nätu
fonte
0

nós também podemos usar o EXPECT BLOCK no ansible para gerar bash e personalizá-lo conforme suas necessidades

- name: Run expect to INSTALL TA
  shell: |
    set timeout 100
    spawn /bin/sh -i

    expect -re "$ "
    send "sudo yum remove -y xyz\n"

    expect "$ "
    send "sudo yum localinstall -y {{ rpm_remotehost_path_for_xyz }}\n"

    expect "~]$ "
    send "\n"

    exit 0
  args:
  executable: /usr/bin/expect
Ashish Ranjan
fonte
0

Muito simples e adicione apenas no arquivo variável:

Exemplo:

$ vim group_vars/all

E adicione estes:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
fonte
Obrigado, mas acho que você quer dizer ansible_become_pass em vez de Ansible_become_pass.
Krishnom 4/10/19
0

Apenas um adendo, para que ninguém mais passe pelo aborrecimento que fiz recentemente:

AFAIK, a melhor solução é uma das linhas gerais de toast38coza's acima. Se fizer sentido vincular seus arquivos de senha e seu manual estaticamente, siga o modelo dele com vars_files(ou include_vars). Se você deseja mantê-los separados, é possível fornecer o conteúdo do cofre na linha de comando da seguinte maneira:

ansible-playbook --ask-vault-pass -e@<PATH_TO_VAULT_FILE> <PLAYBOOK_FILE>

Isso é óbvio em retrospecto, mas aqui estão as dicas:

  1. Aquele maldito sinal @ . Se você deixar de fora, a análise falhará silenciosamente e o ansible-playbook continuará como se você nunca tivesse especificado o arquivo em primeiro lugar.

  2. Você deve importar explicitamente o conteúdo do cofre, com uma linha de comando --extra-vars / -e ou dentro do seu código YAML. O --ask-vault-passsinalizador não faz nada por si só (além de solicitar um valor que pode ou não ser usado posteriormente).

Você pode incluir seus "@" se economizar uma hora.

Eric Anderson
fonte
-3

Isso funcionou para mim ... Arquivo criado /etc/sudoers.d/90-init-users arquivo com NOPASSWD

echo "user ALL=(ALL)       NOPASSWD:ALL" > 90-init-users

onde "usuário" é o seu ID do usuário.

ScottM
fonte