depot/web/lukegbcom/posts/2017-02-19-freenas-freeipa-samba-and-kerberos.md

165 lines
5.8 KiB
Markdown
Raw Normal View History

2022-04-03 23:32:57 +00:00
---
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!