Add SMB attributes for users

SMB attributes are used by Samba domain controller when reporting
details about IPA users via LSA DCE RPC calls.

Based on the initial work from the external plugin:
https://github.com/abbra/freeipa-user-trust-attributes

Related: https://pagure.io/freeipa/issue/3999

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Signed-off-by: Tibor Dudlák <tdudlak@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
This commit is contained in:
Tibor Dudlák
2019-04-02 16:23:09 +02:00
parent 339771b0d8
commit c18ee9b641
6 changed files with 219 additions and 8 deletions

24
API.txt
View File

@@ -4988,7 +4988,7 @@ output: Output('result', type=[<type 'dict'>])
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: ListOfPrimaryKeys('value')
command: stageuser_find/1
args: 1,54,4
args: 1,58,4
arg: Str('criteria?')
option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('carlicense*', autofill=False)
@@ -5008,6 +5008,10 @@ option: Str('in_netgroup*', cli_name='in_netgroups')
option: Str('in_role*', cli_name='in_roles')
option: Str('in_sudorule*', cli_name='in_sudorules')
option: Str('initials?', autofill=False)
option: Str('ipanthomedirectory?', autofill=False, cli_name='smb_home_dir')
option: StrEnum('ipanthomedirectoryrive?', autofill=False, cli_name='smb_home_drive', values=[u'A:', u'B:', u'C:', u'D:', u'E:', u'F:', u'G:', u'H:', u'I:', u'J:', u'K:', u'L:', u'M:', u'N:', u'O:', u'P:', u'Q:', u'R:', u'S:', u'T:', u'U:', u'V:', u'W:', u'X:', u'Y:', u'Z:'])
option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
@@ -5049,7 +5053,7 @@ output: ListOfEntries('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: Output('truncated', type=[<type 'bool'>])
command: stageuser_mod/1
args: 1,47,3
args: 1,51,3
arg: Str('uid', cli_name='login')
option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -5066,6 +5070,10 @@ option: Int('gidnumber?', autofill=False)
option: Str('givenname?', autofill=False, cli_name='first')
option: Str('homedirectory?', autofill=False, cli_name='homedir')
option: Str('initials?', autofill=False)
option: Str('ipanthomedirectory?', autofill=False, cli_name='smb_home_dir')
option: StrEnum('ipanthomedirectoryrive?', autofill=False, cli_name='smb_home_drive', values=[u'A:', u'B:', u'C:', u'D:', u'E:', u'F:', u'G:', u'H:', u'I:', u'J:', u'K:', u'L:', u'M:', u'N:', u'O:', u'P:', u'Q:', u'R:', u'S:', u'T:', u'U:', u'V:', u'W:', u'X:', u'Y:', u'Z:'])
option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
@@ -6072,7 +6080,7 @@ output: Output('result', type=[<type 'bool'>])
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
command: user_find/1
args: 1,57,4
args: 1,61,4
arg: Str('criteria?')
option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('carlicense*', autofill=False)
@@ -6092,6 +6100,10 @@ option: Str('in_netgroup*', cli_name='in_netgroups')
option: Str('in_role*', cli_name='in_roles')
option: Str('in_sudorule*', cli_name='in_sudorules')
option: Str('initials?', autofill=False)
option: Str('ipanthomedirectory?', autofill=False, cli_name='smb_home_dir')
option: StrEnum('ipanthomedirectoryrive?', autofill=False, cli_name='smb_home_drive', values=[u'A:', u'B:', u'C:', u'D:', u'E:', u'F:', u'G:', u'H:', u'I:', u'J:', u'K:', u'L:', u'M:', u'N:', u'O:', u'P:', u'Q:', u'R:', u'S:', u'T:', u'U:', u'V:', u'W:', u'X:', u'Y:', u'Z:'])
option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
@@ -6136,7 +6148,7 @@ output: ListOfEntries('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: Output('truncated', type=[<type 'bool'>])
command: user_mod/1
args: 1,48,3
args: 1,52,3
arg: Str('uid', cli_name='login')
option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False)
@@ -6153,6 +6165,10 @@ option: Int('gidnumber?', autofill=False)
option: Str('givenname?', autofill=False, cli_name='first')
option: Str('homedirectory?', autofill=False, cli_name='homedir')
option: Str('initials?', autofill=False)
option: Str('ipanthomedirectory?', autofill=False, cli_name='smb_home_dir')
option: StrEnum('ipanthomedirectoryrive?', autofill=False, cli_name='smb_home_drive', values=[u'A:', u'B:', u'C:', u'D:', u'E:', u'F:', u'G:', u'H:', u'I:', u'J:', u'K:', u'L:', u'M:', u'N:', u'O:', u'P:', u'Q:', u'R:', u'S:', u'T:', u'U:', u'V:', u'W:', u'X:', u'Y:', u'Z:'])
option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')

View File

@@ -129,7 +129,85 @@ The SMB service object needs to have:
- NT attributes, including `ipaNTSecurityIdentifier`
`ipaNTSecurityIdentifier` is filled in by the SID generation plugin at the
object creation time.
object creation time for SMB service.
`ipaNTSecurityIdentifier` attribute is a part of `ipaNTUserAttrs` object class
for users and SMB services. IPA groups also can contain the attribute via
`ipaNTGroupAttrs` object class.
With the help of the `sidgen` plugin, ipaNTSecurityIdentifier attribute is only
added when:
- the object has POSIX attributes `uidNumber` and `gidNumber`
- the values of those attributes are within 32-bit unsigned integer
- the object has any of the following object classes: `ipaIDObject`,
`posixAccount`, or `posixGroup`
- the object has no `ipaNTSecurityIdentifier` attribute already.
`sidgen` plugin will add `ipaNTUserAttrs` object class for non-group objects and
`ipaNTGroupAttr` for the group object type. A plugin is triggered at an object
creation or via an LDAP task. One can trigger task run by running
`ipa-adtrust-install --add-sids` on the trust controller.
LDAP object class `ipaNTUserAttrs` defines few other attributes. These
attributes, called below 'SMB attributes', are required by the domain controller
to define content of an NT token for an authenticated identity (user or a
machine account).
SMB attributes are:
- `ipaNTLogonScript`
: Path to a script executed on a Windows system at logon
- `ipaNTProfilePath`
: Path to a user profile, in UNC format `\\server\share\`
- `ipaNTHomeDirectory`
: Path to a user's home directory, in UNC format `\\server\share`
- `ipaNTHomeDirectoryDrive`
: a letter `[A-Z]` for the drive to mount the home directory to on a Windows system
All SMB attributes require the presence of `ipaNTUserAttrs` object class in the
user object LDAP entry. This object class cannot be added without
`ipaNTSecurityIdentifier`. Adding SID requires to consume IDs from a range
suitable for SIDs and this logic is recorded in the `sidgen` plugin. Thus, until
SID is generated, no attributes can be set on the user entry.
As result of it, SMB attributes are not available at `ipa user-add` or
`ipa stageuser-add` level. Instead, it is possible to modify a user object with
`ipa user-mod` or `ipa stageuser-mod` commands:
```
$ ipa user-mod --help
Usage: ipa [global-options] user-mod LOGIN [options]
Modify a user.
Options:
...
--smb-logon-script=STR SMB logon script path
--smb-profile-path=STR SMB profile path
--smb-home-dir=STR SMB Home Directory
--smb-home-drive=['A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:', 'K:',
'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:', 'U:', 'V:',
'W:', 'X:', 'Y:', 'Z:']
SMB Home Directory Drive
...
$ ipa stageuser-mod --help
Usage: ipa [global-options] stageuser-mod LOGIN [options]
Modify a stage user.
Options:
...
--smb-logon-script=STR SMB logon script path
--smb-profile-path=STR SMB profile path
--smb-home-dir=STR SMB Home Directory
--smb-home-drive=['A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:', 'K:',
'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:', 'U:', 'V:',
'W:', 'X:', 'Y:', 'Z:']
SMB Home Directory Drive
...
```
Due to limitations on how SMB attributes can be added, Web UI shows the section
"User attributes for SMB services" without any values for those users who have
no SID assigned.
### Changes to LDAP storage
@@ -139,7 +217,7 @@ Since SMB service belongs to `cn=services,cn=accounts,$basedn` subtree, new ACI
has to be added.
```
'System: Read POSIX details of the services': {
'System: Read POSIX details of the SMB services': {
'replaces_global_anonymous_aci': True,
'ipapermbindruletype': 'all',
'ipapermright': {'read', 'search', 'compare'},
@@ -151,6 +229,11 @@ has to be added.
}
```
SMB attributes for users are now accessible for self-modification and also
readable by the members of `cn=adtrust agents,cn=sysaccounts,cn=etc,$basedn`
group which contains, among others, service principals of the domain
controllers.
### Changes to LDAP plugins
As mentioned above, both domain controller and domain member need to know common

View File

@@ -361,6 +361,42 @@ return {
fields: [
{ $type: 'multivalued', name: 'carlicense' }
]
},
{
name: 'smb_attributes',
label: '@i18n:objects.smb_attributes.title',
show_cond: ['oc_ipantuserattrs'],
fields: [{
name: 'ipantlogonscript',
tooltip: {
title: '@i18n:objects.smb_attributes.ipantlogonscript_tooltip'
}
},
{
name: 'ipantprofilepath',
tooltip: {
title: '@i18n:objects.smb_attributes.ipantprofilepath_tooltip'
}
},
{
name: 'ipanthomedirectory',
tooltip: {
title: '@i18n:objects.smb_attributes.ipanthomedirectory_tooltip'
}
},
{
name: 'ipanthomedirectorydrive',
$type: 'select',
options: IPA.create_options([
'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:',
'J:', 'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:',
'S:', 'T:', 'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:'
]),
tooltip: {
title: '@i18n:objects.smb_attributes.ipanthomedirectorydrive_tooltip'
}
}
]
}
],
actions: [
@@ -444,6 +480,7 @@ return {
IPA.user.self_service_other_user_evaluator,
IPA.user.preserved_user_evaluator,
IPA.user.no_password_evaluator,
IPA.object_class_evaluator,
IPA.cert.certificate_evaluator
],
summary_conditions: [
@@ -576,6 +613,7 @@ IPA.user.details_facet = function(spec, no_init) {
});
var user_command = that.details_facet_create_refresh_command();
batch.add_command(user_command);
var pwpolicy_command = rpc.command({

View File

@@ -0,0 +1,5 @@
# Add an explicit self-service ACI to allow writing to manage trust attributes
# for the owner of the object
dn: cn=users,cn=accounts,$SUFFIX
add:aci:(targetattr = "ipantlogonscript || ipantprofilepath || ipanthomedirectory || ipanthomedirectorydrive")(version 3.0;acl "system:Allow trust agents to read user SMB attributes";allow (read) groupdn = "ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)
add:aci:(targetattr = "ipantlogonscript || ipantprofilepath || ipanthomedirectory || ipanthomedirectorydrive")(version 3.0;acl "selfservice:Users can manage their SMB attributes";allow (write) userdn = "ldap:///self";)

View File

@@ -50,6 +50,7 @@ from ipalib.util import (
ensure_krbcanonicalname_set
)
if six.PY3:
unicode = str
@@ -123,6 +124,29 @@ def fix_addressbook_permission_bindrule(name, template, is_new,
template['ipapermbindruletype'] = 'anonymous'
def update_samba_attrs(ldap, dn, entry_attrs, **options):
smb_attrs = {'ipantlogonscript', 'ipantprofilepath',
'ipanthomedirectory', 'ipanthomedirectorydrive'}
if 'objectclass' not in entry_attrs:
try:
oc = ldap.get_entry(dn, ['objectclass'])['objectclass']
except errors.NotFound:
# In case the entry really does not exist,
# compare against an empty list
oc = []
else:
oc = entry_attrs['objectclass']
if 'ipantuserattrs' not in (item.lower() for item in oc):
for attr in smb_attrs:
if options.get(attr, None):
raise errors.ValidationError(
name=attr,
error=_(
'Object class ipaNTUserAttrs is missing, '
'user entry cannot have SMB attributes.'
)
)
class baseuser(LDAPObject):
"""
@@ -136,7 +160,8 @@ class baseuser(LDAPObject):
object_class_config = 'ipauserobjectclasses'
possible_objectclasses = [
'meporiginentry', 'ipauserauthtypeclass', 'ipauser',
'ipatokenradiusproxyuser', 'ipacertmapobject'
'ipatokenradiusproxyuser', 'ipacertmapobject',
'ipantuserattrs'
]
disallow_object_classes = ['krbticketpolicyaux']
permission_filter_objectclasses = ['posixaccount']
@@ -149,7 +174,8 @@ class baseuser(LDAPObject):
'ipatokenradiusconfiglink', 'ipatokenradiususername',
'krbprincipalexpiration', 'usercertificate;binary',
'krbprincipalname', 'krbcanonicalname',
'ipacertmapdata'
'ipacertmapdata', 'ipantlogonscript', 'ipantprofilepath',
'ipanthomedirectory', 'ipanthomedirectorydrive'
]
search_display_attributes = [
'uid', 'givenname', 'sn', 'homedirectory', 'krbcanonicalname',
@@ -378,6 +404,30 @@ class baseuser(LDAPObject):
doc=_('Certificate mapping data'),
flags=['no_create', 'no_update', 'no_search'],
),
Str('ipantlogonscript?',
cli_name='smb_logon_script',
label=_('SMB logon script path'),
flags=['no_create'],
),
Str('ipantprofilepath?',
cli_name='smb_profile_path',
label=_('SMB profile path'),
flags=['no_create'],
),
Str('ipanthomedirectory?',
cli_name='smb_home_dir',
label=_('SMB Home Directory'),
flags=['no_create'],
),
StrEnum('ipanthomedirectoryrive?',
cli_name='smb_home_drive',
label=_('SMB Home Directory Drive'),
flags=['no_create'],
values=(
'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:',
'J:', 'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:',
'S:', 'T:', 'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:'),
),
)
def normalize_and_validate_email(self, email, config=None):
@@ -496,6 +546,7 @@ class baseuser_add(LDAPCreate):
convert_sshpubkey_post(entry_attrs)
radius_dn2pk(self.api, entry_attrs)
class baseuser_del(LDAPDelete):
"""
Prototype command plugin to be implemented by real plugin
@@ -632,6 +683,7 @@ class baseuser_mod(LDAPUpdate):
self.check_objectclass(ldap, dn, entry_attrs)
self.obj.convert_usercertificate_pre(entry_attrs)
self.preserve_krbprincipalname_pre(ldap, entry_attrs, *keys, **options)
update_samba_attrs(ldap, dn, entry_attrs, **options)
def post_common_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)

View File

@@ -1483,6 +1483,23 @@ class i18n_messages(Command):
"trusttype": _("Trust type"),
"ipantadditionalsuffixes": _("Alternative UPN suffixes"),
},
'smb_attributes': {
"title": _(
"User attributes for SMB services"
),
"ipantlogonscript_tooltip": _(
"Path to a script executed on a Windows system at logon"
),
"ipantprofilepath_tooltip": _(
"Path to a user profile, in UNC format \\\\server\\share\\"
),
"ipanthomedirectory_tooltip": _(
"Path to a user home directory, in UNC format"
),
"ipanthomedirectorydrive_tooltip": _(
"Drive to mount a home directory"
),
},
"trustconfig": {
"options": _("Options"),
},