Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Auto generate keys #2

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 113 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@ The role should be self-contained, just provide vars for your hosts and run it.
Role Variables
--------------

### `wireguard_networks`
### `wireguard_manage_keys`

Each host needs to have `wireguard_networks` variable set. It should be a list of WireGuard interface name the host should use, by default it is an empty list. For each `$INTERFACE` specified here the host should have `wireguard_$INTERFACE_interface` and `wireguard_$INTERFACE_peers` vars set.
If `True` ansible automatically generated public and private pair keys. Default `False`.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ansible automatically generated/will automatically generate/


### `wireguard_$INTERFACE_interface`
### `wireguard_interfaces`

Each host needs to have `wireguard_interfaces` variable set. It should be a list of WireGuard interface name the host should use, by default it is an empty list. For each `$INTERFACE` specified here the host should have:
```
wireguard_interface:
$INTERFACE:
key: value
```
and
```
wireguard_peers:
$INTERFACE:
key: value
```
vars set.

### `wireguard_interface: $INTERFACE`

This variable allows configuring the WireGuard interface on the host. It is a dict and the following keys are taken into account:

Expand All @@ -38,7 +54,7 @@ Other configurable things:

These options can be configured for an interface but are unset by default, refer to `wg(8)` and `wg-quick(8)` manpages for their meaning.

### `wireguard_$INTERFACE_peers`
### `wireguard_peers: $INTERFACE`

A hash configuring the host's peers in the form of `peer_name: { ... peer_configuration ... }`.

Expand All @@ -54,8 +70,9 @@ A hash configuring the host's peers in the form of `peer_name: { ... peer_config
Example:

```yaml
wireguard_wg0_peers:
- fugu:
wireguard_peers:
wg0:
fugu:
public_key: 12345
allowed_ips: 10.0.0.0/16
```
Expand All @@ -65,48 +82,54 @@ Dependencies

None.

Example
-------
Examples
--------

### If wireguard_manage_keys is `False`
Star topology (multiple clients connecting to each other through one central server).

```yaml
# host_vars/someserver.yml
wireguard_wg0_interface:
address: 10.0.0.1/16
private_key: someserver_private_key
listen_port: 12345

wireguard_wg0_peers:
client1:
public_key: client1_public_key
allowed_ips: 10.0.0.11/32
client2:
public_key: client2_public_key
allowed_ips: 10.0.0.12/32
wireguard_interface:
wg0:
address: 10.0.0.1/16
private_key: someserver_private_key
listen_port: 12345

wireguard_peers:
wg0:
client1:
public_key: client1_public_key
allowed_ips: 10.0.0.11/32
client2:
public_key: client2_public_key
allowed_ips: 10.0.0.12/32
```

```yaml
# group_vars/client.yml
wireguard_wg0_peers:
someserver:
public_key: someserver_public_key
endpoint: someserver.example.com:12345
allowed_ips: 10.0.0.1/16
wireguard_peers:
wg0:
someserver:
public_key: someserver_public_key
endpoint: someserver.example.com:12345
allowed_ips: 10.0.0.1/16
```

```yaml
# host_vars/client1.yml
wireguard_wg0_interface:
address: 10.0.0.11/16
private_key: client1_private_key
wireguard_interface:
wg0:
address: 10.0.0.11/16
private_key: client1_private_key
```

```yaml
# host_vars/client2.yml
wireguard_wg0_interface:
address: 10.0.0.12/16
private_key: client2_private_key
wireguard_interface:
wg0:
address: 10.0.0.12/16
private_key: client2_private_key
```

```
Expand All @@ -128,6 +151,65 @@ client2
- wireguard
```

### If wireguard_manage_keys is `True`
All hosts is servers and clients (peer2peer).

