Initial Domain Integration Discovery…

2017-11-16T03:12:56+00:00 November 16th, 2017|blog, Domain Integration, PowerShell, Scripting|

If you are intending to be involved in an Active Directory Domain integration with Quest Migration Manager for AD, there are some simple AD attribute discovery checks you should do long before you get serious about such things as user counts and remediation and so forth.  And especially if you’re going to perform an Enterprise multi-Domain integration (many-to-one), its even more critical that you map out your attributes that you will be using for merging & matching the user objects across each domain relationship.

Attribute Analysis

Here at Coretek, we do a lot of Organizational and Enterprise Active Directory integrations, and many of them involve Quest Migration Manager for AD (MMAD).  Just today I was working with a customer to gather some of this early info, so I thought I’d post a note on some of these simple tests so you, too, can run them and see if your AD is in good shape to take on such a project.

The Quest Migration Manager for AD requires that you use a pair of Unicode String attributes for each domain relationship.  The default attributes used in a simple non-Exchange migration are “adminDescription” and “adminDisplayName”.  However, the more common scenarios I see involve Exchange and also multiple domains, requiring the use of other attributes such as “extensionAttribute14” & 15 and others.

The most common scenario I get involved with is where the users have already been created in the destination domain (due to an HR automation or other project), and the user objects from the source domain(s) will be merged, rather than created fresh.  In these cases I typically try to get the customer to check for these following critical things at a pre-project state — or as early as can be done — for the set of user objects that are to be part of the migration/integration:

  • Existing sidHistory — In most cases, existing sidHistory attributes on a user object are just a part of an old migration and may not matter.  However, if something like a previous Exchange migration was left un-complete, the sidHistory might be a critical part of the mailbox access for those users… and removing it without planning would be bad!  Tread carefully!
  • Existing extensionAttribute14, 15, etc. — These are the attributes that are commonly used in Enterprise AD migrations, and you’ll often find them still left-over from previous projects.  Those old project-based values don’t matter on their own; however I’ve also seen these attributes quite commonly used for other semi-hidden administrative items.  Why?  Because in Exchange environments, there’s a nifty GUI capability for editing these attributes, putting them at the fingertips of people that would otherwise leave them alone.  Again, make sure they are free and won’t be overwritten by anyone!

PowerShell Queries

So let’s check for these attributes, and below are some simple ways to see if anything is populated for those critical attributes.

To return a simple list of all user distinguishedNames with “sidHistory” populated with something (command is all-one-line):

(Get-ADUser -Filter {sidHistory -like "*"} -SearchBase "ou=MyOweYou,dc=doemane,dc=lowcull").distinguishedName

…then of course, you can swap out extensionAttribute14 for others… and replace the “.distinguishedName” with others, and we could format the output differently, dump to a CSV, etc.  Here is a similar search, but now we’re formatting the output to a table for easier quick reading (command is all-one-line):

Get-ADUser -Filter {extensionAttribute14 -like "*"} -SearchBase "ou=MyOweYou,dc=doemane,dc=lowcull" -Properties sidHistory,extensionAttribute14 |ft -Property name,sidhistory,extensionattribute14

…or, to pull it all together into one command and search for all three of the attributes I mentioned, do this (command is all-one-line):

Get-ADUser -Filter {(extensionAttribute14 -like "*") -or (extensionAttribute15 -like "*") -or (sidHistory -like "*")} -SearchBase "dc=doemane,dc=lowcull" -Properties sidHistory,extensionAttribute14,extensionAttribute15 |ft -Property name,sidhistory,extensionattribute14,extensionattribute15

Of course, you’ll want to change out the specifics in the commands above to match your domain info and attribute discovery needs, but you get the idea.

I hope that helps get you closer to your domain integration…  And I hope you let us help you out!

 

Azure – Which Public and Private IPs are In Use and By Which VM…?

2017-08-03T03:01:59+00:00 August 10th, 2017|Azure, blog, Cloud, PowerShell|

In my recent thread of simple-but-handy Azure PowerShell tools, I realized one important thing was missing: A tool that grabbed all the public & private IP addresses in use by VMs (plus some additional info).

I searched around, and found an old post by fellow Coreteker Will Anderson, where he’d solved the problem.  Unfortunately, PowerShell had changed since then, and his suggestion didn’t work anymore.  Fortunately however, Will Anderson is now on the other end of Skype from me, so after a quick explanation he gave me some advice on how to fix it within the new PowerShell behavior.  And of course, it would just be wrong not to post if back to the community…

