Skip to content

Commit

Permalink
Add client configuration generator
Browse files Browse the repository at this point in the history
Generate client configuration for OpenVPN and deploy to a secondary
container to test the VPN client connection.
  • Loading branch information
logan2211 committed May 5, 2017
1 parent 1ee9da3 commit 1b852e2
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 16 deletions.
38 changes: 32 additions & 6 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ openvpn_client_cert_days: "{{ openvpn_cert_days }}"
openvpn_ipv4_network: 192.168.250.0/24

# Verify the CN of the client
openvpn_verify_cn: no
openvpn_verify_x509_name: "OpenVPN-Client-{{inventory_hostname}} name-prefix"
openvpn_verify_cn_enabled: no
openvpn_verify_cn_client: "OpenVPN-Client-{{inventory_hostname}} name-prefix"
openvpn_verify_cn_server: "OpenVPN-Server-{{inventory_hostname}} name"

# Configure the OpenVPN management socket
openvpn_management_enabled: yes
Expand All @@ -83,6 +84,10 @@ openvpn_management_user: root
# key: <pregenerated key> (not stored on the server, only used to generate the client config)
openvpn_clients: []

# Enables generation of .ovpn client configurations for managed clients
openvpn_clients_config_generate: yes
openvpn_clients_config_path: "{{ openvpn_key_path }}"

openvpn_server_config:
port: "{{ openvpn_port }}"
proto: "{{ openvpn_protocol }}"
Expand All @@ -91,7 +96,7 @@ openvpn_server_config:
cert: "{{ openvpn_key_path }}/server.crt"
key: "{{ openvpn_key_path }}/server.key"
dh: "{{ openvpn_key_path }}/dh.pem"
tls-auth: "{{ openvpn_key_path }}/tls-auth.key"
tls-auth: "{{ openvpn_key_path }}/tls-auth.key 0"
crl-verify: "{{ openvpn_key_path }}/ca.crl"
tls-server: ''
auth: SHA256
Expand All @@ -105,13 +110,34 @@ openvpn_server_config:
group: "{{ openvpn_group }}"
status: "{{ openvpn_status_file }}"
verb: 3
verify-x509-name: "{{ openvpn_verify_x509_name if (openvpn_verify_cn | bool) else [] }}"
remote-cert-tls: "{{ 'client' if (openvpn_verify_cn | bool) else [] }}"
verify-x509-name: "{{ openvpn_verify_cn_client if (openvpn_verify_cn_enabled | bool) else [] }}"
remote-cert-tls: client
tls-version-min: 1.2
management: "{{ openvpn_management_bind if (openvpn_management_enabled | bool) else [] }}"
management-client-user: "{{ openvpn_management_user if (openvpn_management_enabled | bool) else [] }}"

openvpn_client_config: {}
openvpn_client_config:
client: ''
proto: "{{ openvpn_protocol }}"
remote: "{{ ansible_host }} {{ openvpn_port }}"
auth: SHA256
cipher: AES-256-CBC
dev: tun
remote-cert-tls: server
tls-version-min: 1.2
resolv-retry: infinite
nobind: ''
keepalive: '5 30'
comp-lzo: ''
persist-key: ''
persist-tun: ''
key-direction: 1
verb: 3
verify-x509-name: "{{ openvpn_verify_cn_server if (openvpn_verify_cn_enabled | bool) else [] }}"

# Configure settings in this dict to override the base configuration.
# NOTE(logan): An empty list ie. [] is excluded from the config.
# NOTE(logan): An empty string is outputted as a key-only var with no
# parameter in the config.
openvpn_server_config_overrides: {}
openvpn_client_config_overrides: {}
8 changes: 8 additions & 0 deletions handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Update the CRL
command: >
openssl ca
-config {{ openvpn_key_path }}/openssl.cnf
-gencrl
-out {{ openvpn_key_path }}/ca.crl
changed_when: false

- name: Restart OpenVPN
service:
name: "{{ openvpn_systemd_unit }}"
Expand Down
47 changes: 47 additions & 0 deletions tasks/openvpn_client_configs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
# Copyright 2017, Logan Vig <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: Store CA key
slurp:
src: "{{ openvpn_key_path }}/ca.crt"
register: ca_cert

- name: Store tls-auth key
slurp:
src: "{{ openvpn_key_path }}/tls-auth.key"
register: tls_auth_key

