From 0261e875679f1bf63c8d689da7fc7e014597885d Mon Sep 17 00:00:00 2001 From: Stonewall Jackson Date: Sat, 4 Feb 2023 01:23:43 -0500 Subject: initial commit --- roles/freeradius/defaults/main.yml | 3 + .../systemd/system/radiusd.service.d/override.conf | 6 ++ roles/freeradius/handlers/main.yml | 4 + roles/freeradius/tasks/freeipa.yml | 50 +++++++++ roles/freeradius/tasks/main.yml | 74 ++++++++++++++ .../freeradius/templates/etc/raddb/clients.conf.j2 | 6 ++ .../templates/etc/raddb/mods-available/eap.j2 | 54 ++++++++++ .../templates/etc/raddb/mods-available/ldap.j2 | 113 +++++++++++++++++++++ .../freeradius/templates/etc/raddb/radiusd.conf.j2 | 73 +++++++++++++ .../etc/raddb/sites-available/inner-tunnel.j2 | 90 ++++++++++++++++ roles/freeradius/vars/main.yml | 12 +++ 11 files changed, 485 insertions(+) create mode 100644 roles/freeradius/defaults/main.yml create mode 100644 roles/freeradius/files/etc/systemd/system/radiusd.service.d/override.conf create mode 100644 roles/freeradius/handlers/main.yml create mode 100644 roles/freeradius/tasks/freeipa.yml create mode 100644 roles/freeradius/tasks/main.yml create mode 100644 roles/freeradius/templates/etc/raddb/clients.conf.j2 create mode 100644 roles/freeradius/templates/etc/raddb/mods-available/eap.j2 create mode 100644 roles/freeradius/templates/etc/raddb/mods-available/ldap.j2 create mode 100644 roles/freeradius/templates/etc/raddb/radiusd.conf.j2 create mode 100644 roles/freeradius/templates/etc/raddb/sites-available/inner-tunnel.j2 create mode 100644 roles/freeradius/vars/main.yml (limited to 'roles/freeradius') diff --git a/roles/freeradius/defaults/main.yml b/roles/freeradius/defaults/main.yml new file mode 100644 index 0000000..416d15f --- /dev/null +++ b/roles/freeradius/defaults/main.yml @@ -0,0 +1,3 @@ +freeradius_clients: [] +freeradius_ldap_servers: '{{ freeipa_hosts }}' +freeradius_access_group: role-wifi-access diff --git a/roles/freeradius/files/etc/systemd/system/radiusd.service.d/override.conf b/roles/freeradius/files/etc/systemd/system/radiusd.service.d/override.conf new file mode 100644 index 0000000..d1edca8 --- /dev/null +++ b/roles/freeradius/files/etc/systemd/system/radiusd.service.d/override.conf @@ -0,0 +1,6 @@ +[Unit] +After=syslog.target network-online.target ipa.service dirsrv.target krb5kdc.service mysql.service mariadb.service postgresql.service gssproxy.service +Wants=gssproxy.service + +[Service] +Environment=GSS_USE_PROXY=yes diff --git a/roles/freeradius/handlers/main.yml b/roles/freeradius/handlers/main.yml new file mode 100644 index 0000000..9c89432 --- /dev/null +++ b/roles/freeradius/handlers/main.yml @@ -0,0 +1,4 @@ +- name: restart radiusd + systemd: + name: radiusd + state: restarted diff --git a/roles/freeradius/tasks/freeipa.yml b/roles/freeradius/tasks/freeipa.yml new file mode 100644 index 0000000..945e2a8 --- /dev/null +++ b/roles/freeradius/tasks/freeipa.yml @@ -0,0 +1,50 @@ +- name: create access group + ipagroup: + ipaadmin_principal: '{{ ipa_user }}' + ipaadmin_password: '{{ ipa_pass }}' + name: '{{ freeradius_access_group }}' + description: wifi access + nonposix: yes + state: present + run_once: True + +- name: create service principal + ipaservice: + ipaadmin_principal: '{{ ipa_user }}' + ipaadmin_password: '{{ ipa_pass }}' + name: 'radius/{{ ansible_fqdn }}' + state: present + +- name: retrieve service keytab + include_role: + name: freeipa_keytab + vars: + keytab_principal: 'radius/{{ ansible_fqdn }}' + keytab_path: '{{ freeradius_keytab }}' + +- name: configure gssproxy for kerberized LDAP + include_role: + name: gssproxy_client + vars: + gssproxy_name: freeradius + gssproxy_section: service/freeradius + gssproxy_client_keytab: '{{ freeradius_keytab }}' + gssproxy_cred_usage: initiate + gssproxy_euid: radiusd + +- name: create systemd override directory + file: + path: /etc/systemd/system/radiusd.service.d + state: directory + +- name: create systemd override file + copy: + src: etc/systemd/system/radiusd.service.d/override.conf + dest: /etc/systemd/system/radiusd.service.d/override.conf + register: freeradius_systemd_unit + notify: restart radiusd + +- name: reload systemd units + systemd: + daemon_reload: yes + when: freeradius_systemd_unit.changed diff --git a/roles/freeradius/tasks/main.yml b/roles/freeradius/tasks/main.yml new file mode 100644 index 0000000..a2c926d --- /dev/null +++ b/roles/freeradius/tasks/main.yml @@ -0,0 +1,74 @@ +- name: install freeradius + dnf: + name: '{{ freeradius_packages }}' + state: present + +- import_tasks: freeipa.yml + +- name: request TLS certificate + include_role: + name: getcert_request + vars: + certificate_service: radius + certificate_path: '{{ freeradius_certificate_path }}' + certificate_key_path: '{{ freeradius_certificate_key_path }}' + certificate_ca_path: '{{ freeradius_certificate_ca_path }}' + certificate_owner: radiusd + certificate_hook: systemctl restart radiusd + +- name: generate dhparams + openssl_dhparam: + path: '{{ freeradius_dhparams_path }}' + size: 2048 + +- name: enable ldap module + file: + src: /etc/raddb/mods-available/ldap + dest: /etc/raddb/mods-enabled/ldap + state: link + +- name: generate freeradius configuration + template: + src: etc/raddb/{{ item }}.j2 + dest: /etc/raddb/{{ item }} + owner: root + group: radiusd + mode: 0640 + loop: + - radiusd.conf + - clients.conf + - mods-available/eap + - mods-available/ldap + - sites-available/inner-tunnel + notify: restart radiusd + +- name: create tlscache directory + file: + path: '{{ freeradius_tlscache_dir }}' + state: directory + owner: radiusd + group: radiusd + mode: 0700 + +- name: set up clean-freeradius-tlscache timer + include_role: + name: systemd_timer + vars: + timer_name: clean-freeradius-tlscache + timer_description: Delete old freeradius tlscache files + timer_on_calendar: daily + timer_exec: find {{ freeradius_tlscache_dir }} -mtime +2 -exec rm -vf {} ; + +- name: start freeradius + systemd: + name: radiusd + enabled: yes + state: started + +- name: open firewall ports + firewalld: + service: radius + permanent: yes + immediate: yes + state: enabled + tags: firewalld diff --git a/roles/freeradius/templates/etc/raddb/clients.conf.j2 b/roles/freeradius/templates/etc/raddb/clients.conf.j2 new file mode 100644 index 0000000..f6396e0 --- /dev/null +++ b/roles/freeradius/templates/etc/raddb/clients.conf.j2 @@ -0,0 +1,6 @@ +{% for client in freeradius_clients %} +client {{ client.name }} { + ipaddr = {{ client.address }} + secret = {{ client.secret }} +} +{% endfor %} diff --git a/roles/freeradius/templates/etc/raddb/mods-available/eap.j2 b/roles/freeradius/templates/etc/raddb/mods-available/eap.j2 new file mode 100644 index 0000000..5db0d1f --- /dev/null +++ b/roles/freeradius/templates/etc/raddb/mods-available/eap.j2 @@ -0,0 +1,54 @@ +eap { + default_eap_type = ttls + timer_expire = 60 + ignore_unknown_eap_types = yes + cisco_accounting_username_bug = no + max_sessions = ${max_requests} + + tls-config tls-common { + private_key_password = + private_key_file = {{ freeradius_certificate_key_path }} + certificate_file = {{ freeradius_certificate_path }} + ca_file = {{ freeradius_certificate_ca_path }} + auto_chain = no + ca_path = ${cadir} + cipher_list = "PROFILE=SYSTEM" + cipher_server_preference = no + tls_min_version = "1.2" + tls_max_version = "1.2" + ecdh_curve = "prime256v1" + + cache { + enable = yes + lifetime = 24 # hours + name = "EAP module" + persist_dir = "${db_dir}/tlscache" + store { + Tunnel-Private-Group-Id + } + } + + verify { + skip_if_ocsp_ok = yes + tmpdir = /var/run/radiusd/tmp + client = "/usr/bin/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" + } + + ocsp { + enable = yes + override_cert_url = no + } + } + + tls { + tls = tls-common + } + + ttls { + tls = tls-common + default_eap_type = md5 + copy_request_to_tunnel = no + use_tunneled_reply = no + virtual_server = "inner-tunnel" + } +} diff --git a/roles/freeradius/templates/etc/raddb/mods-available/ldap.j2 b/roles/freeradius/templates/etc/raddb/mods-available/ldap.j2 new file mode 100644 index 0000000..85aede1 --- /dev/null +++ b/roles/freeradius/templates/etc/raddb/mods-available/ldap.j2 @@ -0,0 +1,113 @@ +ldap { +{% for server in freeradius_ldap_servers %} + server = '{{ server }}' +{% endfor %} + + base_dn = '{{ freeipa_user_basedn }}' + + sasl { + mech = 'GSSAPI' + realm = '{{ freeipa_realm }}' + } + + update { + control:Password-With-Header += 'userPassword' + control: += 'radiusControlAttribute' + request: += 'radiusRequestAttribute' + reply: += 'radiusReplyAttribute' + } + + user_dn = "LDAP-UserDn" + + user { + base_dn = "${..base_dn}" +{% raw %} + filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" +{% endraw %} + } + + group { + base_dn = '{{ freeipa_group_basedn }}' + filter = '(objectClass=ipagroup)' + name_attribute = cn +{% raw %} + membership_filter = "(member=%{control:${..user_dn}})" +{% endraw %} + membership_attribute = 'memberOf' + cacheable_name = 'yes' + cacheable_dn = 'yes' + allow_dangling_group_ref = 'yes' + } + + profile { } + + client { + base_dn = "${..base_dn}" + filter = '(objectClass=radiusClient)' + + template { } + + attribute { + ipaddr = 'radiusClientIdentifier' + secret = 'radiusClientSecret' + } + } + + read_clients = no + + accounting { + reference = "%{tolower:type.%{Acct-Status-Type}}" + + type { + start { + update { + description := "Online at %S" + } + } + + interim-update { + update { + description := "Last seen at %S" + } + } + + stop { + update { + description := "Offline at %S" + } + } + } + } + + post-auth { + update { + description := "Authenticated at %S" + } + } + + options { + chase_referrals = yes + rebind = yes + res_timeout = 10 + srv_timelimit = 3 + net_timeout = 1 + idle = 60 + probes = 3 + interval = 3 + ldap_debug = 0x0000 + } + + tls { } + + pool { + start = ${thread[pool].start_servers} + min = ${thread[pool].min_spare_servers} + max = ${thread[pool].max_servers} + + spare = ${thread[pool].max_spare_servers} + uses = 0 + retry_delay = 30 + lifetime = 0 + idle_timeout = 60 + } +} diff --git a/roles/freeradius/templates/etc/raddb/radiusd.conf.j2 b/roles/freeradius/templates/etc/raddb/radiusd.conf.j2 new file mode 100644 index 0000000..ad9b58f --- /dev/null +++ b/roles/freeradius/templates/etc/raddb/radiusd.conf.j2 @@ -0,0 +1,73 @@ +prefix = /usr +exec_prefix = /usr +sysconfdir = /etc +localstatedir = /var +sbindir = /usr/sbin +logdir = ${localstatedir}/log/radius +raddbdir = ${sysconfdir}/raddb +radacctdir = ${logdir}/radacct + +name = radiusd + +confdir = ${raddbdir} +modconfdir = ${confdir}/mods-config +certdir = ${confdir}/certs +cadir = ${confdir}/certs +run_dir = ${localstatedir}/run/${name} + +db_dir = ${localstatedir}/lib/radiusd +libdir = /usr/lib64/freeradius +pidfile = ${run_dir}/${name}.pid +correct_escapes = true +max_request_time = 30 +cleanup_delay = 5 +max_requests = 16384 +hostname_lookups = no +log { + destination = stdout + colourise = no + stripped_names = no + auth = yes + auth_badpass = no + auth_goodpass = no + msg_denied = "You are already logged in - access denied" +} + +checkrad = ${sbindir}/checkrad + +ENV { } + +security { + user = radiusd + group = radiusd + allow_core_dumps = no + max_attributes = 200 + reject_delay = 1 + status_server = yes +} + +proxy_requests = yes +$INCLUDE proxy.conf + +$INCLUDE clients.conf + +thread pool { + start_servers = 5 + max_servers = 32 + min_spare_servers = 3 + max_spare_servers = 10 + max_requests_per_server = 0 + auto_limit_acct = no +} + +modules { + $INCLUDE mods-enabled/ +} + +instantiate { } + +policy { + $INCLUDE policy.d/ +} + +$INCLUDE sites-enabled/ diff --git a/roles/freeradius/templates/etc/raddb/sites-available/inner-tunnel.j2 b/roles/freeradius/templates/etc/raddb/sites-available/inner-tunnel.j2 new file mode 100644 index 0000000..043349a --- /dev/null +++ b/roles/freeradius/templates/etc/raddb/sites-available/inner-tunnel.j2 @@ -0,0 +1,90 @@ +server inner-tunnel { + listen { + ipaddr = 127.0.0.1 + port = 18120 + type = auth + } + + authorize { + filter_username + chap + suffix + + update control { + &Proxy-To-Realm := LOCAL + } + + eap { + ok = return + } + + ldap + if (ok || updated) { + update { + control:Auth-Type := ldap + } + } + + expiration + logintime + pap + } + + authenticate { + Auth-Type PAP { + pap + } + + Auth-Type CHAP { + chap + } + + Auth-Type LDAP { + ldap + } + + eap + } + + session { + radutmp + } + + + post-auth { + -sql + update reply { + User-Name !* ANY + Message-Authenticator !* ANY + EAP-Message !* ANY + Proxy-State !* ANY + MS-MPPE-Encryption-Types !* ANY + MS-MPPE-Encryption-Policy !* ANY + MS-MPPE-Send-Key !* ANY + MS-MPPE-Recv-Key !* ANY + } + + update { + &outer.session-state: += &reply: + } + + Post-Auth-Type REJECT { + -sql + attr_filter.access_reject + + update outer.session-state { + &Module-Failure-Message := &request:Module-Failure-Message + } + } + + if (LDAP-Group != "{{ freeradius_access_group }}") { + reject + } + } + + pre-proxy { } + + post-proxy { + eap + } +} diff --git a/roles/freeradius/vars/main.yml b/roles/freeradius/vars/main.yml new file mode 100644 index 0000000..a99a6aa --- /dev/null +++ b/roles/freeradius/vars/main.yml @@ -0,0 +1,12 @@ +freeradius_packages: + - freeradius + - freeradius-ldap + - freeradius-utils + +freeradius_certificate_path: /etc/pki/tls/certs/radiusd.pem +freeradius_certificate_key_path: /etc/pki/tls/private/radiusd.key +freeradius_certificate_ca_path: /etc/ipa/ca.crt +freeradius_dhparams_path: /etc/raddb/certs/dh +freeradius_tlscache_dir: /var/lib/radiusd/tlscache + +freeradius_keytab: /var/lib/gssproxy/clients/freeradius.keytab -- cgit