library/roles/openvpn: Support to two different kinds of ldap authentication: Via the openvpn-ldap-auth module (no posix groups support, and it crashes on ubuntu 14.04), and via an external perl script.

This commit is contained in:
Andrea Dell'Amico 2016-09-07 17:23:51 +02:00
parent eb7989f07a
commit c7c65cc0ac
6 changed files with 272 additions and 76 deletions

View File

@ -5,14 +5,24 @@ openvpn_pkg_state: latest
openvpn_pkgs:
- openvpn
# Authentication choices
openvpn_cert_auth_enabled: True
openvpn_username_pam_auth: False
openvpn_radius_auth: False
openvpn_radius_pkg:
- openvpn-auth-radius
# With openvpn-auth-ldap. Broken on Ubuntu trusty
openvpn_ldap_auth: False
openvpn_ldap_pkg:
- openvpn-auth-ldap
openvpn_ldap_perl_auth: False
openvpn_perl_pkg:
- libnet-ldap-perl
# Server con parameters
openvpn_conf_dir: /etc/openvpn
openvpn_conf_name: openvpn.conf
@ -26,12 +36,13 @@ openvpn_push_routes:
#openvpn_push_settings:
# - "dhcp-option DNS 10.66.0.4"
openvpn_tls_server: True
openvpn_dh: /etc/openvpn/dh2048.pem
openvpn_tls_auth: '/etc/openvpn/ta.key 0'
openvpn_install_alternative_ca: False
openvpn_alternative_ca_name: ca.pem
openvpn_ca_dir: False
openvpn_ca: '/var/lib/acme/live/{{ ansible_fqdn }}/chain'
openvpn_cert: '/var/lib/acme/live/{{ ansible_fqdn }}/cert'
openvpn_key: '/var/lib/acme/live/{{ ansible_fqdn }}/privkey'
@ -39,9 +50,6 @@ openvpn_key: '/var/lib/acme/live/{{ ansible_fqdn }}/privkey'
openvpn_compression_enabled: False
openvpn_keepalive: '10 120'
openvpn_cert_auth_enabled: True
openvpn_username_pam_auth: False
openvpn_max_clients: 50
openvpn_run_unprivileged: True
openvpn_unprivileged_user: nobody
@ -50,3 +58,33 @@ openvpn_letsencrypt_managed: True
openvpn_verbosity_log: 3
openvpn_mute_after: 20
# LDAP conf
openvpn_ldap_uri: 'ldap:'
openvpn_ldap_host: ldap.example.org
openvpn_ldap_url: '{{ openvpn_ldap_uri }}//{{ openvpn_ldap_host }}'
openvpn_ldap_nonanon_bind: False
openvpn_ldap_binddn: uid=admin
openvpn_ldap_bindpwd: test
openvpn_ldap_ca: '{{ openvpn_ca }}'
openvpn_ldap_use_ca_dir: False
openvpn_ldap_ca_dir: /etc/ssl/certs
openvpn_ldap_starttls: False
openvpn_ldap_tls_auth: False
openvpn_ldap_tls_cert: '{{ openvpn_cert }}'
openvpn_ldap_tls_key: '{{ openvpn_key }}'
openvpn_ldap_tls_ciphersuite: 'ALL:!ADH:@STRENGTH'
# LDAP auth
openvpn_ldap_base_dn: 'ou=People,dc=example,dc=org'
openvpn_ldap_user_search: '(&(uid=%u))'
openvpn_ldap_require_group: False
# See https://github.com/threerings/openvpn-auth-ldap/issues/7
openvpn_ldap_without_posix_groups: True
openvpn_ldap_group_base: 'ou=Groups,dc=example,dc=org'
openvpn_ldap_group_filter: '(|(cn=developers)(cn=artists))'
openvpn_ldap_group_member_attr: uniqueMember
# Perl LDAP conf
openvpn_ldap_perl_auth_ssl: True
openvpn_ldap_perl_auth_sslport: 636
openvpn_ldap_perl_auth_group: vpn_ldap_posix_group

