TrueNAS AD + Linux server w SSSD

svennd

Cadet
Joined
Nov 29, 2021
Messages
5
Hey,

So I connected my TrueNAS with AD, and created some SMB shares. This worked out-of-the-box ! I was amazed, now however I would like to also setup NFS shares. The server that mounts the NFS share is also part of the same AD, although connected through SSSD. When I mount the NFS, the server doesn't resolve the user id and group ID.

Code:
root@server:/mnt# ls -l
total 2
drwxrwxrwx 2 100172585 100028848 2 Dec  1 10:26 dir
drwxrwxrwx 2 100028848 100028848 2 Nov 30 12:05 study_123
-rwxrwxrwx 1 100028848 100028848 0 Nov 30 12:07 test
drwxrwxrwx 2 nobody    100028848 2 Dec  1 10:27 test_123


I'm assuming this has something to do with user mapping / group mapping that is different on both devices. Now I wonder how I can fix this ? (Both are test setups, so I can play with them) Also the NFS share is basically 777 but i'm not to worried about that yet, i first want to get user/group id's resolved correctly.

I found that i can edit the idmap in the webinterface /ui/directoryservice/idmap so I assume there must be a way to get those numbers correctly from the sssd server ?

Thanks!
 

anodos

Sambassador
iXsystems
Joined
Mar 6, 2014
Messages
9,554
All servers in an AD domain should have identical idmap settings. If you look at the idmap settings for TrueNAS, there's a checkbox for idmap_rid for the DS_TYPE_ACTIVEDIRECTORY entry labelled "sssd_compat". Check this box and save the form.
 

anodos

Sambassador
iXsystems
Joined
Mar 6, 2014
Messages
9,554
To answer a bit more:
Generally speaking, Unix servers need to map SID<->ID when joined to AD.

A SID looks something like this "S-1-5-21-2303880075-418591365-3335292507-1001" and every user, group, and computer account in AD has one.

Our default algorithm to handle this is to take the last component "1001" above and add it to the low-range associated with the AD domain. If the low range is "100000", then "S-1-5-21-2303880075-418591365-3335292507-1001" maps to ID "101001".

SSSD derives its mappings from a murmur3 hash of "S-1-5-21-2303880075-418591365-3335292507" for the above domain (combined with particular SSSD parameters). We can roughly approximate how SSSD does things (it works for the first SSSD ID slice), but more development work is needed to implement the SSSD algorithm in its entirety for winbindd to ensure that SSSD and winbindd are compatible with id assignments. My time for such things is vanishingly small these days. So compromise solution is what we have for now.
 

svennd

Cadet
Joined
Nov 29, 2021
Messages
5
Hey Anodos,

That is a really clear explanation, thanks ! I found the flag and once I rebuild the idmap index, I could, see the id being resolved "correctly".
I'm not sure, how well the compromise solution is working, for now it seems to work fine, and the domain i'm in, is pretty large, so I guess it works very well.

Thank you ! (the entire system is super smooth to work with!)
 

anodos

Sambassador
iXsystems
Joined
Mar 6, 2014
Messages
9,554
Hey Anodos,

That is a really clear explanation, thanks ! I found the flag and once I rebuild the idmap index, I could, see the id being resolved "correctly".
I'm not sure, how well the compromise solution is working, for now it seems to work fine, and the domain i'm in, is pretty large, so I guess it works very well.

Thank you ! (the entire system is super smooth to work with!)
The default slice size is 200,000 for SSSD. You should be good up to this count, but things become non-deterministic after this on the SSSD-side, and so having things work perfectly in super-large environments is challenging with SSSD imho.
 

anodos

