mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add RADIUS proxy support to ipalib CLI
https://fedorahosted.org/freeipa/ticket/3368
This commit is contained in:
committed by
Petr Viktorin
parent
efffcfdbc2
commit
4cb2c2813d
95
API.txt
95
API.txt
@@ -523,7 +523,7 @@ option: Int('ipasearchrecordslimit', attribute=True, autofill=False, cli_name='s
|
||||
option: Int('ipasearchtimelimit', attribute=True, autofill=False, cli_name='searchtimelimit', minvalue=-1, multivalue=False, required=False)
|
||||
option: Str('ipaselinuxusermapdefault', attribute=True, autofill=False, cli_name='ipaselinuxusermapdefault', multivalue=False, required=False)
|
||||
option: Str('ipaselinuxusermaporder', attribute=True, autofill=False, cli_name='ipaselinuxusermaporder', multivalue=False, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password',))
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password', u'radius'))
|
||||
option: Str('ipauserobjectclasses', attribute=True, autofill=False, cli_name='userobjectclasses', csv=True, multivalue=True, required=False)
|
||||
option: IA5Str('ipausersearchfields', attribute=True, autofill=False, cli_name='usersearch', multivalue=False, required=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
@@ -2552,6 +2552,81 @@ option: Str('version?', exclude='webui')
|
||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: radiusproxy_add
|
||||
args: 1,11,3
|
||||
arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
|
||||
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
|
||||
option: Int('ipatokenradiusretries', attribute=True, cli_name='retries', maxvalue=10, minvalue=0, multivalue=False, required=False)
|
||||
option: Password('ipatokenradiussecret', attribute=True, cli_name='secret', confirm=True, multivalue=False, required=True)
|
||||
option: Str('ipatokenradiusserver', attribute=True, cli_name='server', multivalue=True, required=True)
|
||||
option: Int('ipatokenradiustimeout', attribute=True, cli_name='timeout', minvalue=1, multivalue=False, required=False)
|
||||
option: Str('ipatokenusermapattribute', attribute=True, cli_name='userattr', multivalue=False, required=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
option: Str('setattr*', cli_name='setattr', exclude='webui')
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: radiusproxy_del
|
||||
args: 1,2,3
|
||||
arg: Str('cn', attribute=True, cli_name='name', multivalue=True, primary_key=True, query=True, required=True)
|
||||
option: Flag('continue', autofill=True, cli_name='continue', default=False)
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Output('result', <type 'dict'>, None)
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: radiusproxy_find
|
||||
args: 1,13,4
|
||||
arg: Str('criteria?', noextrawhitespace=False)
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
|
||||
option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
|
||||
option: Int('ipatokenradiusretries', attribute=True, autofill=False, cli_name='retries', maxvalue=10, minvalue=0, multivalue=False, query=True, required=False)
|
||||
option: Password('ipatokenradiussecret', attribute=True, autofill=False, cli_name='secret', confirm=True, multivalue=False, query=True, required=False)
|
||||
option: Str('ipatokenradiusserver', attribute=True, autofill=False, cli_name='server', multivalue=True, query=True, required=False)
|
||||
option: Int('ipatokenradiustimeout', attribute=True, autofill=False, cli_name='timeout', minvalue=1, multivalue=False, query=True, required=False)
|
||||
option: Str('ipatokenusermapattribute', attribute=True, autofill=False, cli_name='userattr', multivalue=False, query=True, required=False)
|
||||
option: Flag('pkey_only?', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
option: Int('sizelimit?', autofill=False, minvalue=0)
|
||||
option: Int('timelimit?', autofill=False, minvalue=0)
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Output('count', <type 'int'>, None)
|
||||
output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('truncated', <type 'bool'>, None)
|
||||
command: radiusproxy_mod
|
||||
args: 1,14,3
|
||||
arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
|
||||
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Str('delattr*', cli_name='delattr', exclude='webui')
|
||||
option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
|
||||
option: Int('ipatokenradiusretries', attribute=True, autofill=False, cli_name='retries', maxvalue=10, minvalue=0, multivalue=False, required=False)
|
||||
option: Password('ipatokenradiussecret', attribute=True, autofill=False, cli_name='secret', confirm=True, multivalue=False, required=False)
|
||||
option: Str('ipatokenradiusserver', attribute=True, autofill=False, cli_name='server', multivalue=True, required=False)
|
||||
option: Int('ipatokenradiustimeout', attribute=True, autofill=False, cli_name='timeout', minvalue=1, multivalue=False, required=False)
|
||||
option: Str('ipatokenusermapattribute', attribute=True, autofill=False, cli_name='userattr', multivalue=False, required=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
option: Str('rename', cli_name='rename', multivalue=False, primary_key=True, required=False)
|
||||
option: Flag('rights', autofill=True, default=False)
|
||||
option: Str('setattr*', cli_name='setattr', exclude='webui')
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: radiusproxy_show
|
||||
args: 1,4,3
|
||||
arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||
option: Flag('rights', autofill=True, default=False)
|
||||
option: Str('version?', exclude='webui')
|
||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: realmdomains_mod
|
||||
args: 0,11,3
|
||||
option: Str('add_domain', attribute=True, autofill=False, cli_name='add_domain', multivalue=False, required=False)
|
||||
@@ -3597,7 +3672,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: user_add
|
||||
args: 1,37,3
|
||||
args: 1,39,3
|
||||
arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, required=True)
|
||||
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
@@ -3611,7 +3686,9 @@ option: Str('givenname', attribute=True, cli_name='first', multivalue=False, req
|
||||
option: Str('homedirectory', attribute=True, cli_name='homedir', multivalue=False, required=False)
|
||||
option: Str('initials', attribute=True, autofill=True, cli_name='initials', multivalue=False, required=False)
|
||||
option: Str('ipasshpubkey', attribute=True, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password',))
|
||||
option: Str('ipatokenradiusconfiglink', attribute=True, cli_name='radius', multivalue=False, required=False)
|
||||
option: Str('ipatokenradiususername', attribute=True, cli_name='radius_username', multivalue=False, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password', u'radius'))
|
||||
option: Str('krbprincipalname', attribute=True, autofill=True, cli_name='principal', multivalue=False, required=False)
|
||||
option: Str('l', attribute=True, cli_name='city', multivalue=False, required=False)
|
||||
option: Str('loginshell', attribute=True, cli_name='shell', multivalue=False, required=False)
|
||||
@@ -3662,7 +3739,7 @@ output: Output('result', <type 'bool'>, None)
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('value', <type 'unicode'>, None)
|
||||
command: user_find
|
||||
args: 1,47,4
|
||||
args: 1,49,4
|
||||
arg: Str('criteria?', noextrawhitespace=False)
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=False, query=True, required=False)
|
||||
@@ -3679,7 +3756,9 @@ option: Str('in_netgroup*', cli_name='in_netgroups', csv=True)
|
||||
option: Str('in_role*', cli_name='in_roles', csv=True)
|
||||
option: Str('in_sudorule*', cli_name='in_sudorules', csv=True)
|
||||
option: Str('initials', attribute=True, autofill=False, cli_name='initials', multivalue=False, query=True, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, query=True, required=False, values=(u'password',))
|
||||
option: Str('ipatokenradiusconfiglink', attribute=True, autofill=False, cli_name='radius', multivalue=False, query=True, required=False)
|
||||
option: Str('ipatokenradiususername', attribute=True, autofill=False, cli_name='radius_username', multivalue=False, query=True, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, query=True, required=False, values=(u'password', u'radius'))
|
||||
option: Str('krbprincipalname', attribute=True, autofill=False, cli_name='principal', multivalue=False, query=True, required=False)
|
||||
option: Str('l', attribute=True, autofill=False, cli_name='city', multivalue=False, query=True, required=False)
|
||||
option: Str('loginshell', attribute=True, autofill=False, cli_name='shell', multivalue=False, query=True, required=False)
|
||||
@@ -3716,7 +3795,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
|
||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||
output: Output('truncated', <type 'bool'>, None)
|
||||
command: user_mod
|
||||
args: 1,38,3
|
||||
args: 1,40,3
|
||||
arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True)
|
||||
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||
@@ -3731,7 +3810,9 @@ option: Str('givenname', attribute=True, autofill=False, cli_name='first', multi
|
||||
option: Str('homedirectory', attribute=True, autofill=False, cli_name='homedir', multivalue=False, required=False)
|
||||
option: Str('initials', attribute=True, autofill=False, cli_name='initials', multivalue=False, required=False)
|
||||
option: Str('ipasshpubkey', attribute=True, autofill=False, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password',))
|
||||
option: Str('ipatokenradiusconfiglink', attribute=True, autofill=False, cli_name='radius', multivalue=False, required=False)
|
||||
option: Str('ipatokenradiususername', attribute=True, autofill=False, cli_name='radius_username', multivalue=False, required=False)
|
||||
option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password', u'radius'))
|
||||
option: Str('l', attribute=True, autofill=False, cli_name='city', multivalue=False, required=False)
|
||||
option: Str('loginshell', attribute=True, autofill=False, cli_name='shell', multivalue=False, required=False)
|
||||
option: Str('mail', attribute=True, autofill=False, cli_name='email', multivalue=True, required=False)
|
||||
|
||||
2
VERSION
2
VERSION
@@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000
|
||||
# #
|
||||
########################################################
|
||||
IPA_API_VERSION_MAJOR=2
|
||||
IPA_API_VERSION_MINOR=69
|
||||
IPA_API_VERSION_MINOR=70
|
||||
|
||||
@@ -24,5 +24,5 @@ attributeTypes: (2.16.840.1.113730.3.8.16.1.19 NAME 'ipatokenRadiusRetries' DESC
|
||||
attributeTypes: (2.16.840.1.113730.3.8.16.1.20 NAME 'ipatokenUserMapAttribute' DESC 'Attribute to map from the user entry for RADIUS server authentication' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'IPA OTP')
|
||||
objectClasses: (2.16.840.1.113730.3.8.16.2.1 NAME 'ipaToken' SUP top ABSTRACT DESC 'Abstract token class for tokens' MUST (ipatokenUniqueID) MAY (description $ ipatokenOwner $ ipatokenDisabled $ ipatokenNotBefore $ ipatokenNotAfter $ ipatokenVendor $ ipatokenModel $ ipatokenSerial) X-ORIGIN 'IPA OTP')
|
||||
objectClasses: (2.16.840.1.113730.3.8.16.2.2 NAME 'ipatokenTOTP' SUP ipaToken STRUCTURAL DESC 'TOTP Token Type' MAY (ipatokenOTPkey $ ipatokenOTPalgorithm $ ipatokenOTPdigits $ ipatokenTOTPclockOffset $ ipatokenTOTPtimeStep) X-ORIGIN 'IPA OTP')
|
||||
objectClasses: (2.16.840.1.113730.3.8.16.2.3 NAME 'ipatokenRadiusProxyUser' SUP top AUXILIARY DESC 'Radius Proxy User' MUST (ipatokenRadiusConfigLink) MAY (ipatokenRadiusUserName) X-ORIGIN 'IPA OTP')
|
||||
objectClasses: (2.16.840.1.113730.3.8.16.2.3 NAME 'ipatokenRadiusProxyUser' SUP top AUXILIARY DESC 'Radius Proxy User' MAY (ipatokenRadiusConfigLink $ ipatokenRadiusUserName) X-ORIGIN 'IPA OTP')
|
||||
objectClasses: (2.16.840.1.113730.3.8.16.2.4 NAME 'ipatokenRadiusConfiguration' SUP top STRUCTURAL DESC 'Proxy Radius Configuration' MUST (cn $ ipatokenRadiusServer $ ipatokenRadiusSecret) MAY (description $ ipatokenRadiusTimeout $ ipatokenRadiusRetries $ ipatokenUserMapAttribute) X-ORIGIN 'IPA OTP')
|
||||
|
||||
@@ -136,3 +136,10 @@ default:ObjectClass: top
|
||||
default:ObjectClass: nsIndex
|
||||
default:nsSystemIndex: false
|
||||
default:nsIndexType: eq
|
||||
|
||||
dn: cn=ipatokenradiusconfiglink,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
|
||||
default:cn: ipatokenradiusconfiglink
|
||||
default:ObjectClass: top
|
||||
default:ObjectClass: nsIndex
|
||||
default:nsSystemIndex: false
|
||||
only:nsIndexType: eq,pres,sub
|
||||
|
||||
@@ -11,3 +11,4 @@ add: nsslapd-pluginArg14: memberallowcmd
|
||||
add: nsslapd-pluginArg15: memberdenycmd
|
||||
add: nsslapd-pluginArg16: ipasudorunas
|
||||
add: nsslapd-pluginArg17: ipasudorunasgroup
|
||||
add: nsslapd-pluginArg18: ipatokenradiusconfiglink
|
||||
|
||||
@@ -7,3 +7,8 @@ dn: $SUFFIX
|
||||
add: aci:'(targetfilter = "(objectClass=ipaToken)")(targetattrs = "objectclass || ipatokenUniqueID || description || ipatokenOwner || ipatokenNotBefore || ipatokenNotAfter || ipatokenVendor || ipatokenModel || ipatokenSerial")(version 3.0; acl "Users can read basic token info"; allow (read, search, compare) userattr = "ipatokenOwner#USERDN";)'
|
||||
add: aci:'(targetfilter = "(objectClass=ipaToken)")(targetattrs = "ipatokenUniqueID || description || ipatokenOwner || ipatokenNotBefore || ipatokenNotAfter || ipatokenVendor || ipatokenModel || ipatokenSerial")(version 3.0; acl "Users can write basic token info"; allow (write) userattr = "ipatokenOwner#USERDN";)'
|
||||
add: aci:'(targetfilter = "(objectClass=ipatokenTOTP)")(targetattrs = "ipatokenOTPkey || ipatokenOTPalgorithm || ipatokenOTPdigits || ipatokenTOTPclockOffset || ipatokenTOTPtimeStep")(version 3.0; acl "Users can add TOTP token secrets"; allow (write, search) userattr = "ipatokenOwner#USERDN";)'
|
||||
|
||||
dn: cn=radiusproxy,$SUFFIX
|
||||
default: objectClass: nsContainer
|
||||
default: objectClass: top
|
||||
default: cn: radiusproxy
|
||||
|
||||
@@ -109,6 +109,7 @@ DEFAULT_CONFIG = (
|
||||
('container_dna_posix_ids', DN(('cn', 'posix-ids'), ('cn', 'dna'), ('cn', 'ipa'), ('cn', 'etc'))),
|
||||
('container_realm_domains', DN(('cn', 'Realm Domains'), ('cn', 'ipa'), ('cn', 'etc'))),
|
||||
('container_otp', DN(('cn', 'otp'))),
|
||||
('container_radiusproxy', DN(('cn', 'radiusproxy'))),
|
||||
|
||||
# Ports, hosts, and URIs:
|
||||
('xmlrpc_uri', 'http://localhost:8888/ipa/xml'),
|
||||
|
||||
@@ -202,7 +202,7 @@ class config(LDAPObject):
|
||||
cli_name='user_auth_type',
|
||||
label=_('Default user authentication types'),
|
||||
doc=_('Default types of supported user authentication'),
|
||||
values=(u'password',),
|
||||
values=(u'password', u'radius'),
|
||||
csv=True,
|
||||
),
|
||||
)
|
||||
|
||||
168
ipalib/plugins/radiusproxy.py
Normal file
168
ipalib/plugins/radiusproxy.py
Normal file
@@ -0,0 +1,168 @@
|
||||
# Authors:
|
||||
# Nathaniel McCallum <npmccallum@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2013 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ipalib.plugins.baseldap import *
|
||||
from ipalib import api, Str, Int, Password, _, ngettext
|
||||
from ipalib.plugable import Registry
|
||||
from ipalib.util import validate_hostname, validate_ipaddr
|
||||
from ipalib.errors import ValidationError
|
||||
import re
|
||||
|
||||
__doc__ = _("""
|
||||
RADIUS Proxy Servers
|
||||
|
||||
Manage RADIUS Proxy Servers.
|
||||
|
||||
IPA supports the use of an external RADIUS proxy server for krb5 OTP
|
||||
authentications. This permits a great deal of flexibility when
|
||||
integrating with third-party authentication services.
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
Add a new server:
|
||||
ipa radiusproxy-add MyRADIUS --server=radius.example.com:1812
|
||||
|
||||
Find all servers whose entries include the string "example.com":
|
||||
ipa radiusproxy-find example.com
|
||||
|
||||
Examine the configuration:
|
||||
ipa radiusproxy-show MyRADIUS
|
||||
|
||||
Change the secret:
|
||||
ipa radiusproxy-mod MyRADIUS --secret
|
||||
|
||||
Delete a configuration:
|
||||
ipa radiusproxy-del MyRADIUS
|
||||
""")
|
||||
|
||||
register = Registry()
|
||||
|
||||
LDAP_ATTRIBUTE = re.compile("^[a-zA-Z][a-zA-Z0-9-]*$")
|
||||
def validate_attributename(ugettext, attr):
|
||||
if not LDAP_ATTRIBUTE.match(attr):
|
||||
raise ValidationError(name="ipatokenusermapattribute",
|
||||
error=_('invalid attribute name'))
|
||||
|
||||
def validate_radiusserver(ugettext, server):
|
||||
split = server.rsplit(':', 1)
|
||||
server = split[0]
|
||||
if len(split) == 2:
|
||||
try:
|
||||
port = int(split[1])
|
||||
if (port < 0 or port > 65535):
|
||||
raise ValueError()
|
||||
except ValueError:
|
||||
raise ValidationError(name="ipatokenradiusserver",
|
||||
error=_('invalid port number'))
|
||||
|
||||
if validate_ipaddr(server):
|
||||
return
|
||||
|
||||
try:
|
||||
validate_hostname(server, check_fqdn=True, allow_underscore=True)
|
||||
except ValueError, e:
|
||||
raise errors.ValidationError(name="ipatokenradiusserver",
|
||||
error=e.message)
|
||||
|
||||
|
||||
@register()
|
||||
class radiusproxy(LDAPObject):
|
||||
"""
|
||||
RADIUS Server object.
|
||||
"""
|
||||
container_dn = api.env.container_radiusproxy
|
||||
object_name = _('RADIUS proxy server')
|
||||
object_name_plural = _('RADIUS proxy servers')
|
||||
object_class = ['ipatokenradiusconfiguration']
|
||||
default_attributes = ['cn', 'description', 'ipatokenradiusserver',
|
||||
'ipatokenradiustimeout', 'ipatokenradiusretries', 'ipatokenusermapattribute'
|
||||
]
|
||||
search_attributes = ['cn', 'description', 'ipatokenradiusserver']
|
||||
rdn_is_primary_key = True
|
||||
label = _('RADIUS Servers')
|
||||
label_singular = _('RADIUS Server')
|
||||
|
||||
takes_params = (
|
||||
Str('cn',
|
||||
cli_name='name',
|
||||
label=_('RADIUS proxy server name'),
|
||||
primary_key=True,
|
||||
),
|
||||
Str('description?',
|
||||
cli_name='desc',
|
||||
label=_('Description'),
|
||||
doc=_('A description of this RADIUS proxy server'),
|
||||
),
|
||||
Str('ipatokenradiusserver+', validate_radiusserver,
|
||||
cli_name='server',
|
||||
label=_('Server'),
|
||||
doc=_('The hostname or IP (with or without port)'),
|
||||
),
|
||||
Password('ipatokenradiussecret',
|
||||
cli_name='secret',
|
||||
label=_('Secret'),
|
||||
doc=_('The secret used to encrypt data'),
|
||||
confirm=True,
|
||||
flags=['no_option'],
|
||||
),
|
||||
Int('ipatokenradiustimeout?',
|
||||
cli_name='timeout',
|
||||
label=_('Timeout'),
|
||||
doc=_('The total timeout across all retries (in seconds)'),
|
||||
minvalue=1,
|
||||
),
|
||||
Int('ipatokenradiusretries?',
|
||||
cli_name='retries',
|
||||
label=_('Retries'),
|
||||
doc=_('The number of times to retry authentication'),
|
||||
minvalue=0,
|
||||
maxvalue=10,
|
||||
),
|
||||
Str('ipatokenusermapattribute?', validate_attributename,
|
||||
cli_name='userattr',
|
||||
label=_('User attribute'),
|
||||
doc=_('The username attribute on the user object'),
|
||||
),
|
||||
)
|
||||
|
||||
@register()
|
||||
class radiusproxy_add(LDAPCreate):
|
||||
__doc__ = _('Add a new RADIUS proxy server.')
|
||||
msg_summary = _('Added RADIUS proxy server "%(value)s"')
|
||||
|
||||
@register()
|
||||
class radiusproxy_del(LDAPDelete):
|
||||
__doc__ = _('Delete a RADIUS proxy server.')
|
||||
msg_summary = _('Deleted RADIUS proxy server "%(value)s"')
|
||||
|
||||
@register()
|
||||
class radiusproxy_mod(LDAPUpdate):
|
||||
__doc__ = _('Modify a RADIUS proxy server.')
|
||||
msg_summary = _('Modified RADIUS proxy server "%(value)s"')
|
||||
|
||||
@register()
|
||||
class radiusproxy_find(LDAPSearch):
|
||||
__doc__ = _('Search for RADIUS proxy servers.')
|
||||
msg_summary = ngettext(
|
||||
'%(count)d RADIUS proxy server matched', '%(count)d RADIUS proxy servers matched', 0
|
||||
)
|
||||
|
||||
@register()
|
||||
class radiusproxy_show(LDAPRetrieve):
|
||||
__doc__ = _('Display information about a RADIUS proxy server.')
|
||||
@@ -124,6 +124,12 @@ def validate_nsaccountlock(entry_attrs):
|
||||
raise errors.ValidationError(name='nsaccountlock',
|
||||
error=_('must be TRUE or FALSE'))
|
||||
|
||||
def radius_dn2pk(api, entry_attrs):
|
||||
cl = entry_attrs.get('ipatokenradiusconfiglink', None)
|
||||
if cl:
|
||||
pk = api.Object['radiusproxy'].get_primary_key_from_dn(cl[0])
|
||||
entry_attrs['ipatokenradiusconfiglink'] = [pk]
|
||||
|
||||
def convert_nsaccountlock(entry_attrs):
|
||||
if not 'nsaccountlock' in entry_attrs:
|
||||
entry_attrs['nsaccountlock'] = False
|
||||
@@ -199,7 +205,8 @@ class user(LDAPObject):
|
||||
object_class = ['posixaccount']
|
||||
object_class_config = 'ipauserobjectclasses'
|
||||
possible_objectclasses = [
|
||||
'meporiginentry', 'ipauserauthtypeclass', 'ipauser'
|
||||
'meporiginentry', 'ipauserauthtypeclass', 'ipauser',
|
||||
'ipatokenradiusproxyuser'
|
||||
]
|
||||
disallow_object_classes = ['krbticketpolicyaux']
|
||||
search_attributes_config = 'ipausersearchfields'
|
||||
@@ -207,7 +214,8 @@ class user(LDAPObject):
|
||||
'uid', 'givenname', 'sn', 'homedirectory', 'loginshell',
|
||||
'uidnumber', 'gidnumber', 'mail', 'ou',
|
||||
'telephonenumber', 'title', 'memberof', 'nsaccountlock',
|
||||
'memberofindirect', 'ipauserauthtype', 'userclass'
|
||||
'memberofindirect', 'ipauserauthtype', 'userclass',
|
||||
'ipatokenradiusconfiglink', 'ipatokenradiususername'
|
||||
]
|
||||
search_display_attributes = [
|
||||
'uid', 'givenname', 'sn', 'homedirectory', 'loginshell',
|
||||
@@ -371,7 +379,7 @@ class user(LDAPObject):
|
||||
cli_name='user_auth_type',
|
||||
label=_('User authentication types'),
|
||||
doc=_('Types of supported user authentication'),
|
||||
values=(u'password',),
|
||||
values=(u'password', u'radius'),
|
||||
csv=True,
|
||||
),
|
||||
Str('userclass*',
|
||||
@@ -380,6 +388,14 @@ class user(LDAPObject):
|
||||
doc=_('User category (semantics placed on this attribute are for '
|
||||
'local interpretation)'),
|
||||
),
|
||||
Str('ipatokenradiusconfiglink?',
|
||||
cli_name='radius',
|
||||
label=_('RADIUS proxy configuration'),
|
||||
),
|
||||
Str('ipatokenradiususername?',
|
||||
cli_name='radius_username',
|
||||
label=_('RADIUS proxy username'),
|
||||
),
|
||||
)
|
||||
|
||||
def _normalize_and_validate_email(self, email, config=None):
|
||||
@@ -560,6 +576,19 @@ class user_add(LDAPCreate):
|
||||
and 'ipauser' not in entry_attrs['objectclass']):
|
||||
entry_attrs['objectclass'].append('ipauser')
|
||||
|
||||
if 'ipatokenradiusconfiglink' in entry_attrs:
|
||||
cl = entry_attrs['ipatokenradiusconfiglink']
|
||||
if cl:
|
||||
if 'objectclass' not in entry_attrs:
|
||||
_entry = ldap.get_entry(dn, ['objectclass'])
|
||||
entry_attrs['objectclass'] = _entry['objectclass']
|
||||
|
||||
if 'ipatokenradiusproxyuser' not in entry_attrs['objectclass']:
|
||||
entry_attrs['objectclass'].append('ipatokenradiusproxyuser')
|
||||
|
||||
answer = self.api.Object['radiusproxy'].get_dn_if_exists(cl)
|
||||
entry_attrs['ipatokenradiusconfiglink'] = answer
|
||||
|
||||
return dn
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
@@ -604,9 +633,8 @@ class user_add(LDAPCreate):
|
||||
pass
|
||||
|
||||
self.obj.get_password_attributes(ldap, dn, entry_attrs)
|
||||
|
||||
convert_sshpubkey_post(ldap, dn, entry_attrs)
|
||||
|
||||
radius_dn2pk(self.api, entry_attrs)
|
||||
return dn
|
||||
|
||||
api.register(user_add)
|
||||
@@ -654,18 +682,31 @@ class user_mod(LDAPUpdate):
|
||||
# save the password so it can be displayed in post_callback
|
||||
setattr(context, 'randompassword', entry_attrs['userpassword'])
|
||||
if ('ipasshpubkey' in entry_attrs or 'ipauserauthtype' in entry_attrs
|
||||
or 'userclass' in entry_attrs):
|
||||
or 'userclass' in entry_attrs or 'ipatokenradiusconfiglink' in entry_attrs):
|
||||
if 'objectclass' in entry_attrs:
|
||||
obj_classes = entry_attrs['objectclass']
|
||||
else:
|
||||
(_dn, _entry_attrs) = ldap.get_entry(dn, ['objectclass'])
|
||||
_entry_attrs = ldap.get_entry(dn, ['objectclass'])
|
||||
obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
|
||||
|
||||
if 'ipasshpubkey' in entry_attrs and 'ipasshuser' not in obj_classes:
|
||||
obj_classes.append('ipasshuser')
|
||||
if 'ipauserauthtype' in entry_attrs and 'ipauserauthtype' not in obj_classes:
|
||||
|
||||
if 'ipauserauthtype' in entry_attrs and 'ipauserauthtypeclass' not in obj_classes:
|
||||
obj_classes.append('ipauserauthtypeclass')
|
||||
|
||||
if 'userclass' in entry_attrs and 'ipauser' not in obj_classes:
|
||||
obj_classes.append('ipauser')
|
||||
|
||||
if 'ipatokenradiusconfiglink' in entry_attrs:
|
||||
cl = entry_attrs['ipatokenradiusconfiglink']
|
||||
if cl:
|
||||
if 'ipatokenradiusproxyuser' not in obj_classes:
|
||||
obj_classes.append('ipatokenradiusproxyuser')
|
||||
|
||||
answer = self.api.Object['radiusproxy'].get_dn_if_exists(cl)
|
||||
entry_attrs['ipatokenradiusconfiglink'] = answer
|
||||
|
||||
return dn
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
@@ -680,6 +721,7 @@ class user_mod(LDAPUpdate):
|
||||
self.obj._convert_manager(entry_attrs, **options)
|
||||
self.obj.get_password_attributes(ldap, dn, entry_attrs)
|
||||
convert_sshpubkey_post(ldap, dn, entry_attrs)
|
||||
radius_dn2pk(self.api, entry_attrs)
|
||||
return dn
|
||||
|
||||
api.register(user_mod)
|
||||
@@ -703,6 +745,12 @@ class user_find(LDAPSearch):
|
||||
manager = options.get('manager')
|
||||
if manager is not None:
|
||||
options['manager'] = self.obj._normalize_manager(manager)
|
||||
|
||||
# Ensure that the RADIUS config link is a dn, not just the name
|
||||
cl = 'ipatokenradiusconfiglink'
|
||||
if cl in options:
|
||||
options[cl] = self.api.Object['radiusproxy'].get_dn(options[cl])
|
||||
|
||||
return super(user_find, self).execute(self, *args, **options)
|
||||
|
||||
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options):
|
||||
@@ -742,6 +790,7 @@ class user_show(LDAPRetrieve):
|
||||
self.obj._convert_manager(entry_attrs, **options)
|
||||
self.obj.get_password_attributes(ldap, dn, entry_attrs)
|
||||
convert_sshpubkey_post(ldap, dn, entry_attrs)
|
||||
radius_dn2pk(self.api, entry_attrs)
|
||||
return dn
|
||||
|
||||
api.register(user_show)
|
||||
|
||||
Reference in New Issue
Block a user