Как генерировать SSH ключи хоста через ansible?

11

Я пытаюсь заново сгенерировать ключи хоста ssh на нескольких удаленных серверах через ansible (и ssh-keygen), но файлы, похоже, не отображаются. Playbook работает нормально, но файлы на пульте не изменяются.

Мне нужно прибегнуть к echo -eвзлому, так как эти пульты работают под управлением Ubuntu 14.04 и не имеют правильной python-pexpectдоступной версии (согласно ansible).

Что мне не хватает? Мой playbook и вывод ниже:

сборник пьес

---
- 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

вывод

$ 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  
Ошибка сервера
источник

Ответы:

14

Насколько я знаю, единственная причина, по которой вам нужно было бы передать 'y' в ssh-keygen, заключается в том, что ваша команда заменяет существующий файл. На мой взгляд, это не очень хороший способ сделать что-то из инструмента управления конфигурацией.

Вы должны скорректировать свои задачи, чтобы сделать их идемпотентными. В частности, если вы добавите команду creates: filenameк своей команде, то новые ключи будут создаваться только тогда, когда они еще не существуют, а не заменяться при каждом запуске этой книги воспроизведения.

---
- 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

Если по какой-то причине вы хотели заменить эти ключи, например, если они были слишком старыми или что-то еще, вы можете добавить еще одну задачу для их удаления. Вот простое удаление

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

Если вы хотите удалить файлы, сгенерированные раньше определенного времени, вы можете использовать модуль stat для получения подробной информации об этих файлах и настроить whenусловия для выборочного удаления их, если они были старше определенной даты или чего-то еще.

Zoredache
источник
Отличный пример и спасибо за мысли о поддержании идемпотентности. Для моего случая использования я готовлю клонированные виртуальные машины, поэтому всегда будут ключи для перезаписи. Я вроде нужен ядерный вариант, чтобы просто удалить и заменить.
Ошибка сервера
Если вы всегда хотите, чтобы это удалили, то я бы, вероятно, применил file: state:absent ...подход к пайпингу в ssh-keygen. Хотя, вероятно, нет особой разницы.
Zoredache
Ах хорошо. это имеет больше смысла. Я не знал absentпару дней назад. Фактически это удалит файл до повторной генерации ключа. Это гораздо более четкий подход. Спасибо.
Ошибка сервера
6

Анзибль commandмодуль не передавать команды через оболочку . Это означает, что вы не можете использовать операторы оболочки, такие как канал, и поэтому вы видите символ канала в выходных данных. Что касается ansible, он выполнил команду echoсо всей остальной частью строки в качестве аргументов echo.

Если вам нужна командная строка, обработанная оболочкой, используйтеshell вместо command.

И должен быть лучший способ регенерировать ключи хоста ssh, но я не могу найти один прямо сейчас ...

Майкл Хэмптон
источник
Спасибо за командную оболочку и подсказку о команде (теперь работает отлично) Я не знал - все еще довольно плохо знаком с ansible
Ошибка сервера
Относительно последнего оператора (по крайней мере, для CentOS / RHEL), если вы удалите старые ключи и перезапустите, ключи хоста демона будут восстановлены для вас. Вам все равно нужно будет перезапустить службу, так что это определенно выглядит несколько лучше.
Аарон Копли
@AaronCopley Я имел в виду скорее роль Ansible, чем службу дистрибутива. Я знаю, что в большинстве крупных дистрибутивов есть сервис systemd, который генерирует ключи хоста ssh. К сожалению, этот сервис имеет небольшие различия между дистрибутивами (он даже различается в CentOS и Fedora). Роль была бы хорошим способом инкапсулировать все это, но я не могу найти один случайный.
Майкл Хэмптон
Не беспокойся, просто подумал, что упомяну это. (Вы можете знать, но ОП не может.)
Аарон Копли
@AaronCopley - кстати, это то, что я в итоге сделал. echo ...немного не сделали работу после второго запуска (я тестировал в /tmp/которой ключи не были в первый раз). Как вы упомянули, я прибегнул к удалению ключей хоста и генерации новых. Что касается автоматического восстановления ключей, это зависит от вашего распространения, правильно? Не все дистрибутивы Linux используют systemd.
Ошибка сервера
2

Используйте специальный модуль для этой задачи:

- 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
источник
Это не ключи хоста ssh
KumZ
1

извините, но я не мог использовать «создает» в задаче. я получил следующую ошибку:

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

следовательно, я использую следующие задачи:

- 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
источник
2
Используйте текущую версию Ansible.
Майкл Хэмптон
Вы правы, моя версия Ansible немного устарела: 2.0.0.2 ... (в Ubuntu 16.04). Я должен измениться!
МаксиРеглисс,
1

@Zoredache имеет правильный ответ, но он терпит неудачу (замечено @MaxiReglisse) для последних версий Ansible. Вместо этого используйте следующий код:

---
- 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
Дэвид Вебер
источник
1

Другой вариант - использовать пользовательский модуль. Положительной стороной этого является то, что вы получите идемпотентную задачу. Вот пример того, как генерировать ключи SSH на локальном хосте:

- 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
источник
1
Разве это не для ключей пользователя, а не ключей хоста?
MadHatter,
Вы также можете использовать его для ключей хоста, потому что на самом деле это то же самое. Только не забудьте восстановить контекст selinux, если вы используете SELinux в принудительном режиме
HeroFromEarth
Мне не понятно из документации, что вы можете. Если бы вы переписали свой ответ так, чтобы в нем явно отображались создаваемые ключи хоста, я бы удалил свое понижение.
MadHatter
Хорошо, может быть, это было неясно. Я добавил еще одну задачу, чтобы объяснить, как копировать эти ключи на удаленном компьютере. И, конечно, это только мой случай (мне нужны одни и те же ключи на нескольких машинах для кластера, поэтому мне нужно сгенерировать их на локальном хосте), и я уверен, что вы можете использовать модуль 'user' для генерации ключей для сервера ssh на удаленный компьютер (посмотрите на 'ssh_key_file')
HeroFromEarth
Я до сих пор не уверен, что это что-то кроме взлома (не в последнюю очередь потому, что он оставляет одного пользователя с копией закрытого ключа хоста!), Но по крайней мере это то, что теперь ответит на вопрос, как было задано, поэтому я удалил свой downvote.
MadHatter
0

Используйте модули openssh_keypair и authorized_key для одновременного создания и развертывания ключей, не сохраняя их на своем хосте.

- 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 Бельгия
источник