So here is my script, with help from Will and another blogger Rhoderick Milne, where I found some additional input.  When executed, this script writes some quick handy info to screen, as in this lab example:

…which might be enough for you if you just want a quick review, but then it also dumps my preferred info for each VM to a csv, as follows: “Subscription”, “Mode”, “Name”, “PublicIPAddress”, “PrivateIPAddress”, “ResourceGroupName”, “Location”, “VMSize”, “Status”, “OsDisk”, “DataDisksCount”, “AvailabilitySet”

Just paste the below  into a script file, change the subscription name in the variable to your choice, and execute.  If you don’t know which subscription name to use, you can always run “Get-AzureRmSubscription” after you run “Login-AzureRmAccount” and find it in the list.  So grab the code, hack at it, and let me know where you take it!

# Thanks for help from Will Anderson, Rhoderick Milne for the assistance.
#
# Get Date; Used only for output file name.
$Date = Get-Date
$NOW = $Date.ToString("yyyyMMddhhmm")
#
# Variables
$MySubscriptionName = "Windows Azure  MSDN - Visual Studio Premium"
$VmsOutFilePath = "C:\temp"
$VmsOutFile = "$VmsOutFilePath\VmList-$NOW.csv"
#
$NeedToLogin = Read-Host "Do you need to log in to Azure? (Y/N)"
if ($NeedToLogin -eq "Y")
{
  Login-AzureRmAccount
  Select-AzureRmSubscription -SubscriptionName $MySubscriptionName
}
elseif ($NeedToLogin -eq "N")
{
  Write-Host "You must already be logged in then.  Fine. Continuing..."
}
else
{
  Write-Host ""
  Write-Host "You made an invalid choice.  Exiting..."
  exit
}
#
$vms = Get-AzureRmVm 
$vmobjs = @()
foreach ($vm in $vms)
{
  #Write-Host ""
  $vmname = $vm.name
  Write-Host -NoNewline "For VM $vmname... "
  Start-Sleep 1
  $vmInfo = [pscustomobject]@{
      'Subscription'= $MySubscriptionName
      'Mode'='ARM'
      'Name'= $vm.Name
      'PublicIPAddress' = $null
      'PrivateIPAddress' = $null
      'ResourceGroupName' = $vm.ResourceGroupName
      'Location' = $vm.Location
      'VMSize' = $vm.HardwareProfile.VMSize
      'Status' = $null
      'OsDisk' = $vm.StorageProfile.OsDisk.Vhd.Uri
      'DataDisksCount' = $vm.StorageProfile.DataDisks.Count
      'AvailabilitySet' = $vm.AvailabilitySetReference.Id }
  $vmStatus = $vm | Get-AzureRmVM -Status
  $vmInfo.Status = $vmStatus.Statuses[1].DisplayStatus
  $vmInfoStatus = $vmStatus.Statuses[1].DisplayStatus
  Write-Host -NoNewline "Get status `("
  if ($vmInfoStatus -eq "VM deallocated")
  {
    Write-Host -ForegroundColor Magenta -NoNewline "$vmInfoStatus"
  }
  elseif ($vmInfoStatus -eq "VM stopped")
  {
    Write-Host -ForegroundColor Yellow -NoNewline "$vmInfoStatus"
  }
  elseif ($vmInfoStatus -eq "VM generalized")
  {
    Write-Host -ForegroundColor Gray -NoNewline "$vmInfoStatus"
  }
  else
  {
    Write-Host -ForegroundColor White -NoNewline "$vmInfoStatus"
  }
  Write-Host -NoNewline "`)... "
  $VMagain = (Get-AzureRmVm -ResourceGroupName $vm.ResourceGroupName -Name $vmname)
  $NifName = ($VMagain.NetworkProfile[0].NetworkInterfaces.Id).Split('/') | Select-Object -Last 1
  $MyInterface = (Get-AzureRmNetworkInterface -Name $NifName -ResourceGroupName $VMagain.ResourceGroupName).IpConfigurations
  $PrivIP = $MyInterface.privateipaddress
  $vmInfo.PrivateIPAddress = $PrivIP
  Write-Host -NoNewline "Getting Private IP `($PrivIP`)... "
  try
  {
    $PubIPName = (($MyInterface).PublicIPAddress.Id).split('/') | Select-Object -Last 1
    $vmPublicIpAddress = (Get-AzureRmPublicIpAddress -Name $PubIPName -ResourceGroupName $Vmagain.ResourceGroupName).IpAddress 
    Write-Host -NoNewline "Getting public IP `("
    Write-Host -ForegroundColor Cyan -NoNewline "$vmPublicIpAddress"
    Write-Host -NoNewline "`)... "
    $vmInfo.PublicIPAddress = $vmPublicIpAddress
  }
  catch
  {
    Write-Host -NoNewline "No public IP... "
  }
  Write-Host -NoNewline "Add server object to output array... "
  $vmobjs += $vmInfo
  Write-Host "Done."
}  
Write-Host "Writing to output file: $VmsOutFile"
$vmobjs | Export-Csv -NoTypeInformation -Path $VmsOutFile
Write-Host "...Complete!"