Sambassador
iXsystems
Joined
Mar 6, 2014
Messages
9,554
SSSD manpages detail this fairly in-depth. Technical details are following in case someone stumbles across this in the future. I could probably simplify algorithm.
Code:
    @private
    async def get_sssd_low_range(self, domain, sssd_config=None, seed=0xdeadbeef):
        """
        This is best effort attempt for SSSD compatibility. It will allocate low
        range for then initial slice in the SSSD environment. The SSSD allocation algorithm
        is non-deterministic. Domain SID string is converted to a 32-bit hashed value
        using murmurhash3 algorithm.
        The modulus of this value with the total number of available slices is used to
        pick the slice. This slice number is then used to calculate the low range for
        RID 0. With the default settings in SSSD this will be deterministic as long as
        the domain has less than 200,000 RIDs.
        """
        sid = (await self.domain_info(domain))['sid']
        sssd_config = {} if not sssd_config else sssd_config
        range_size = sssd_config.get('range_size', 200000)
        range_low = sssd_config.get('range_low', 10001)
        range_max = sssd_config.get('range_max', 2000200000)
        max_slices = int((range_max - range_low) / range_size)

        data = bytearray(sid.encode())
        datalen = len(data)
        hash = seed
        data_bytes = data

        c1 = 0xcc9e2d51
        c2 = 0x1b873593
        r1 = 15
        r2 = 13
        n = 0xe6546b64

        while datalen >= 4:
            k = int.from_bytes(data_bytes[:4], byteorder='little') & 0xFFFFFFFF
            data_bytes = data_bytes[4:]
            datalen = datalen - 4
            k = (k * c1) & 0xFFFFFFFF
            k = (k << r1 | k >> 32 - r1) & 0xFFFFFFFF
            k = (k * c2) & 0xFFFFFFFF
            hash ^= k
            hash = (hash << r2 | hash >> 32 - r2) & 0xFFFFFFFF
            hash = (hash * 5 + n) & 0xFFFFFFFF

        if datalen > 0:
            k = 0
            if datalen >= 3:
                k = k | data_bytes[2] << 16
            if datalen >= 2:
                k = k | data_bytes[1] << 8
            if datalen >= 1:
                k = k | data_bytes[0]
                k = (k * c1) & 0xFFFFFFFF
                k = (k << r1 | k >> 32 - r1) & 0xFFFFFFFF
                k = (k * c2) & 0xFFFFFFFF
                hash ^= k

        hash = (hash ^ len(data)) & 0xFFFFFFFF
        hash ^= hash >> 16
        hash = (hash * 0x85ebca6b) & 0xFFFFFFFF
        hash ^= hash >> 13
        hash = (hash * 0xc2b2ae35) & 0xFFFFFFFF
        hash ^= hash >> 16

        return (hash % max_slices) * range_size + range_size
 

svennd

Cadet
Joined
Nov 29, 2021
Messages
5
Hey Anodos,

Is there a way I can actually get an estimate of this RID number (as a domain user)? I found that a domain admin should be able to check the RID pool manager, but i'm not a domain admin (actually on "older" AD's).

In TrueNAS I found these are the limit (/slice?) :
1914800000
2014800000

my (linux) id maps in this range : 1914972584, however some newer groups i'm part of, map not in this slice eg. 1369678467

For now this seems to "work", how worried should I be this suddenly stops working ?

Code:
# ad
1914800000 # AD lower limit
2014800000 # AD upper limit

# my id (within this limit)
1914972584

# some "newer" group id's 
1369678467
1369679524
1369679520
1369687678

# other ranges defined in TrueNAS
10000
90000000

90000001
100000000

 

anodos

Sambassador
iXsystems
Joined
Mar 6, 2014
Messages
9,554
Hey Anodos,

Is there a way I can actually get an estimate of this RID number (as a domain user)? I found that a domain admin should be able to check the RID pool manager, but i'm not a domain admin (actually on "older" AD's).

In TrueNAS I found these are the limit (/slice?) :
1914800000
2014800000

my (linux) id maps in this range : 1914972584, however some newer groups i'm part of, map not in this slice eg. 1369678467

For now this seems to "work", how worried should I be this suddenly stops working ?

Code:
# ad
1914800000 # AD lower limit
2014800000 # AD upper limit

# my id (within this limit)
1914972584

# some "newer" group id's
1369678467
1369679524
1369679520
1369687678

# other ranges defined in TrueNAS
10000
90000000

90000001
100000000

Yes, this is the general issue I was highlighting. There's no way be compatible in this case. I'd have to write a new idmap backend for winbindd and my free time for such things is extremely limited (especially in context of Core users).
 

svennd

Cadet
Joined
Nov 29, 2021
Messages
5
I'm part of a larger domain. (Although only very limited amount of users will use my systems). Ill try and see if I can setup samba to do authentication instead of SSSD.

Thanks for your work and explanation on this topic.
 

mijohnst

Cadet
Joined
Mar 5, 2022
Messages
7
I had this exact same issue today and this thread helped. I set my idmap_range_min and idmap_range_max to mirror what I had my sssd.conf file and then enabled sssd_compat. The only thing that would add is that in order to find the sssd_compat option, you need to look under Credentials > Directory Services > Advanced Settings > Idmap. It took me a bit to find it.
 
Top