Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Current »

This guide is intended to give you some ideas about how to generate an eduPersonPrincipal (ePPN) for users.

eduPerson

eduPersonPrincipalName is defined in eduPerson 1.0, OID:1.3.6.1.4.1.5923.1.1.1.6

A scoped identifier for a person. It should be represented in the form "user@scope" where 'user' is a name-based identifier for the person and where the "scope" portion MUST be the administrative domain of the identity system where the identifier was created and assigned. Each value of 'scope' defines a namespace within which the assigned identifiers MUST be unique. Given this rule, if two eduPersonPrincipalName (ePPN) values are the same at a given point in time, they refer to the same person. There must be one and only one "@" sign in valid values of eduPersonPrincipalName.

ePPN

In Skolfederation ePPN must be:

  • properly scoped with a domain name owned by the Member Organization

  • uniquely represents a single user

  • never reassigned

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

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}

Days : 0
Hours : 0
Minutes : 27
Seconds : 41
Milliseconds : 812
Ticks : 16618126324
TotalDays : 0.0192339425046296
TotalHours : 0.461614620111111
TotalMinutes : 27.6968772066667
TotalSeconds : 1661.8126324
TotalMilliseconds : 1661812.6324

  • No labels