```yaml
# group_vars/all.yml
wireguard_listen_port: 5888
wireguard_wg0_preshared_key: secret_preshared_key
wireguard_wg0_peer_settings: >
{% set _peers = {} -%}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know one could do jinja templating within host/group vars files. Could you point me to docs where this is described?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not find a direct indication in the official documentation. But here is a link to changing variables using the filters https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#transforming-variables-with-jinja2-filters
and a links to the possibility of using a jean in the values ​​of variables:
https://groups.google.com/forum/m/#!topic/ansible-project/ZDz-8tcsdTA

Probably, I can transfer this part of the code to the template, but this can lead to loss of flexibility in the settings. In any case, I'll think about how to improve the code. If you have any suggestions, I will be glad to hear them.
P.S. Sorry for the delay in response, I was on vacation.
P.P.S. This PR is an attempt to combine the functionality of your role and this role https://github.com/mawalu/wireguard-private-networking

{%- for node in groups['all'] | map('extract', hostvars) -%}
{%- if (node['wg0_ipv4'] is defined and inventory_hostname != node['inventory_hostname']) -%}
{%- set _data = {} -%}
{%- set _endpoint_data = [] -%}
{{- _endpoint_data.append(node.ip_v4) -}}
{{- _endpoint_data.append(wireguard_listen_port) -}}
{%- set _endpoint = _endpoint_data | join(':') -%}
{%- set x=_data.__setitem__('public_key', node.public_wg0.content | b64decode | trim) -%}
{%- set x=_data.__setitem__('allowed_ips', node.wg0_ipv4) -%}
{%- set x=_data.__setitem__('preshared_key', wireguard_wg0_preshared_key) -%}
{%- set x=_data.__setitem__('endpoint', _endpoint) -%}
{%- set x=_peers.__setitem__(node['inventory_hostname'], _data) -%}
{%- endif -%}
{%- endfor -%}
{{- _peers }}

wireguard_manage_keys: True
wireguard_manage_services: True
wireguard_interfaces:
- wg0

wireguard_peers:
wg0: "{{ wireguard_wg0_peer_settings }}"

wireguard_interface:
wg0:
address: "{{ wg0_ipv4 }}"
private_key: "{{ private_wg0.content | b64decode | trim }}"
listen_port: "{{ wireguard_listen_port }}"
```

```
# inventory file
[wireguard-servers]
server1 wg0_ipv4=10.0.0.1/32
server2 wg0_ipv4=10.0.0.2/32
server3 wg0_ipv4=10.0.0.3/32
```

```yaml
# playbook.yml
- hosts: all
vars:
wireguard_interfaces:
- wg0
roles:
- wireguard
```


Supported platforms
-------------------

Expand Down
52 changes: 29 additions & 23 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
---
wireguard_manage_services: true
wireguard_networks: []
# wireguard_networks:
wireguard_manage_keys: False
wireguard_manage_services: True

wireguard_interfaces: []
# wireguard_interfaces:
# - wg0
# wireguard_wg0_peers:
# - foobar:
# public_key:
# allowed_ips:
# # endpoint:
# # preshared_key:
# # persistent_keepalive:
wireguard_peers: {}
# wireguard_peers:
# wg0:
# - foobar:
# public_key:
# allowed_ips:
# #endpoint:
# #preshared_key:
# #persistent_keepalive:

# wireguard_wg0_interface:
# address:
# private_key:
# # listen_port:
# # fw_mark:
# # dns: []
# # MTU:
# # Table:
# # pre_up: []
# # post_up: []
# # pre_down: []
# # post_down: []
# # save_config:
wireguard_interface: {}
# wireguard_interface:
# wg0:
# address:
# private_key:
# #listen_port:
# #fw_mark:
# #dns: []
# #mtu:
# #table:
# #pre_up: []
# #post_up: []
# #pre_down: []
# #post_down: []
# #save_config:

25 changes: 25 additions & 0 deletions tasks/configure_network.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
---
- name: Read private key {{ item }}
stat:
path: "/etc/wireguard/privatekey_{{ item }}"
register: privatekey_{{ item }}
when: wireguard_manage_keys

