Come gestire le modifiche alla porta SSH con Ansible?


27

Sto cercando di utilizzare Ansible per automatizzare il processo di installazione di nuove istanze del server. Una delle attività di installazione modifica la porta SSH predefinita, pertanto mi richiede di aggiornare l'elenco degli host.

È possibile automatizzare ciò avendo Ansible fallback su una porta specificata se non è stato possibile stabilire la connessione alla porta SSH predefinita?

Risposte:


15

Potresti provare una local_action sugli host per vedere se riesci a connetterti alle rispettive porte e registrare quella che ha successo e impostarla come un dato di fatto. Si desidera disattivare la raccolta dei dati poiché in caso contrario il modulo di installazione non riuscirà quando si tenta di connettersi con gli host che sono già stati riconfigurati. Una volta terminato questo gioco, aggiungine altri di seguito con gather_facts e tutto il resto.

- 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

Mi è stato fatto notare che questo farà esplodere il tempo per i playbook in cui lo usi. È inoltre possibile impostare ansible_ssh_port nella sezione vars delle riproduzioni che dovrebbe essere eseguita solo su host con porta ssh riconfigurata. per esempio

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

La tua strategia di port testing insieme alla definizione dei fatti sembra un approccio ideale per questi casi. Grazie!!!
Jay Taylor,

10

@RichardSalts grazie per avermi iniziato con questo. Ho usato nc per controllare le porte che dovrebbero essere molto più veloci. Questo è il mio bootstrap.xml:

Testato utilizzando ansible 1.5 (devel 3b8fd62ff9) ultimo aggiornamento 28/01/2014 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

Dal momento che probabilmente distribuisci la tua configurazione ssh in anticipo, dovresti davvero mantenerlo semplice. Configura il tuo inventario con il target ansible_ssh_porte utilizzalo -equando distribuisci la tua configurazione ssh per la prima volta:

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

Si noti che ansible_ssh_portè deprecato in 2.0 (sostituito da ansible_port)


3

È possibile automatizzare ciò avendo Ansible fallback su una porta specificata se non è stato possibile stabilire la connessione alla porta SSH predefinita?

Avevo anche bisogno di funzionalità simili, quindi ho biforcato e patchato il plugin Ansible ssh sperando che Ansible Inc. lo adottasse; non lo fecero. Verifica le specifiche della porta ssh non standard per vedere se sono aperte e, in caso contrario, ripristina la porta ssh predefinita. È una patch molto piccola, disponibile su https://github.com/crlb/ansible .


1

Se hai un elenco di porte e vuoi controllarle tutte e utilizzarne una funzionante, puoi usarla nel tuo 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

Ho creato un robusto elenco di attività idempotenti per ricoprire un ruolo per cambiare la porta SSH e gestire la connessione alla porta giusta senza dover modificare il file di inventario. Ho pubblicato i dettagli sul mio blog: https://dmsimard.com/2016/03/15/changing-the-ssh-port-with-ansible/


3
Preferiamo davvero che le risposte contengano contenuti piuttosto che puntatori a contenuti che possono essere facilmente persi.
user9517 supporta GoFundMonica il

Anche lo script non riesce, default_ssh.state solleva un'eccezione'dict object' has no attribute 'state'
sandre89,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.