จะจัดการกับการเปลี่ยนแปลงของพอร์ต SSH ด้วย Ansible ได้อย่างไร


27

ฉันพยายามใช้ Ansible สำหรับการตั้งค่าเซิร์ฟเวอร์อินสแตนซ์ใหม่โดยอัตโนมัติ หนึ่งในภารกิจการตั้งค่าเปลี่ยนพอร์ต SSH เริ่มต้นดังนั้นจึงต้องให้ฉันอัปเดตรายการโฮสต์

เป็นไปได้หรือไม่ที่จะทำสิ่งนี้โดยอัตโนมัติโดยให้ Ansible fallback ไปยังพอร์ตที่ระบุหากไม่สามารถสร้างการเชื่อมต่อกับพอร์ต SSH เริ่มต้นได้

คำตอบ:


15

คุณสามารถลอง local_action บนโฮสต์เพื่อดูว่าคุณสามารถเชื่อมต่อกับพอร์ตที่เกี่ยวข้องและลงทะเบียนพอร์ตที่ทำสำเร็จและตั้งค่าเป็นจริง คุณต้องการปิดการรวบรวมข้อเท็จจริงเพราะมิฉะนั้นโมดูลการติดตั้งจะล้มเหลวเมื่อพยายามเชื่อมต่อกับโฮสต์ที่มีการกำหนดค่าใหม่แล้ว เมื่อคุณเล่นเสร็จแล้วให้เพิ่มคนอื่น ๆ ด้านล่างด้วย gather_facts และส่วนที่เหลือทั้งหมด

- name: determine ssh port
  hosts: all
  gather_facts: false
  vars:
    custom_ssh_port: 222
  tasks:
    - name: test default ssh port
      local_action: wait_for port=22 timeout=5 host={{inventory_hostname}}
      register: default_ssh
      ignore_errors: true
    - name: set ansible_ssh_port to default
      set_fact: ansible_ssh_port=22
      when: default_ssh.elapsed < 5
    - name: test ssh on high port
      local_action: wait_for port={{custom_ssh_port}} timeout=5 host={{inventory_hostname}}
      register: high_ssh
      when: default_ssh.elapsed >= 5
      ignore_errors: true
    - name: set ansible_ssh_port high
      set_fact: ansible_ssh_port={{custom_ssh_port}}
      when: default_ssh.elapsed >= 5 and high_ssh.elapsed < 5

มันชี้ให้ฉันเห็นว่านี่จะเป็นการระเบิดเวลาสำหรับ playbooks ที่คุณใช้สิ่งนี้ คุณยังสามารถตั้งค่า ansible_ssh_port ในส่วน vars ของการเล่นที่ควรรันบนโฮสต์ที่มีพอร์ต ssh ที่กำหนดค่าใหม่เท่านั้น เช่น

- name: change ssh ports
  tasks:
    - name: edit sshd_config
      lineinfile ..
      notify: restart ssh
   handlers:
     - name: restart ssh
       service: sshd state=restarted
- name: continue setup
  vars:
    - ansible_ssh_port : 5422
  tasks:
    ...

กลยุทธ์การทดสอบพอร์ตของคุณร่วมกับการตั้งค่าข้อเท็จจริงดูเหมือนเป็นวิธีที่ดีที่สุดสำหรับกรณีเหล่านี้ ขอบคุณ !!!
Jay Taylor

10

@RichardSalts ขอบคุณที่ให้ฉันเริ่มต้นด้วยสิ่งนี้ ฉันใช้ NC เพื่อตรวจสอบพอร์ตซึ่งควรจะเร็วกว่ามาก นี่คือ bootstrap.xml ของฉัน:

ผ่านการทดสอบโดยใช้ ansible 1.5 (devel 3b8fd62ff9) อัปเดตล่าสุด 2014/01/28 20:26:03

---
# Be sure to set the following variables for all hosts:
# vars:
#   oldsshport: 22
#   sshport: 555
# Might fail without setting remote_tmp = /tmp/ansible/$USER in your ansible.cfg. Also fix for directly below.
# Once host is setup most of the checks are skipped and works very quickly.
# Also, be sure to set non-standard shells in a different playbook later. Stick with /bin/bash until you can run apt install.
# Assumes root user has sshkey setup already. Not sure how to utilize the --ask-pass option. For now, use ssh-copy-id prior to running playbook on new host for root user (if needed).

# Test new ssh port
- name: ssh test nc {{ sshport }}
  local_action: shell nc -z -w5 {{ inventory_hostname }} {{ sshport }}
  register: nc_ssh_port
  failed_when: nc_ssh_port.stdout.find('failed') != -1
  changed_when: nc_ssh_port.stdout == ""
  ignore_errors: yes

# Set port to new port if connection success
- name: set ansible_ssh_port
  set_fact: ansible_ssh_port={{ sshport }}
  when: nc_ssh_port|success

# Fail back to old port if new ssh port fails
- name: ssh test nc port {{ oldsshport }}
  local_action: shell nc -z -w5 {{ inventory_hostname }} {{ oldsshport }}
  register: nc_ssh_default
  changed_when: nc_ssh_default.stdout == ""
  ignore_errors: yes
  when: nc_ssh_port|changed

