Merge pull request 'freeradius rol install + config' (#3) from TEST-freeradius-totp-playbook into main
Reviewed-on: #3
This commit is contained in:
commit
dfa3e1889f
|
@ -0,0 +1,6 @@
|
|||
# restart freeradius service to apply changes
|
||||
- name: restart freeradius
|
||||
service:
|
||||
name: "{{ freeradius_daemon }}"
|
||||
state: restarted
|
||||
enabled: yes
|
|
@ -0,0 +1,131 @@
|
|||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Install and configure FREERADIUS TOTP
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# install packages if there are not present in the system
|
||||
- name: install freeradius packages if is not in the system
|
||||
apt:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- freeradius
|
||||
- freeradius-ldap
|
||||
- libpam-google-authenticator
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config symbolic files to enable modules
|
||||
- name: create a symbolic link
|
||||
ansible.builtin.file:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
state: link
|
||||
loop:
|
||||
- { src: '"{{ freeradius_mods_available_folder }}"ldap', dest: '"{{ freeradius_mods_enabled_folder }}"ldap' }
|
||||
- { src: '"{{ freeradius_mods_available_folder }}"pam', dest: '"{{ freeradius_mods_enabled_folder }}"pam' }
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/sites-enabled/default
|
||||
- name: config default file
|
||||
ansible.builtin.template:
|
||||
src: default.j2
|
||||
dest: "{{ freeradius_default_config }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/mods-available/ldap
|
||||
- name: config ldap file
|
||||
ansible.builtin.template:
|
||||
src: ldap.j2
|
||||
dest: "{{ freeradius_mod_ldap }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/dictionary
|
||||
- name: config dictionary file
|
||||
ansible.builtin.template:
|
||||
src: dictionary.j2
|
||||
dest: "{{ freeradius_dictionary_config }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/clients.conf
|
||||
- name: config clients.conf file
|
||||
ansible.builtin.template:
|
||||
src: clients.j2
|
||||
dest: "{{ freeradius_clients_config }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/policy.d/filter
|
||||
- name: config filter file
|
||||
ansible.builtin.template:
|
||||
src: filter.j2
|
||||
dest: "{{ freeradius_filter_config }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/freeradius/3.0/radiusd.conf
|
||||
- name: config radius.conf file
|
||||
ansible.builtin.template:
|
||||
src: radiusd.j2
|
||||
dest: "{{ freeradius_base_config }}"
|
||||
owner: freerad
|
||||
group: freerad
|
||||
mode: '0640'
|
||||
backup: yes
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /etc/pam.d/radiusd
|
||||
- name: config pam radiusd file
|
||||
ansible.builtin.template:
|
||||
src: radiusdpam.j2
|
||||
dest: "{{ freeradius_pam_config }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# config default file /lib/systemd/system/freeradius.service
|
||||
- name: config freeradius systemd service file
|
||||
ansible.builtin.template:
|
||||
src: freeradiusservice.j2
|
||||
dest: "{{ freeradius_service_config }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# force systemd to reread configs
|
||||
- name: Just force systemd to reread configs (2.4 and above)
|
||||
ansible.builtin.systemd_service:
|
||||
daemon_reload: true
|
||||
notify: restart freeradius
|
||||
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
@ -0,0 +1,4 @@
|
|||
client opnsense {
|
||||
ipaddr = 0.0.0.0/0
|
||||
secret = "{{ bindradiusclient_password }}"
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
server default {
|
||||
listen {
|
||||
type = auth
|
||||
ipaddr = *
|
||||
port = 0
|
||||
limit {
|
||||
max_connections = 16
|
||||
lifetime = 0
|
||||
idle_timeout = 30
|
||||
}
|
||||
}
|
||||
listen {
|
||||
ipaddr = *
|
||||
port = 0
|
||||
type = acct
|
||||
limit {
|
||||
}
|
||||
}
|
||||
authorize {
|
||||
filter_username
|
||||
filter_google_totp
|
||||
ldap
|
||||
if (&Google-Password) {
|
||||
update control {
|
||||
&User-Password := "%{&Google-Password}"
|
||||
Auth-Type := PAP
|
||||
}
|
||||
}
|
||||
}
|
||||
authenticate {
|
||||
Auth-Type PAP {
|
||||
pap
|
||||
if (&Google-Password) {
|
||||
update request {
|
||||
&User-Password := "%{&Google-Password}"
|
||||
}
|
||||
pam
|
||||
} else {
|
||||
update reply {
|
||||
Reply-Message := "Login incorrect: TOTP Fail"
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
pam
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
ATTRIBUTE Google-Password 3000 string
|
|
@ -0,0 +1,103 @@
|
|||
deny_realms {
|
||||
if (&User-Name && (&User-Name =~ /@|\\/)) {
|
||||
reject
|
||||
}
|
||||
}
|
||||
filter_username {
|
||||
if (&User-Name) {
|
||||
if (&User-Name =~ / /) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: User-Name contains whitespace'
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&User-Name =~ /@[^@]*@/ ) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Multiple @ in User-Name'
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&User-Name =~ /\.\./ ) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: User-Name contains multiple ..s'
|
||||
}
|
||||
reject
|
||||
}
|
||||
if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Realm does not have at least one dot separator'
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&User-Name =~ /\.$/) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Realm ends with a dot'
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&User-Name =~ /@\./) {
|
||||
update request {
|
||||
&Module-Failure-Message += 'Rejected: Realm begins with a dot'
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
}
|
||||
filter_password {
|
||||
if (&User-Password && \
|
||||
(&User-Password != "%{string:User-Password}")) {
|
||||
update request {
|
||||
&Tmp-String-0 := "%{string:User-Password}"
|
||||
&User-Password := "%{string:Tmp-String-0}"
|
||||
&Tmp-String-0 !* ""
|
||||
}
|
||||
}
|
||||
}
|
||||
filter_inner_identity {
|
||||
if (!&outer.request:User-Name || !&User-Name) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is required for tunneled authentication"
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&outer.request:User-Name != &User-Name) {
|
||||
if (&outer.request:User-Name =~ /@([^@]+)$/) {
|
||||
update request {
|
||||
Outer-Realm-Name = "%{1}"
|
||||
}
|
||||
if (&outer.request:User-Name !~ /^(anon|@)/) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is not anonymized"
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
elsif (&outer.request:User-Name !~ /^anon/) {
|
||||
update request {
|
||||
Module-Failure-Message = "User-Name is not anonymized"
|
||||
}
|
||||
reject
|
||||
}
|
||||
if (&User-Name =~ /@([^@]+)$/) {
|
||||
update request {
|
||||
Inner-Realm-Name = "%{1}"
|
||||
}
|
||||
if (&Outer-Realm-Name && \
|
||||
(&Inner-Realm-Name != &Outer-Realm-Name) && \
|
||||
(&Inner-Realm-Name !~ /\.%{Outer-Realm-Name}$/)) {
|
||||
update request {
|
||||
Module-Failure-Message = "Inner realm '%{Inner-Realm-Name}' and outer realm '%{Outer-Realm-Name}' are not from the same domain."
|
||||
}
|
||||
reject
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
filter_google_totp {
|
||||
if (&User-Password =~ /^(.*)([0-9]{6})$/) {
|
||||
update request {
|
||||
&User-Password := "%{1}"
|
||||
&Google-Password := "%{2}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
[Unit]
|
||||
Description=FreeRADIUS multi-protocol policy server
|
||||
After=network-online.target
|
||||
Documentation=man:radiusd(8) man:radiusd.conf(5) http://wiki.freeradius.org/ http://networkradius.com/doc/
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
WatchdogSec=60
|
||||
NotifyAccess=all
|
||||
EnvironmentFile=-/etc/default/freeradius
|
||||
|
||||
# FreeRADIUS can do static evaluation of policy language rules based
|
||||
# on environmental variables which is very useful for doing per-host
|
||||
# customization.
|
||||
# Unfortunately systemd does not allow variable substitutions such
|
||||
# as %H or $(hostname) in the EnvironmentFile.
|
||||
# We provide HOSTNAME here for convenience.
|
||||
Environment=HOSTNAME=%H
|
||||
|
||||
# Limit memory to 2G this is fine for %99.99 of deployments. FreeRADIUS
|
||||
# is not memory hungry, if it's using more than this, then there's probably
|
||||
# a leak somewhere.
|
||||
MemoryLimit=2G
|
||||
|
||||
# Ensure the daemon can still write its pidfile after it drops
|
||||
# privileges. Combination of options that work on a variety of
|
||||
# systems. Test very carefully if you alter these lines.
|
||||
RuntimeDirectory=freeradius
|
||||
RuntimeDirectoryMode=0775
|
||||
#User=freerad
|
||||
#Group=freerad
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
ExecStartPre=/usr/sbin/freeradius $FREERADIUS_OPTIONS -Cx -lstdout
|
||||
ExecStart=/usr/sbin/freeradius -f $FREERADIUS_OPTIONS
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
ExecReload=/usr/sbin/freeradius $FREERADIUS_OPTIONS -Cxm -lstdout
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
# Don't elevate privileges after starting
|
||||
NoNewPrivileges=true
|
||||
|
||||
# Allow binding to secure ports, broadcast addresses, and raw interfaces.
|
||||
#AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_CHOWN CAP_DAC_OVERRIDE
|
||||
|
||||
# Private /tmp that isn't shared by other processes
|
||||
PrivateTmp=true
|
||||
|
||||
# cgroups are readable only by radiusd, and child processes
|
||||
ProtectControlGroups=true
|
||||
|
||||
# don't load new kernel modules
|
||||
ProtectKernelModules=true
|
||||
|
||||
# don't tune kernel parameters
|
||||
ProtectKernelTunables=true
|
||||
|
||||
# Only allow native system calls
|
||||
SystemCallArchitectures=native
|
||||
|
||||
# We shouldn't be writing to the configuration directory
|
||||
ReadOnlyDirectories=/etc/freeradius/
|
||||
|
||||
# We can read and write to the log directory.
|
||||
ReadWriteDirectories=/var/log/freeradius/
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,60 @@
|
|||
ldap {
|
||||
server = 'ldap.verdnatura.es'
|
||||
identity = 'cn=admin,dc=verdnatura,dc=es'
|
||||
password = "{{ bindradiusldap_password }}"
|
||||
base_dn = 'dc=verdnatura,dc=es'
|
||||
user_dn = "LDAP-UserDn"
|
||||
update {
|
||||
control:Password-With-Header += 'userPassword'
|
||||
control:NT-Password := 'sambaNTPassword'
|
||||
}
|
||||
user {
|
||||
base_dn = "ou=users,${..base_dn}"
|
||||
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
|
||||
}
|
||||
group {
|
||||
base_dn = "ou=groups,${..base_dn}"
|
||||
name_attribute = 'cn'
|
||||
membership_attribute = 'memberUid'
|
||||
membership_filter = "(memberUid=%{%{Stripped-User-Name}:-%{User-Name}})"
|
||||
filter = '(objectClass=posixGroup)'
|
||||
cacheable_name = yes
|
||||
}
|
||||
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 {
|
||||
rebind = yes
|
||||
res_timeout = 10
|
||||
srv_timelimit = 3
|
||||
net_timeout = 1
|
||||
idle = 60
|
||||
probes = 3
|
||||
interval = 3
|
||||
ldap_debug = 0x0028
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
prefix = /usr
|
||||
exec_prefix = /usr
|
||||
sysconfdir = /etc
|
||||
localstatedir = /var
|
||||
sbindir = ${exec_prefix}/sbin
|
||||
logdir = /var/log/freeradius
|
||||
raddbdir = /etc/freeradius/3.0
|
||||
radacctdir = ${logdir}/radacct
|
||||
name = freeradius
|
||||
confdir = ${raddbdir}
|
||||
modconfdir = ${confdir}/mods-config
|
||||
certdir = ${confdir}/certs
|
||||
cadir = ${confdir}/certs
|
||||
run_dir = ${localstatedir}/run/${name}
|
||||
db_dir = ${raddbdir}
|
||||
libdir = /usr/lib/freeradius
|
||||
pidfile = ${run_dir}/${name}.pid
|
||||
max_request_time = 30
|
||||
cleanup_delay = 5
|
||||
max_requests = 16384
|
||||
hostname_lookups = no
|
||||
log {
|
||||
destination = files
|
||||
colourise = yes
|
||||
file = ${logdir}/radius.log
|
||||
syslog_facility = daemon
|
||||
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 = root
|
||||
group = root
|
||||
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/
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# /etc/pam.d/radiusd - PAM configuration for FreeRADIUS
|
||||
#
|
||||
|
||||
# We fall back to the system default in /etc/pam.d/common-*
|
||||
#
|
||||
auth required pam_google_authenticator.so forward_pass
|
||||
#@include common-auth
|
||||
#@include common-account
|
||||
#@include common-password
|
||||
#@include common-session
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
# vars file
|
||||
freeradius_base_folder: /etc/freeradius/3.0/
|
||||
freeradius_mods_available_folder: '"{{ freeradius_base_folder }}"mods-available/'
|
||||
freeradius_mods_enabled_folder: '"{{ freeradius_base_folder }}"mods-enabled/'
|
||||
freeradius_sites_available_folder: '"{{ freeradius_base_folder }}"sites-available/'
|
||||
freeradius_base_config: '"{{ freeradius_base_folder }}"radiusd.conf'
|
||||
freeradius_default_config: '"{{ freeradius_sites_available_folder }}"default'
|
||||
freeradius_dictionary_config: '"{{ freeradius_base_folder }}"dictionary'
|
||||
freeradius_clients_config: '"{{ freeradius_base_folder }}"clients.conf'
|
||||
freeradius_mod_ldap: '"{{ freeradius_mods_available_folder }}"ldap'
|
||||
freeradius_filter_config: '"{{ freeradius_base_folder }}"policy.d/filter'
|
||||
freeradius_daemon: freeradius
|
||||
bindradiusldap_password: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
66633833303261326432393637656134323532346134333361326333343737633662383935663761
|
||||
3737336530626166373035666632663338343331396162350a646337376435346534323131386136
|
||||
30333834643532656632366139343436663565326635303037326537633135323935393830373064
|
||||
3361393262623030620a353333353337643836636534366334646565633332393633626362626134
|
||||
31633237373761666637333364383435663633383363373134393432653136663235
|
||||
bindradiusclient_password: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
62356138356239653862643333303865323030383461396235356231653738343537366363636538
|
||||
3062303464396239313832613965336333343033356430660a663031653434393234666530613632
|
||||
31656339623365353236303130663732323138636335356562376562306430326231303662336339
|
||||
3732373766646663380a343430306437393436313163383162313532626138623235356132663035
|
||||
36303837353661643130323635343263303661376566306438373364386539623535
|
||||
freeradius_pam_config: /etc/pam.d/radiusd
|
||||
freeradius_service_config: /lib/systemd/system/freeradius.service
|
Loading…
Reference in New Issue