Commit 9787f8a9 authored by Jonathan Gazeley's avatar Jonathan Gazeley
Browse files

Add support for configuring LDAP natively

parent d515f272
......@@ -17,6 +17,7 @@
* [`freeradius::config`](#freeradiusconfig)
* [`freeradius::dictionary`](#freeradiusdictionary)
* [`freeradius::instantiate`](#freeradiusinstantiate)
* [`freeradius::ldap`](#freeradiusldap)
* [`freeradius::module`](#freeradiusmodule)
* [`freeradius::policy`](#freeradiuspolicy)
* [`freeradius::site`](#freeradiussite)
......@@ -267,6 +268,93 @@ Instantiate a module that is not automatically instantiated.
freeradius::instantiate { 'mymodule': }
```
#### `freeradius::ldap`
Configure LDAP support for FreeRADIUS
##### `identity`
LDAP account for searching the directory. Required.
##### `password`
Password for the `identity` account. Required.
##### `basedn`
Unless overridden in another section, the dn from which all searches will start from. Required.
##### `server`
Hostname of IP address of the LDAP server. Note that this needs to match the name(s) in the LDAP server
certificate, if you're using ldaps. Default: `localhost`
##### `port`
Port to connect to the LDAP server on. Default: `389`
##### `uses`
How many times the connection can be used before being re-established. This is useful for things
like load balancers, which may exhibit sticky behaviour without it. `0` is unlimited. Default: `0`
##### `idle`
Sets the idle time before keepalive probes are sent. Default `60`
This option may not be supported by your LDAP library. If this configuration entry appears in the
output of `radiusd -X` then it is supported. Otherwise, it is unsupported and changing it will do nothing.
##### `probes`
Sets the maximum number of keepalive probes TCP should send before dropping the connection. Default: `3`
This option may not be supported by your LDAP library. If this configuration entry appears in the
output of `radiusd -X` then it is supported. Otherwise, it is unsupported and changing it will do nothing.
##### `interval`
Setss the interval in seconds between individual keepalive probes. Default: `3`
This option may not be supported by your LDAP library. If this configuration entry appears in the
output of `radiusd -X` then it is supported. Otherwise, it is unsupported and changing it will do nothing.
##### `timeout`
Number of seconds to wait for LDAP query to finish. Default: `10`
##### `start`
Connections to create during module instantiation. If the server cannot create specified number of
connections during instantiation it will exit. Set to 0 to allow the server to start without the
directory being available. This option only works with FR3; setting it on FR2 will have no effect.
Default: `${thread[pool].start_servers}`
##### `min`
Minimum number of connections to keep open. This option only works with FR3; setting it on FR2 will have no effect.
Default: `${thread[pool].min_spare_servers}`
##### `max`
Maximum number of connections. Default: `${thread[pool].max_servers}`
##### `spare`
Spare connections to be left idle. This option only works with FR3; setting it on FR2 will have no effect.
Default: `${thread[pool].max_spare_servers}`
##### `starttls`
Set this to 'yes' to use TLS encrypted connections to the LDAP database by using the StartTLS extended operation.
The StartTLS operation is supposed to be used with normal ldap connections instead of using ldaps (port 636) connections
Default: `no`
##### `cafile`
Path to CA cert file for TLS
##### `certfile`
Path to cert file for TLS
##### `keyfile`
Path to key file for TLS
##### `requirecert`
Certificate Verification requirements. Choose from:
'never' (do not even bother trying)
'allow' (try, but don't fail if the certificate cannot be verified)
'demand' (fail if the certificate does not verify)
'hard' (similar to 'demand' but fails if TLS cannot negotiate)
Default: `allow`
#### `freeradius::module`
Install a module from a flat file.
......
# Configure LDAP support for FreeRADIUS
define freeradius::ldap (
$identity,
$password,
$basedn,
$server = 'localhost',
$port = 389,
$uses = 0,
$idle = 60,
$probes = 3,
$interval = 3,
$timeout = 10,
$start = '${thread[pool].start_servers}',
$min = '${thread[pool].min_spare_servers}',
$max = '${thread[pool].max_servers}',
$spare = '${thread[pool].max_spare_servers}',
$ensure = 'present',
$starttls = 'no',
$cafile = '',
$certfile = '',
$keyfile = '',
$requirecert = 'allow',
) {
$fr_package = $::freeradius::params::fr_package
$fr_service = $::freeradius::params::fr_service
$fr_modulepath = $::freeradius::params::fr_modulepath
$fr_group = $::freeradius::params::fr_group
# Validate our inputs
# Hostnames
unless (is_domain_name($server) or is_ip_address($server)) {
fail('$server must be a valid hostname or IP address')
}
# Fake booleans (FR uses yes/no instead of true/false)
unless $starttls in ['yes', 'no'] {
fail('$starttls must be yes or no')
}
# Validate multiple choice options
unless $requirecert in ['never', 'allow', 'demand', 'hard'] {
fail('$requirecert must be one of never, allow, demand, hard')
}
# Validate integers
unless is_integer($port) {
fail('$port must be an integer')
}
unless is_integer($uses) {
fail('$uses must be an integer')
}
unless is_integer($idle) {
fail('$idle must be an integer')
}
unless is_integer($probes) {
fail('$probes must be an integer')
}
unless is_integer($interval) {
fail('$interval must be an integer')
}
unless is_integer($timeout) {
fail('$timeout must be an integer')
}
# Generate a module config, based on ldap.conf
file { "${fr_modulepath}/${name}":
ensure => $ensure,
mode => '0640',
owner => 'root',
group => $fr_group,
content => template("freeradius/ldap.fr${::freeradius_maj_version}.erb"),
require => [Package[$fr_package], Group[$fr_group]],
notify => Service[$fr_service],
}
}
# -*- text -*-
#
# $Id$
# Lightweight Directory Access Protocol (LDAP)
#
# This module definition allows you to use LDAP for
# authorization and authentication.
#
# See raddb/sites-available/default for reference to the
# ldap module in the authorize and authenticate sections.
#
# However, LDAP can be used for authentication ONLY when the
# Access-Request packet contains a clear-text User-Password
# attribute. LDAP authentication will NOT work for any other
# authentication method.
#
# This means that LDAP servers don't understand EAP. If you
# force "Auth-Type = LDAP", and then send the server a
# request containing EAP authentication, then authentication
# WILL NOT WORK.
#
# The solution is to use the default configuration, which does
# work.
#
# Setting "Auth-Type = LDAP" is ALMOST ALWAYS WRONG. We
# really can't emphasize this enough.
#
ldap {
#
# Note that this needs to match the name in the LDAP
# server certificate, if you're using ldaps.
server = "<%= @server %>"
#identity = "<%= @identity %>"
#password = <%= @password %>
basedn = "<%= @basedn %>"
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
#base_filter = "(objectclass=radiusprofile)"
# How many connections to keep open to the LDAP server.
# This saves time over opening a new LDAP socket for
# every authentication request.
ldap_connections_number = <%= @max %>
# How many times the connection can be used before
# being re-established. This is useful for things
# like load balancers, which may exhibit sticky
# behaviour without it. (0) is unlimited.
max_uses = <%= @uses %>
# Port to connect on, defaults to 389. Setting this to
# 636 will enable LDAPS if start_tls (see below) is not
# able to be used.
#port = <%= @port %>
# seconds to wait for LDAP query to finish. default: 20
timeout = <%= @timeout %>
# seconds LDAP server has to process the query (server-side
# time limit). default: 20
#
# LDAP_OPT_TIMELIMIT is set to this value.
timelimit = 3
#
# seconds to wait for response of the server. (network
# failures) default: 10
#
# LDAP_OPT_NETWORK_TIMEOUT is set to this value.
net_timeout = 1
#
# This subsection configures the tls related items
# that control how FreeRADIUS connects to an LDAP
# server. It contains all of the "tls_*" configuration
# entries used in older versions of FreeRADIUS. Those
# configuration entries can still be used, but we recommend
# using these.
#
tls {
# Set this to 'yes' to use TLS encrypted connections
# to the LDAP database by using the StartTLS extended
# operation.
#
# The StartTLS operation is supposed to be
# used with normal ldap connections instead of
# using ldaps (port 636) connections
start_tls = <%= @starttls %>
<% if @cafile %> cacertfile = <%= @cafile %><% end %>
# cacertdir = /path/to/ca/dir/
<% if @certfile %> certfile = <%= @certfile %><% end %>
<% if @keyfile %> keyfile = <%= @keyfile %><% end %>
# randfile = /path/to/rnd
# Certificate Verification requirements. Can be:
# "never" (don't even bother trying)
# "allow" (try, but don't fail if the cerificate
# can't be verified)
# "demand" (fail if the certificate doesn't verify.)
#
# The default is "allow"
require_cert = "<%= @requirecert %>"
}
# default_profile = "cn=radprofile,ou=dialup,o=My Org,c=UA"
# profile_attribute = "radiusProfileDn"
# access_attr = "dialupAccess"
# Mapping of RADIUS dictionary attributes to LDAP
# directory attributes.
dictionary_mapping = ${confdir}/ldap.attrmap
# Set password_attribute = nspmPassword to get the
# user's password from a Novell eDirectory
# backend. This will work ONLY IF FreeRADIUS has been
# built with the --with-edir configure option.
#
# See also the following links:
#
# http://www.novell.com/coolsolutions/appnote/16745.html
# https://secure-support.novell.com/KanisaPlatform/Publishing/558/3009668_f.SAL_Public.html
#
# Novell may require TLS encrypted sessions before returning
# the user's password.
#
# password_attribute = userPassword
# Un-comment the following to disable Novell
# eDirectory account policy check and intruder
# detection. This will work *only if* FreeRADIUS is
# configured to build with --with-edir option.
#
edir_account_policy_check = no
#
# Group membership checking. Disabled by default.
#
# groupname_attribute = cn
# groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{control:Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:Ldap-UserDn})))"
# groupmembership_attribute = radiusGroupName
# compare_check_items = yes
# do_xlat = yes
# access_attr_used_for_allow = yes
#
# The following two configuration items are for Active Directory
# compatibility. If you see the helpful "operations error"
# being returned to the LDAP module, uncomment the next
# two lines.
#
# chase_referrals = yes
# rebind = yes
#
# By default, if the packet contains a User-Password,
# and no other module is configured to handle the
# authentication, the LDAP module sets itself to do
# LDAP bind for authentication.
#
# THIS WILL ONLY WORK FOR PAP AUTHENTICATION.
#
# THIS WILL NOT WORK FOR CHAP, MS-CHAP, or 802.1x (EAP).
#
# You can disable this behavior by setting the following
# configuration entry to "no".
#
# allowed values: {no, yes}
# set_auth_type = yes
# ldap_debug: debug flag for LDAP SDK
# (see OpenLDAP documentation). Set this to enable
# huge amounts of LDAP debugging on the screen.
# You should only use this if you are an LDAP expert.
#
# default: 0x0000 (no debugging messages)
# Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS)
#ldap_debug = 0x0028
#
# Keepalive configuration. This MAY NOT be supported by your
# LDAP library. If these configuration entries appear in the
# output of "radiusd -X", then they are supported. Otherwise,
# they are unsupported, and changing them will do nothing.
#
keepalive {
# LDAP_OPT_X_KEEPALIVE_IDLE
idle = <%= @idle %>
# LDAP_OPT_X_KEEPALIVE_PROBES
probes = <%= @probes %>
# LDAP_OPT_X_KEEPALIVE_INTERVAL
interval = <%= @interval %>
}
}
# -*- text -*-
#
# $Id$
#
# Lightweight Directory Access Protocol (LDAP)
#
ldap {
# Note that this needs to match the name(s) in the LDAP server
# certificate, if you're using ldaps. See OpenLDAP documentation
# for the behavioral semantics of specifying more than one host.
#
# Depending on the libldap in use, server may be an LDAP URI.
# In the case of OpenLDAP this allows additional the following
# additional schemes:
# - ldaps:// (LDAP over SSL)
# - ldapi:// (LDAP over Unix socket)
# - ldapc:// (Connectionless LDAP)
server = '<%= @server %>'
# server = 'ldap.rrdns.example.org'
# server = 'ldap.rrdns.example.org'
# Port to connect on, defaults to 389, will be ignored for LDAP URIs.
# port = <%= @port %>
# Administrator account for searching and possibly modifying.
# If using SASL + KRB5 these should be commented out.
# identity = '<%= @identity %>'
# password = mypass
# Unless overridden in another section, the dn from which all
# searches will start from.
base_dn = '<%= @basedn %>'
#
# SASL parameters to use for admin binds
#
# When we're prompted by the SASL library, the config items in the SASL
# section (in addition to the identity password config items above)
# determine the responses given.
#
# If any directive is commented out, a NULL response will be
# provided to cyrus-sasl.
#
# Unfortunately the only way to control Keberos here is through
# environmental variables, as cyrus-sasl provides no API to
# set the kerberos (libkrb5) config directly.
#
# Full documentation for MIT krb5 can be found here:
#
# http://web.mit.edu/kerberos/krb5-devel/doc/admin/env_variables.html
#
# At a minimum you probably want to set KRB5_CLIENT_KTNAME.
#
sasl {
# SASL mechanism
# mech = 'PLAIN'
# SASL authorisation identity to proxy.
# proxy = 'autz_id'
# SASL realm. Used for kerberos.
# realm = 'example.org'
}
#
# Generic valuepair attribute
#
# If set, this will attribute will be retrieved in addition to any
# mapped attributes.
#
# Values should be in the format:
# <radius attr> <op> <value>
#
# Where:
# <radius attr>: Is the attribute you wish to create
# with any valid list and request qualifiers.
# <op>: Is any assignment operator (=, :=, +=, -=).
# <value>: Is the value to parse into the new valuepair.
# If the value is wrapped in double quotes it
# will be xlat expanded.
# valuepair_attribute = 'radiusAttribute'
#
# Mapping of LDAP directory attributes to RADIUS dictionary attributes.
#
# WARNING: Although this format is almost identical to the unlang
# update section format, it does *NOT* mean that you can use other
# unlang constructs in module configuration files.
#
# Configuration items are in the format:
# <radius attr> <op> <ldap attr>
#
# Where:
# <radius attr>: Is the destination RADIUS attribute
# with any valid list and request qualifiers.
# <op>: Is any assignment attribute (=, :=, +=, -=).
# <ldap attr>: Is the attribute associated with user or
# profile objects in the LDAP directory.
# If the attribute name is wrapped in double
# quotes it will be xlat expanded.
#
# Request and list qualifiers may also be placed after the 'update'
# section name to set defaults destination requests/lists
# for unqualified RADIUS attributes.
#
# Note: LDAP attribute names should be single quoted unless you want
# the name value to be derived from an xlat expansion, or an
# attribute ref.
update {
control:Password-With-Header += 'userPassword'
# control:NT-Password := 'ntPassword'
# reply:Reply-Message := 'radiusReplyMessage'
# reply:Tunnel-Type := 'radiusTunnelType'
# reply:Tunnel-Medium-Type := 'radiusTunnelMediumType'
# reply:Tunnel-Private-Group-ID := 'radiusTunnelPrivategroupId'
# Where only a list is specified as the RADIUS attribute,
# the value of the LDAP attribute is parsed as a valuepair
# in the same format as the 'valuepair_attribute' (above).
#control: += 'radiusControlAttribute'
#request: += 'radiusRequestAttribute'
#reply: += 'radiusReplyAttribute'
}
# Set to yes if you have eDirectory and want to use the universal
# password mechanism.
# edir = no
# Set to yes if you want to bind as the user after retrieving the
# Cleartext-Password. This will consume the login grace, and
# verify user authorization.
# edir_autz = no
# Note: set_auth_type was removed in v3.x.x
# Equivalent functionality can be achieved by adding the following
# stanza to the authorize {} section of your virtual server.
#
# ldap
# if ((ok || updated) && User-Password) {
# update {
# control:Auth-Type := ldap
# }
# }
#
# User object identification.
#
user {
# Where to start searching in the tree for users
base_dn = "${..base_dn}"
# Filter for user objects, should be specific enough
# to identify a single user object.
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
# SASL parameters to use for user binds
#
# When we're prompted by the SASL library, these control
# the responses given.
#
# Any of the config items below may be an attribute ref
# or and expansion. This allows different SASL mechs,
# proxy IDs and realms to be used for different users.
#
sasl {
# SASL mechanism
# mech = 'PLAIN'
# SASL authorisation identity to proxy.
# proxy = &User-Name
# SASL realm. Used for kerberos.
# realm = 'example.org'
}
# Search scope, may be 'base', 'one', sub' or 'children'
# scope = 'sub'
# Server side result sorting
#
# A list of space delimited attributes to order the result
# set by, if the filter matches multiple objects.
# Only the first result in the set will be processed.
#
# If the attribute name is prefixed with a hyphen '-' the
# sorting order will be reversed for that attribute.
#
# If sort_by is set, and the server does not support sorting
# the search will fail.
# sort_by = '-uid'
# If this is undefined, anyone is authorised.
# If it is defined, the contents of this attribute
# determine whether or not the user is authorised
# access_attribute = 'dialupAccess'
# Control whether the presence of 'access_attribute'
# allows access, or denys access.
#
# If 'yes', and the access_attribute is present, or
# 'no' and the access_attribute is absent then access
# will be allowed.
#
# If 'yes', and the access_attribute is absent, or
# 'no' and the access_attribute is present, then
# access will not be allowed.
#
# If the value of the access_attribute is 'false', it
# will negate the result.
#
# e.g.
# access_positive = yes
# access_attribute = userAccessAllowed
#
# With an LDAP object containing:
# userAccessAllowed: false
#
# Will result in the user being locked out.
# access_positive = yes
}
#
# User membership checking.
#
group {
# Where to start searching in the tree for groups
base_dn = "${..base_dn}"
# Filter for group objects, should match all available
# group objects a user might be a member of.
filter = '(objectClass=posixGroup)'
# Search scope, may be 'base', 'one', sub' or 'children'
# scope = 'sub'
# Attribute that uniquely identifies a group.
# Is used when converting group DNs to group
# names.
# name_attribute = cn
# Filter to find group objects a user is a member of.
# That is, group objects with attributes that
# identify members (the inverse of membership_attribute).
# membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
# The attribute in user objects which contain the names
# or DNs of groups a user is a member of.
#
# Unless a conversion between group name and group DN is
# needed, there's no requirement for the group objects
# referenced to actually exist.
membership_attribute = 'memberOf'
# If cacheable_name or cacheable_dn are enabled,
# all group information for the user will be
# retrieved from the directory and written to LDAP-Group
# attributes appropriate for the instance of rlm_ldap.
#
# For group comparisons these attributes will be checked
# instead of querying the LDAP directory directly.
#
# This feature is intended to be used with rlm_cache.
#
# If you wish to use this feature, you should enable
# the type that matches the format of your check items
# i.e. if your groups are specified as DNs then enable
# cacheable_dn else enable cacheable_name.
# cacheable_name = 'no'
# cacheable_dn = 'no'
# Override the normal cache attribute (<inst>-LDAP-Group or