จะสร้างคีย์ SSH โฮสต์ผ่าน ansible ได้อย่างไร


11

ฉันกำลังพยายามสร้างคีย์โฮสต์ ssh อีกครั้งบนเซิร์ฟเวอร์ระยะไกลจำนวนหนึ่งผ่านทาง ansible (และssh-keygen) แต่ไฟล์ดูเหมือนจะไม่ปรากฏขึ้น Playbook นั้นใช้งานได้ดี แต่ไฟล์ในรีโมตจะไม่เปลี่ยนแปลง

ฉันต้องหันไปใช้echo -eแฮ็คเกอร์เนื่องจากรีโมตเหล่านี้ใช้งาน Ubuntu 14.04 และยังไม่มีเวอร์ชั่นที่ถูกต้องของรุ่นที่python-pexpectใช้งานได้ (อ้างอิงจาก ansible)

ฉันกำลังคิดถึงอะไร Playbook และผลลัพธ์ของฉันอยู่ด้านล่าง:

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 คือถ้าคำสั่งของคุณเปลี่ยนไฟล์ที่มีอยู่ ในความคิดของฉันนี่ไม่ใช่วิธีที่ดีในการทำบางสิ่งจากเครื่องมือการจัดการการกำหนดค่า

คุณควรปรับภารกิจของคุณเพื่อให้ idempotent โดยเฉพาะถ้าคุณเพิ่มcreates: filenameคำสั่งของคุณแล้วปุ่มใหม่จะถูกสร้างขึ้นเมื่อพวกเขายังไม่มีอยู่แทนที่จะถูกแทนที่ในแต่ละครั้งที่คุณเรียกใช้ playbook นั้น

---
- 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เงื่อนไขการตั้งค่าเพื่อเลือกลบไฟล์หากไฟล์เก่ากว่าบางวันหรือบางวัน


ตัวอย่างที่ดีและขอบคุณสำหรับความคิดในการรักษา idempotence สำหรับกรณีการใช้งานของฉันฉันกำลังเตรียมเครื่องเสมือนโคลนดังนั้นจะมีกุญแจสำหรับเขียนทับอยู่เสมอ ฉันต้องการตัวเลือกนิวเคลียร์เพียงแค่ลบและแทนที่
ข้อผิดพลาดของเซิร์ฟเวอร์

หากคุณต้องการที่จะลบมันออกไปฉันก็อาจทำตามfile: state:absent ...วิธีการเกี่ยวกับการวางท่อกับ ssh-keygen แม้ว่าอาจมีความแตกต่างไม่มาก
Zoredache

อาโอเค. ที่เหมาะสมมากขึ้น เมื่อไม่absentกี่วันก่อนฉันไม่รู้ อย่างมีประสิทธิภาพที่จะลบไฟล์ก่อนที่จะสร้างคีย์ใหม่ มันเป็นวิธีที่ชัดเจนกว่ามาก ขอบคุณ
ข้อผิดพลาดของเซิร์ฟเวอร์

6

เบิ้ลcommandโมดูล ไม่ผ่านคำสั่งผ่านเปลือก ซึ่งหมายความว่าคุณไม่สามารถใช้ตัวดำเนินการเชลล์เช่นไพพ์ได้และนั่นคือสาเหตุที่คุณเห็นสัญลักษณ์ไพพ์ในเอาต์พุต เท่าที่เบิ้ลเป็นห่วงก็มีการดำเนินการคำสั่งที่มีทั้งหมดของส่วนที่เหลือของสายเป็นข้อโต้แย้งกับechoecho

หากคุณต้องการบรรทัดคำสั่งประมวลผลโดยเชลล์ใช้shellcommandแทน

และควรมีวิธีที่ดีกว่าในการสร้างคีย์โฮสต์ ssh ใหม่ แต่ตอนนี้ฉันหาไม่พบ ...


ขอบคุณสำหรับคำสั่ง shell vs. command (ใช้งานได้ดีตอนนี้) ฉันไม่รู้ - ยังค่อนข้างใหม่สำหรับ ansible
ข้อผิดพลาดของเซิร์ฟเวอร์

