Como posso implementar com segurança senhas com senhas por host?

108

Eu gostaria de usar o ansible para gerenciar um grupo de servidores existentes. Criei um ansible_hostsarquivo e testei com sucesso (com a -Kopção) com comandos que segmentam apenas um único host

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Meu problema agora é que as senhas de usuário em cada host são diferentes, mas não consigo encontrar uma maneira de lidar com isso no Ansible.

Usando -K, sou solicitada apenas uma única senha sudo antecipadamente, que parece ser tentada para todos os hosts subseqüentes sem avisar:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Pesquisa até agora:

  • uma pergunta StackOverflow com uma resposta incorreta ("use -K") e uma resposta do autor dizendo "Descobri que precisava de sudo sem senha"

  • os documentos Ansible , que dizem "O uso do sudo sem senha facilita a automatização das coisas, mas não é necessário ". (ênfase minha)

  • esta questão de segurança StackExchange, que aceita a leitura NOPASSWDnecessária

  • artigo "Provisionamento escalável e compreensível ...", que diz:

    "executar o sudo pode exigir a digitação de uma senha, o que é uma maneira segura de bloquear o Ansible para sempre. Uma solução simples é executar o visudo no host de destino e garantir que o usuário que o Ansible usará para efetuar o login não precise digitar uma senha"

  • artigo "Manual básico de instruções" , que diz

    "O Ansible pode fazer login no servidor de destino como root e evitar a necessidade de sudo, ou permitir que o usuário ansible o sudo sem uma senha, mas o pensamento de fazer isso faz com que meu baço ameace saltar meu esófago e bloquear minha traqueia, então eu não "

    Meus pensamentos exatamente, mas como estender além de um único servidor?

  • questão # 1227 , "Ansible deve solicitar a senha do sudo para todos os usuários em um manual", que foi encerrada há um ano por mpdehaan com o comentário "Não vi muita demanda por isso, acho que a maioria das pessoas está usando apenas um conta de usuário ou usando chaves na maioria das vezes. "

Então ... como as pessoas estão usando o Ansible em situações como essas? Definir NOPASSWDem /etc/sudoers, reutilização de senha em hosts ou ativar o login SSH raiz todos parecem reduções bastante drásticas em segurança.

supervacuo
fonte
2
Existe um motivo para você não estar usando chaves SSH?
Trondh
22
Eu já estou usando chaves SSH; eles não afetam sudo(o que ainda deve exigir uma senha).
Supervacuo
1
Pode não ser exatamente o que você está procurando, mas nas caixas do Ubuntu ainda uso chaves, ou seja, colocando minha chave pública em / root / allowed_keys para entrar diretamente como root. A desvantagem óbvia é permitir logins raiz no ssh ... Também não permito logins de senhas no ssh e corro fail2ban para aumentar a segurança.
Senorsmile
27
@senorsmile obrigado pela resposta! Você se importaria em transformá-la em uma resposta, para que eu possa lhe dar um voto negativo por não ter lido a pergunta?
supervacuo
4
isto é, a ansible_ssh_passwordconfiguração se aplica apenas à senha SSH (a pista está no nome ...). Já estou usando o login SSH baseado em chave.
Supervacuo

Respostas:

53

Você certamente fez sua pesquisa ...

De toda a minha experiência com o ansible, o que você deseja realizar não é suportado. Como você mencionou, o ansible afirma que não requer sudo sem senha e você está correto, não. Mas ainda não vi nenhum método de usar várias senhas sudo no ansible, sem, é claro, executar várias configurações.

Portanto, não posso oferecer a solução exata que você está procurando, mas você perguntou ...

"Então ... como as pessoas estão usando o Ansible em situações como essas? Definir NOPASSWD em / etc / sudoers, reutilizar senha em hosts ou ativar o login SSH raiz parece uma redução drástica na segurança."

Eu posso te dar uma visão sobre isso. Meu caso de uso são 1k nós em vários datacenters que oferecem suporte a uma empresa SaaS global na qual eu tenho que projetar / implementar alguns controles de segurança incrivelmente rígidos devido à natureza de nossos negócios. Segurança é sempre um ato de equilíbrio, mais usabilidade menos segurança, esse processo não é diferente se você estiver executando 10 servidores ou 1.000 ou 100.000.

Você está absolutamente correto em não usar logins raiz via senha ou chaves ssh. De fato, o login root deve ser totalmente desativado se os servidores tiverem um cabo de rede conectado a eles.

Vamos falar sobre a reutilização de senhas, em uma grande empresa, é razoável solicitar que os administradores de sistemas tenham senhas diferentes em cada nó? talvez para alguns nós, mas meus administradores / engenheiros se amotinariam se tivessem que ter senhas diferentes em 1000 nós. Ao implementar isso também seria quase impossível, cada usuário teria que armazenar suas próprias senhas em algum lugar, espero que seja um passe de chave, não uma planilha. E toda vez que você coloca uma senha em um local onde ela pode ser retirada em texto simples, você diminui bastante sua segurança. Eu preferiria que eles soubessem, de cor, uma ou duas senhas realmente fortes do que precisassem consultar um arquivo de senha sempre que precisassem entrar ou invocar o sudo em uma máquina.

