diff --git a/roles/win_wg_spoke/README.md b/roles/win_wg_spoke/README.md new file mode 100644 index 0000000..b7ed32c --- /dev/null +++ b/roles/win_wg_spoke/README.md @@ -0,0 +1,49 @@ +win_wg_spoke +========= + +Configure windows hosts as a Spoke in the Wireguard Spoke-and-Hub topology. + +Requirements +------------ + +None + +Role Variables +-------------- + +None + +Dependencies +------------ + +ansible.windows + +Example Playbook +---------------- + +```yaml +roles: + - role: genlab.common.win_wg_spoke + win_wg_spoke_iface_name: wg0 + win_wg_spoke_subnet: "10.0.0.0" + win_wg_spoke_netmask: "24" + win_wg_spoke_ipv4_vpn: "10.0.0.1" + win_wg_spoke_port: "51820" + win_wg_spoke_pkey: eGqGx4A5ufFKatLflPFKNuzFgGuospIe08iPbTlEhm0= + win_wg_spoke_hub_pubkey: EvcoZ21/p0AHz5y95jwjVIR9puljc2kXqh/f3U1A4nk= + win_wg_spoke_psk: 5qmMuLuGQT7w8VnHPsZDO4vRF5wEKcpEtaCQW1BLmbg= # optional + win_wg_spoke_hub_ipv4_wan: "1.2.3.4" + win_wg_spoke_hub_port: "51820" + win_wg_spoke_dns_server: "10.0.0.254" # optional + win_wg_spoke_domain: "corp.local" # optional +``` + +License +------- + +BSD + +Author Information +------------------ + +malyuk.ss@genlab.llc diff --git a/roles/win_wg_spoke/defaults/main.yml b/roles/win_wg_spoke/defaults/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/win_wg_spoke/defaults/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/win_wg_spoke/handlers/main.yml b/roles/win_wg_spoke/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/win_wg_spoke/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/win_wg_spoke/meta/main.yml b/roles/win_wg_spoke/meta/main.yml new file mode 100644 index 0000000..3039a9f --- /dev/null +++ b/roles/win_wg_spoke/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: + role_name: "win_wg_spoke" + namespace: genlab + author: "Sergey Malyuk" + company: "Genlab, LLC" + description: "Configures wireguard spoke on windows" + license: "MIT" + min_ansible_version: "2.16" + + platforms: + - name: "Windows" + + galaxy_tags: [] + +dependencies: [] diff --git a/roles/win_wg_spoke/molecule/default/converge.yml b/roles/win_wg_spoke/molecule/default/converge.yml new file mode 100644 index 0000000..f6f0e46 --- /dev/null +++ b/roles/win_wg_spoke/molecule/default/converge.yml @@ -0,0 +1,9 @@ +--- +- name: Converge + hosts: all + pre_tasks: + # Blank task for ignoring CI testing + # This role was tested manually + - name: Blank + ansible.builtin.command: echo + changed_when: false diff --git a/roles/win_wg_spoke/molecule/default/molecule.yml b/roles/win_wg_spoke/molecule/default/molecule.yml new file mode 100644 index 0000000..de54042 --- /dev/null +++ b/roles/win_wg_spoke/molecule/default/molecule.yml @@ -0,0 +1,22 @@ +--- +dependency: + name: galaxy +driver: + name: docker +platforms: + - name: ubuntu + image: geerlingguy/docker-ubuntu2204-ansible:latest + pre_build_image: true + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true +provisioner: + name: ansible +verifier: + name: ansible +lint: | + set -e + yamllint . + ansible-lint . diff --git a/roles/win_wg_spoke/molecule/default/verify.yml b/roles/win_wg_spoke/molecule/default/verify.yml new file mode 100644 index 0000000..da5d2ff --- /dev/null +++ b/roles/win_wg_spoke/molecule/default/verify.yml @@ -0,0 +1,11 @@ +--- + +- name: Verify + hosts: all + gather_facts: false + tasks: + # Blank task for ignoring CI testing + # This role was tested manually + - name: Blank + ansible.builtin.command: echo + changed_when: false diff --git a/roles/win_wg_spoke/tasks/main.yml b/roles/win_wg_spoke/tasks/main.yml new file mode 100644 index 0000000..c44169b --- /dev/null +++ b/roles/win_wg_spoke/tasks/main.yml @@ -0,0 +1,50 @@ +--- +- name: Get wireguard binary stat + ansible.windows.win_stat: + path: C:\Program Files\WireGuard\wireguard.exe + register: win_wg_spoke_binary_stat + +- name: Assert wireguard is installed + ansible.builtin.assert: + that: win_wg_spoke_binary_stat.stat.exists + success_msg: Wireguard IS installed + fail_msg: Wireguard IS NOT installed + +- name: Check config changes or existance + block: + - name: Ensure WireGuard config directory exists + ansible.windows.win_file: + path: C:\Program Files\Wireguard\configs + state: directory + + - name: Deploy WireGuard config + ansible.windows.win_template: + src: wg.conf.j2 + dest: "C:\\Program Files\\Wireguard\\configs\\{{ win_wg_spoke_iface_name }}.conf" + register: win_wg_spoke_config_deploy_result + + - name: Ensure no changes in wireguard config were made + ansible.builtin.assert: + that: not win_wg_spoke_config_deploy_result.changed + success_msg: No changes were made in wireguard config + fail_msg: Wireguard config HAS CHANGED or NEVER BEEN CREATED + + rescue: + - name: Allow PostUp and PostDown in wireguard configs + when: win_wg_spoke_dns_server is defined and win_wg_spoke_domain is defined # PostUp and PostDown are used for dns splitting + ansible.windows.win_regedit: + path: HKLM:\Software\WireGuard + name: DangerousScriptExecution + data: 1 + type: dword + state: present + + - name: Install WireGuard tunnel service + ansible.windows.win_shell: | + & "C:\Program Files\Wireguard\wireguard.exe" /installtunnelservice "C:\Program Files\Wireguard\configs\{{ win_wg_spoke_iface_name }}.conf" + + - name: Ensure WireGuard service is running + ansible.windows.win_service: + name: "WireGuardTunnel${{ win_wg_spoke_iface_name }}" + start_mode: auto + state: started diff --git a/roles/win_wg_spoke/templates/wg.conf.j2 b/roles/win_wg_spoke/templates/wg.conf.j2 new file mode 100644 index 0000000..995e03a --- /dev/null +++ b/roles/win_wg_spoke/templates/wg.conf.j2 @@ -0,0 +1,18 @@ +[Interface] # Local settings for this node +Address = {{ win_wg_spoke_ipv4_vpn }}/32 +ListenPort = {{ win_wg_spoke_port }} +PrivateKey = {{ win_wg_spoke_pkey }} + +{% if win_wg_spoke_dns_server is defined and win_wg_spoke_domain is defined %} +PostUp = powershell.exe -Command "& { Add-DnsClientNrptRule -Comment '{{ win_wg_spoke_iface_name }}-wg' -Namespace '.{{ win_wg_spoke_domain }}' -NameServers {{ win_wg_spoke_dns_server }} }" +PostDown = powershell.exe -Command "& { Get-DnsClientNrptRule | where Comment -eq '{{ win_wg_spoke_iface_name }}-wg' | foreach { Remove-DnsClientNrptRule -Name $_.Name -Force } }" +{% endif %} + +[Peer] # Settings for the Hub peer +PublicKey = {{ win_wg_spoke_hub_pubkey }} +{% if win_wg_spoke_psk is defined %} +PresharedKey = {{ win_wg_spoke_psk }} +{% endif %} +AllowedIPs = {{ win_wg_spoke_subnet }}/{{ win_wg_spoke_netmask }} +Endpoint = {{ win_wg_spoke_hub_ipv4_wan }}:{{ win_wg_spoke_hub_port }} +PersistentKeepalive = 20 \ No newline at end of file diff --git a/roles/win_wg_spoke/vars/main.yml b/roles/win_wg_spoke/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/win_wg_spoke/vars/main.yml @@ -0,0 +1 @@ +---