View File

@ -1,79 +1,113 @@
---
- name: Install the OpenVPN main packages
apt: pkg={{ item }} state={{ openvpn_pkg_state }} update_cache=yes
with_items: '{{ openvpn_pkgs }}'
tags: openvpn
- block:
- name: Install the OpenVPN main packages
apt: pkg={{ item }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
with_items: '{{ openvpn_pkgs }}'
- name: Install the OpenVPN radius auth plugin package
apt: pkg={{ item }} state={{ openvpn_pkg_state }}
with_items: '{{ openvpn_radius_pkg }}'
when: openvpn_radius_auth
tags: openvpn
- name: Create the auth, ipp and status subdirs
file: dest={{ openvpn_conf_dir }}/{{ item }} state=directory owner={{ openvpn_unprivileged_user }} group=root mode=0770
with_items:
- ipp
- status
- auth
- name: Install the OpenVPN ldap auth plugin package
apt: pkg={{ item }} state={{ openvpn_pkg_state }}
with_items: '{{ openvpn_ldap_pkg }}'
when: openvpn_ldap_auth
tags: openvpn
- name: Install the OpenVPN PAM auth plugin
shell: cp /usr/lib/openvpn/openvpn-plugin-auth-pam.so {{ openvpn_conf_dir }}/openvpn-plugin-auth-pam.so
args:
creates: '{{ openvpn_conf_dir }}/openvpn-plugin-auth-pam.so'
when: openvpn_username_pam_auth
tags: openvpn
- name: Remove the OpenVPN PSM auth plugin
file: dest={{ openvpn_conf_dir }}/openvpn-plugin-auth-pam.so state=absent
when: not openvpn_username_pam_auth
tags: openvpn
- name: Create the ipp and status subdirs
file: dest={{ openvpn_conf_dir }}/{{ item }} state=directory
with_items:
- ipp
- status
tags: openvpn
- name: Install the main OpenVPN configuration file
template: src=openvpn.conf.j2 dest={{ openvpn_conf_dir }}/{{ openvpn_conf_name }} owner=root group=root mode=0444
notify: Reload OpenVPN
tags: openvpn
- name: Create the dh file
shell: openssl dhparam -out {{ openvpn_conf_dir }}/dh2048.pem 2048 ; chmod 444 {{ openvpn_conf_dir }}/dh2048.pem
args:
creates: '{{ openvpn_conf_dir }}/dh2048.pem'
tags: openvpn
- name: Create the ta key
shell: cd {{ openvpn_conf_dir }} ; openvpn --genkey --secret ta.key ; chmod 400 {{ openvpn_conf_dir }}/ta.key
args:
creates: '{{ openvpn_conf_dir }}/ta.key'
tags: openvpn
- name: Ensure that the OpenVPN service is enabled and running
service: name=openvpn state=started enabled=yes
when: openvpn_enabled
tags: openvpn
- name: Ensure that the OpenVPN service is stopped and disabled
service: name=openvpn state=stopped enabled=no
when: not openvpn_enabled
- block:
- name: Install the OpenVPN radius auth plugin package
apt: pkg={{ item }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
with_items: '{{ openvpn_radius_pkg }}'
when: openvpn_radius_auth
tags: [ 'openvpn', 'openvpn_radius' ]
- block:
- name: apt key for the internal ppa repository. Needed by the openvpn ldap auth with posix groups
apt_key: url=http://ppa.research-infrastructures.eu/system/keys/system-archive.asc state=present
when:
- openvpn_ldap_auth
- not openvpn_ldap_without_posix_groups
- name: Setup the internal apt repository
apt_repository: repo='deb http://ppa.research-infrastructures.eu/system trusty main'
when:
- openvpn_ldap_auth
- not openvpn_ldap_without_posix_groups
- name: Install the OpenVPN ldap auth plugin package
apt: pkg={{ item }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
with_items: '{{ openvpn_ldap_pkg }}'
- name: Install the LDAP auth configuration file
template: src=auth-ldap.conf.j2 dest={{ openvpn_conf_dir }}/auth/auth-ldap.conf owner=root group={{ openvpn_unprivileged_group }} mode=0440
notify: Reload OpenVPN
- name: Remove the LDAP auth configuration file if LDAP is not used
file: dest={{ openvpn_conf_dir }}/auth/auth-ldap.conf state=absent
notify: Reload OpenVPN
when: not openvpn_ldap_auth
when: openvpn_ldap_auth
tags: [ 'openvpn', 'openvpn_ldap' ]
- block:
- name: Install the perl libraries needed by the LDAP client authentication script
apt: pkg={{ item }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
with_items: '{{ openvpn_perl_pkg }}'
- name: Install the perl LDAP auth script
template: src=auth-ldap.pl.j2 dest={{ openvpn_conf_dir }}/auth/auth-ldap owner=root group={{ openvpn_unprivileged_group }} mode=0550
when: openvpn_ldap_perl_auth
tags: [ 'openvpn', 'openvpn_ldap' ]
- block:
- name: Install the main OpenVPN configuration file
template: src=openvpn.conf.j2 dest={{ openvpn_conf_dir }}/{{ openvpn_conf_name }} owner=root group={{ openvpn_unprivileged_group }} mode=0440
notify: Reload OpenVPN
- name: Create the dh file
shell: openssl dhparam -out {{ openvpn_conf_dir }}/dh2048.pem 2048 ; chmod 444 {{ openvpn_conf_dir }}/dh2048.pem
args:
creates: '{{ openvpn_conf_dir }}/dh2048.pem'
- name: Create the ta key
shell: cd {{ openvpn_conf_dir }} ; openvpn --genkey --secret ta.key ; chmod 400 {{ openvpn_conf_dir }}/ta.key
args:
creates: '{{ openvpn_conf_dir }}/ta.key'
tags: [ 'openvpn', 'openvpn_conf' ]
- block:
- name: Enable kernel forwarding
sysctl: name={{ item }} value=1 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when:
- openvpn_enable_system_forward
- openvpn_enabled
- name: Disable kernel forwarding
sysctl: name={{ item }} value=0 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when: not openvpn_enable_system_forward
- name: Ensure that the OpenVPN service is enabled and running
service: name=openvpn state=started enabled=yes
when: openvpn_enabled
- name: Ensure that the OpenVPN service is stopped and disabled
service: name=openvpn state=stopped enabled=no
when: not openvpn_enabled
tags: openvpn
- name: Enable kernel forwarding
sysctl: name={{ item }} value=1 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when: openvpn_enable_system_forward
tags: openvpn
- name: Disable kernel forwarding
sysctl: name={{ item }} value=0 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when: not openvpn_enable_system_forward
tags: openvpn

View File

@ -0,0 +1,67 @@
<LDAP>
# LDAP server URL
URL {{ openvpn_ldap_url }}
{% if openvpn_ldap_nonanon_bind %}
# Bind DN (If your LDAP server doesn't support anonymous binds)
BindDN {{ openvpn_ldap_binddn }}
# Bind Password
Password {{ openvpn_ldap_bindpwd }}
{% endif %}
# Network timeout (in seconds)
Timeout 15
{% if openvpn_ldap_starttls %}
# Enable Start TLS
TLSEnable yes
{% endif %}
# Follow LDAP Referrals (anonymously)
FollowReferrals yes
# TLS CA Certificate File
TLSCACertFile {{ openvpn_ldap_ca }}
{% if openvpn_ldap_use_ca_dir %}
# TLS CA Certificate Directory
# TLSCACertDir {{ openvpn_ldap_ca_dir }}
{% endif %}
{% if openvpn_ldap_tls_auth %}
# Client Certificate and key
# If TLS client authentication is required
TLSCertFile {{ openvpn_ldap_tls_cert }}
TLSKeyFile {{ openvpn_ldap_tls_key }}
{% endif %}
# Cipher Suite
# The defaults are usually fine here
TLSCipherSuite {{ openvpn_ldap_tls_ciphersuite }}
</LDAP>
<Authorization>
# Base DN
BaseDN "{{ openvpn_ldap_base_dn }}"
# User Search Filter
# SearchFilter "(&(uid=%u)(accountStatus=active))"
SearchFilter "{{ openvpn_ldap_user_search }}"
# Require Group Membership
RequireGroup {{ openvpn_ldap_require_group }}
{% if openvpn_ldap_require_group %}
# Add non-group members to a PF table (disabled)
#PFTable ips_vpn_users
<Group>
BaseDN "{{ openvpn_ldap_group_base }}"
SearchFilter "{{ openvpn_ldap_group_filter }}"
RFC2307bis {{ openvpn_ldap_without_posix_groups }}
MemberAttribute {{ openvpn_ldap_group_member_attr }}
# Add group members to a PF table (disabled)
# #PFTable ips_vpn_eng
</Group>
{% endif %}
</Authorization>

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl -w
{% if openvpn_ldap_perl_auth_ssl %}
use Net::LDAPS;
{% else %}
use Net::LDAP;
{% endif %}
use strict;
my $ldap;
my $result;
my $opt_uri = "{{ openvpn_ldap_host }}";
my $opt_user = $ENV{'username'};
my $opt_passwd = $ENV{'password'};
my $opt_group = "cn={{ openvpn_ldap_perl_auth_group }},{{ openvpn_ldap_group_base }}";
my $opt_binddn = "uid=".$opt_user.",{{ openvpn_ldap_base_dn }}";
{% if openvpn_ldap_perl_auth_ssl %}
$ldap = Net::LDAPS->new($opt_uri, version => 3,
port => '{{ openvpn_ldap_perl_auth_sslport }}',
verify => 'require',
{% if openvpn_ca_dir %}
capath => '{{ openvpn_ldap_ca }}'
{% else %}
cafile => '{{ openvpn_ldap_ca }}'
{% endif %}
) or die("LDAPS connect to $opt_uri failed!");
{% else %}
$ldap = Net::LDAP->new($opt_uri) or die("LDAP connect to $opt_uri failed!");
{% endif %}
{% if openvpn_ldap_nonanon_bind %}
$result = $ldap->bind('{{ openvpn_ldap_binddn }}', password => '{{ openvpn_ldap_bindpwd }}');
{% else %}
$result = $ldap->bind($opt_binddn, password => $opt_passwd);
{% endif %}
$result->code and die($result->error);
$result = $ldap->search(base=>$opt_group, filter => "(&({{ openvpn_ldap_group_member_attr }}=$opt_user))");
$result->code();
if ($result->count == 1) { exit 0; }
unless($result->count){ exit 1; }

View File

@ -44,7 +44,16 @@ client-cert-not-required
{% if openvpn_username_pam_auth %}
username-as-common-name
# PAM login
plugin /etc/openvpn/openvpn-plugin-auth-pam.so login
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
{% endif %}
{% if openvpn_ldap_auth %}
plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth/auth-ldap.conf
{% endif %}
{% if openvpn_ldap_perl_auth %}
auth-user-pass-verify /etc/openvpn/auth/auth-ldap via-env
script-security 3 execve
{% endif %}
max-clients {{ openvpn_max_clients }}

View File

@ -53,6 +53,12 @@
ignore_errors: True
tags: packages
- name: setup system apt repository for specific distributions
apt_repository: repo='deb http://ppa.research-infrastructures.eu/system {{ ansible_distribution_release }} main' update_cache=yes
when: is_trusty
ignore_errors: True
tags: packages
- name: install common packages
apt: pkg={{ item }} state={{ pkg_state }}
with_items: '{{ common_packages }}'