# Set ansible to old port since new failed
- name: set ansible_ssh_port to {{ oldsshport }}
  set_fact: ansible_ssh_port={{ oldsshport }}
  when: nc_ssh_default|success and nc_ssh_port|changed

# Check if root user can ssh
- name: find user
  local_action: shell ssh -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=5 -p {{ ansible_ssh_port }} root@{{ inventory_hostname }} exit
  register: ssh_as_root
  failed_when: ssh_as_root.stdout.find('failed') != -1
  changed_when: ssh_as_root.stderr.find('Permission denied') == -1

# If root user success, set this up to change later
- name: first user
  set_fact: first_user={{ ansible_ssh_user }}
  when: ssh_as_root|changed

# Set ssh user to root
- name: root user
  set_fact: ansible_ssh_user=root
  when: ssh_as_root|changed

# ANSIBLE FIX: /tmp/ansible isn't world-writable for setting remote_tmp = /tmp/ansible/$USER in ansible.cfg
- name: /tmp/ansible/ directory exists with 0777 permission
  file: path=/tmp/ansible/ owner=root group=root mode=0777 recurse=no state=directory
  changed_when: False
  sudo: yes

# Setup user accounts
- include: users.yml

# Set ssh user back to default user (that was setup in users.yml)
- name: ansible_ssh_user back to default
  set_fact: ansible_ssh_user={{ first_user }}
  when: ssh_as_root|changed

# Reconfigure ssh with new port (also disables non-ssh key logins and disable root logins)
- name: sshd.conf
  template: src=sshd_config.j2 dest=/etc/ssh/sshd_config owner=root group=root mode=0644
  register: sshd_config
  sudo: yes

# Force changes immediately to ssh
- name: restart ssh
  service: name=ssh state=restarted
  when: sshd_config|changed
  sudo: yes

# Use updated ssh port
- name: set ansible_ssh_port
  set_fact: ansible_ssh_port={{ sshport }}
  when: nc_ssh_port|changed

5

เนื่องจากคุณอาจปรับใช้ ssh config ของคุณก่อนคุณควรทำให้ง่ายนี้ เพียงกำหนดค่าสินค้าคงคลังของคุณด้วยเป้าหมายansible_ssh_portและใช้-eเมื่อปรับใช้การกำหนดค่า ssh ของคุณเป็นครั้งแรก:

ansible-playbook bootstrap_ssh.yml -e 'ansible_ssh_port=22'

โปรดทราบว่าansible_ssh_portเลิกใช้แล้วใน 2.0 (ถูกแทนที่ด้วยansible_port)


3

เป็นไปได้หรือไม่ที่จะทำสิ่งนี้โดยอัตโนมัติโดยให้ Ansible fallback ไปยังพอร์ตที่ระบุหากไม่สามารถสร้างการเชื่อมต่อกับพอร์ต SSH เริ่มต้นได้

ฉันต้องการฟังก์ชั่นที่คล้ายกันดังนั้นฉันจึงรวบรวมและแก้ไขปลั๊กอิน Ansible ssh โดยหวังว่า Ansible Inc. จะปรับใช้มัน พวกเขาไม่ได้ มันทดสอบข้อมูลจำเพาะพอร์ตที่ไม่ใช่ std เพื่อดูว่าพวกเขาเปิดอยู่และเปลี่ยนกลับเป็นพอร์ต ssh เริ่มต้นหรือไม่ มันเป็นแพทช์ขนาดเล็กมากที่มีอยู่ในhttps://github.com/crlb/ansible


1

หากคุณมีรายการพอร์ตและคุณต้องการตรวจสอบพอร์ตทั้งหมดและใช้พอร์ตที่ใช้งานได้คุณสามารถใช้สิ่งนี้ใน playbook ของคุณ:

- name: just test
  hosts: server
  gather_facts: false
  vars:
    list_of_ssh_ports: [22, 222, 234]
  tasks:
    - name: test ssh on port
      sudo: no
      local_action: wait_for port={{item}} timeout=5 host={{inventory_hostname}}
      register: ssh_checks
      with_items: "{{list_of_ssh_ports}}"
      ignore_errors: true
    - debug: msg = "{{item}}"
      with_items: "{{ssh_checks.results}}"
    - name: set available ansible_ssh_port 
      sudo: no
      set_fact: ansible_ssh_port={{item.item}}
      when: ssh_checks is defined and {{item.elapsed}} < 5
      with_items: "{{ssh_checks.results}}"

0

ฉันมากับรายการงาน idempotent ที่มีประสิทธิภาพเพื่อกำหนดบทบาทในการเปลี่ยนพอร์ต SSH และจัดการการเชื่อมต่อกับพอร์ตที่ถูกต้องโดยไม่ต้องเปลี่ยนไฟล์คลังโฆษณาของคุณ ฉันโพสต์รายละเอียดในบล็อกของฉัน: https://dmsimard.com/2016/03/15/changing-the-ssh-port-with-ansible/


3
เราต้องการคำตอบที่มีเนื้อหาไม่ใช่ตัวชี้ไปยังเนื้อหาที่อาจสูญหายได้ง่าย
user9517 รองรับ GoFundMonica

นอกจากนี้สคริปต์ของคุณล้มเหลว default_ssh.state ก็มีข้อยกเว้น'dict object' has no attribute 'state'
sandre89
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.