Powershell script to create sAMAccountName

Hey guys!

We are developing a Before Create rule to create an unique sAMAccountName based on the first letter of the user’s name and an incremental number, but it doesn’t start on 0.
So we have the number on a file, and the rule should read that number and update it when the account is created on Active Directory .
One part of the rule is working, where the number is read and update, and it prints on the log file the sAMAccountName created. But the account created doesn’t have the right sAMAccountName.

Here is the rule now:

#include SailPoint library
Add-Type -Path "c:\SailPoint\IQService\Utils.dll";

#import AD cmdlets
Import-Module activeDirectory

#log file info
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\adbeforecreate_incremental_log_$logDate.log"
$enableDebug = $true

# Path do arquivo que armazena o número incremental
$incrementalFile = "c:\SailPoint\sAMAccountName_incremental.txt"

###############################################################################################################################
# HELPER FUNCTIONS
###############################################################################################################################

function LogToFile([String] $info) {
    if($enableDebug) {
        $info | Out-File $logFile -Append
    }
}

#if we have a non-null account request, get our value; otherwise return nothing
function Get-AttributeValueFromAccountRequest([Sailpoint.Utils.objects.AccountRequest] $request, [String] $targetAttribute) {
    $value = $null;

    if ($request) {
        LogToFile("Procurando atributo '$targetAttribute' na requisicao...")
        LogToFile("Total de atributos na requisicao: $($request.AttributeRequests.Count)")
        
        foreach ($attrib in $request.AttributeRequests) {
            # Log detalhado de cada atributo
            LogToFile("Atributo encontrado: [Nome: $($attrib.Name), Operacao: $($attrib.Operation), Valor: $($attrib.Value)]")
            
            if ($attrib.Name -eq $targetAttribute) {
                $value = $attrib.Value;
                LogToFile("Atributo '$targetAttribute' encontrado com valor: $value")
                break;
            }
        }
        
        if (-not $value) {
            LogToFile("Atributo '$targetAttribute' não encontrado na requisição")
        }
    } else {
        LogToFile("ERRO: Account request object was null");
    }
    
    return $value;
}


function Get-NextIncrementalNumber {
    try {
        # Verifica se o arquivo existe, se não, cria com valor inicial 50000
        if (-not (Test-Path $incrementalFile)) {
            "50000" | Out-File $incrementalFile
            return 50000
        }
        
        # Lê o número atual do arquivo
        $currentNumber = [int](Get-Content $incrementalFile)
        $nextNumber = $currentNumber + 1
        
        # Atualiza o arquivo com o próximo número
        $nextNumber | Out-File $incrementalFile -Force
        
        return $currentNumber
    }
    catch {
        LogToFile("Error in Get-NextIncrementalNumber: $($_.Exception.Message)")
        throw
    }
}

###############################################################################################################################
# BODY
###############################################################################################################################

LogToFile("Starting before create rule")
LogToFile($env:Request)

try {

    $sReader = New-Object System.IO.StringReader([System.String]$env:Request);
    $xmlReader = [System.xml.XmlTextReader]([SailPoint.Utils.xml.XmlUtil]::getReader($sReader));
    $requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
    
    # Get users first name
    $firstName = Get-AttributeValueFromAccountRequest $requestObject "givenName"
    if (-not $firstName) {
        throw "First name (givenName) not found in account request"
    }
    
    # Get first letter of first name (lowercase)
    $firstLetter = $firstName.Substring(0,1).ToLower()
    LogToFile("First letter of name: $firstLetter")
    
    # Get next incremental number
    $incrementalNumber = Get-NextIncrementalNumber
    LogToFile("Incremental number: $incrementalNumber")
    
    # Create sAMAccountName
    $sAMAccountName = "$firstLetter$incrementalNumber"
    LogToFile("Generated sAMAccountName: $sAMAccountName")
    
    $attributeObject = New-Object SailPoint.Utils.objects.AttributeRequest;
    $attributeObject.Name = "sAMAccountName";
    $newsAMAccountName = New-Object System.Collections.ArrayList;
    $newsAMAccountName.Add($sAMAccountName);
    $attributeObject.Operation = "Set";
    $requestObject.AttributeRequests.Add($attributeObject);

    $requestObject.toxml()|out-file $args[0];

    LogToFile("Rule completed successfully")
}
catch {
    $ErrorMessage = $_.Exception.Message
    $ErrorItem = $_.Exception.ItemName
    LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
    throw
}

