Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

One way to achieve this is for example to use a Base36 number (alphanumeric) that is stored as a string, padding the string left with zeros for sorting. ePPN is incremented for every new user. If we use a length of 6 (36^6), that gives us 2176782336 ePPN's before overflow occurs. Either append the scope, a owned domain, before storing the ePPN or do it later e.g., in the IdP.

Example for AD

Below is a sample script for Active Directory. The script assigns ePPN to users where the attribute is empty. The script check the AD for the highest assigned ePPN, increments it, and then assign the new ePPN. This script can be run manually or as a scheduled job. Do not execute more than one instance of the script at a time for the same SearchBase to avoid a race condition

On Github

Code Block
languagepowershell
param (
    [Parameter(
        Mandatory,
        HelpMessage="The name of the attribute that holds the ePPN"
    )]
    [string]$Attribute,
    [Parameter(
        Mandatory,
        HelpMessage="Specifies an Active Directory path to search under"
    )]
    [ValidateScript({[adsi]::Exists("LDAP://$_")})]
    [string]$SearchBase,
    [Parameter(
        Mandatory,
        HelpMessage="The length of the ePPN i.e, EppnLen 3, will generate ePPN's from 001 to zzz"
    )]
    [int]$EppnLen,
    [Parameter(
        HelpMessage='If set, the value "@$Scope" will be appended to the ePPN'
    )]
    [string]$Scope
)

$DebugPreference = "Continue"

function IncStr
{
    [CmdletBinding()]
    param ([string]$eppnPre="")

    $alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
    $alen = $alphabet.Length - 1
    $incremented = ""
    foreach ($i in $eppnPre.tolower()[$eppnPre.length..0])
    {
        $count++
        $index = $alphabet.IndexOf($i)
        if ($alphabet.IndexOf($i) -eq $alen)
        {
            $index = 0
        } else {
            $incremented = $eppnPre.Substring(0, $eppnPre.Length - $count) + $alphabet.Substring($index +1 ,1) + $incremented
            break
        }
        $incremented = $alphabet.Substring($index,1)+$incremented
        if ($count -eq $eppnPre.length)
        {
            $incremented = $alphabet.Substring(1,1)+$incremented
        }

    }
    $incremented
}

$newUsers = Get-ADUser -Filter {-not($Attribute -like "*")} -Properties $Attribute -SearchBase $SearchBase -ErrorAction Stop
if ($newUsers) {
    $users = Get-ADUser -Filter '$Attribute -like "*"' -Properties $Attribute | Select-Object $Attribute
    $eppn = "0"
    $users | ForEach-Object {
        $prefix = ($_.$Attribute -split "@")[0]
        if ($prefix -gt $eppn) {
            $eppn = $prefix
        }
    }
    $newUsers  | ForEach-Object {
        $eppn = (IncStr -eppnPre $eppn).PadLeft($EppnLen,'0')
        if ($eppn.Length -gt $EppnLen){
            throw "ePPN lenght overflows EppnLen: $EppnLen"
        }
        if ($Scope) {
            $params= @{"Identity" = $_
            $Attribute = "$eppn@$Scope"}
        } else {
            $params= @{"Identity" = $_
            $Attribute = $eppn}
         }
        Set-ADUser @params
	    Write-Debug "Added $eppn"
    }
    Write-Debug "New Users added"
}

Parameters

  • Attribute <String>
    REQUIRED. The name of the attribute that holds the ePPN

  • SearchBase <String>
    REQUIRED. Specifies an Active Directory path to search under

  • EppnLen <Int>
    REQUIRED. The length of the ePPN i.e, EppnLen 3, will generate ePPN's from 001 to zzz

  • Scope <String>
    OPTIONAL. If set, the value "@$Scope" will be appended to the ePPN

Execution

Exampel of how to execute the script.

ad-eppn.ps1 -Attribute eduPersonPrincipalName -SearchBase "OU=Pupils,DC=example,DC=com" -EppnLen 6 -Scope exampel.com

Messurment

I measured the time it took to run scripts on a SearchBase with 100,000 users. The test was run on a computer with rather low performance and took 28 min.

Measure-Command {ad-eppn.ps1 -Attribute eduPersonPrincipalName -SearchBase "OU=Pupils,DC=example,DC=com" -EppnLen 6 -Scope exampel.com}

...

Exampel Scripts

The examples shows how you can add the attribute to users by utilizing scripts. The scripts are built so that it should be possible to run them with a scheduler.

ePPN for Google Workspace on Github

ePPN for Microsoft AD on Github