Skip to content

Commit dc982b6

Browse files
committed
(openvpnas) openvpnas module install tests
1 parent b4acfd0 commit dc982b6

File tree

5 files changed

+397
-0
lines changed

5 files changed

+397
-0
lines changed

Puppetfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod 'lsst/java_artisanal', '3.4.1'
3030
mod 'lsst/kubectl', '1.2.0'
3131
mod 'lsst/maven', '3.1.0'
3232
mod 'lsst/nm', '0.3.0'
33+
mod 'lsst/openvpnas', git: 'https://github.com/lsst-it/puppet-openvpnas', ref: '026a9c4'
3334
mod 'lsst/pi', '1.0.0'
3435
mod 'lsst/powertop', '0.1.2'
3536
mod 'lsst/rke', '2.1.0'

hieradata/role/openvpnas.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
classes:
3+
- "profile::core::common"
4+
- "profile::core::openvpnas"
5+
6+
profile::core::openvpnas::version: "3.0.1_84b60e70"
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# @summary
2+
# Installs and configures OpenVPN Access Server with LDAP authentication and group setup.
3+
#
4+
# @param version
5+
# Sets version lock for OpenVPN package.
6+
#
7+
# @param bind_pw
8+
# Optional. LDAP bind password for OpenVPN Access Server.
9+
#
10+
class profile::core::openvpnas (
11+
String[1] $version,
12+
Optional[String[1]] $bind_pw = undef,
13+
) {
14+
include profile::core::letsencrypt
15+
16+
$fqdn = fact('networking.fqdn')
17+
$le_root = "/etc/letsencrypt/live/${fqdn}"
18+
$ldap_pw = pick($bind_pw, 'testpassword')
19+
$sacli = '/usr/local/openvpn_as/scripts/sacli'
20+
21+
# --- CERTIFICATE MANAGEMENT ---
22+
letsencrypt::certonly { $fqdn:
23+
plugin => 'dns-route53',
24+
manage_cron => true,
25+
}
26+
27+
class { 'openvpnas':
28+
manage_repo => true,
29+
version => $version,
30+
versionlock_enable => true,
31+
versionlock_release => '1.el9',
32+
manage_service => true,
33+
manage_web_certs => true,
34+
cert_source_path => $le_root,
35+
require => Letsencrypt::Certonly[$fqdn],
36+
}
37+
38+
exec { 'wait_for_openvpnas_socket':
39+
command => '/bin/true',
40+
unless => '/usr/bin/test -S /usr/local/openvpn_as/etc/sock/sagent',
41+
require => Service['openvpnas'],
42+
}
43+
44+
exec { 'wait_for_openvpnas_ready':
45+
command => "${sacli} ConfigQuery > /dev/null 2>&1",
46+
tries => 10,
47+
try_sleep => 3,
48+
timeout => 60,
49+
require => Exec['wait_for_openvpnas_socket'],
50+
}
51+
52+
exec { 'set_auth_module_ldap':
53+
command => "${sacli} --key 'auth.module.type' --value 'ldap' ConfigPut",
54+
unless => "${sacli} ConfigQuery | grep -q '\"auth.module.type\": \"ldap\"'",
55+
require => Exec['wait_for_openvpnas_ready'],
56+
}
57+
58+
exec { 'set_ldap_primary':
59+
command => "${sacli} --key 'auth.ldap.0.server.0.host' --value 'ipa1.cp.lsst.org' ConfigPut",
60+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.0.host\": \"ipa1.cp.lsst.org\"'",
61+
require => Exec['set_auth_module_ldap'],
62+
}
63+
64+
exec { 'set_ldap_secondary':
65+
command => "${sacli} --key 'auth.ldap.0.server.1.host' --value 'ipa1.ls.lsst.org' ConfigPut",
66+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.1.host\": \"ipa1.ls.lsst.org\"'",
67+
require => Exec['set_ldap_primary'],
68+
}
69+
70+
exec { 'set_ldap_bind_dn':
71+
command => "${sacli} --key 'auth.ldap.0.bind_dn' --value 'uid=svc_openvpnas,cn=users,cn=accounts,dc=lsst,dc=cloud' ConfigPut",
72+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.bind_dn\": \"uid=svc_openvpnas,cn=users,cn=accounts,dc=lsst,dc=cloud\"'",
73+
require => Exec['set_ldap_secondary'],
74+
}
75+
76+
exec { 'set_ldap_bind_pw':
77+
command => "${sacli} --key 'auth.ldap.0.bind_pw' --value '${ldap_pw}' ConfigPut",
78+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.bind_pw\":'",
79+
require => Exec['set_ldap_bind_dn'],
80+
}
81+
82+
exec { 'set_ldap_users_base_dn':
83+
command => "${sacli} --key 'auth.ldap.0.users_base_dn' --value 'cn=accounts,dc=lsst,dc=cloud' ConfigPut",
84+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.users_base_dn\": \"cn=accounts,dc=lsst,dc=cloud\"'",
85+
require => Exec['set_ldap_bind_pw'],
86+
}
87+
88+
exec { 'set_ldap_uname_attr':
89+
command => "${sacli} --key 'auth.ldap.0.uname_attr' --value 'uid' ConfigPut",
90+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.uname_attr\": \"uid\"'",
91+
require => Exec['set_ldap_users_base_dn'],
92+
}
93+
94+
exec { 'enable_ldap_auth':
95+
command => "${sacli} --key 'auth.ldap.0.enable' --value 'true' ConfigPut",
96+
unless => "${sacli} ConfigQuery | grep -q '\"auth.ldap.0.enable\": \"true\"'",
97+
require => Exec['set_ldap_uname_attr'],
98+
}
99+
100+
exec { 'restart_openvpnas_after_ldap':
101+
command => "${sacli} start",
102+
refreshonly => true,
103+
subscribe => Exec['enable_ldap_auth'],
104+
}
105+
106+
exec { 'create_group_vpn_default':
107+
command => "${sacli} --user 'vpn-default' --key 'type' --value 'group' UserPropPut && \
108+
${sacli} --user 'vpn-default' --key 'group_declare' --value 'true' UserPropPut && \
109+
${sacli} start",
110+
unless => "${sacli} UserPropGet vpn-default | grep -q '\"group_declare\": \"true\"'",
111+
require => Exec['restart_openvpnas_after_ldap'],
112+
path => ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin'],
113+
}
114+
115+
exec { 'create_group_vpn_it':
116+
command => "${sacli} --user 'vpn-it' --key 'type' --value 'group' UserPropPut && \
117+
${sacli} --user 'vpn-it' --key 'group_declare' --value 'true' UserPropPut && \
118+
${sacli} start",
119+
unless => "${sacli} UserPropGet vpn-it | grep -q '\"group_declare\": \"true\"'",
120+
require => Exec['create_group_vpn_default'],
121+
path => ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin'],
122+
}
123+
124+
exec { 'grant_admin_to_vpn_it':
125+
command => "${sacli} --user 'vpn-it' --key 'prop_superuser' --value 'true' UserPropPut && ${sacli} start",
126+
unless => "${sacli} UserPropGet vpn-it | grep -q '\"prop_superuser\": \"true\"'",
127+
require => Exec['create_group_vpn_it'],
128+
path => ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin'],
129+
}
130+
131+
exec { 'restart_openvpnas_after_groups':
132+
command => "${sacli} start",
133+
refreshonly => true,
134+
subscribe => [Exec['create_group_vpn_default'], Exec['create_group_vpn_it'], Exec['grant_admin_to_vpn_it']],
135+
path => ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin'],
136+
}
137+
138+
file { '/root/ldap.py':
139+
ensure => file,
140+
owner => 'root',
141+
group => 'root',
142+
mode => '0644',
143+
content => @(EOF/L)
144+
#!/usr/bin/env python3
145+
import re
146+
from pyovpn.plugin import *
147+
148+
re_group = re.compile(r"^CN=([^,]+)", re.IGNORECASE)
149+
150+
def ldap_groups_parse(res):
151+
ret = set()
152+
for g in res:
153+
m = re.match(re_group, g)
154+
if m:
155+
ret.add(m.groups()[0])
156+
return ret
157+
158+
def post_auth(authcred, attributes, authret, info):
159+
group = "vpn-default"
160+
proplist_save = {}
161+
if info.get('auth_method') == 'ldap':
162+
user_dn = info['user_dn']
163+
with info['ldap_context'] as l:
164+
ldap_groups = set()
165+
if hasattr(l, 'search_ext_s'):
166+
import ldap
167+
ldap_groups = l.search_ext_s(user_dn, ldap.SCOPE_SUBTREE, attrlist=["memberOf"])[0][1]['memberOf']
168+
if ldap_groups:
169+
ldap_groups = ldap_groups_parse(ldap_groups)
170+
else:
171+
search_base = info['search_base']
172+
uname_attr = info['ldap_context'].authldap.parms['uname_attr']
173+
search_filter = '(%s=%s)' % (uname_attr, user_dn)
174+
attribute = 'memberOf'
175+
if l.search(search_base, search_filter, attributes=[attribute]):
176+
ldap_groups = getattr(l.entries[0], attribute).value
177+
if not isinstance(ldap_groups, (list, tuple)):
178+
ldap_groups = {ldap_groups}
179+
if ldap_groups:
180+
ldap_groups = ldap_groups_parse(ldap_groups)
181+
else:
182+
print('POST_AUTH: Ldap groups for user %r not found, please check filters %r' % (user_dn, search_filter))
183+
184+
if ldap_groups:
185+
print("LDAP_GROUPS %s" % ldap_groups)
186+
if 'vpn-it' in ldap_groups:
187+
group = "vpn-it"
188+
elif 'vpn-science' in ldap_groups:
189+
group = "vpn-science"
190+
elif 'vpn-users' in ldap_groups:
191+
group = "vpn-users"
192+
elif 'vpn-cucm' in ldap_groups:
193+
group = "vpn-cucm"
194+
elif 'vpn-tssw' in ldap_groups:
195+
group = "vpn-tssw"
196+
elif 'vpn-comm' in ldap_groups:
197+
group = "vpn-comm"
198+
elif 'vpn-clyso' in ldap_groups:
199+
group = "vpn-clyso"
200+
201+
if group:
202+
print("POST_AUTH: Setting group %r for %r" % (group, user_dn))
203+
authret['proplist']['conn_group'] = group
204+
proplist_save['conn_group'] = group
205+
else:
206+
print("POST_AUTH: No mapping found for %r, using default" % user_dn)
207+
authret['proplist']['conn_group'] = group
208+
proplist_save['conn_group'] = group
209+
return authret, proplist_save
210+
| EOF
211+
}
212+
213+
exec { 'install_post_auth_script':
214+
command => "${sacli} -k auth.module.post_auth_script --value_file=/root/ldap.py ConfigPut && ${sacli} start",
215+
refreshonly => true,
216+
subscribe => File['/root/ldap.py'],
217+
require => Exec['restart_openvpnas_after_groups'],
218+
path => ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin'],
219+
}
220+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
describe 'profile::core::openvpnas' do
6+
on_supported_os.each do |os, os_facts|
7+
next unless os =~ %r{almalinux-9-x86_64}
8+
9+
context "on #{os}" do
10+
let(:facts) do
11+
os_facts.merge(
12+
networking: {
13+
fqdn: 'foo.example.com',
14+
}
15+
)
16+
end
17+
18+
let(:fqdn) { facts[:networking][:fqdn] }
19+
let(:le_root) { "/etc/letsencrypt/live/#{fqdn}" }
20+
let(:sacli) { '/usr/local/openvpn_as/scripts/sacli' }
21+
22+
context 'with default parameters' do
23+
let(:params) do
24+
{
25+
version: '3.0.1_84b60e70',
26+
}
27+
end
28+
29+
it { is_expected.to compile.with_all_deps }
30+
31+
it do
32+
is_expected.to contain_letsencrypt__certonly(fqdn).with(
33+
plugin: 'dns-route53',
34+
manage_cron: true
35+
)
36+
end
37+
38+
it do
39+
is_expected.to contain_class('openvpnas').with(
40+
manage_repo: true,
41+
version: '3.0.1_84b60e70',
42+
versionlock_enable: true,
43+
versionlock_release: '1.el9',
44+
manage_service: true,
45+
manage_web_certs: true,
46+
cert_source_path: le_root,
47+
require: "Letsencrypt::Certonly[#{fqdn}]"
48+
)
49+
end
50+
51+
it do
52+
is_expected.to contain_exec('wait_for_openvpnas_socket').with(
53+
command: '/bin/true',
54+
unless: '/usr/bin/test -S /usr/local/openvpn_as/etc/sock/sagent',
55+
require: 'Service[openvpnas]'
56+
)
57+
end
58+
59+
it do
60+
is_expected.to contain_exec('wait_for_openvpnas_ready').with(
61+
command: "#{sacli} ConfigQuery > /dev/null 2>&1",
62+
tries: 10,
63+
try_sleep: 3,
64+
timeout: 60,
65+
require: 'Exec[wait_for_openvpnas_socket]'
66+
)
67+
end
68+
69+
it do
70+
is_expected.to contain_exec('set_auth_module_ldap').with(
71+
command: "#{sacli} --key 'auth.module.type' --value 'ldap' ConfigPut",
72+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.module.type\": \"ldap\"'",
73+
require: 'Exec[wait_for_openvpnas_ready]'
74+
)
75+
end
76+
77+
it do
78+
is_expected.to contain_exec('set_ldap_primary').with(
79+
command: "#{sacli} --key 'auth.ldap.0.server.0.host' --value 'ipa1.cp.lsst.org' ConfigPut",
80+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.0.host\": \"ipa1.cp.lsst.org\"'",
81+
require: 'Exec[set_auth_module_ldap]'
82+
)
83+
end
84+
85+
it do
86+
is_expected.to contain_exec('set_ldap_secondary').with(
87+
command: "#{sacli} --key 'auth.ldap.0.server.1.host' --value 'ipa1.ls.lsst.org' ConfigPut",
88+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.1.host\": \"ipa1.ls.lsst.org\"'",
89+
require: 'Exec[set_ldap_primary]'
90+
)
91+
end
92+
93+
it do
94+
is_expected.to contain_exec('enable_ldap_auth').with(
95+
command: "#{sacli} --key 'auth.ldap.0.enable' --value 'true' ConfigPut",
96+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.enable\": \"true\"'",
97+
require: 'Exec[set_ldap_uname_attr]'
98+
)
99+
end
100+
101+
it do
102+
is_expected.to contain_exec('restart_openvpnas_after_ldap').with(
103+
command: "#{sacli} start",
104+
refreshonly: true,
105+
subscribe: 'Exec[enable_ldap_auth]'
106+
)
107+
end
108+
109+
it do
110+
is_expected.to contain_exec('restart_openvpnas_after_groups').with(
111+
command: "#{sacli} start",
112+
refreshonly: true,
113+
subscribe: ['Exec[create_group_vpn_default]', 'Exec[create_group_vpn_it]', 'Exec[grant_admin_to_vpn_it]'],
114+
path: ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin']
115+
)
116+
end
117+
118+
it do
119+
is_expected.to contain_file('/root/ldap.py').with(
120+
ensure: 'file',
121+
owner: 'root',
122+
group: 'root',
123+
mode: '0644'
124+
).with_content(%r{#!/usr/bin/env python3})
125+
.with_content(%r{def post_auth\(})
126+
.with_content(%r{group = "vpn-default"})
127+
end
128+
129+
it do
130+
is_expected.to contain_exec('install_post_auth_script').with(
131+
command: "#{sacli} -k auth.module.post_auth_script --value_file=/root/ldap.py ConfigPut && #{sacli} start",
132+
refreshonly: true,
133+
subscribe: 'File[/root/ldap.py]',
134+
require: 'Exec[restart_openvpnas_after_groups]',
135+
path: ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin']
136+
)
137+
end
138+
end
139+
end
140+
end
141+
end

0 commit comments

Comments
 (0)