Nac Getting in Control of Your Mab Enabled Clients

It has been a while since I wrote a paper about the implementation of NAC. Now almost a year later it is finally in progress of implementation. One of the most time consuming processes and error sensitive ones is the adding of MAC addresses to the Active Directory of devices which doesn’t support Dot1X. Unfortunately there are a lot of devices which don’t speak Dot1X or having troubles with it. So if you want to do it right (IMO) you put these devices in different categories (and subnets) so you can put ACL’s on it (MAC spoofing can be easily done). At this moment we have three different categories within MAB authentication, which may grow in the near future; Thin clients, Printers and temporarily devices. To keep an clean view of all these MAC addresses in the AD I categories these MAC address in different OU’s, so I have three different OU’s which represent the different devices. We use Microsoft NPS server as Radius server and unfortunately you can’t (at least I didn’t find it) use the OU as a hit for a rule. So you also need to make three groups in which you place the MAC addresses (these are user objects in the AD). You also want to delete the “Domain User” group from the MAC address. Otherwise people would be able to login with MAC address on you domain members. So there you have already three different steps to just add one MAC address.

  1. Add the MAC address to the right OU.
  2. Add the MAC address to the right group.
  3. Delete the group Domain Users (to accomplish this, set the other group as primary.)

This isn’t a problem, but if you have to add MAC addresses regularly, this is quiet annoying and you easily forget one of those steps. Another thing you might consider is that most of the time MAC addresses are added by other persons, it would be nice if you give them a tool which makes it easier for them and less faulty. To accomplish this I wrote a Powershell script (actual my first one, so be nice :-) ). This scripts draws a simple menu where a user simply can add or delete a MAC address. Since we in the same project move the printers to DHCP (reservations) I also added this option.

Below you find the powershell script, make sure the users have rights to the right OU in the AD, in the example it is “Network Access” and also give them rights on the User folder in the AD, otherwise the “Domain Users” group can’t be deleted (Took me almost an hour). If you also want to use the DHCP functionality, make sure they have rights there too. The script makes use of Quest “ ActiveRoles Management Shelf”, so this one needs to be installed. I tried to translate all the Dutch comment, to English and I also filled the variables with fictional values. If you have any comments or improvements, please let me know. Since it is my first powershell script, I’m sure there are.

# =============================================================
#	 NAAM: nac_menu.ps1
#  AUTEUR: Rob Maas
#   DATUM: 21-03-2011
# COMMENT: Adding/deleting MAC addresses to the AD for MAB.
# =============================================================

#[ GENERAL ]
# DHCP Settings
$dhcpServer 		= "DHCPSERVER1"
$dhcpScopePrinters 	= "192.168.1.0"

# Apparaat specifieke eigenschappen
$printer 	= @{"Name" = "Printer"; `
		       "OU" = "ou=Printers,ou=MAC,ou=Network Access,ou=corporation,dc=domain,dc=com"; `
		       "GRP" = "NA_Printers"}
$thinclient	= @{"Name" = "Thin Client"; `
		       "OU" = "ou=Thin Client,ou=MAC,ou=Network Access,ou=corporation,dc=domain,dc=com"; `
		       "GRP" = "NA_Thinclient"}
$temporary = @{"Name" = "Temporarily device"; `
		       "OU" = "ou=Temporarily,ou=MAC,ou=Network Access,ou=corporation,dc=domain,dc=com"; `
		       "GRP" = "NA_Temporarily"}

#[ MENU Declaration ]
# MAINMENU
$mnuMainTitle = "NAC Menu"	#Title
# Name
$mnuMainItems = @((0..4),(0..4))	#Dummy values
$mnuMainItems[0][0] = "Add MAC address"
$mnuMainItems[0][1] = "Delete MAC address"
$mnuMainItems[0][2] = "Add printer to DHCP "
$mnuMainItems[0][3] = "Delete printer from DHCP"
$mnuMainItems[0][4] = "Exit"
# Corresponding functions
$mnuMainItems[1][0] = {ShowAddMacMenu}
$mnuMainItems[1][1] = {DelMAC}
$mnuMainItems[1][2] = {AddPrinterToDHCP}
$mnuMainItems[1][3] = {DelPrinterFromDHCP}
$mnuMainItems[1][4] = {Exit}

