Bagaimana cara menghasilkan kunci SSH host melalui ansible?


11

Saya mencoba untuk menghasilkan kembali kunci host ssh pada beberapa server jarak jauh via ansible (dan ssh-keygen), tetapi file-file tersebut tampaknya tidak muncul. Playbook berjalan OK, tetapi file pada remote tidak diubah.

Saya perlu menggunakan echo -ehackery karena remote ini menjalankan Ubuntu 14.04 dan belum memiliki versi yang benar dari yang python-pexpecttersedia (sesuai dengan yang dimungkinkan).

Apa yang saya lewatkan? Buku pedoman dan hasil saya di bawah:

buku pedoman

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

keluaran

$ 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  

Jawaban:


14

Sejauh yang saya tahu satu-satunya alasan mengapa Anda perlu mengirimkan 'y' ke ssh-keygen, adalah jika perintah Anda mengganti file yang ada. Menurut pendapat saya ini bukan cara yang baik untuk melakukan sesuatu dari alat manajemen konfigurasi.

Anda harus menyesuaikan tugas Anda untuk membuatnya idempoten. Khususnya jika Anda menambahkan creates: filenameke perintah Anda, maka kunci baru hanya akan dibuat ketika belum ada, alih-alih diganti setiap kali Anda menjalankan playbook itu.

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

Jika karena alasan tertentu Anda ingin mengganti kunci-kunci itu misalnya jika terlalu lama atau sesuatu, Anda mungkin ingin menambahkan tugas lain untuk menghapusnya. Ini adalah penghapusan sederhana

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

Jika Anda ingin menghapus file yang dihasilkan sebelum waktu tertentu, Anda dapat menggunakan modul stat untuk mengambil detail tentang file ini, dan mengatur whenkondisi untuk menghapusnya secara selektif jika mereka lebih tua dari tanggal tertentu atau sesuatu.


Contoh yang bagus dan terima kasih atas pemikiran untuk mempertahankan idempotensi. Untuk kasus penggunaan saya, saya sedang menyediakan Mesin Virtual kloning sehingga akan selalu ada kunci untuk ditimpa. Saya agak membutuhkan opsi nuklir untuk menghapus dan mengganti.
Kesalahan Server

Jika Anda selalu ingin menghapusnya, maka saya mungkin akan melakukan file: state:absent ...pendekatan atas hal-hal perpipaan ke ssh-keygen. Meskipun mungkin tidak ada banyak perbedaan.
Zoredache

Ah, baiklah. itu lebih masuk akal. Saya tidak tahu tentang absentbeberapa hari yang lalu. Secara efektif itu akan menghapus file sebelum menghasilkan kembali kunci. Ini pendekatan yang jauh lebih jelas. Terima kasih.
Kesalahan Server

6

The ansible commandmodul tidak lulus perintah melalui shell . Ini berarti Anda tidak dapat menggunakan operator shell seperti pipa, dan itulah sebabnya Anda melihat simbol pipa di output. Sejauh menyangkut yang mungkin, itu telah mengeksekusi perintah echodengan semua sisa baris sebagai argumen echo.

Jika Anda membutuhkan baris perintah yang diproses oleh shell, gunakanshell sebagai ganti command.

Dan, seharusnya ada cara yang lebih baik untuk membuat kembali kunci host ssh, tapi saya tidak dapat menemukannya sekarang ...


Terima kasih untuk shell vs tip perintah (berfungsi dengan baik sekarang) Saya tidak tahu - masih cukup baru untuk memungkinkan
Server Fault

Mengenai pernyataan terakhir (setidaknya pada CentOS / RHEL) jika Anda menghapus kunci lama dan memulai kembali kunci host daemon dibuat ulang untuk Anda. Anda tetap harus me-restart layanan jadi ini sepertinya agak lebih baik.
Aaron Copley

@AaronCopley Saya lebih mengacu pada peran Ansible daripada layanan distro. Saya sadar bahwa sebagian besar distro utama memiliki layanan systemd yang menghasilkan kunci host ssh. Sayangnya layanan tersebut memiliki perbedaan distro yang sangat halus (bahkan berbeda antara CentOS dan Fedora). Peran akan menjadi cara yang bagus untuk merangkum semua itu, tetapi saya tidak dapat menemukannya secara langsung.
Michael Hampton

Jangan khawatir, hanya berpikir saya akan menyebutkannya. (Anda mungkin tahu, tapi OP mungkin tidak.)
Aaron Copley

@AaronCopley - kebetulan, inilah yang akhirnya saya lakukan. yang echo ...sedikit tidak bekerja setelah menjalankan kedua (saya sedang menguji di /tmp/mana tombol tidak ada pertama kali sekitar). Saya terpaksa menghapus kunci host terlebih dahulu, seperti yang Anda sebutkan, dan menghasilkan yang baru. Sejauh membuat kunci secara otomatis dibuat kembali, ini tergantung pada distribusi Anda, benar? Tidak semua distro Linux menggunakan systemd.
Kesalahan Server

2

Gunakan modul khusus untuk tugas ini:

- 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

Itu bukan kunci host ssh
KumZ

1

maaf, tapi saya tidak bisa menggunakan "create" dalam suatu tugas. saya mendapatkan kesalahan berikut:

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

secara konsekuen, saya menggunakan tugas-tugas berikut:

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

2
Gunakan versi Ansible saat ini.
Michael Hampton

Anda benar, versi Ansible saya agak lama: 2.0.0.2 ... (Di Ubuntu 16.04). Saya harus berubah !
MaxiReglisse

1

@Zoredache memiliki jawaban yang benar tetapi gagal (dicatat oleh @MaxiReglisse) untuk versi terbaru dari Ansible. Gunakan kode berikut sebagai gantinya:

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

Pilihan lain adalah menggunakan modul pengguna . Sisi positifnya adalah Anda akan mendapatkan tugas idempoten. Berikut adalah contoh cara membuat kunci ssh di 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 }}"

1
Bukankah itu untuk kunci pengguna, bukan kunci host?
MadHatter

Anda dapat menggunakannya untuk kunci host juga karena itu adalah hal yang sama sebenarnya. Hanya saja, jangan lupa untuk mengembalikan konteks selinux jika Anda menggunakan SELinux dalam mode penegakan
HeroFromEarth

Tidak jelas bagi saya dari dokumentasi yang Anda bisa. Jika Anda akan menulis ulang jawaban Anda sehingga secara eksplisit menunjukkan kunci host yang sedang dibuat, saya akan menghapus downvote saya.
MadHatter

Oke, mungkin tidak jelas. Saya telah menambahkan tugas lain untuk menjelaskan cara menyalin kunci ini di mesin jarak jauh. Dan tentu saja ini hanya kasus saya (saya perlu tombol yang sama pada beberapa mesin untuk sebuah cluster jadi saya perlu membuatnya di localhost) dan saya cukup yakin bahwa Anda dapat menggunakan modul 'pengguna' untuk menghasilkan kunci untuk ssh server pada mesin jarak jauh (lihat 'ssh_key_file')
HeroFromEarth

Saya masih tidak yakin apakah itu selain hack (paling tidak karena meninggalkan satu pengguna dengan salinan kunci pribadi host!) Tetapi setidaknya itu adalah sesuatu yang sekarang akan menjawab pertanyaan seperti yang ditanyakan, jadi saya telah menghapus downvote.
MadHatter

0

Gunakan openssh_keypair dan module berwenang_key untuk membuat dan menggunakan kunci secara bersamaan tanpa menyimpannya ke host yang memungkinkan.

- 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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.