6

I'm looking for either:

A plugin that will auto-generate a unique uidNumber attribute value for new users and a unique gidNumber attribute value for new groups upon creation.

A configurable user/group management application that can generate the unique values above as well as populate the various other attributes required for Linux integration

We present are using a home-grown script and web page to do all this, but we're looking for something that we don't have to maintain and a little more polished.

Anyone know of a good tool that fits the bill?

Thanks!

Rich
  • 135
  • 8
jasonpvp
  • 61
  • 1
  • 2
  • You might want to base generation on objectguid, which is unique forest wide and can be generated on the fly. – Jim B May 17 '16 at 00:16

3 Answers3

3

I don't know of any existing tools that actually trigger on creation. Though like Nic mentioned, it is hypothetically possible to write something that could do that.

But realistically, how often are users/groups getting created outside of already automated processes? If they're not already, your existing provisioning processes should be augmented to add the relevant RFC2307 attributes also described in this TechNet blog post. For the stragglers that are created manually, you can have a script run at whatever interval you like that looks for objects missing the attributes and populating them as necessary.

In our environment, the script we have runs every 5 min on the DC holding the PDC Emulator role. But we could probably drop it down to once a minute without much additional impact. We also generate our UID/GID values from an algorithm that's based on the object's SID rather than a simple auto-incrementing value. It has the benefit that they're guaranteed* unique between domains/forests and we don't need to do any lookups to find the next value or make sure the value we want to use isn't already in use. I can post that function if you'd like. But it sounds like you guys may already have your own system for that.

*Guaranteed = as much as you can guarantee that two domains won't be created with the same randomly generated domain ID.

Edit: By request, here's the Powershell function we use to generate UIDs/GIDs from a SID.

function Get-UidFromSid()
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [System.Security.Principal.SecurityIdentifier]$sid
    )

    # convert sid to byte array
    $sidBytes = New-Object byte[] $sid.BinaryLength
    $sid.GetBinaryForm($sidBytes, 0)
    Write-Verbose ("SID bytes: $([System.BitConverter]::ToString($sidBytes))")

    # copy the sections we need
    $ridDomainBytes = New-Object byte[] 8
    [System.Array]::Copy($sidBytes, 16, $ridDomainBytes, 0, 4)
    $ridUserBytes = New-Object byte[] 8
    [System.Array]::Copy($sidBytes, 24, $ridUserBytes, 0, 4)
    Write-Verbose ("Domain portion: $([System.BitConverter]::ToString($ridDomainBytes))")
    Write-Verbose ("User portion: $([System.BitConverter]::ToString($ridUserBytes))")

    # fix endian'ness if necessary
    if (![System.BitConverter]::IsLittleEndian)
    {
        [System.Array]::Reverse($ridDomainBytes)
        [System.Array]::Reverse($ridUserBytes)
    }

    # convert the byte arrays to longs
    $ridDomain = [System.BitConverter]::ToInt64($ridDomainBytes, 0);
    $ridUser = [System.BitConverter]::ToInt64($ridUserBytes, 0);
    Write-Verbose "Domain(Int64) = $ridDomain, User(Int64) = $ridUser"

    # Now we're going to use the first 9 bits of the domain rid followed by the
    # first 22 bits of the user rid to make a single 31 bit integer (32-bit signed)
    # that will be the new unique UID value for this SID
    $ridDomain = ($ridDomain -band 0x1ff) -shl 22
    $ridUser = $ridUser -band 0x3fffff
    Write-Verbose "Domain(Int64) = $ridDomain, User(Int64) = $ridUser"

    return ($ridDomain + $ridUser)

<#
.SYNOPSIS
    Calculate the UID value for a Windows SID.

.DESCRIPTION
    This function duplicates Centrify's algorithm for generating unique UID
    values for Active Directory users and groups. The original algorithm was
    provided by Centrify and ported to PowerShell by Ryan Bolger.

.PARAMETER sid
    The SecurityIdentifier (SID) object to calculate against.

.OUTPUTS
    System.Int32 value of the resulting UID.

.EXAMPLE
    Get-UidFromSid ([System.Security.Principal.SecurityIdentifier]'S-1-5-21-3040497277-3966670145-4188292625-1137')

    Calculate a UID from a fictional SID.

.EXAMPLE
    Get-ADUser myuser | Get-UidFromSid

    Calculate a UID from an existing Active Directory user via pipeline input.
#>

}

Here is a GitHub gist with some additional implementations such as C#, Bash, and Python.

Ryan Bolger
  • 16,472
  • 3
  • 40
  • 59
  • Objectguid is guaranteed to be unique within the forest and generated on object creation – Jim B Jun 19 '16 at 15:29
  • Ryan, I'd be interested to see the function you mentioned, if that's something you're still able to provide - I believe it would add value to the original answer as an edit too. – JimNim Jul 19 '17 at 15:55
  • Done. I also have C#, Bash, and Python versions as well. – Ryan Bolger Jul 23 '17 at 00:00
  • This violates POSIX, uid_t types are only 16 bits but may be larger such as on Linux – nwmcsween Jan 08 '20 at 21:33
1

You could assign the gidNumber attribute from a PowerShell script. To make it automatic, call the script as a scheduled task. I wrote a cmdlet called Initialize-GroupGids which assigns unique gids to AD groups, and can be customized for different environments with parameters.

But basically, you can just to do something like this in PowerShell.

# Find the highest GID used on any group in the domain
$highGid = Get-ADGroup -LDAPFilter "(gidNumber=*)" -Properties gidNumber |
    Measure-Object -Property gidNumber -Maximum |
    Select-Object -ExpandProperty Maximum

# Avoid assigning GIDs below 1000
$highGid = [Math]::max( $highGid, 1000 )

# Find every security group without a gidNumber, and give it one.
Get-ADGroup -LDAPFilter "(!gidNumber=*)" |
    ? {$_.GroupCategory -eq "Security"} |
    $groups | Set-ADGroup -Add @{ gidNumber=++$highGid }

This could easily be adopted to work with users and uidNumbers too.

If you want the assignment of uids/gids to be instantaneous, Microsoft has an interesting technote about listening to change notifications from Active Directory via LDAP. I think that's a bit too sophisticated for PowerShell though.

Nic
  • 13,025
  • 16
  • 59
  • 102
1

With inspiration from answers here, and from the Samba mailing list, I wrote a tool called ADAM to assign UID/GID values:

https://gitlab.com/JonathonReinhart/adam

Currently (June 2019), this has only been tested on Linux, running against a Samba Active Directory domain. However, it should work (or be very close) running on Windows, and/or against a Windows Active Directory domain.

Jonathon Reinhart
  • 446
  • 1
  • 8
  • 25