- name: Store client certificates
slurp:
src: "{{ openvpn_key_path }}/{{ item }}.crt"
register: client_certs
with_items: "{{ openvpn_clients_generate }}"

- name: Store client keys
slurp:
src: "{{ openvpn_key_path }}/{{ item }}.key"
register: client_keys
with_items: "{{ openvpn_clients_generate }}"

- name: Generate client configurations
template:
src: client.ovpn.j2
dest: "{{ openvpn_clients_config_path }}/{{ item.0.item }}.ovpn"
owner: root
group: root
mode: '0600'
with_together:
- "{{ client_certs.results }}"
- "{{ client_keys.results }}"
4 changes: 4 additions & 0 deletions tasks/openvpn_keys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@
changed_when: false

- include: openvpn_keys_client.yml
- include: openvpn_client_configs.yml
when:
- openvpn_clients_config_generate | bool
- openvpn_clients_generate | length > 0
2 changes: 2 additions & 0 deletions tasks/openvpn_keys_ca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
state: touch
owner: root
group: root
notify:
- Update the CRL
with_items:
- "{{ openvpn_key_path }}/index.txt"
- "{{ openvpn_key_path }}/ca.crl"
Expand Down
11 changes: 2 additions & 9 deletions tasks/openvpn_keys_client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,9 @@
-revoke {{ openvpn_key_path }}/{{ item }}.crt
with_items: "{{ openvpn_clients_revoke }}"
register: cert_revoke
notify:
- Update the CRL
changed_when: cert_revoke.rc == 0
failed_when:
- cert_revoke.rc == 1
- "'Already revoked' not in cert_revoke.stdout"

- name: Update the CRL file
command: >
openssl ca
-config {{ openvpn_key_path }}/openssl.cnf
-gencrl
-out {{ openvpn_key_path }}/ca.crl
when: cert_revoke | changed
changed_when: false
33 changes: 33 additions & 0 deletions templates/client.ovpn.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# {{ ansible_managed }}

{% set _ = openvpn_client_config.update(openvpn_client_config_overrides) %}

{% for i in openvpn_client_config | dictsort %}
{% set key = i.0 %}
{% set param = i.1 %}
{% if param is iterable and param is not string %}
{# The key is a list so we output multiple config items with the same key #}
{% for inner_param in param %}
{{ key }} {{ inner_param }}
{% endfor %}
{% else %}
{{ key }}{% if param != '' %} {{ param }}{% endif %}

{% endif %}
{% endfor %}

<ca>
{{ ca_cert.content | b64decode }}
</ca>

<tls-auth>
{{ tls_auth_key.content | b64decode }}
</tls-auth>

<cert>
{{ item.0.content | b64decode }}
</cert>

<key>
{{ item.1.content | b64decode }}
</key>
3 changes: 2 additions & 1 deletion templates/server.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
{{ key }} {{ inner_item }}
{% endfor %}
{% else %}
{{ key }} {{ item }}
{{ key }}{% if item != '' %} {{ item }}{% endif %}

{% endif %}
{% endfor %}
27 changes: 27 additions & 0 deletions tests/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,32 @@
failed_when: openvpn_pid.rc != 0
register: openvpn_pid
changed_when: false
- name: Fetch the openvpn client configuration
slurp:
src: "{{ openvpn_key_path }}/{{ openvpn_clients[0] }}.ovpn"
register: test_client_config
- name: Set the ping test IP
set_fact:
test_ping_ip: "{{ openvpn_ipv4_network | ipaddr(1) | ipaddr('address') }}"
vars_files:
- test-vars.yml

- name: Test the OpenVPN client connection
hosts: openvpn_clients
tasks:
- name: Install OpenVPN in the client
package:
name: openvpn
- name: Drop the client configuration
copy:
content: "{{ hostvars[groups['openvpn_servers'][0]].test_client_config.content | b64decode }}"
dest: /etc/openvpn/client.conf
- name: Start the OpenVPN client
service:
name: '[email protected]'
state: restarted
post_tasks:
- name: Ping the OpenVPN server over the tunnel
command: >
ping -c4 {{ hostvars[groups['openvpn_servers'][0]].test_ping_ip }}
changed_when: false

0 comments on commit 1b852e2

Please sign in to comment.