- name: Generate wireguard keys {{ item }}
shell: "umask 077; wg genkey | tee /etc/wireguard/privatekey_{{ item }} | wg pubkey > /etc/wireguard/publickey_{{ item }}"
when:
- not privatekey_{{ item }}.stat.exists
- wireguard_manage_keys
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to swap these two to have it work with wireguard_manage_keys: False


- name: Read private key {{ item }}
slurp:
src: "/etc/wireguard/privatekey_{{ item }}"
register: private_{{ item }}
when: wireguard_manage_keys

- name: Read public key {{ item }}
slurp:
src: "/etc/wireguard/publickey_{{ item }}"
register: public_{{ item }}
when: wireguard_manage_keys

- name: Configure {{ item }}
template:
src: wgX.conf.j2
dest: /etc/wireguard/{{ item }}.conf
mode: '0400'
register: configuration

- name: Enable wg-quick@{{ item }} service
Expand Down
19 changes: 18 additions & 1 deletion tasks/debian_packages.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
---
- include_tasks: "{{ ansible_distribution | lower }}_repositories.yml"

- name: Install linux headers (Ubuntu)
apt:
name:
- linux-headers-generic
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an ubuntu guy, are headers-generic required if you install kernel flavor specific headers (linux-headers-{{ ansible_kernel }}

- linux-headers-{{ ansible_kernel }}
state: present
update_cache: yes
when: ansible_distribution == "Ubuntu"

- name: Install kernel headers (Debian)
apt:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails on obscure devices with

fatal: [c2]: FAILED! => {"changed": false, "msg": "No package matching 'linux-headers-4.18.8-odroidc2' is available"}

name: linux-headers-{{ ansible_kernel }}
state: present
update_cache: yes
when: ansible_distribution == "Debian"

- name: Install wireguard
package:
apt:
name: wireguard
state: present
update_cache: yes
2 changes: 1 addition & 1 deletion tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
group: root

- include_tasks: configure_network.yml
with_items: "{{ wireguard_networks }}"
with_items: "{{ wireguard_interfaces }}"
tags:
- configure
4 changes: 2 additions & 2 deletions templates/wgX.conf.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% set interface = vars.get('wireguard_' + item + '_interface', {}) -%}
{% set peers = vars.get('wireguard_' + item + '_peers', {}) -%}
{% set interface = wireguard_interface[item] -%}
{% set peers = wireguard_peers[item] -%}

{% set interface_required_keys = { 'address': 'Address', 'private_key': 'PrivateKey' } -%}
{% set interface_optional_keys = {
Expand Down
50 changes: 27 additions & 23 deletions tests/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,38 @@
- hosts: all
vars:
wireguard_manage_services: false
wireguard_networks:
wireguard_interfaces:
- wg0
- wg1

wireguard_wg0_interface:
address: 10.0.0.1/24
private_key: 12345
listen_port: 12345
wireguard_interface:
wg0:
address: 10.0.0.1/24
private_key: 12345
listen_port: 12345

wireguard_wg0_peers:
peer-0-0:
public_key: 0-12345-pub
allowed_ips: 10.0.0.10/24
peer-0-1:
public_key: 0-23456-pub
allowed_ips: 10.0.0.11/24
wireguard_peers:
wg0:
peer-0-0:
public_key: 0-12345-pub
allowed_ips: 10.0.0.10/24
peer-0-1:
public_key: 0-23456-pub
allowed_ips: 10.0.0.11/24

wireguard_wg1_interface:
address: 10.0.1.1/24
private_key: 23456
listen_port: 23456
wireguard_interface:
wg1:
address: 10.0.1.1/24
private_key: 23456
listen_port: 23456

wireguard_wg1_peers:
peer-1-0:
public_key: 1-12345-pub
allowed_ips: 10.0.1.10/24
peer-1-1:
public_key: 1-23456-pub
allowed_ips: 10.0.1.11/24
wireguard_peers:
wg1:
peer-1-0:
public_key: 1-12345-pub
allowed_ips: 10.0.1.10/24
peer-1-1:
public_key: 1-23456-pub
allowed_ips: 10.0.1.11/24
roles:
- role_under_test