|
| 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 | +} |
0 commit comments