Portanto, a reutilização e a padronização de senhas são algo completamente aceitável e padrão, mesmo em um ambiente seguro. Caso contrário, o LDAP, o keystone e outros serviços de diretório não precisariam existir.

Quando passamos para usuários automatizados, as teclas ssh funcionam muito bem para você, mas você ainda precisa passar pelo sudo. Suas opções são uma senha padronizada para o usuário automatizado (que é aceitável em muitos casos) ou para ativar o NOPASSWD conforme indicado. A maioria dos usuários automatizados executa apenas alguns comandos; portanto, é possível e certamente desejável ativar o NOPASSWD, mas apenas para comandos pré-aprovados. Eu sugiro usar o gerenciamento de configuração (neste caso, ansible) para gerenciar seu arquivo sudoers, para que você possa atualizar facilmente a lista de comandos sem senha.

Agora, existem algumas etapas que você pode executar quando iniciar o dimensionamento para isolar ainda mais os riscos. Embora tenhamos cerca de 1000 nós, nem todos são servidores de "produção", alguns são ambientes de teste etc. Nem todos os administradores podem acessar servidores de produção, aqueles que podem usar a mesma chave de usuário / senha SSO que usariam em outros lugares. . Mas os usuários automatizados são um pouco mais seguros, por exemplo, uma ferramenta automatizada que os administradores que não são de produção podem acessar possui um usuário e credenciais que não podem ser usadas na produção. Se você deseja iniciar o ansible em todos os nós, precisará fazê-lo em dois lotes, um para não produção e outro para produção.

No entanto, também usamos o fantoche, uma vez que é uma ferramenta de gerenciamento de configuração impositiva, para que a maioria das alterações em todos os ambientes seja promovida.

Obviamente, se a solicitação de recurso que você citou for reaberta / concluída, o que você está procurando fazer será totalmente suportado. Mesmo assim, a segurança é um processo de avaliação e comprometimento de riscos. Se você tiver apenas alguns nós nos quais se lembra das senhas sem recorrer a uma nota de post-it, senhas separadas seriam um pouco mais seguras. Mas para a maioria de nós, não é uma opção viável.

Zeb
fonte
Obrigado, @Zeb - eu imaginava que os usuários com dezenas de milhares de servidores usariam NOPASSWDpor motivos de sanidade de qualquer maneira (provavelmente suportados por regras mais rígidas de firewall etc. ), mas é bom ler seus casos de uso e pensamentos sobre a ameaça modelo.
Supervacuo
16
Um comentário, no entanto, sobre a sua sugestão sobre a restrição de sudocomandos "pré-aprovados" (o que me ocorreu quando descobri que NOPASSWDé praticamente necessário). Infelizmente, isso também parece completamente sem suporte - o prometido não promete promessas de chamar, por exemplo, binários chownou mkdirdiretamente, e precisa conseguir que a sudo /bin/shmaioria dos módulos funcione.
supervacuo
Parece que me lembro de um de meus engenheiros reclamando disso há um tempo, isso é chato.
Zeb
36

A partir do Ansible 1.5, é possível usar um cofre criptografado para host_vars e outras variáveis. Isso permite pelo menos armazenar uma ansible_sudo_passvariável por host (ou por grupo) com segurança. Infelizmente, --ask-vault-passvocê solicitará apenas uma senha de cofre por invocação possível, portanto, você ainda estará restrito a uma senha de cofre para todos os hosts que você usará juntos.

No entanto, para alguns usos, isso pode ser uma melhoria em relação a ter uma única senha do sudo em vários hosts, pois um invasor sem acesso aos seus host_vars criptografados ainda precisaria de uma senha do sudo separada para cada máquina (ou grupo de máquinas) que ele ou ela atacar.

Daniel Neades
fonte
3
A ansible_sudo_passopção também parece nova - e parece fazer o que eu estava pedindo. Uma única senha do cofre também é ideal para meus propósitos. Obrigado!
Supervacuo
Existe uma maneira de evitar criptografar todos host_vars usando esse método? (uma limitação potencial observado por Alex Dupuy)
supervacuo
1
@supervacuo - Para evitar criptografar todos os host vars, basta usar um diretório var host contendo main.yml (não criptografado) e secret.yml (criptografado) - consulte a última parte desta seção do documento, onde ele fala sobre o grupo "raleigh" - a mesma técnica funciona para vars de host e vars de grupo. Eu uso muito isso, a única variação é que, se um segredo é necessário apenas para alguns playbooks, pode ser útil armazená-lo em uma árvore diferente e incluir por um caminho que inclua o nome do host ou var.
RichVel 14/09/16
1
Se eu criptografei o valor 'ansible_ssh_pass' no vault, também preciso duplicar o valor 'ansible_sudo_pass'? Existe uma maneira do segundo valor sudo_pass referenciar o primeiro valor 'ssh_pass'?
Emeraldjava
Uma boa cobertura sobre o uso de senha
com cofre
22