#ADDMAC MENU
$mnuAddMacTitle = "Add MAC address"
$mnuAddMAC = @((0..3),(0..3))
#Name
$mnuAddMac[0][0] = "Add Thinclient"
$mnuAddMac[0][1] = "Add printer"
$mnuAddMac[0][2] = "Add temporarily device"
$mnuAddMac[0][3] = "Main menu"
#Corresponding
$mnuAddMac[1][0] = {AddMac $thinclient}
$mnuAddMac[1][1] = {AddMac $printer}
$mnuAddMac[1][2] = {AddMac $temporarily}
$mnuAddMac[1][3] = {ShowMainMenu}

#[ -- SCRIPT -- ]
#Methods in alphabeticall order

function AddMac{
	param($device)
	$address = GetMac;
	#New device
	Write-Host "Give in the" $device["Name"] "name: " -NoNewline
	$name = $Host.UI.ReadLine()
	New-QADUser -Name $address -UserPassword $address `
		-DisplayName $address `
		-LastName $address `
		-FirstName $address `
		-UserPrincipalName $address `
		-Description $name `
		-SamAccountName $address `
		-ParentContainer $device["OU"]
	#Unable to change password
	Set-QADUser -Identity $address -PasswordNeverExpires $true | Out-Null
	#Add to right group and delete "domain users" group
	Add-QADGroupMember -Identity $device["GRP"] -Member $address | Out-Null
	Set-QADUser -Identity $address -ObjectAttributes @{PrimaryGroupID=(Get-QADGroup -Identity $device["GRP"]).PrimaryGroupToken } #| Out-Null
	Remove-QADGroupMember -Identity "Domain Users" -Member $address #| Out-Null
	Write-Host "Account is created !!!" -ForegroundColor Yellow
	#If it is a printer, add to DHCP?
	if ($device -eq $printer){
		$dhcp = Read-Host "Add the printer to DHCP? (Y|N) ?"
		if ($dhcp -eq "y") {AddPrinterToDHCP $name $address}
	}
	if (Again) {AddMac $device} else {ShowMainMenu}
}

function Again{
	$again = Read-Host "Again (Y|N) ? "
	switch ($again){
		"Y" {return $true}
		default {return $false}
	}
}

#Add printer to DHCP
function AddPrinterToDHCP{
	param($name, $address)
	if (($address -eq $null) -or ($name -eq $null)){
		$name = Read-Host "Printer name: "
		$address = GetMac $false
	}
	$ip = Read-Host "The IP address of the printer (192.168.1.0)?"
	Write-Host "Printer: `t $name"
	Write-Host "IP: `t`t $ip"
	Write-Host "MAC: `t`t $address"
	$ok = Read-Host "Are the above details correct (Y|N|X = Menu) ?"
	switch ($ok){
		"y" {
			 Invoke-Expression -Command "netsh dhcp server $dhcpServer scope $dhcpScopePrinters add reservedip $ip $address $name" | Out-Null
			 Invoke-Expression -Command "netsh dhcp server $dhcpserver scope $dhcpScopePrinters set reservedoptionvalue $ip 012 STRING $name"
			 if (Again) {AddPrinterToDHCP} else {ShowMainMenu}
			 break}
		"n" {$name = $null
			 $address = $null
			 AddPrinterToDHCP
			 break}
		"x" {ShowMainMenu
			 break}
	}
	$name = $null
	$address = $null
	if (Again) {AddPrinterToDHCP} else {ShowMainMenu}
}

function DelMaC{
	$address = GetMac $false $true
	$delete = Read-Host "Are you sure, you want to delete $address (Y|N) ? "
	switch ($delete){
		"y" {Remove-QADObject -Force -Identity $address | Out-Null
			 Write-Host "$address verwijderd!" -ForegroundColor Yellow
			 if (Again) {DelMac} else {ShowMainMenu}
			 break}
		default {ShowMainMenu
				 break}
	}
}

