0 votes

We are looking to automate moving of computers from the staging OU we start them in to the office specific OU we have setup in AD. Currently, they all sit in one OU and that contains 12,000 pcs. We have the need (Group Policy) to separate out each office location to its own OU. We would like to associate the IP address (xxx.xxx.xxx) to the OU and have adaxes move the pc when it comes online at a new IP. Can you provide instructions or scripting to accomplish this?

by (3.2k points)
0

Hello,

This can be achieved using a PowerShell script. To write it for you, we need more details. Would you like for the IP addresses and corresponding OUs to be entered directly into the script or the IP address can be stored in a property of the corresponding OU (e.g. one of Adaxes custom attributes)?

0

Thank you Support.

The way i envision this script working is, each OU has an attribute with the IP address (xxx.xxx.xxx) stored in the object. We will have a staging/holding OU where all new computer will be joined to the system will reside. On a scheduled time, we will have Adaxes scan that OU and then scan any computers that are found within and move them to the corresponding OUs depending on the scan results.

We do have a request to delete the DNS record of that computer object as well to be a check and balance that we are moving the proper computer being reported and not a stale object or DNS record.

1 Answer

0 votes
by (215k points)
selected by
Best answer

Hello,

We recommend using a Scheduled Task for this purpose. To create one:

  1. Create a new a Scheduled Task.
  2. On step 3 of the Create Scheduled Task wizard, select Computer.
  3. On step 4, add the Run a program or PowerShell script action and paste the following script from our repository: http://www.adaxes.com/script-repository ... s-s485.htm.
  4. Modify the parameter of the script. It must contain the name of the attribute of Organizational Units that will hold the 1st 3 parts of IP addresses.
  5. Enter a short description and click OK.
  6. Double-click Always.
  7. Select If <property> <relation> <value>.
  8. Specify If DNS Host Name is not empty. This will exclude computer objects that have never logged in to AD.
  9. Click OK. You should receive something like this:
0

Support team, thank you for this script. We would like to add two things to this script if possible.

1. exclude xxx.xxx.xxx.50 or xxx.xxx.xxx.51 from being moved ever
2. Upon completion of script send email with detailed results of script.

0

Hello,

Find the updated script below. To run the script you need to use a Schedule Task configured for Domain-DNS object type. No conditions need to be added to the task.

$networkPrefixProperty = "description" # TODO: modify me
$hostIdentifierToSkip = @("50", "51") # TODO: modify me

# Email message settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Move computer based on IP address report" # TODO: modify me
$reportHeader = "<b>Move computer based on IP address report</b><br/><br/>" # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me

