Add windows role
Set up network interfaces and SSH for Windows hosts. We can’t gather facts before we know which remote shell to use, so first run a win_ping to determine if a given host is running Windows.
This commit is contained in:
parent
aa78b407c8
commit
91de26af57
7 changed files with 123 additions and 21 deletions
|
@ -1,3 +1,30 @@
|
||||||
|
# Read secrets and keys.
|
||||||
|
- name: Get SSH keys
|
||||||
|
delegate_to: localhost
|
||||||
|
check_mode: false
|
||||||
|
run_once: true
|
||||||
|
block:
|
||||||
|
- name: Get GPG key IDs
|
||||||
|
shell: cat ${PASSWORD_STORE_DIR:-~/.password-store}/.gpg-id
|
||||||
|
changed_when: false
|
||||||
|
register: gpg_ids
|
||||||
|
|
||||||
|
- name: Export public SSH keys
|
||||||
|
shell: echo "$(gpg --export-ssh-key {{ item }} | cut -d ' ' -f 1,2) $(gpg --list-keys --with-colons {{ item }} | sed -n 's@uid:.*<\(.*\)>.*@\1@p')"
|
||||||
|
loop: '{{ gpg_ids.stdout_lines }}'
|
||||||
|
changed_when: false
|
||||||
|
register: ssh_export
|
||||||
|
|
||||||
|
- name: Set SSH keys to deploy on servers
|
||||||
|
set_fact:
|
||||||
|
ssh_keys: '{{ ssh_export.results | map(attribute="stdout") }}'
|
||||||
|
failed_when: not ssh_keys # something must be terribly wrong so let’s not lock everyone out
|
||||||
|
|
||||||
|
- name: Get passwords
|
||||||
|
delegate_to: localhost
|
||||||
|
set_fact:
|
||||||
|
password: '{{ lookup("passwordstore", ("vm/" if is_virtual else "host/")~inventory_hostname, returnall=true, missing="empty") | from_yaml }}'
|
||||||
|
|
||||||
# Make expensive lookups to NetBox once for later reference by any host.
|
# Make expensive lookups to NetBox once for later reference by any host.
|
||||||
- when: lookup("env", "NETBOX_API") != ""
|
- when: lookup("env", "NETBOX_API") != ""
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
|
@ -22,28 +49,25 @@
|
||||||
cluster_services: '{{ (cluster_services|default([])) + query("netbox.netbox.nb_lookup", "services", raw_data=true, api_filter="id="+item) }}'
|
cluster_services: '{{ (cluster_services|default([])) + query("netbox.netbox.nb_lookup", "services", raw_data=true, api_filter="id="+item) }}'
|
||||||
loop: '{{ cluster.custom_fields.services | map(attribute="id") | map("string") }}'
|
loop: '{{ cluster.custom_fields.services | map(attribute="id") | map("string") }}'
|
||||||
|
|
||||||
- name: Fetch passwords
|
# Set host-specific connection parameters.
|
||||||
|
- name: Set SSH connection username
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
set_fact:
|
set_fact:
|
||||||
password: '{{ lookup("passwordstore", ("vm/" if is_virtual else "host/")~inventory_hostname, returnall=true, missing="empty") | from_yaml }}'
|
ansible_ssh_user: "{{ password.user }}"
|
||||||
|
when: password.user is defined
|
||||||
|
|
||||||
- name: Get SSH keys
|
- name: Check if the host is running Windows
|
||||||
delegate_to: localhost
|
win_ping:
|
||||||
check_mode: false
|
vars:
|
||||||
run_once: true
|
ansible_shell_type: powershell
|
||||||
block:
|
failed_when: false
|
||||||
- name: Get GPG key IDs
|
ignore_errors: true
|
||||||
shell: cat ${PASSWORD_STORE_DIR:-~/.password-store}/.gpg-id
|
ignore_unreachable: true
|
||||||
changed_when: false
|
register: result
|
||||||
register: gpg_ids
|
|
||||||
|
|
||||||
- name: Export public SSH keys
|
- name: Set connection parameters for Windows
|
||||||
shell: echo "$(gpg --export-ssh-key {{ item }} | cut -d ' ' -f 1,2) $(gpg --list-keys --with-colons {{ item }} | sed -n 's@uid:.*<\(.*\)>.*@\1@p')"
|
|
||||||
loop: '{{ gpg_ids.stdout_lines }}'
|
|
||||||
changed_when: false
|
|
||||||
register: ssh_export
|
|
||||||
|
|
||||||
- name: Set SSH keys to deploy on servers
|
|
||||||
set_fact:
|
set_fact:
|
||||||
ssh_keys: '{{ ssh_export.results | map(attribute="stdout") }}'
|
ansible_shell_type: powershell
|
||||||
failed_when: not ssh_keys # something must be terribly wrong so let’s not lock everyone out
|
ansible_become_method: runas
|
||||||
|
ansible_become_flags: ""
|
||||||
|
when: result.ping|default("") == "pong"
|
||||||
|
|
3
roles/windows/README.md
Normal file
3
roles/windows/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Set up a generic Windows host.
|
||||||
|
|
||||||
|
Rename and configure network interfaces. Configure the SSH server.
|
5
roles/windows/handlers/main.yml
Normal file
5
roles/windows/handlers/main.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- name: restart sshd
|
||||||
|
win_service:
|
||||||
|
name: sshd
|
||||||
|
state: restarted
|
||||||
|
when: "'handler' not in ansible_skip_tags"
|
12
roles/windows/tasks/interface.yml
Normal file
12
roles/windows/tasks/interface.yml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
- name: Rename interface
|
||||||
|
win_shell: >
|
||||||
|
Get-NetAdapter
|
||||||
|
| Where-Object -Property MacAddress -eq "{{ interface.mac_address | replace(':', '-') }}"
|
||||||
|
| Rename-NetAdapter -NewName "{{ interface.name }}"
|
||||||
|
changed_when: false # not really but we don’t care
|
||||||
|
|
||||||
|
- include_tasks: interface_address.yml
|
||||||
|
loop: "{{ interface.ip_addresses }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ interface.name }}"
|
||||||
|
loop_var: address
|
22
roles/windows/tasks/interface_address.yml
Normal file
22
roles/windows/tasks/interface_address.yml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
- name: Add IP address
|
||||||
|
win_shell: >
|
||||||
|
New-NetIPAddress -InterfaceAlias {{ interface.name }}
|
||||||
|
-AddressFamily IPv{{ address.family.value }}
|
||||||
|
-IPAddress "{{ address.address | ipaddr("address") }}" -PrefixLength {{ address.address | ipaddr("prefix") }}
|
||||||
|
register: result
|
||||||
|
changed_when: "not result.stderr or 'Instance MSFT_NetIPAddress already exists' not in result.stderr"
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
prefix: "{{ prefixes | selectattr('prefix', '==', address.address|ipaddr('subnet')) | first }}"
|
||||||
|
|
||||||
|
- name: Set gateway
|
||||||
|
when: address.family.value == 4 and prefix.custom_fields.gateway
|
||||||
|
win_shell: >
|
||||||
|
New-NetRoute -InterfaceAlias {{ interface.name }}
|
||||||
|
-AddressFamily IPv{{ address.family.value }}
|
||||||
|
-DestinationPrefix {{ "0.0.0.0/0" if address.family.value == 4 else "::/0" }}
|
||||||
|
-NextHop {{ prefix.custom_fields.gateway.address | ipaddr("address") }}
|
||||||
|
register: result
|
||||||
|
changed_when: "not result.stderr or 'Instance MSFT_NetRoute already exists' not in result.stderr"
|
||||||
|
failed_when: false
|
35
roles/windows/tasks/main.yml
Normal file
35
roles/windows/tasks/main.yml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
- include_tasks: interface.yml
|
||||||
|
loop: "{{ interfaces }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ interface.name }}"
|
||||||
|
loop_var: interface
|
||||||
|
|
||||||
|
- name: Disable SSH password authentication
|
||||||
|
win_lineinfile:
|
||||||
|
path: c:\ProgramData\ssh\sshd_config
|
||||||
|
regexp: '^#?{{ item.key }}'
|
||||||
|
line: "{{ item.key }} {{ item.value }}"
|
||||||
|
loop:
|
||||||
|
- key: "PasswordAuthentication"
|
||||||
|
value: "no"
|
||||||
|
- key: "PermitRootLogin"
|
||||||
|
value: "prohibit-password"
|
||||||
|
notify: restart sshd
|
||||||
|
|
||||||
|
- name: Set default shell to powershell
|
||||||
|
win_regedit:
|
||||||
|
path: HKLM:\SOFTWARE\OpenSSH
|
||||||
|
name: DefaultShell
|
||||||
|
data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
|
||||||
|
notify: restart sshd
|
||||||
|
|
||||||
|
- name: Set authorized SSH keys
|
||||||
|
win_copy:
|
||||||
|
dest: C:\ProgramData\ssh\administrators_authorized_keys
|
||||||
|
content: "{{ ssh_keys | join('\n') }}"
|
||||||
|
|
||||||
|
- name: Enable ssh
|
||||||
|
win_service:
|
||||||
|
name: sshd
|
||||||
|
start_mode: auto
|
||||||
|
state: started
|
|
@ -8,6 +8,7 @@
|
||||||
roles:
|
roles:
|
||||||
- { role: alpine, when: ansible_distribution == 'Alpine' }
|
- { role: alpine, when: ansible_distribution == 'Alpine' }
|
||||||
- { role: debian, when: ansible_distribution == 'Debian' }
|
- { role: debian, when: ansible_distribution == 'Debian' }
|
||||||
|
- { role: windows, when: ansible_os_family == 'Windows' }
|
||||||
|
|
||||||
# hosts
|
# hosts
|
||||||
- hosts: mgmt-gw
|
- hosts: mgmt-gw
|
||||||
|
|
Loading…
Reference in a new issue