I hope that helps!

Azure – What tags are we using again…?

2017-07-27T00:00:55+00:00 July 7th, 2017|Azure, blog, PowerShell|

Have you wondered what tags are assigned to all your Azure VMs?  Do you not have ARM Policies in place to enforce your preferred tags yet?

I was in just such a situation the other day.  Just like in my previous post on quick Azure-related scripts, I was working with a customer that just wanted a quick utility to report on what VMs are properly tagged (or not) in their implementation, without having to fish around the Portal.  No ARM Policies there yet…  *yet*.

So I whipped this together.  And much like that previous script, you just paste this into a PS1 file, set the subscription name in the variable, and then run it.

# GetVmTags - Jeremy Pavlov @ Coretek Services 
# Setting the subscription here
$MySubscriptionName = "My Subscription"
# Set some empty arrays
$vmobjs = @()
$vmTagsKeys = @()
$vmTagsValues = @()
# Get the VMs...
$vms = Get-AzureRmVm 
#
$NeedToLogin = Read-Host "Do you need to log in to Azure? (Y/N)"
if ($NeedToLogin -eq "Y")
{
  Login-AzureRmAccount
  Select-AzureRmSubscription -SubscriptionName $MySubscriptionName
}
elseif ($NeedToLogin -eq "N")
{
  Write-Host "You must already be logged in then.  Fine. Continuing..."
}
else
{
  Write-Host ""
  Write-Host "You made an invalid choice.  Exiting..."
  exit
}
#
foreach ($vm in $vms)
{
    Write-Host ""
    $vmname = $vm.name
    $MyResourceGroup = $vm.ResourceGroupName
    Write-Host "Checking tags for VM $vmname... "
    Start-Sleep 1
    $vmTags = (Get-AzureRmVM -name $vmname -ResourceGroupName $MyResourceGroup).Tags
    $vmTagsCount = $vmTags.Count
    if ($vmTagsCount -gt 0)
    {
      $vmTagsKeys = $vmTags.Keys -split '
[\r\n]' $vmTagsValues = $vmTags.Values -split '[\r\n]' for ($i=0;$i -lt $vmTagsCount; $i++) { $CurrentTagKey = $vmTagsKeys[$i] $CurrentTagValue = $vmTagsValues[$i] Write-Host -ForegroundColor Green "Key : Value -- $CurrentTagKey : $CurrentTagValue" } } else { Write-Host -ForegroundColor Yellow "No tags for $vmname" } }

The results should look something like this, except hopefully a lot more serious and business-y:

Have fun with it, change it up, and let me know what you do with it…   I hope it helps.  Enjoy!

Azure – Next Available IP Address…

2017-06-01T19:53:53+00:00 June 15th, 2017|Azure, blog, Cloud, PowerShell|

The other day, I was working at a customer location with one of their IT admins named Jim, designing an Azure IaaS-based deployment.  During our session, he challenged me to make an easy way for him and his coworkers to see if a particular address is available, or find the next available “local” address in their various Azure VNets.

Because while addressing can be handled with ARM automation — or just dynamically by the nature of IaaS server creation — in an Enterprise it is usually necessary to document and review the build information by a committee before deployment.  And as a result, Jim wanted to be able to detect and select the addresses he’d be using as part of build designs, and he wanted his coworkers to be able to do the same without him present.  So, this one is for Jim.

I wanted to write it to be user-friendly, with clear variables, and be easy-to-read, and easy-to-run.  …unlike so much of what you find these days…  😉

Copy these contents below to a file (if you wish, edit the dummy values for subscription, Resource Group, and VNet) and run it with PowerShell.  It will do a mild interview of you, asking about the necessary environment values (and if you need to change them), and then asking you for an address to validate as available.  If the address you specified is available, it tells you so; if it is not, it returns the next few values in the subnet from which the address you entered resides.

# TestIpaddress - Jeremy Pavlov @ Coretek Services 
# You just want to know if an internal IP address is available in your Azure VNet/Subnet.
# This script will get you there.  
#
# Pre-reqs:
# You need a recent version of the AzureRm.Network module, which is 4.0.0 at his writing.  
# You can check with this command: 
#     Get-Command -Module azurerm.network
# …and by the way, I had to update my version and overwrite old version with this command:
#     Install-Module AzureRM -AllowClobber
#
# Some things may need to be hard-coded for convenience...
$MySubscriptionName = "My Subscription"
$MyResourceGroup = "My Resource Group"
$MyVnet = "My VNet"
#
Start-Sleep 1
Write-Host ""
Write-Host "Here are the current settings:"
Write-Host "Current subscription: $MySubscriptionName"
Write-Host "Current Resource Group: $MyResourceGroup"
Write-Host "Current VNet: $MyVnet"
Write-Host ""
$ChangeValues = read-host "Do you wish to change these values? (Y/N)"
if ($ChangeValues -eq "Y")
{
  Write-Host ""
  $ChangeSub = read-host "Change subscription? (Y/N)"
  if ($ChangeSub -eq "Y")
  {
    $MySubscriptionName = Read-host "Enter subscription name "
  }
  Write-Host ""
  $ChangeRg = read-host "Change resource group? (Y/N)"
  if ($ChangeRg -eq "Y")
  {
    $MyResourceGroup = Read-host "Enter Resource group "
  }
  Write-Host ""
  $ChangeVnet = read-host "Change Vnet? (Y/N)"
  if ($ChangeVnet -eq "Y")
  {
    $MyVnet = Read-host "Enter VNet "
  }
}
#
try
{
  $MySubs = Get-AzureRmSubscription
}
catch
{
  Write-Host ""
  Write-Host -ForegroundColor Yellow "Unable to retrieve subscriptions."
}
$MySubsName = $MySubs.name
Start-Sleep 1
Write-Host ""
if ($MySubsName -contains "$MySubscriptionName")
{
  Write-Host "You are logged in and have access to `"$MySubscriptionName`"..."
}
else
{
  Write-Host "It appears that you are not logged in."
  Write-Host ""
  $NeedToLogin = Read-Host "Do you need to log in to Azure? (Y/N)"
  if ($NeedToLogin -eq "Y")
  {
    Login-AzureRmAccount
    Select-AzureRmSubscription -SubscriptionName $MySubscriptionName
  }
  elseif ($NeedToLogin -eq "N")
  {
    Write-Host "You must already be logged in then.  Fine. Continuing..."
  }
  else
  {
    Write-Host ""
    Write-Host "You made an invalid choice.  Exiting..."
    exit
  }
}
#
Start-Sleep 1
Write-Host ""
Write-Host "We will now check to see if a given IP address is available from any subnet in VNet `"$MyVnet`" "
Write-Host "...and if it is not available, provide the next few available on that subnet."
Start-Sleep 1
Write-Host ""
$MyTestIpAddress = Read-Host "What address to you wish to test for availability?"
#
$MyNetwork = Get-AzureRmVirtualNetwork -name $MyVnet -ResourceGroupName $MyResourceGroup
$MyResults = Test-AzureRmPrivateIPAddressAvailability -VirtualNetwork $MyNetwork -IPAddress $MyTestIpAddress
$MyResultsAvailableIPAddresses = $MyResults.AvailableIPAddresses
$MyResultsAvailable = $MyResults.Available
#
Start-Sleep 1
if ($MyResultsAvailable -eq $False)
{
  Write-Host ""
  Write-Host -ForegroundColor Yellow "Sorry, but $MyTestIpAddress is not available."
  Write-Host ""
  Write-Host -ForegroundColor Green "However, the following adddresses are free to use:"
  Write-Host ""
  $MyResultsAvailableIPAddresses
}
else
{
  Write-Host ""
  Write-Host -ForegroundColor Green "Yes! $MyTestIpAddress is available."
}
Write-Host ""
Write-Host " ...Complete"

Now, if you know a better way to handle it, or have tips for improvement — or if you find a bug — I’d love to hear them (and so would Jim).  I hope it helps you out there…

Thanks, and enjoy!