เกี่ยวกับคำสั่งล่าสุด (อย่างน้อยใน CentOS / RHEL) หากคุณลบคีย์เก่าและรีสตาร์ทโฮสต์โฮสต์ daemon จะถูกสร้างใหม่สำหรับคุณ คุณจะต้องเริ่มบริการใหม่อีกครั้งดังนั้นนี่จึงค่อนข้างดีกว่า
Aaron Copley

@AaronCopley ฉันหมายถึงบทบาท Ansible มากกว่าบริการ distro ฉันทราบว่า distros สำคัญส่วนใหญ่มีบริการ systemd ที่สร้างคีย์โฮสต์ ssh น่าเสียดายที่บริการมีความแตกต่างเฉพาะของ distro (มันต่างกันมากระหว่าง CentOS และ Fedora) บทบาทจะเป็นวิธีที่ดีในการสรุปแค็ปซูลทั้งหมด แต่ฉันไม่สามารถหาคนเดียวได้
Michael Hampton

ไม่ต้องกังวลแค่คิดว่าฉันจะพูดถึงมัน (คุณอาจจะรู้ แต่ OP อาจจะไม่ได้)
Aaron Copley

@AaronCopley - โดยบังเอิญนี่คือสิ่งที่ฉันทำ echo ...บิตไม่ได้ทำงานหลังจากที่ระยะที่สอง (ฉันถูกทดสอบใน/tmp/คีย์ที่ไม่ได้อยู่ครั้งแรกรอบ) ฉันหันไปใช้การลบคีย์โฮสต์ก่อนตามที่คุณพูดถึงและการสร้างคีย์ใหม่ เท่าที่มีการสร้างกุญแจโดยอัตโนมัติสิ่งนี้จะขึ้นอยู่กับการกระจายของคุณถูกต้องหรือไม่ Linux distros บางตัวใช้ 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

สิ่งเหล่านี้ไม่ใช่กุญแจโฮสต์ 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 ""

2
ใช้ Ansible รุ่นปัจจุบัน
Michael Hampton

คุณพูดถูกแล้วรุ่น Ansible ของฉันเก่าไปหน่อย: 2.0.0.2 ... (บน Ubuntu 16.04) ฉันต้องเปลี่ยน!
MaxiReglisse

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

ตัวเลือกอื่นคือการใช้โมดูลผู้ใช้ ด้านบวกของสิ่งนี้คือคุณจะได้งาน idempotent นี่คือตัวอย่างวิธีการสร้างคีย์ ssh บน 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
นั่นไม่ใช่สำหรับรหัสผู้ใช้ไม่ใช่รหัสโฮสต์ใช่หรือไม่
MadHatter

คุณสามารถใช้มันสำหรับโฮสต์คีย์ด้วยเหมือนกันจริง ๆ อย่าลืมเรียกคืนบริบท selinux ถ้าคุณใช้ SELinux ในโหมดบังคับใช้
HeroFromEarth

ไม่ชัดเจนสำหรับฉันจากเอกสารที่คุณสามารถทำได้ หากคุณต้องการเขียนคำตอบของคุณใหม่เพื่อให้แสดงรหัสโฮสต์ที่ถูกสร้างขึ้นอย่างชัดเจนฉันจะลบ downvote ของฉัน
MadHatter

โอเคบางทีมันอาจจะไม่ชัดเจน ฉันได้เพิ่มงานอื่นเพื่ออธิบายวิธีคัดลอกคีย์เหล่านี้ในเครื่องระยะไกล และแน่นอนมันเป็นเพียงกรณีของฉัน (ฉันต้องการคีย์เดียวกันบนเครื่องไม่กี่เครื่องสำหรับคลัสเตอร์ดังนั้นฉันต้องสร้างพวกเขาบน localhost) และฉันค่อนข้างแน่ใจว่าคุณสามารถใช้โมดูล 'ผู้ใช้' เพื่อสร้างคีย์สำหรับเซิร์ฟเวอร์ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.