Update to 2021-12-01 19:13

This commit is contained in:
Daniel Berteaud
2021-12-01 19:13:34 +01:00
commit 4c4556c660
2153 changed files with 60999 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
---
rad_clients: []
# rad_clients:
# - name: ap-wifi
# ip: 192.168.7.0/24
# secret: p@ssw0rd
# nas_type: other
rad_auth_port: 1812
rad_acc_port: 1813
rad_ports: [ "{{ rad_auth_port }}", "{{ rad_acc_port }}" ]
rad_src_ip: []
# An optional password if the private key is protected
# rad_tls_key_pass:
# The CA (full chain) to verify client's certificates
# rad_tls_ca: |
# ---- BEGIN CERTIFICATE ----
# ---- END CERTIFICATE ----
# The certificate of the radius server
# rad_tls_cert: |
# ---- BEGIN CERTIFICATE ----
# ---- END CERTIFICATE ----
# The private key of the radius server
# rad_tls_key: |
# -----BEGIN RSA PRIVATE KEY-----
# -----END RSA PRIVATE KEY-----
# An optional CRL to check client's certificate against
# Can either be a raw CRL in PEM format, or an http or https URL
# where to fetch it
# If undefined, no check will be performed, and revoked certificates will be accepted
# rad_tls_crl:
# An email address to notify in case of CRL issue.
# In case the CRL couldn't be fetched or is outdated, and rad_notify_crl is defined
# the validation script will allow the authentication and notify the adress instead of failing
# rad_notify_crl: admin@example.org
# The issuer of the clients certificate
# This can be usefull if you have several intermediate CA
# all signed by the same root CA, but only want to trust clients from
# one of them
# rad_tls_issuer: /C=FR/ST=Aquitaine/L=Bordeaux/O=Firewall Services/OU=Security/CN=wifi

View File