function DelPrinterFromDHCP{
	$address = GetMac $false $true
	$ip = Read-Host "The IP address of the printer (192.168.1.0)?"
	Write-Host "MAC Adres: `t $address"
	Write-Host "IP Adres: `t $ip"
	$ok = Read-Host "Are the above details correc (Y|N|X = Menu) ?"
	switch ($ok){
		"y" {
			 Invoke-Expression -Command "netsh dhcp server $dhcpServer scope $dhcpScopePrinters delete reservedip $ip $address"
			 if (Again) {DelPrinterFromDHCP} else {ShowMainMenu}
			 ShowMainMenu
			 break}
		"n" {$address = $Null
			 DelPrinterFromDHCP
			 break}
		"x" {ShowMainMenu
			 break}
	}
}

function DrawMenu{
	param($menuItems, $menuTitle, $menuPosition)
	$fgColor = $Host.UI.RawUI.ForegroundColor
	$bgColor = $Host.UI.RawUI.BackgroundColor
	cls
	$l = $menuItems[0].Length - 1;
	$menuWidth = $menuTitle.Length + 8
	Write-Host "`t" -NoNewline
	Write-Host ("*" * $menuWidth) -ForegroundColor $fgColor -BackgroundColor $bgColor
	Write-Host "`t" -NoNewline
	Write-Host "*   $menuTitle   *" -ForegroundColor $fgColor -BackgroundColor $bgColor
	Write-Host "`t" -NoNewline
	Write-Host ("*" * $menuWidth) -ForegroundColor $fgColor -BackgroundColor $bgColor
	Write-Host ""
	Write-Debug "L: $l MenuItems: $menuItems MenuPosition: $menuPosition"
	for ($i = 0; $i -le $l; $i++){
		Write-Host "`t" -NoNewline
		if ($i -eq $menuPosition){
			Write-Host " $($menuItems[0][$i])" -ForegroundColor $bgcolor -BackgroundColor $fgColor
		} else {
			Write-Host " $($menuItems[0][$i])" -ForegroundColor $fgcolor -BackgroundColor $bgColor
		}
	}
	Write-Host
}

function Exit{
	Invoke-Expression -Command "exit"

}

#Check if the given MAC address is valid.
function GetMAC{
	param([bool]$new = $true,		#Has to be new in the AD
		  [bool]$exist = $false)	#Must exist in the AD
	$mac = Read-Host "Give in the MAC address in lowercase and withouth punctuations: "
	#Check if the address has a length of 12
	If ($mac.length -ne 12){
		Write-Host "Invalid address!" -ForegroundColor Red
		if (Again) {GetMac $new $exist; return} else {ShowMainMenu; return}
	}
	If (($new) -and (Get-QADUser -Name $mac)){
		# Already exist
		Write-Host "Address already exist!" -ForegroundColor Red
		if (Again) {GetMAC $new $exist; return} else {ShowMainMenu; return}
	}
	if ((-not $new) -and ($exist) -and (-not (Get-QADUser -Name $mac))){
		#Address not found
		Write-Host "Address not found! " -ForegroundColor Red
		if (Again) {GetMAC $new $exist; return} else {ShowMainMenu; return}
	}
	return $mac
}

function Menu{
	param($menuItems, $menuTitle)
	$vkeyCode = 0
	$menuPosition = 0
	DrawMenu $menuItems $menuTitle $menuPosition
	While ($vkeycode -ne 13){
		$press = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
		$vkeyCode = $press.virtualkeycode
		Write-Host "$($press.character)" -NoNewLine
		If ($vkeyCode -eq 38) {$menuPosition--}	#Down
		If ($vkeyCode -eq 40) {$menuPosition++}	#Up
		If ($menuPosition -lt 0) {$menuPosition = $menuItems[0].Length - 1}
		If ($menuPosition -ge $menuItems[0].Length) {$menuPosition = 0}
		DrawMenu $menuItems $menuTitle $menuPosition
	}
	$($menuItems[1][$menuPosition]).Invoke()
}

function ShowAddMACMenu{
	Menu $mnuAddMac $mnuAddMacTitle
}

function ShowMainMenu{
	Menu $mnuMainItems $mnuMainTitle
}

ShowMainMenu
Rob Maas
Rob Maas
Technical Challanger at ON2IT

If it is broken, fix it! If it ain’t broken, make it better!

Related