Com o Ansible 1.5, é possível definir a variável ansible_sudo_pass usando lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Acho isso mais conveniente do que usar arquivos host_vars/por vários motivos:

  • Na verdade, eu uso with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" para provisionar as senhas do usuário remoto de implantação (que é necessário para o sudo ), para que elas já estejam presentes nos arquivos (embora essas pesquisas em texto sem formatação percam o valor salt armazenado no arquivo quando o valor do hash é gerado) .

  • Isso mantém apenas as senhas no arquivo (sem ansible_sudo_pass:texto sem formatação) para um aumento de epsilon na segurança criptográfica. Mais significativamente, significa que você não está criptografando todas as outras variáveis ​​específicas do host, para que possam ser lidas sem a senha do cofre.

  • Colocar as senhas em um diretório separado facilita manter os arquivos fora do controle de origem ou usar uma ferramenta como o git-crypt para armazená-los em forma criptografada (você pode usá-lo com o Ansible anterior que não possui o recurso de cofre). Eu uso o git-crypt e como só faço check-out do repositório em forma descriptografada em sistemas de arquivos criptografados, não me preocupo com o cofre e, portanto, não preciso digitar uma senha do cofre. (Usar os dois seria, naturalmente, mais seguro.)

Você também pode usar a função de pesquisa com ansible_ssh_pass ; isso pode até ser possível com versões anteriores do Ansible que não possuem ansible_sudo_pass .

Alex Dupuy
fonte
2
I finalmente got para tentar isso, mas não posso ver como ele iria trabalhar sem (obrigado!) git-crypt; tão longe quanto eu consigo ver. Parece que o Ansible ainda não tem suporte para usar lookupem um cofre criptografado. Os passworddocumentos do módulo dizem que há algum suporte ainda não documentado para armazenamento criptografado, mas ainda preciso encontrar detalhes. Alguma pista?
Supervacuo
19

O uso de pass é um método simples para fornecer senhas sudo para ansible. O pass armazena uma senha por arquivo, o que facilita o compartilhamento de senhas via git ou outros métodos. Também é seguro (usando o GnuPG) e se você estiver usando o gpg-agent, ele permite que você use o ansible sem inserir uma senha em cada uso.

Para fornecer a senha armazenada como o servers/fooservidor foopara ansible, use-a em um arquivo de inventário como este:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Como você desbloqueou a chave do gpg-agent anteriormente, isso será executado sem a necessidade de digitar nenhuma senha.

fqxp
fonte
3

Este é um tópico bastante antigo, no entanto:

  • Utilizamos dois sistemas de autenticação diferentes internamente, o gerenciamento de máquinas é feito em estações de trabalho locais da minha equipe.
  • Eu escrevi um vars_pluginpara o Ansible (uma implementação bastante completa pode ser encontrada em https://gist.github.com/mfriedenhagen/e488235d732b7becda81 ), que diferencia vários sistemas de autenticação:
  • O nome do sistema de autenticação é específico do grupo.
  • O usuário de login / sudo usado é específico do grupo e do administrador.
  • Por isso, retiro o usuário do ambiente do administrador e a senha correspondente através da biblioteca python-keyring de um cofre com senha (usamos o chaveiro do Mac OS X, mas também da documentação kwallet Gnome e _win_crypto).
  • Defino permissões nas senhas nas chaves do Mac OS X para me notificar sobre o fato de que a segurança do programa de linha de comando solicita acesso a uma senha para todos os sistemas de autenticação usados ​​pelos hosts, portanto, executo "ansible -s all -m ping" e recebo dois avisos (um para cada sistema de autenticação) onde pressiono a barra de espaço e o ansible pega as senhas.
Mirko Friedenhagen
fonte
Parece muito legal, obrigado - eu gosto da ideia de não precisar armazenar senhas em dois lugares. No momento, estou preso usando o KeepassX (porque o chaveiro do GNOME não parece muito portátil), mas talvez eu possa fazer o python-keepasstrabalho?
Supervacuo
Tanto quanto eu entendo, python-keyring é uma abstração para isso, então seus colegas podem usar outros sistemas operacionais. Ou você armazena o keepassx db em um pendrive e precisa administrar a partir de estações de trabalho com sistemas operacionais diferentes?
Mirko Friedenhagen
Entendido; Eu quis dizer que já tenho que usar o KeepassX para ter acesso a senhas em sistemas não-GNOME, portanto, armazená-las gnome-keyringsignificaria manter registros duplicados. Ainda maneira mais agradável de usar NOPASSWD, embora ...
supervacuo
0

Uma maneira possível de fazer isso é usar variáveis ​​ambientais.

por exemplo

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Em seguida, nas execuções, você pode procurar a senha do sudo usando:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Paul Calabro
fonte