@@ -0,0 +1,97 @@
#!/usr/bin/perl -w
use warnings;
use strict;
use Getopt::Long;
use LWP::Simple qw($ua getstore);
use Net::Domain qw(hostname hostfqdn hostdomain domainname);
use Mail::Sendmail;
my $cert;
my $ca = '/etc/radius/certs/ca.pem';
my $crl;
my $issuer;
my $notify_crl;
GetOptions(
'certificate=s' => \$cert,
'cacert=s' => \$ca,
'crl=s' => \$crl,
'notify-crl=s' => \$notify_crl,
'issuer=s' => \$issuer
);
# Set a 5 sec timeout to fetch the CRL
$ua->timeout(5);
my $crl_file;
my $crl_age;
if ($crl){
if ($crl =~ m{^/} && -e $crl){
$crl_file = $crl;
$crl_age = time - ( stat($crl) )[9];
} elsif ($crl =~ m{^https?://}) {
$crl_age = 9999999;
if (-e '/run/radiusd/tls/crl.pem'){
$crl_age = time - ( stat('/run/radiusd/tls/crl.pem') )[9];
$crl_file = '/run/radiusd/tls/crl.pem';
}
if (!-e '/run/radiusd/tls/crl.pem' or $crl_age > 900){
my $code = getstore($crl, '/run/radiusd/tls/crl.pem');
if ($code == 200){
$crl_age = 0;
$crl_file = '/run/radiusd/tls/crl.pem';
}
}
}
}
if (defined $crl and (not defined $crl_file or ($crl =~ m{https?://} and $crl_age > 7200))){
if (defined $notify_crl){
my %mail = (
To => $notify_crl,
From => 'radius@' . hostdomain(),
Subject => 'CRL issue',
Message => 'Authentication done with an outdated CRL'
);
sendmail(%mail);
} else {
die "CRL is too old or missing\n";
}
}
my $cmd = "openssl verify -trusted $ca -purpose sslclient";
$cmd .= " -crl_check -CRLfile $crl_file" if (defined $crl_file);
$cmd .= " $cert";
my $ca_check = qx($cmd);
if ($? != 0){
print "openssl verify command returned non zero\n";
print $ca_check;
exit 1;
}
chomp($ca_check);
if ($ca_check !~ m/^$cert:\s+OK$/){
print "openssl failed to verify $cert against $ca\n";
exit 1;
}
my $expire_check = qx(openssl x509 -in $cert -checkend 0);
if ($? != 0 || $expire_check !~ m/^Certificate will not expire/){
print "certificate is expired\n";
exit 1;
}
if ($issuer){
my $issuer_check = qx(openssl x509 -in $cert -noout -issuer);
chomp($issuer_check);
$issuer_check =~ s/^issuer=\s*//;
unless ($issuer_check eq $issuer){
print "Certificate is signed by $issuer_check instead of $issuer\n";
exit 1;
}
}
exit 0;

View File

@@ -0,0 +1,4 @@
---
- name: restart radiusd
service: name=radiusd state=restarted

View File

@@ -0,0 +1,116 @@
---
- name: Install packages
yum:
name:
- freeradius
- freeradius-utils
- perl-LWP-Protocol-https # For the check script to be able to fetch CRL on https URL
- perl-Mail-Sendmail
tags: radius
- name: Create configuration directories
file: path=/etc/radius/{{ item }} state=directory group=radiusd mode=750
with_items:
- certs
- modules
tags: radius
- name: Create radiusd unit snippet dir
file: path=/etc/systemd/system/radiusd.service.d/ state=directory
tags: radius
- name: Remove obsolete systemd unit override
file: path=/etc/systemd/system/radiusd.service state=absent
register: rad_old_unit
tags: radius
- name: Overwrite radiusd unit file
copy:
content: |
[Service]
ExecStartPre=
ExecStartPre=-/bin/chown -R radiusd.radiusd /var/run/radiusd
ExecStartPre=/usr/sbin/radiusd -C -d /etc/radius
ExecStart=
ExecStart=/usr/sbin/radiusd -d /etc/radius
dest: /etc/systemd/system/radiusd.service.d/99-ansible.conf
register: rad_unit
notify: restart radiusd
tags: radius
- name: Reload systemd
systemd: daemon_reload=True
when: rad_unit.changed or rad_old_unit.changed
tags: radius
- name: Install client certificate checker script
copy: src=rad_check_client_cert dest=/usr/local/bin/rad_check_client_cert mode=755
tags: radius
- name: Deploy configuration
template: src={{ item }}.j2 dest=/etc/radius/{{ item }} group=radiusd mode=640
with_items:
- radiusd.conf
- clients.conf
- modules/eap.conf
- sites.conf
notify: restart radiusd
tags: radius
- name: Create DH param
shell: /usr/bin/openssl dhparam -out /etc/radius/certs/dh.pem 2048
args:
creates: /etc/radius/certs/dh.pem
notify: restart radiusd
tags: radius
- name: Deploy certificates
copy: content={{ item.content }} dest=/etc/radius/certs/{{ item.dest }} group=radiusd mode={{ item.mode | default(omit) }}
with_items:
- content: "{{ rad_tls_ca }}"
dest: ca.pem
- content: "{{ rad_tls_cert }}"
dest: cert.pem
- content: "{{ rad_tls_key }}"
dest: key.pem
mode: 640
notify: restart radiusd
no_log: True
tags: radius
- name: Deploy CRL
copy: content={{ rad_tls_crl }} dest=/etc/radiusd/certs/crl.pem
when:
- rad_tls_crl is defined
- rad_tls_crl is not search('^https?://')
tags: radius
- name: Deploy tmpfile fragment
template: src=tmpfiles.conf dest=/etc/tmpfiles.d/radiusd.conf
register: rad_tmpfiles
tags: radius
- name: Create tmpfiles
command: systemd-tmpfiles --create
when: rad_tmpfiles.changed
tags: radius
- name: Handle radius ports
iptables_raw:
name: radius_ports
state: "{{ (rad_src_ip | length > 0) | ternary('present','absent') }}"
rules: "-A INPUT -m state --state new -p udp -m multiport --dports {{ rad_ports | join(',') }} -s {{ rad_src_ip | join(',') }} -j ACCEPT"
when: iptables_manage | default(True)
tags: [firewall,radius]
# This is needed to allow the verification script to send email notification
# when the CRL is too old
- name: Configure SELinux
seboolean: name=nis_enabled state=True persistent=True
when: ansible_selinux.status == 'enabled'
tags: radius
- name: Start and enable the service
service: name=radiusd state=started enabled=True
tags: radius

View File

@@ -0,0 +1,7 @@
{% for client in rad_clients %}
client {{ client.name }} {
ipaddr = {{ client.ip }}
secret = {{ client.secret }}
nas_type = {{ client.nas_type | default('other') }}
}
{% endfor %}

View File

@@ -0,0 +1,27 @@
eap {
default_eap_type = tls
tls-config tls-common {
{% if rad_tls_key_pass is defined %}
private_key_password = {{ rad_tls_key_pass }}
{% endif %}
private_key_file = /etc/radius/certs/key.pem
certificate_file = /etc/radius/certs/cert.pem
{% if rad_tls_ca is defined %}
ca_file = /etc/radius/certs/ca.pem
{% endif %}
dh_file = /etc/radius/certs/dh.pem
ca_path = /etc/radius/certs/
ecdh_curve = "prime256v1"
{% if rad_tls_issuert is defined %}
check_cert_issuer = "{{ rad_tls_issuer }}"
{% endif %}
verify {
tmpdir = /run/radiusd/tls
client = "/usr/local/bin/rad_check_client_cert --cert %{TLS-Client-Cert-Filename}{% if rad_tls_crl is defined %} --crl {{ (rad_tls_crl is search ('https?://')) | ternary(rad_tls_crl,'/etc/radius/certs/crl.pem') }}{% endif %}{% if rad_tls_issuer is defined %} --issuer '{{ rad_tls_issuer }}'{% endif %}{% if rad_crl_notify is defined %} --notify-crl='{{ rad_crl_notify }}'{% endif %}"
}
}
tls {
tls = tls-common
}
}

View File

@@ -0,0 +1,46 @@
prefix = /usr
localstatedir = /var/lib/radiusd
logdir = /var/log/radius
run_dir = /run/radiusd
correct_escapes = true
max_request_time = 30
cleanup_delay = 5
max_requests = 16384
hostname_lookups = no
log {
destination = syslog
syslog_facility = daemon
colourise = yes
stripped_names = no
auth = yes
auth_badpass = no
auth_goodpass = no
}
security {
user = radiusd
group = radiusd
allow_core_dumps = no
max_attributes = 200
reject_delay = 1
status_server = yes
}
proxy_requests = no
$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 modules/eap.conf
}
instantiate {
}
policy {
}
$INCLUDE sites.conf

View File

@@ -0,0 +1,21 @@
[Unit]
Description=FreeRADIUS high performance RADIUS server.
After=syslog.target network.target ipa.service dirsrv.target krb5kdc.service
[Service]
Type=simple
PIDFile=/var/run/radiusd/radiusd.pid
ExecStartPre=/usr/sbin/radiusd -C
ExecStart=/usr/sbin/radiusd -f -d /etc/radius
ExecReload=/usr/sbin/radiusd -C
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=256M
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,31 @@
server site {
listen {
type = auth
ipaddr = *
port = {{ rad_auth_port }}
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
authorize {
eap {
ok = return
}
}
authenticate {
eap
}
session {
}
post-auth {
update {
&reply: += &session-state:
}
}
}

View File

@@ -0,0 +1,2 @@
d /run/radiusd 710 radiusd radiusd
d /run/radiusd/tls 700 radiusd radiusd