Skip to content

Commit

Permalink
implemented carp-vip dependency for wireguard-servers (fix #43)
Browse files Browse the repository at this point in the history
  • Loading branch information
ansibleguy committed Jan 1, 2024
1 parent 353cef6 commit a3d6f27
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 15 deletions.
29 changes: 16 additions & 13 deletions docs/source/modules/wireguard.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ For basic parameters see: [Basics](https://opnsense.ansibleguy.net/en/latest/usa

### ansibleguy.opnsense.wireguard_server

| Parameter | Type | Required | Default value | Aliases | Comment |
|:---------------|:--------|:---------|:--------------|:---------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | string | true | - | - | The unique name of the local WireGuard server instance |
| peers | list | false | - | clients | List of existing peers that |
| allowed_ips | list | false | - | tunnel_ips, tunnel_ip, tunneladdress, tunnel_adresses, tunnel_address, addresses, address, allowed | One or multiple IP addresses that are used inside the tunnel |
| public_key | string | false | - | pubkey, pub | Optionally provide an existing WireGuard Public Key. If none is provided - a key-pair will be generated automatically or the existing one will be used. |
| private_key | string | false | - | privkey, priv | Optionally provide an existing WireGuard Private Key. If none is provided - a key-pair will be generated automatically or the existing one will be used. |
| port | integer | false | - | - | Optionally provide a port for the server instance. Needed if dynamic peers will connect to this instance! |
| mtu | integer | false | 1420 | - | Integer between 1 and 9300 |
| dns_servers | list | false | - | dns | List of DNS servers that will be used to resolve peer endpoint-names |
| disable_routes | boolean | false | false | disableroutes | If automatically created routes should be disabled. Needs to be set if you want to use [policy-based routing](https://docs.opnsense.org/manual/firewall.html#policy-based-routing), [dynamic routing](https://docs.opnsense.org/manual/dynamic_routing.html) or 'manually' created static routes |
| gateway | string | false | - | gw | IP address to use as gateway. Can only be used if you enable the 'disable_routes' option. |
| reload | boolean | false | true | - | If the running config should be reloaded on change - this will take some time. For mass-managing items you might want to reload it 'manually' after all changes are done => using the [reload module](https://opnsense.ansibleguy.net/en/latest/modules/2_reload.html). |
| Parameter | Type | Required | Default value | Aliases | Comment |
|:---------------|:--------|:---------|:--------------|:------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | string | true | - | - | The unique name of the local WireGuard server instance |
| peers | list | false | - | clients | List of existing peers that |
| allowed_ips | list | false | - | tunnel_ips, tunnel_ip, tunneladdress, tunnel_adresses, tunnel_address, addresses, address, allowed | One or multiple IP addresses that are used inside the tunnel |
| public_key | string | false | - | pubkey, pub | Optionally provide an existing WireGuard Public Key. If none is provided - a key-pair will be generated automatically or the existing one will be used. |
| private_key | string | false | - | privkey, priv | Optionally provide an existing WireGuard Private Key. If none is provided - a key-pair will be generated automatically or the existing one will be used. |
| port | integer | false | - | - | Optionally provide a port for the server instance. Needed if dynamic peers will connect to this instance! |
| mtu | integer | false | 1420 | - | Integer between 1 and 9300 |
| dns_servers | list | false | - | dns | List of DNS servers that will be used to resolve peer endpoint-names |
| disable_routes | boolean | false | false | disableroutes | If automatically created routes should be disabled. Needs to be set if you want to use [policy-based routing](https://docs.opnsense.org/manual/firewall.html#policy-based-routing), [dynamic routing](https://docs.opnsense.org/manual/dynamic_routing.html) or 'manually' created static routes |
| gateway | string | false | - | gw | IP address to use as gateway. Can only be used if you enable the 'disable_routes' option. |
| vip | string | false | - | vip_depend, carp, carp_depend | The Virtual-CARP-IP (CARP VHID) to depend on. When this virtual address is not in master state, then the instance will be shutdown |
| reload | boolean | false | true | - | If the running config should be reloaded on change - this will take some time. For mass-managing items you might want to reload it 'manually' after all changes are done => using the [reload module](https://opnsense.ansibleguy.net/en/latest/modules/2_reload.html). |

### ansibleguy.opnsense.wireguard_peer

Expand Down Expand Up @@ -198,6 +199,7 @@ To make a dynamic WireGuard endpoint to re-connect you may want to create a [gat
# mtu: 1420
# dns_servers: []
# disable_routes: false
# vip: ''
# gateway: ''
# enabled: true
# debug: false
Expand All @@ -210,6 +212,7 @@ To make a dynamic WireGuard endpoint to re-connect you may want to create a [gat
allowed_ips: ['10.200.0.1/32']
peers: ['peer1']
port: 51820
vip: '192.168.2.1'

- name: Disabling server
ansibleguy.opnsense.wireguard_server:
Expand Down
39 changes: 37 additions & 2 deletions plugins/module_utils/main/wireguard_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ class Server(BaseModule):
'del': 'delServer',
'set': 'setServer',
'search': 'get',
'detail': 'getServer',
'toggle': 'toggleserver',
}
API_KEY_PATH = 'server.servers.server'
API_KEY = 'server'
API_KEY_PATH = f'server.servers.{API_KEY}'
API_MOD = 'wireguard'
API_CONT = 'server'
API_CONT_REL = 'service'
API_CMD_REL = 'reconfigure'
FIELDS_CHANGE = [
'public_key', 'private_key', 'port', 'mtu', 'dns_servers', 'allowed_ips',
'disable_routes', 'gateway', 'peers',
'disable_routes', 'gateway', 'peers', 'vip',
]
FIELDS_ALL = [FIELD_ID, 'enabled']
FIELDS_ALL.extend(FIELDS_CHANGE)
Expand All @@ -35,11 +37,13 @@ class Server(BaseModule):
'private_key': 'privkey',
'allowed_ips': 'tunneladdress',
'disable_routes': 'disableroutes',
'vip': 'carp_depend_on',
}
FIELDS_TYPING = {
'bool': ['enabled', 'disable_routes'],
'list': ['dns_servers', 'allowed_ips', 'peers'],
'int': ['port', 'mtu', 'instance'],
'select' : ['vip'],
}
FIELDS_DIFF_EXCLUDE = ['private_key']
INT_VALIDATIONS = {
Expand All @@ -54,6 +58,7 @@ def __init__(self, module: AnsibleModule, result: dict, session: Session = None)
BaseModule.__init__(self=self, m=module, r=result, s=session)
self.server = {}
self.existing_peers = None
self.existing_vips = {}

def check(self) -> None:
if self.p['state'] == 'present':
Expand Down Expand Up @@ -99,6 +104,9 @@ def check(self) -> None:

if self.p['state'] == 'present':
self.p['peers'] = self._find_peers()
if not is_unset(self.p['vip']):
self.p['vip'] = self._find_vip()

self.r['diff']['after'] = self.b.build_diff(data=self.p)

def _find_peers(self) -> list:
Expand All @@ -121,3 +129,30 @@ def _find_peers(self) -> list:
peers.append(existing[peer])

return peers

def _find_vip(self) -> str:
# "[192.168.1.1] on opt1 (vhid 1)"
search_vip = f"[{self.p['vip']}]"
existing_vips = []

for uuid, values in self.existing_vips.items():
if values['value'].find(search_vip) != -1:
return uuid

if values['value'].find('[') != -1:
existing_vips.append(values['value'].split('[', 1)[1].split(']')[0])

self.m.fail_json(f"Provided VIP '{self.p['vip']}' was not found! Existing ones: {existing_vips}")

def _search_call(self) -> list:
raw = self.b.search()
if len(raw) > 0:
self.existing_vips = raw[list(raw.keys())[0]][self.FIELDS_TRANSLATE['vip']]

if len(raw) == 0:
self.existing_vips = self.s.get(cnf={
**self.call_cnf,
'command': self.CMDS['detail'],
})[self.API_KEY][self.FIELDS_TRANSLATE['vip']]

return raw
6 changes: 6 additions & 0 deletions plugins/modules/wireguard_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ def run_module():
),
disable_routes=dict(type='bool', default=False, required=False, aliases=['disableroutes']),
gateway=dict(type='str', required=False, default='', aliases=['gw']),
vip=dict(
type='str', required=False, default='',
aliases=['vip_depend', 'carp', 'carp_depend'],
description='The Virtual-CARP-IP (CARP VHID) to depend on. '
'When this virtual address is not in master state, then the instance will be shutdown'
),
peers=dict(type='list', elements='str', required=False, default=[], aliases=['clients']),
**RELOAD_MOD_ARG,
**STATE_MOD_ARG,
Expand Down
2 changes: 2 additions & 0 deletions tests/cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@
loop:
- 'ANSIBLE_TEST_1_1'
- 'ANSIBLE_TEST_1_2'
- 'ANSIBLE_TEST_1_3'
- 'ANSIBLE_TEST_1_4'

- name: Cleanup wireguard peers
ansibleguy.opnsense.wireguard_peer:
Expand Down
55 changes: 55 additions & 0 deletions tests/wireguard_server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@
register: opn20
failed_when: not opn20.failed

- name: Adding 1 - failing because of non-existent CARP-VIP
ansibleguy.opnsense.wireguard_server:
name: 'ANSIBLE_TEST_1_1'
allowed_ips: ['192.168.0.1']
private_key: "{{ test.priv1 }}"
public_key: "{{ test.pub1 }}"
vip: '192.168.3.1'
register: opn24
failed_when: not opn24.failed

- name: Adding 1
ansibleguy.opnsense.wireguard_server:
name: 'ANSIBLE_TEST_1_1'
Expand Down Expand Up @@ -232,6 +242,43 @@
opn16.changed
when: not ansible_check_mode

- name: Adding dummy CARP-VIP
ansibleguy.opnsense.interface_vip:
interface: 'opt1'
address: '192.168.2.1/24'
mode: 'carp'
vhid: 10
password: 'top_secret'
when: not ansible_check_mode

- name: Adding 4 - linked to CARP-VIP
ansibleguy.opnsense.wireguard_server:
name: 'ANSIBLE_TEST_1_4'
allowed_ips: ['192.168.3.1']
public_key: "{{ test.pub2 }}"
private_key: "{{ test.priv2 }}"
peers: ['ANSIBLE_TEST_2_1']
vip: '192.168.2.1'
register: opn21
failed_when: >
opn21.failed or
not opn21.changed
when: not ansible_check_mode

- name: Adding 4 - nothing changed
ansibleguy.opnsense.wireguard_server:
name: 'ANSIBLE_TEST_1_4'
allowed_ips: ['192.168.3.1']
public_key: "{{ test.pub2 }}"
private_key: "{{ test.priv2 }}"
peers: ['ANSIBLE_TEST_2_1']
vip: '192.168.2.1'
register: opn22
failed_when: >
opn22.failed or
opn22.changed
when: not ansible_check_mode

- name: Cleanup
ansibleguy.opnsense.wireguard_server:
name: "{{ item }}"
Expand All @@ -240,6 +287,7 @@
- 'ANSIBLE_TEST_1_1'
- 'ANSIBLE_TEST_1_2'
- 'ANSIBLE_TEST_1_3'
- 'ANSIBLE_TEST_1_4'
when: not ansible_check_mode

- name: Cleanup peer
Expand All @@ -248,6 +296,13 @@
state: 'absent'
when: not ansible_check_mode

- name: Cleanup VIP
ansibleguy.opnsense.interface_vip:
interface: 'opt1'
address: '192.168.2.1/24'
state: 'absent'
when: not ansible_check_mode

- name: Listing
ansibleguy.opnsense.list:
register: opn2
Expand Down

0 comments on commit a3d6f27

Please sign in to comment.