Como gerar chaves SSH de host via ansible?

11

Estou tentando gerar novamente as chaves do host ssh em um punhado de servidores remotos via ansible (e ssh-keygen), mas os arquivos não parecem estar aparecendo. O manual funciona bem, mas os arquivos no controle remoto não são alterados.

Eu preciso recorrer ao echo -ehackery, pois esses controles remotos estão executando o Ubuntu 14.04 e não têm a versão correta do python-pexpectdisponível (de acordo com a ansible).

o que estou perdendo? Meu manual e saída estão abaixo:

livro de cantadas

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
    - name: Generate /etc/ssh/ RSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

    - name: Generate /etc/ssh/ DSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

    - name: Generate /etc/ssh/ ECDSA host key
      command : echo -e 'y\n'|ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
      register: output
    - debug: var=output.stdout_lines

resultado

$ ansible-playbook ./playbooks/ssh-hostkeys.yml -l myhost.mydom.com, 
SUDO password: 

PLAY [all] **********************************************************************************************

TASK [Generate /etc/ssh/ RSA host key] ******************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C  -N "
    ]
}

TASK [Generate /etc/ssh/ DSA host key] ******************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C  -N "
    ]
}

TASK [Generate /etc/ssh/ ECDSA host key] ****************************************************************
changed: [myhost.mydom.com]

TASK [debug] ********************************************************************************************
ok: [myhost.mydom.com] => {
    "output.stdout_lines": [
        "y", 
        "|ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C  -N "
    ]
}

PLAY RECAP **********************************************************************************************
myhost.mydom.com : ok=6    changed=3    unreachable=0    failed=0  
Falha no servidor
fonte

Respostas:

14

Até onde eu sei, a única razão pela qual você precisaria enviar um 'y' ao ssh-keygen é se o seu comando está substituindo um arquivo existente. Na minha opinião, essa não é uma boa maneira de fazer algo com uma ferramenta de gerenciamento de configuração.

Você deve ajustar suas tarefas para torná-las idempotentes. Especificamente, se você adicionar o creates: filenamecomando, as novas chaves serão criadas apenas quando ainda não existirem, em vez de serem substituídas sempre que você executar esse manual.

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
  - name: Generate /etc/ssh/ RSA host key
    command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_rsa_key

  - name: Generate /etc/ssh/ DSA host key
    command : ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_dsa_key

  - name: Generate /etc/ssh/ ECDSA host key
    command : ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_ecdsa_key

Se, por algum motivo, você quiser substituir essas chaves, por exemplo, se elas forem muito antigas ou algo assim, você poderá adicionar outra tarefa para removê-las. Aqui está uma simples exclusão

- file:
    state: absent:
    path: "{{item}}"
  loop:
  - /etc/ssh/ssh_host_rsa_key
  - /etc/ssh/ssh_host_dsa_key
  - /etc/ssh/ssh_host_ecdsa_key

Se você deseja excluir os arquivos gerados antes de um certo tempo, você pode usar o módulo stat para recuperar detalhes sobre esses arquivos e configurar as whencondições para removê-los seletivamente se eles eram mais antigos que uma determinada data ou algo assim.

Zoredache
fonte
Ótimo exemplo e obrigado por pensar em manter a idempotência. Para o meu caso de uso, estou provisionando máquinas virtuais clonadas para que sempre haja chaves a serem substituídas. Eu meio que preciso da opção nuclear para apenas remover e substituir.
Falha no servidor
Se você sempre quiser removê-lo, provavelmente faria a file: state:absent ...abordagem de canalizar coisas para o ssh-keygen. Embora provavelmente não exista muita diferença.
Zoredache
Ah ok. Isso faz mais sentido. Eu não sabia sobre absentalguns dias atrás. Efetivamente, isso excluirá o arquivo antes de gerar novamente a chave. É uma abordagem muito mais clara. Obrigado.
Falha no servidor
6

O commandmódulo ansible não passa comandos através de um shell . Isso significa que você não pode usar operadores de shell, como o tubo, e é por isso que você está vendo o símbolo do tubo na saída. No que diz respeito ao ansible, ele executou o comando echocom todo o restante da linha como argumento para echo.

Se você precisar da linha de comando processada por um shell, use emshell vez de command.

E deveria haver uma maneira melhor de regenerar as chaves do host ssh, mas não consigo encontrar uma agora ...

Michael Hampton
fonte
Obrigado pela dica comando shell vs. (funciona bem agora) Eu não sabia - ainda muito novo para ansible
Servidor Fault
Em relação à última instrução (pelo menos no CentOS / RHEL), se você remover as chaves antigas e reiniciar, as chaves do host daemon serão regeneradas para você. Você precisará reiniciar o serviço de qualquer maneira, então isso definitivamente parece um pouco melhor.
Aaron Copley
@AaronCopley Eu estava me referindo mais a um papel Ansible do que ao serviço de distribuição. Estou ciente de que a maioria das principais distribuições possui um serviço systemd que gera chaves de host ssh. Infelizmente, esse serviço possui diferenças sutis de distribuição específica (é ainda diferente entre o CentOS e o Fedora). Um papel seria uma boa maneira de encapsular tudo isso, mas não consigo encontrar um de imediato.
Michael Hampton
Não se preocupe, apenas pensei em mencionar. (Você pode saber, mas OP talvez não.)
Aaron Copley
@AaronCopley - aliás, foi isso que acabei fazendo. o echo ...bit não funcionou após uma segunda execução (eu estava testando em /tmp/que as chaves não existiam na primeira vez). Recorri a remover as chaves do host primeiro, como você mencionou, e as novas geradoras. Na medida em que as chaves são regeneradas automaticamente, isso depende da sua distribuição, correto? Nem todas as distribuições Linux usam systemd.
Falha no servidor
2

