0 votes

How can I check or run reports on an entire Property Pattern to ensure integrity?

I know I can run a check on an individual property, but this is really inefficient since I have already defined a Property Pattern for a specific object to abide by.

by (120 points)
0

Hello,

This can be done with the help of a PowerShell script. For example, you can use a script that creates a CSV file with all the objects the properties of which do not match Property Patterns. We've asked our script guys to write such a script for and will update you as soon as they come up with something.

1 Answer

0 votes
by (215k points)

Hello,

The script that you can find below creates a CSV file containing all existing AD objects that do not comply with the Property Patterns applied to them. To run the script:

  1. Save the script to a file with the .ps1 extension on the computer where your Adaxes service is installed.

  2. Launch Windows PowerShell. To do this:

    • Press Win+R.
    • Type powershell.exe and press Enter.
  3. In the PowerShell console, navigate to the folder where you saved the script. For example, if you saved it to C:\Scripts, type:

     cd C:\Scripts
  4. Run the script using the following command line:

     .\MyScript.ps1 <CSV file path> <username> <password>

    where

    • MyScript.ps1 - the name of the script file that you've created on step 1,
    • <CSV file path> - full path to the CSV file that will be created by the script,
    • <username>, <password> - credentials that will be used to access Adaxes service. These parameters are optional. If you omit them, credentials of the currently logged on user will be used. The minimum permissions required are the permissions to read all Property Patterns and the permissions to read all objects that you want to check against Property patterns.

The script:

Param([Parameter(Mandatory=$True,Position=1)]$csvFilePath, [Parameter(Mandatory=$False,Position=2)]$username, [Parameter(Mandatory=$False,Position=3)]$password)

[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

function ReportRecord($objectDn, $propertyPatternName, $propertyName, $errorText)
{
    Write-Host "Object DN:'$objectDn' Property Pattern:'$propertyPatternName' Property Name:'$propertyName' Error Text:'$errorText'"    
    $reportRecord = new-object PSObject
    $reportRecord | add-member NoteProperty "Object DN" "$objectDn"
    $reportRecord | add-member NoteProperty "Property Pattern" "$propertyPatternName"
    $reportRecord | add-member NoteProperty "Property Name" "$propertyName"
    $reportRecord | add-member NoteProperty "Error Text" "$errorText"
    return $reportRecord
}

$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly("localhost")

# Bind to the Property Patterns container
$propertyPatternsPath = $admService.Backend.GetConfigurationContainerPath("PropertyPatterns")
$propertyPatternsContainer = $admService.OpenObject($propertyPatternsPath, $username, $password, 0)

# Configure object searcher to search for all objects
$searcher = $admService.OpenObject("Adaxes://rootDSE", $username, $password, 0)
$searcher.SearchFilter = "(objectClass=*)"
$searcher.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.PageSize = 500
$searcher.VirtualRoot = $True
$searchResults = $searcher.ExecuteSearch()

# Get backend server name and port number
$backendServer = $admService.Backend.DnsHostName + ":" + $admService.Backend.PortNumber

$report = @()
While ($searchResults.MoveNext())
{
    # Bind to the AD object
    $object = $admService.OpenObject($searchResults.Current.ADsPath, $username, $password, 0)       

    # Get Distinguished Name
    $objectDN = $object.GetEx("distinguishedName")

    # Get effective Property Patterns
    $propertyPatterns = $propertyPatternsContainer.GetEffectivePropertyPatterns($object)

    foreach ($patternGuidByte in $propertyPatterns)
    {
        # Bind to the Property Pattern
        $patternGuid = New-Object "System.Guid" @(,$patternGuidByte)
        $patternPath = "Adaxes://$backendServer/<GUID=$patternGuid>" 
        $propertyPattern = $admService.OpenObject($patternPath, $username, $password, 0)

        # Get Property Pattern name
        $patternName = $propertyPattern.PatternName

        # Get Property Pattern items
        $patternItems = $propertyPattern.Items
        for ($patternItem = 0; $patternItem -lt $patternItems.Count; $patternItem++)
        {
            $item = $patternItems.GetObject($patternItem)            
            # Get the property name
            $propertyName = $item.PropertyName

            # Get the current value for the property
            $object.GetInfoEx(@($propertyName), $NULL)
            $propertyEntry = $NULL
            try
            {
                $propertyEntry = $object.Item($propertyName)
                $propertyEntry.ControlCode = "ADS_PROPERTY_UPDATE"
            }
            catch [Exception]
            {
                if ($item.IsPropertyRequired)
                {
                    # The object doesn't have a property that's required
                    $errorMessage = "The '$propertyName' property is required"
                    $report += ReportRecord $objectDN $patternName $propertyName $errorMessage
                }
                continue
            }
            # Get constraints for the property
            $constraints = $item.GetConstraints()
            foreach ($constraint in $constraints)
            {          
                $errorMessage = ""
                # Check the the property value against the constraint
                $isValid = $constraint.Check($propertyEntry, $object, [ref]$errorMessage)
                if ( -not $isValid)
                {
                    $report += ReportRecord $objectDN $patternName $propertyName $errorMessage
                }
            } 

        }
    }
}

$searchResults.Dispose()

#Write the report to the csv file
$report | Export-Csv $csvFilePath -NoTypeInformation
Report based on Property Pattern Value

Related questions

0 votes
1 answer

Is there an order of precendence for Property Patterns? If I set a property pattern at a level lower than another property pattern is set what happens? Will one work and the other won't?

asked Aug 18, 2020 by ComputerHabit (790 points)
0 votes
1 answer

Hello, I am trying to create a custom command that handles the process of converting a user account for a temp to a FTE. This needs to: 1. move the user to a new OU. 2. change ... to "xxx" OU Set 2: Always --Modify the user: set employee type to...... etc.

asked Jul 26, 2013 by DFassett (710 points)
0 votes
1 answer

Hi, I need to run a schedule task only if a customattribute is not empty. Can I use ConditionIsMet?

asked Oct 7, 2021 by Simone.Vailati (270 points)
0 votes
1 answer

Dear Adaxes Support, I'm trying to check the uniqueness of the Initials-proberty. My script works well so far. Import-Module Adaxes $value = $Context.GetModifiedPropertyValue("initials"); if ( ... Have you a idea how I can do this in the right way? Thanks :-)

asked Aug 13, 2013 by Napoleon (700 points)
0 votes
1 answer
2,779 questions
2,512 answers
6,574 comments
26,281 users