Skip to content

Commit 98620fd

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

File tree

5 files changed

+377
-0
lines changed

5 files changed

+377
-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: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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+
# Only test AlmaLinux 9 for now
8+
next unless os =~ %r{almalinux-9-x86_64}
9+
10+
context "on #{os}" do
11+
let(:facts) do
12+
os_facts.merge(
13+
networking: {
14+
fqdn: 'foo.example.com',
15+
}
16+
)
17+
end
18+
19+
let(:fqdn) { facts[:networking][:fqdn] }
20+
let(:le_root) { "/etc/letsencrypt/live/#{fqdn}" }
21+
let(:sacli) { '/usr/local/openvpn_as/scripts/sacli' }
22+
23+
context 'with default parameters' do
24+
let(:params) do
25+
{
26+
version: '3.0.1_84b60e70',
27+
}
28+
end
29+
30+
it { is_expected.to compile.with_all_deps }
31+
32+
it do
33+
is_expected.to contain_letsencrypt__certonly(fqdn).with(
34+
plugin: 'dns-route53',
35+
manage_cron: true
36+
)
37+
end
38+
39+
it do
40+
is_expected.to contain_class('openvpnas').with(
41+
manage_repo: true,
42+
version: '3.0.1_84b60e70',
43+
versionlock_enable: true,
44+
versionlock_release: '1.el9',
45+
manage_service: true,
46+
manage_web_certs: true,
47+
cert_source_path: le_root,
48+
require: "Letsencrypt::Certonly[#{fqdn}]"
49+
)
50+
end
51+
52+
it do
53+
is_expected.to contain_exec('wait_for_openvpnas_socket').with(
54+
command: '/bin/true',
55+
unless: '/usr/bin/test -S /usr/local/openvpn_as/etc/sock/sagent',
56+
require: 'Service[openvpnas]'
57+
)
58+
end
59+
60+
it do
61+
is_expected.to contain_exec('wait_for_openvpnas_ready').with(
62+
command: "#{sacli} ConfigQuery > /dev/null 2>&1",
63+
tries: 10,
64+
try_sleep: 3,
65+
timeout: 60,
66+
require: 'Exec[wait_for_openvpnas_socket]'
67+
)
68+
end
69+
70+
it do
71+
is_expected.to contain_exec('set_auth_module_ldap').with(
72+
command: "#{sacli} --key 'auth.module.type' --value 'ldap' ConfigPut",
73+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.module.type\": \"ldap\"'",
74+
require: 'Exec[wait_for_openvpnas_ready]'
75+
)
76+
end
77+
78+
it do
79+
is_expected.to contain_exec('set_ldap_primary').with(
80+
command: "#{sacli} --key 'auth.ldap.0.server.0.host' --value 'ipa1.cp.lsst.org' ConfigPut",
81+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.0.host\": \"ipa1.cp.lsst.org\"'",
82+
require: 'Exec[set_auth_module_ldap]'
83+
)
84+
end
85+
86+
it do
87+
is_expected.to contain_exec('set_ldap_secondary').with(
88+
command: "#{sacli} --key 'auth.ldap.0.server.1.host' --value 'ipa1.ls.lsst.org' ConfigPut",
89+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.server.1.host\": \"ipa1.ls.lsst.org\"'",
90+
require: 'Exec[set_ldap_primary]'
91+
)
92+
end
93+
94+
it do
95+
is_expected.to contain_exec('enable_ldap_auth').with(
96+
command: "#{sacli} --key 'auth.ldap.0.enable' --value 'true' ConfigPut",
97+
unless: "#{sacli} ConfigQuery | grep -q '\"auth.ldap.0.enable\": \"true\"'",
98+
require: 'Exec[set_ldap_uname_attr]'
99+
)
100+
end
101+
102+
it do
103+
is_expected.to contain_exec('restart_openvpnas_after_ldap').with(
104+
command: "#{sacli} start",
105+
refreshonly: true,
106+
subscribe: 'Exec[enable_ldap_auth]'
107+
)
108+
end
109+
110+
it do
111+
is_expected.to contain_exec('restart_openvpnas_after_groups').with(
112+
command: "#{sacli} start",
113+
refreshonly: true,
114+
subscribe: ['Exec[create_group_vpn_default]', 'Exec[create_group_vpn_it]', 'Exec[grant_admin_to_vpn_it]'],
115+
path: ['/usr/local/openvpn_as/scripts', '/usr/bin', '/bin']
116+
)
117+
end
118+
end
119+
end
120+
end
121+
end

spec/hosts/roles/openvpnas_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
role = 'openvpnas'
6+
7+
describe "#{role} role" do
8+
on_supported_os.each do |os, os_facts|
9+
next unless os =~ %r{almalinux-9-x86_64}
10+
11+
context "on #{os}" do
12+
lsst_sites.each do |site|
13+
describe "#{role}.#{site}.lsst.org", :sitepp do
14+
let(:node_params) do
15+
{
16+
role:,
17+
site:,
18+
}
19+
end
20+
let(:facts) { lsst_override_facts(os_facts) }
21+
22+
it { is_expected.to compile.with_all_deps }
23+
24+
include_examples('common', os_facts:, site:)
25+
end # host
26+
end # lsst_sites
27+
end # on os
28+
end # on_supported_os
29+
end # role

0 commit comments

Comments
 (0)