Use o módulo especial para esta tarefa:

- name: Generate an OpenSSH keypair with the default values (4096 bits, rsa)
  openssh_keypair:
    path: /home/youruser/.ssh/id_rsa
    owner: youruser
    group: youruser

- name: Fix owner of the generated pub key
  file:
    path: /home/youruser/.ssh/id_rsa.pub
    owner: youruser
    group: youruser
Jorj
fonte
Essas não são chaves de host ssh
KumZ
1

desculpe, mas o i não poderia usar "cria" em uma tarefa. eu obtive o seguinte erro:

ERROR! 'creates' is not a valid attribute for a Task

consequentemente, eu uso as seguintes tarefas:

- name: remove existing ssh_host keys
  file: path={{ item }} state=absent
  with_items:
    - "/etc/ssh/ssh_host_rsa_key"
    - "/etc/ssh/ssh_host_dsa_key"
    - "/etc/ssh/ssh_host_ecdsa_key"

- name: Generate /etc/ssh/ RSA host key
  command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""

- name: Generate /etc/ssh/ DSA host key
  command : ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N ""

- name: Generate /etc/ssh/ ECDSA host key
  command : ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N ""
MaxiReglisse
fonte
2
Use uma versão atual do Ansible.
Michael Hampton
Você está certo, minha versão do Ansible é um pouco antiga: 2.0.0.2 ... (No Ubuntu 16.04). Eu tenho que mudar !
MaxiReglisse
1

@Zoredache tem a resposta correta, mas falha (observada por @MaxiReglisse) nas versões recentes do Ansible. Use o seguinte código:

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
  - name: Generate /etc/ssh/ RSA host key
    command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N ""
    args:
      creates: /etc/ssh/ssh_host_rsa_key
David Weber
fonte
1

Outra opção é usar o módulo do usuário . O lado positivo disso é que você terá uma tarefa idempotente. Aqui está um exemplo de como gerar chaves ssh no localhost:

- name: Generate ssh keys
  local_action:
    module: "user"
    name: "{{ lookup('env','USER') }}"
    generate_ssh_key: true
    ssh_key_type: "{{ item.0 }}"
    ssh_key_bits: "{{ item.1 }}"
    ssh_key_file: "{{ playbook_dir }}/{{ item.0 }}_{{ item.1 }}_key"
  with_together:
  - [ 'rsa', 'dsa' ]
  - [ 2048, 1024 ]
  loop_control:
    label: "{{ item.0 }}_{{ item.1 }}_key"

- name: Copy generated ssh keys to remote machine
  copy:
    src: "{{ playbook_dir }}/{{ item.0 }}_{{ item.1 }}_key"
    dest: "/etc/ssh/ssh_host_{{ item.0 }}_key{{ item.1 }}"
  with_nested:
  - [ 'rsa', 'dsa' ]
  - [ '', '.pub' ]
  notify:
  - Restart sshd
  loop_control:
    label: "/etc/ssh/ssh_host_{{ item.0 }}_key{{ item.1 }}"
HeroFromEarth
fonte
1
Isso não é para chaves de usuário, não para chaves de host?
MadHatter
Você pode usá-lo também para chaves do host, porque na verdade é a mesma coisa. Só não se esqueça de restaurar o contexto do selinux se você usar o SELinux no modo de imposição
HeroFromEarth 15/02/19
Não está claro para mim a partir da documentação que você pode. Se você reescrever sua resposta para mostrar explicitamente as chaves do host que estão sendo criadas, eu removerei meu voto negativo.
MadHatter
Ok, talvez não estivesse claro. Adicionei outra tarefa para explicar como copiar essas chaves em uma máquina remota. E é claro que é apenas o meu caso (eu preciso das mesmas chaves em algumas máquinas para um cluster, por isso preciso gerá-las no host local) e tenho certeza de que você pode usar o módulo 'user' para gerar chaves para o servidor ssh a máquina remota (veja 'ssh_key_file')
HeroFromEarth 15/02/19
Ainda não tenho certeza de que seja algo diferente de um hack (pelo menos porque deixa um usuário com uma cópia da chave privada do host!), Mas pelo menos é algo que agora responderá à pergunta conforme solicitado, então removi meu voto negativo.
MadHatter
0

Use os módulos openssh_keypair e allowed_key para criar e implantar as chaves ao mesmo tempo sem salvá-las em seu host ansível.

- openssh_keypair:
    group: root
    owner: root
    path: /some/path/in/your/server
    register: ssh_key

- name: Store public key into origin
  delegate_to: central_server_name
  authorized_key:
     key: "{{ssh_key.public_key}}"
     comment: "{{ansible_hostname}}"
     user: any_user_on_central
MUY Bélgica
fonte