Validate/Modify User Input Using a Script


With Adaxes, you can enforce various constraints on the data entered in Active Directory. For example, using Property Patterns it is possible to validate property values with regular expressions, specify a list of allowed values for a property, make a property required, etc.

However, sometimes that's not enough. For example, you may want to ensure that the employee ID specified for a new user is unique in Active Directory, verify that the HR database contains a record for the user, add a digit to the username if it already exists, etc. This can be done with the help of PowerShell scripts.

In this tutorial, you will learn how to create a Business Rule to automatically execute a script before a user account is created in Active Directory, and how to use the script to validate and modify the information entered for the user.

  1. Launch Adaxes Administration Console, right-click your Adaxes service, point to New and click Business Rule.



    Enter a name for the new Business Rule and click Next.

  2. To trigger the Business Rule before a user account is created:

    • Select User in the Object Type list.
    • Select Before and then select Creating a User.


    Click Next.

  3. Click Add an action and select Run a program or PowerShell script.

    Click the button to provide a custom description for the action.
  4. Click the Edit button to open the script editor.



    To get information about the user you can use value references (e.g. %username%). Value references will be replaced with corresponding property values of the user account.

     $htable = @{FirstName="%firstname%";LastName="%lastname%";Department="%department%";}
    

    After replacing the value references, the script will look as follows:

     $htable = @{FirstName="John";LastName="Doe";Department="Marketing";}
    

    To get and update user account properties and control operation execution, you can use a variable called $Context. It is a predefined PowerShell variable of type ExecuteScriptContext.

    To determine whether a value was specified for a property, call the IsPropertyModified() method. To get a property value, call the GetModifiedPropertyValue() method. To update a property value, use the SetModifiedPropertyValue() method.

      if ($Context.IsPropertyModified("samAccountName"))
      {
          # Get property value
          $newValue = $Context.GetModifiedPropertyValue("samAccountName")
          # Modify the value
          $newValue = $newValue + "1"
          # Update the value
          $Context.SetModifiedPropertyValue("samAccountName", $newValue)
      }

    To determine whether the user's password was modified during the operation, use the IsPasswordChanged() method. To get the new password, call the GetNewPassword() method.

      if ($Context.IsPasswordChanged())
      {
          $newPassword = $Context.GetNewPassword()
          ...
      }

    To cancel the operation, call the Cancel() method.

      if ($isValueInvalid)
      {
          $Context.Cancel("The value is invalid.")
          return
      }

    To add a record to the operation Execution Log, use the LogMessage() method. The second parameter of the method can take the following values: "Information", "Warning" and "Error".

      $Context.LogMessage("The username has been changed.", "Information")

    To get the domain name of the user, call the GetObjectDomain() method. The method takes the distinguished name (DN) of an object as the input parameter.

      $domainName = $Context.GetObjectDomain("%distinguishedName%")

    To send an email or SMS message, use SendMail() and SendSms() methods.

      $Context.SendMail($toAddress, $subject, $bodyText, $bodyHtml)
      $Context.SendSms($mobileNumber, $text)

    Import-Module Adaxes
    
    if ($Context.IsPropertyModified("employeeID"))
    {
        # Get the value
        $value = $Context.GetModifiedPropertyValue("employeeID")
    
        # Validate the value
        if (([System.String]::IsNullOrEmpty($value)) -or (-not($value.Contains("-"))))
        {
            $Context.Cancel("Invalid Employee ID!")
            return
        }
    
        # Check whether the value is unique
        if ((Get-AdmUser -Filter 'employeeID -eq $value') -ne $NULL)
        {
            $Context.Cancel("A user with the specified Employee ID already exists!")
            return
        }
    }
    To use the script, you need to install Adaxes PowerShell Module on the computer, where your Adaxes service is running.
    Import-Module Adaxes
    
    function IsUserNameUnique($username)
    {
       $user = Get-AdmUser $username -erroraction silentlycontinue
       return $user -eq $Null
    }
    # Get the username
    $username = $Context.GetModifiedPropertyValue("samAccountName")
    # Check if it is unique
    if (IsUserNameUnique($username))
    {
        return
    }
    # If the username is not unique, add a digit to it
    $uniqueUsername = $Null
    for ($i = 1; $True; $i++)
    {
        $uniqueUsername = $username + $i
        if (IsUserNameUnique($uniqueUsername))
        {
            break
        }
    }
    
    # Update User Logon Name (pre-Windows 2000)
    $Context.SetModifiedPropertyValue("samAccountName", $uniqueUsername)
    
    # Update User Logon Name
    $upnSuffix = $Context.GetObjectDomain("%distinguishedName%")
    $userLogonName = $uniqueUsername + "@" + $upnSuffix
    $Context.SetModifiedPropertyValue("userPrincipalName", $userLogonName)
    
    $Context.LogMessage("The username has been changed to " + $userLogonName `
      + ".", "Information")
    To use the script, you need to install Adaxes PowerShell Module on the computer, where your Adaxes service is running.
    Import-Module Adaxes
    
    function DoesObjectExist($objectDN)
    {
        $obj = Get-AdmObject $objectDN.ToString() -erroraction silentlycontinue
        return $obj -ne $Null
    }
    
    # Get the user's distinguished name (DN)
    $objectDN = $Context.TargetObject.ObjectInfo.DN
    # Check whether an object with the same DN already exists
    if (-not (DoesObjectExist($objectDN)))
    {
        return
    }
    $objectLeaf = $objectDN.Leaf
    for ($i = 1;; $i++)
    {
        # Build new DN
        $objectName = $objectLeaf.Value + $i
        $objectRdn = New-Object "Softerra.Adaxes.Ldap.Rdn" $objectLeaf.Type,$objectName
        $objectDN = $objectDN.Parent
        $objectDN.AddLeaf($objectRdn)
        if (-not (DoesObjectExist($objectDN)))
        {
            # Rename the user
            $Context.SetModifiedPropertyValue("name", $objectName)
            $Context.LogMessage("Full Name has been changed to " + $objectName `
             + ".", "Information")
            break
        }
    }
    To use the script, you need to install Adaxes PowerShell Module on the computer, where your Adaxes service is running.
    $PasswordMinLength = 5
    if ($Context.IsPasswordChanged())
    {
        # Get the password
        $newPassword = $Context.GetNewPassword()
        # Check the password length
        if ($newPassword.Length -lt $PasswordMinLength)
        {
            $Context.Cancel("The password is too short.")
            return
        }
    }
    $spacesRemoved = $False
    # User Logon Name (pre-Windows 2000)
    if ($Context.IsPropertyModified("samAccountName"))
    {
        $samAccountName = $Context.GetModifiedPropertyValue("samAccountName")
        if ($samAccountName.Contains(" "))
        {
            # Remove spaces
            $samAccountName = $samAccountName.Replace(" ", "")
            # Update sAMAccountName
            $Context.SetModifiedPropertyValue("samAccountName", $samAccountName)
            $spacesRemoved = $True
        }
    }
    # User Logon Name
    if ($Context.IsPropertyModified("userPrincipalName"))
    {
        $userPrincipalName = $Context.GetModifiedPropertyValue("userPrincipalName")
        if ($userPrincipalName.Contains(" "))
        {
            # Remove spaces
            $userPrincipalName = $userPrincipalName.Replace(" ", "")
            # Update the username
            $Context.SetModifiedPropertyValue("userPrincipalName", $userPrincipalName)
            $spacesRemoved = $True
        }
    }
    # Log a message
    if ($spacesRemoved)
    {
        $Context.LogMessage("Spaces have been removed from the username.",
            "Information")
    }
    $props = @("sAMAccountName", "userPrincipalName")
    $map =@{ "å"="a"; "ö"="o"; "ä"="a";"ü"="u"; "ñ"="n"; "é"="e"; " "="-"; }
    
    foreach ($prop in $props)
    {
        if ($Context.IsPropertyModified($prop))
        {
            $value = $Context.GetModifiedPropertyValue($prop)
    
            foreach ($key in $map.Keys)
            {
                $value = $value.Replace($key, $map[$key])
            }
    
            $Context.SetModifiedPropertyValue($prop, $value)
            $Context.LogMessage($prop + ": " + $value, "Information")
        }
    }

    For more information on how to create scripts for Business Rules, see Server-Side Scripting.

    For information about the cmdlets included in the Adaxes PowerShell module, see Adaxes PowerShell Module.

  5. Optionally, you may want the Business Rule to run the script only if certain conditions are met.

    • Right-click the action and select Add Condition in the context menu.


    • Select the If <property> <relation> <value> condition.


    • In the Condition Parameters section specify Employee Type - equals - Subcontractor.


    • Click OK.


    You can also use scripts to check conditions.

    • Right-click the action and select Add Condition in the context menu.


    • Select the If PowerShell script returns true condition.


    • Click the Edit button to open the script editor.


    • When done, click OK.



    If a condition is met, the script must set the ConditionIsMet property of the $Context variable to $True:

     $Context.ConditionIsMet = $True

    $username = "%username%"
    foreach ($char in $username.ToCharArray())
    {
        if ([System.Char]::IsDigit($char))
        {
            $Context.ConditionIsMet = $True
            return
        }
    }
    $departmentModified = $Context.IsPropertyModified("department")
    $managerModified = $Context.IsPropertyModified("manager")
    $Context.ConditionIsMet = $departmentModified -and -not $managerModified
    $DatabaseHost = "localhost"
    $DatabaseName = "HRDatabase"
    $DatabaseTableName = "Users"
    $DatabaseIDField = "UserId"
    
    # Connect using the credentials of the Adaxes service accouunt
    $DatabaseUsername = $NULL
    $DatabasePassword = $NULL
    
    $Context.ConditionIsMet = $True
    
    $employeeId = "%employeeID%"
    if ([System.String]::IsNullOrEmpty($employeeId))
    {
        $Context.LogMessage("Employee ID is not specified!", "Warning")
        return
    }
    
    $connectionString =`
        "Data Source=$DatabaseHost; Initial Catalog=$DatabaseName;"
    if ($DatabaseUsername -eq $NULL)
    {
        $connectionString = $connectionString + "Integrated Security=SSPI;"
    }
    else
    {
        $connectionString =`
            $connectionString + "User ID=$DatabaseUsername;Password=$DatabasePassword;"
    }
    $connection = New-Object "System.Data.SqlClient.SqlConnection"  $connectionString
    $connection.Open()
    $command = $connection.CreateCommand()
    $command.CommandText = "SELECT COUNT(*) FROM " + $DatabaseTableName + " WHERE " +`
        $DatabaseIDField + "=@UserID"
    $command.Parameters.Add("@UserID", $employeeId) | Out-Null
    $count = $command.ExecuteScalar()
    $Context.ConditionIsMet = $count -eq 0
    
    $command.Dispose()
    $connection.Close()

    For information on how to create scripts for Business Rules, see Server-Side Scripting.



    When done, click Next.

  6. To define the scope of activity for the Business Rule, click Add.

    In the Activity Scope dialog, select the following items:

    • All Objects - select to execute the Business Rule when a user account is created in any domain managed by Adaxes.

    • Specific Domain - select to execute the Business Rule when a user account is created in a specific AD domain.

    • OU or Container - select to execute the Business Rule when a user account is created in a specific Organizational Unit or container.

    You can exclude specific Organizational Units and domains from the activity scope of the Business Rule. For example, if you've assigned the Business Rule over the whole domain, but do not want it to trigger when a user account is created in a specific Organizational Unit, you can exclude the Organizational Unit from the activity scope. To exclude an object, select the Exclude option in the Assignment Options dialog box.

    • Click the object you want to exclude.

    • In the Assignment Options dialog, select the Exclude option.


    • Click OK.
  7. When done, click OK and then click Finish.
Open tutorial filtering

Got questions?
Support Forum