164 lines
5.8 KiB
Markdown
164 lines
5.8 KiB
Markdown
---
|
|
title: FreeNAS, FreeIPA, Samba and Kerberos
|
|
date: 2017-02-19
|
|
layout: Post
|
|
tags:
|
|
- university tech
|
|
---
|
|
|
|
As a foreword: the below solution is *not* recommended - it relies on a prerelease version of FreeNAS for some of its functionality, which isn't supported.
|
|
|
|
FreeNAS 10 comes with the ability to bind to a FreeIPA directory. Hooray! Let's try it out.
|
|
|
|
---
|
|
|
|
## Struggling with binding to the directory
|
|
|
|
Hmm, using the GUI to bind to the directory doesn't seem to work at all, or even create the entry. Let's try the CLI instead.
|
|
|
|
After spending a few minutes learning how the CLI works, I got it down to the following commands:
|
|
|
|
```txt
|
|
freenas# cli
|
|
Welcome to the FreeNAS CLI! Type 'help' to get started.
|
|
|
|
[...snip...]
|
|
|
|
unix::>directoryservice directories
|
|
unix::/directoryservice/directories>create media type=freeipa enumerate=yes enabled=no
|
|
unix::/directoryservice/directories>media properties
|
|
unix::/directoryservice/directories/media/properties>set realm=media.su.ic.ac.uk username=<privileged username> password=<privileged password> server=cog.media.su.ic.ac.uk
|
|
unix::/directoryservice/directories/media/properties>..
|
|
unix::/directoryservice/directories/media>set enabled=yes
|
|
```
|
|
|
|
Turns out that because of the setup (the SRV records are misconfigured if you're doing a Kerberos bind to the LDAP server - the LDAP server doesn't have a keytab for ldap.media.su.ic.ac.uk), you need to set the `server` property or FreeNAS gives you some random Python exception. Ho hum.
|
|
|
|
Having bound to the directory you can set things up as usual on a FreeNAS system, creating shares, but wait...
|
|
|
|
## FreeNAS doesn't seem to respect groups
|
|
|
|
There appears to be a bug in FreeNAS' dscache plugin for FreeIPA -- it doesn't find any groups other than the main POSIX group.
|
|
|
|
At a first glance, this appears to be because it's searching for all groups by `dn`, which isn't a property you can filter on in an LDAP search. Bah.
|
|
|
|
I applied the following patch. I should probably contribute this back to https://github.com/freenas/middleware...
|
|
|
|
```diff
|
|
diff -u a/FreeIPAPlugin.py b/FreeIPAPlugin.py
|
|
--- a/FreeIPAPlugin.py 2017-02-19 18:46:41.508852583 +0000
|
|
+++ b/FreeIPAPlugin.py 2017-02-19 18:48:03.768854453 +0000
|
|
@@ -32,6 +32,7 @@
|
|
import logging
|
|
import errno
|
|
import krb5
|
|
+from collections import defaultdict
|
|
from threading import Thread, Condition
|
|
from datetime import datetime
|
|
from plugin import DirectoryServicePlugin, DirectoryState
|
|
@@ -55,6 +56,14 @@
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
+def _split_bases(dns):
|
|
+ out = defaultdict(list)
|
|
+ for dn in dns:
|
|
+ rdn, _, base_dn = dn.partition(',')
|
|
+ out[base_dn].append(rdn)
|
|
+ return out
|
|
+
|
|
+
|
|
class FreeIPAPlugin(DirectoryServicePlugin):
|
|
def __init__(self, context):
|
|
self.context = context
|
|
@@ -124,14 +133,13 @@
|
|
group = dict(ret['attributes'])
|
|
|
|
if get(entry, 'memberOf'):
|
|
- builder = LdapQueryBuilder()
|
|
- qstr = builder.build_query([
|
|
- ('dn', 'in', get(entry, 'memberOf'))
|
|
- ])
|
|
-
|
|
- for r in self.search(self.base_dn, qstr):
|
|
- r = dict(r['attributes'])
|
|
- groups.append(get(r, 'ipaUniqueID.0'))
|
|
+ for base_dn, rdns in _split_bases(get(entry, 'memberOf')).items():
|
|
+ qstr = '(|({0}))'.format(')('.join(rdns))
|
|
+
|
|
+ for r in self.search(base_dn, qstr):
|
|
+ r = dict(r['attributes'])
|
|
+ if get(r, 'ipaUniqueID.0'):
|
|
+ groups.append(get(r, 'ipaUniqueID.0'))
|
|
|
|
if contains(entry, 'ipaNTHash'):
|
|
nthash = binascii.hexlify(entry['ipaNTHash']).decode('ascii')
|
|
```
|
|
|
|
One `cli system reboot` later, `groups leg13` is now correctly showing all of my groups. Hurrah!
|
|
|
|
## Authenticating Samba against passwords
|
|
|
|
By default, however, this setup won't work, since FreeNAS won't have permission to read the `ipaNTHash` attribute on users. Per https://bugs.freenas.org/issues/19976#note-24, the following commands sort that out too:
|
|
|
|
```txt
|
|
freeipa$ ipa permission-add 'ipaNTHash service read' --attrs=ipaNTHash --type=user --right=read
|
|
freeipa$ ipa privilege-add 'SMB services'
|
|
freeipa$ ipa privilege-add-permission 'SMB services' --permissions='ipaNTHash service read'
|
|
freeipa$ ipa role-add trustagent --desc="Trust agent (e.g. Samba servers)"
|
|
freeipa$ ipa role-add-privilege trustagent --privileges='SMB services'
|
|
freeipa$ ipa role-add-member trustagent --users=<trusted binding user>
|
|
```
|
|
|
|
To check, use:
|
|
|
|
```txt
|
|
freenas# dispatcherctl call dscached.account.getpwnam '"admin"'
|
|
```
|
|
which should show non-`null` entries for `"nthash"` and `"sid"`.
|
|
|
|
and
|
|
|
|
```txt
|
|
freenas# pdbedit -Lw admin
|
|
```
|
|
which shouldn't show Xs in the fourth column.
|
|
|
|
## Authenticating Samba against FreeIPA Kerberos
|
|
|
|
This is all well and good, but it would be nice if clients with valid Kerberos tickets could also authenticate...
|
|
|
|
First, FreeIPA needs to know about the FreeNAS server, since FreeNAS doesn't do a "proper" directory bind:
|
|
|
|
```txt
|
|
freeipa$ ipa host-add sparkplug.media.su.ic.ac.uk
|
|
freeipa$ ipa service-add cifs/sparkplug.media.su.ic.ac.uk
|
|
freeipa$ ipa service-add-host cifs/sparkplug.media.su.ic.ac.uk --hosts=sparkplug.media.su.ic.ac.uk
|
|
```
|
|
|
|
Then, you can fetch a keytab for it:
|
|
|
|
```txt
|
|
freeipa$ ipa-getkeytab -p cifs/sparkplug.media.su.ic.ac.uk -k sparkplug.kt
|
|
```
|
|
|
|
Communicate this to some location (I used `/root/sparkplug.kt`) on the FreeNAS box, then:
|
|
|
|
```txt
|
|
freenas# cli
|
|
|
|
unix::>directoryservice kerberos keytab
|
|
unix::/directoryservice/kerberos/keytab>create cifs keytab=/root/sparkplug.kt
|
|
```
|
|
|
|
This will add the keys in the keytab to `/etc/krb5.keytab`. Excellent.
|
|
|
|
Now we need to configure Samba on FreeNAS to respect the Keytab:
|
|
|
|
```txt
|
|
freenas# net conf setparm global 'realm' 'MEDIA.SU.IC.AC.UK'
|
|
freenas# net conf setparm global 'kerberos method' 'system keytab'
|
|
freenas# net conf setparm global 'security' 'ads'
|
|
```
|
|
|
|
...and that should be that!
|