function SearchObjects($filter, $properties, $domainName, $searchInAllDomains)
{
    if ($searchInAllDomains)
    {
        $searcher = $Context.BindToObject("Adaxes://rootDSE")
        $searcher.VirtualRoot = $searchInAllDomains
    }
    else
    {
        $searcher = $Context.BindToObject("Adaxes://$domainName/rootDSE")
    }

    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad($properties)

    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()

        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

function AddReportRecord($records, $computerName, $parentName, $newParentName)
{
    [void]$records.Append("<tr><td>$computerName</td><td>$parentName</td><td>$newParentName</td></tr>")
}

# Search all computers
$computersSearchResults = SearchObjects "(&(objectCategory=computer)(dNSHostName=*)(!(userAccountControl:1.2.840.113556.1.4.803:=8192)))" @("dNSHostName", "name", "distinguishedName") $NULL $True

$records = New-Object "System.Text.StringBuilder"
$ouInfos = @{}
for ($i = 0; $i -lt $computersSearchResults.Length; $i++)
{
    # Get computer info
    $computerSearchResult = $computersSearchResults[$i]
    $computerName = $computerSearchResult.Properties["name"].Value
    $computerDN = New-Object "Softerra.Adaxes.Ldap.DN" $computerSearchResult.Properties["distinguishedName"].Value
    $parentName = $Context.GetDisplayNameFromAdsPath("Adaxes://" + $computerDN.Parent)

    # Get IP address
    try
    {
        $addresses = [System.Net.Dns]::GetHostAddresses($computerSearchResult.Properties["dNSHostName"].Value)
    }
    catch
    {

        $message = "An error occurred when searching for the computer IP address. Error: " + $_.Exception.Message
        $Context.LogMessage("$computerName`: $message", "Warning")
        AddReportRecord $records $computerName $parentName $message
        continue
    }

    $ipAddress = $addresses | Where-Object {$_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork}
    if ($ipAddress -is [System.Array])
    {
        $message = "Found more than one IP address for the computer. Addresses: " + [System.String]::Join(";", $ipAddress)
        $Context.LogMessage("$computerName`: $message", "Warning")
        AddReportRecord $records $computerName $parentName $message
        continue
    }
    if ($ipAddress -eq $NULL)
    {
        $message = "No IPv4 addresses found."
        $Context.LogMessage("$computerName`: $message", "Warning")
        AddReportRecord $records $computerName $parentName $message
        continue
    }

    # Find target OU
    $hostIdentifier = ($ipAddress | Select-String -Pattern "[0-9]{1,3}$").Matches[0].ToString()
    if ($hostIdentifierToSkip -contains $hostIdentifier)
    {
        continue
    }
    $networkPrefix = ($ipAddress | Select-String -Pattern "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}").Matches[0].ToString()

    if (-not($ouInfos.ContainsKey($networkPrefix)))
    {
        $domainName = $Context.GetObjectDomain($computerDN)
        $ouSearchResults = SearchObjects "(&(objectCategory=organizationalUnit)($networkPrefixProperty=$networkPrefix))" @("distinguishedName") $domainName $False
        if ($ouSearchResults.Length -eq 0)
        {
            $message = "Organizational Unit for IP prefix '$networkPrefix' not found."
            $Context.LogMessage("$computerName`: $message", "Warning")
            AddReportRecord $records $computerName $parentName $message
            continue
        }
        elseif ($ouSearchResults.Length -gt 1)
        {
            $message = "Found more than one Organizational Unit for IP prefix '$networkPrefix'."
            $Context.LogMessage("$computerName`: $message", "Warning")
            AddReportRecord $records $computerName $parentName $message
            continue
        }

        $ouInfos.Add($networkPrefix, $ouSearchResults[0])
    }
    $ouSearchResult = $ouInfos[$networkPrefix]

    $newParentDN = New-Object "Softerra.Adaxes.Ldap.DN" $ouSearchResult.Properties["distinguishedName"].Value
    if ($computerDN.Parent -eq $newParentDN)
    {
        continue
    }

    # Move computer to the OU
    $newParentPath = $ouSearchResult.AdsPath
    $ou = $Context.BindToObjectEx($newParentPath, $True)
    $ou.MoveHere($computerSearchResult.AdsPath, $NULL)

    $newParentName = $Context.GetDisplayNameFromAdsPath($newParentPath)
    AddReportRecord $records $computerName $parentName $newParentName
}

# Build report
$html = New-Object "System.Text.StringBuilder"
[void]$html.Append($reportHeader)
if ($records.Length -eq 0)
{
    [void]$html.Append("<b>No computers found</b>")
}
else
{
    [void]$html.Append("<table border='1' width='100%%'>")
    [void]$html.Append("<tr>")
    [void]$html.Append("<th>Computer name</th>")
    [void]$html.Append("<th>Old parent name</th>")
    [void]$html.Append("<th>New parent name</th>")
    [void]$html.Append("</tr>")
    [void]$html.Append($records.ToString())
    [void]$html.Append("</table>")
}
[void]$html.Append($reportFooter)

# Send report
$Context.SendMail($to, $subject, $NULL, $html.ToString())
0

We were testing the script today and received the following error (see below):


Here is the OU with the IP added to the attribute as the script asked for:


We also need a verison for cleanup purposes that will parse all computers with dnsHostName field filled in and move to proper OU.

Thank You

0

Hello,

The error occurs because you chose to use an Adaxes custom attribute to store the IP address prefix in the OUs. The thing is that, when moving a computer, the script gets the computer's IP, extracts the address prefix and searches for an OU that contains the same prefix. However, searching by Adaxes custom attributes is not supported. You need to use an actual AD property instead (e.g. Description, Web Page etc).

We also need a verison for cleanup purposes that will parse all computers with dnsHostName field filled in and move to proper OU.

You don't need a script for that. You can do that using built-in Adaxes actions and conditions, for example:

Related questions

0 votes
1 answer

I have a root OU that I created called Disabled. I want to give the Computer Manager role the necessary permissions to move a computer to any OU/sub tree desired. They can ... -in computer OU but nothing else. What Permissions do I need to give them? Thanks!

asked Apr 30, 2012 by mpaul (360 points)
0 votes
0 answers

It would be great if we could run a report on an OU and get the following information: Computer Name Local Accounts Whether or not the account is an administrator ... this is less important. Thanks in advance. Your support team is great and appreciated.

asked Sep 8, 2021 by mikek (80 points)
0 votes
1 answer

Hi Team! I'm currently looking for a solution to create an exchange mailbox on-premise, sync it to Office 365 and assign the license in one business rule. I didn't ... solution from our side? Please let me know how to configure this. Best Regards Marco Jandl

asked Apr 6 by marco_jandl (60 points)
0 votes
1 answer

We are trying to extend our Adaxes management to O365 / Azure only user objects. Currently we use employee type to add traditional active directory accounts to business units and ... so, can this be used to create dynamic mail enabled security groups in O365?

asked May 3 by adaxes_user2 (20 points)
0 votes
1 answer

Receive "Index operation failed; the array index evaluated to null. Stack trace: at &lt;ScriptBlock&gt;, &lt;No file&gt;: line 104&gt;" and "Index operation failed; the ... $GroupName, $GroupDN." } } #foreach write-output "" Write-Output "" Stop-Transcript

asked Apr 14 by jbahou (20 points)
2,740 questions
2,474 answers
6,475 comments
1,371,948 users