Do you guys know where is the error on this script?
Thanks in advance!

did you see anything in logs?

Hey I see you are not adding generated sAMAccountName to the AttributeRequest object that you have created in this lines. Can you add the value and try again

$attributeObject = New-Object SailPoint.Utils.objects.AttributeRequest;
$attributeObject.Name = "sAMAccountName";
$newsAMAccountName = New-Object System.Collections.ArrayList;
$newsAMAccountName.Add($sAMAccountName);
$attributeObject.Operation = "Set";
$requestObject.AttributeRequests.Add($attributeObject);

I’ve managed to make it work, here’s the full code:

#include SailPoint library
Add-Type -Path "c:\IQService\Utils.dll";

#import AD cmdlets
Import-Module activeDirectory

#Infos para log
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\adbeforecreate_incremental_log_$logDate.log"
$enableDebug = $true

# Path arquivo que armazena o número incremental
$incrementalFile = "c:\SailPoint\sAMAccountName_incremental.txt"

###############################################################################################################################
# HELPER FUNCTIONS
###############################################################################################################################

function LogToFile([String] $info) {
    if($enableDebug) {
        $info | Out-File $logFile -Append
    }
}

#if we have a non-null account request, get our value; otherwise return nothing
function Get-AttributeValueFromAccountRequest([Sailpoint.Utils.objects.AccountRequest] $request, [String] $targetAttribute) {
    $value = $null;

    if ($request) {
        foreach ($attrib in $request.AttributeRequests) {            
            if ($attrib.Name -eq $targetAttribute) {
                $value = $attrib.Value;
            }
        }
        
        if (-not $value) {
            LogToFile("Atributo '$targetAttribute' não encontrado na requisição")
        }
    } else {
        LogToFile("ERROR: Account request object was null");
    }
    
    return $value;
}


function Get-NextIncrementalNumber {
    try {
        if (-not (Test-Path $incrementalFile)) {
            throw            
        }   
        # Le o numero atual do arquivo
        $currentNumber = [int](Get-Content $incrementalFile)
        $nextNumber = $currentNumber + 1
        
        # Atualiza o arquivo com o próximo número
        $nextNumber | Out-File $incrementalFile -Force
        
        return $currentNumber
    }
    catch {
        LogToFile("Error in Get-NextIncrementalNumber: $($_.Exception.Message)")
        LogToFile("abababab")
        throw
    }
}

###############################################################################################################################
# BODY
###############################################################################################################################

LogToFile("Starting before create rule")
#LogToFile($env:Request) 

try {

    $sReader = New-Object System.IO.StringReader([System.String]$env:Request);
    $xmlReader = [System.xml.XmlTextReader]([SailPoint.Utils.xml.XmlUtil]::getReader($sReader));
    $requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
    
    # Pega primeiro nome do usuario
    $firstName = Get-AttributeValueFromAccountRequest $requestObject "givenName"
    if (-not $firstName) {
        throw "First name (givenName) not found in account request"
    }
    
    # Pega primeira letra do primeiro nome (lowercase)
    $firstLetter = $firstName.Substring(0,1).ToLower()
    #LogToFile("First letter of name: $firstLetter")
    
    # Pega o proximo numero incremental
    $incrementalNumber = Get-NextIncrementalNumber
    #LogToFile("Incremental number: $incrementalNumber")
    
    # Concatena para criar sAMAccountName
    $sAMAccountName = "$firstLetter$incrementalNumber"
    #LogToFile("Generated sAMAccountName: $sAMAccountName")

    # Adiciona o sAMAccountName na request
    $attributeObject = New-Object SailPoint.Utils.objects.AttributeRequest;
    $attributeObject.Name = "sAMAccountName";
    $attributeObject.Value = $sAMAccountName;
    $attributeObject.Operation = "Set";

    $requestObject.AttributeRequests.Add($attributeObject);

    #LogToFile($requestObject.toxml())
    LogToFile("Rule completed successfully")

    $requestObject.toxml()|out-file $args[0];
}
catch {
    $ErrorMessage = $_.Exception.Message
    $ErrorItem = $_.Exception.ItemName
    LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
    throw
}

But we have another problem now: we won’t be able to use a file on the IQS server, so we’ll have to find another way to get the incremental. I will make another post in this regard. Thanks!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.