Thursday, June 28, 2012

Can you trust the man in the red underpants?

The man in the red underpants.  A great short story on how to trust ideas and beliefs.   The book starts by pointing out that you're not going to like it and it will talk about things you don't want to think about.  But, its a quick read, so why would you let that stop you? 

Click on the man to start exercising your mind.

Wednesday, June 27, 2012

Getting AD object metadata via powershell

Occasionally I receive requests in my organization to see when was a user changed, when was someone added removed from a group, etc etc.  I thought it would be nice to get away from repadmin with this and come up with something that can provide enough information, be somewhat easy to use, and not require any special rights or tools.  So I put together this script to pull metadata (either attribute changes, or multivalue changes) on computers, users, or group objects.  In the script, you provide the common name of the object and the type of object.  From here it searches the global catalog for it, pulls the metadata, cuts down the attributes and outputs it in pre-sorted columns.  From there it can be searched or further formated using typical powershell commandlets to manipulate objects.  For those that want to take this further, you can follow the example of how to pull the metadata via ldap and manipulate the XML to include the attributes you want.  Some caveats with this which you won't find in repadmin /showobjmeta is that the times are in Z time, and recording domain controller data is using the domain controller GUID.  So there are some opportunities for expansion and improvement of this script for a more tech oriented audience.




#requires -version 2

param(
 [parameter(mandatory=$true)][alias('samaccountname','cn','username','groupname')]$name,
 [parameter(mandatory=$true)][ValidateSet("Group","Computer","User")]
  [alias('object','objecttype')]$type,
 [switch][alias("members","member")]$valuemeta
)

#Set up connection to forest
$de = New-Object directoryservices.DirectoryEntry("GC://dc=contoso,dc=com")
$ds = new-object directoryservices.directorysearcher($de)

#set an appropriate search filter for each type of object
switch ($type) {
  "group" {$ds.filter = "(&(objectclass=group)(|(samaccountname=$name)(cn=$name)))" }
  "computer" { $ds.filter = "(&(objectclass=computer)(cn=$name))" }
  "user" { $ds.filter = "(&(objectclass=user)(samaccountname=$name))" }
} 

#load up metadata attribs and search
$ds.propertiestoload.add("distinguishedname") > $null
$fu = $ds.findone()
if ($fu -ne $null) {
 $de = New-Object directoryservices.DirectoryEntry("LDAP://" + $fu.properties.distinguishedname[0])
} else {
 Write-Error "Object not found in AD"
 exit 1
}
$ds.searchroot = $de
$ds.propertiestoload.add("msDS-ReplAttributeMetaData") > $null
$ds.propertiestoload.add("msDS-ReplValueMetaData") > $Null
$fu = $ds.findone()

#display the requested type of data
if ($valuemeta) {
 $xml = "<root>" + $fu.properties."msds-replvaluemetadata" + "</root>"
 $xml = [xml]$xml
 $xml.root.DS_REPL_VALUE_META_DATA | 
  Select-Object @{name="Attribute"; expression={$_.pszAttributeName}},@{name="objectDN";expression={$_.pszObjectDN}},ftimeDeleted,ftimeCreated |
  Sort-Object attribute
} else {
 $xml = "" + $fu.properties."msds-replattributemetadata" + ""
 $xml = [xml]$xml
 $xml.root.DS_REPL_ATTR_META_DATA |
  select-object @{name="Attribute";expression={$_.pszAttributeName}},@{name="ChangeTime";expression={$_.ftimeLastOriginatingChange}}|
  Sort-Object attribute
}

<#
.DESCRIPTION
 Show-ADObjMeta will show the attributes and last time written on the object.
 
.PARAMETER Name
 The name of the user/computer/group that you want to pull the metadata for.  This should be the logon
 id if it is a user, the computer name for computers, and the groupname (cn or samaccountname) for groups.

.PARAMETER ValueMeta
 Use this parameter if you want to view multivalue item metadata, like Group Member add/remove details
 
.PARAMETER Type
 Specify the type of object: User, Group, Computer
 
.EXAMPLE
 Show-ADObjMeta -type user -name myuser

 Get the metadata for attributes of myuser
 
#>

Tuesday, June 26, 2012

Bulk adding users to a domain group based on their email address

This is a quick script I threw together to help out someone with adding two thousand users to a group based on an email list. As you may notice, the format of the email and the domain DN is specified here, so if you want to use it in your environment, change the "contoso" parts to whatever is valid for your forest. This script assumes that the group that you want to add users to is a uniquely named group, as I didn't write anything to handle multiple groups in different domains with the same CN value. The script will take the email addresses from a text file (one per line) and add them to the group. If the email can't be found, or group can't be modified it will provide error details on a per email basis.




#requires -version 2

#Bulk add by email address value

param(
 [parameter(mandatory=$true)][ValidateScript({Test-path $_ -PathType Leaf})]$userlist,
 
 [parameter(mandatory=$true)][ValidateScript( {
  #This validator will check AD to see if the group exists, and it will set $script:tgtgrp to the object that
  #will be modified
  $validatesearcher = New-Object directoryservices.DirectorySearcher("GC://dc=contoso,dc=com")
  $validatesearcher.filter = "(&(objectclass=group)(cn=$_))"
  $script:tgtgrp = $validatesearcher.findone()
  return $tgtgrp
 })]$groupname
)

$script:tgtgrp = [adsi]$script:tgtgrp.path
$users = get-Content $userlist
$de = New-Object directoryservices.DirectoryEntry("GC://dc=contoso,dc=com")
$searcher = New-Object directoryservices.Directorysearcher($de)
foreach ($user in $users) {
 try {
  if ($user -notmatch "@contoso.com") {
   throw "Entry: $user  is not a valid email address"
  }
  
  $searcher.filter = "(&(objectclass=user)(proxyaddresses=SMTP:$user))"
  $userobj = $searcher.findone()
  if ($userobj -eq $null) {
   throw "Entry: $user  could not be found in active directory"
  }
  
   try {
    $script:tgtgrp.properties["member"].add($userobj.properties.distinguishedname[0]) |out-null
    $script:tgtgrp.setinfo()
   } catch {
    throw "Error occurred when trying to add member:$($userobj.properties.distinguishedname[0]) to group"
   }
  
 } catch {
  Out-Default -InputObject $_.exception
 }
}

<#
.DESCRIPTION
 Add-BulkUserByEmail will add users to a specified group (Used quotes around groups with spaces in them)
 from a text file list of user email addresses (one user per line)
 
.PARAMETER Userlist
 The full path to the userlist text file (ex: c:\temp\userlist.txt)
 
.PARAMETER Groupname
 The name of the group object in active directory (CN attribute value).  This name must be unique in the 
 forest, or the wrong group may be selected

.EXAMPLE
 Add-BulkUserByEmail -userlist c:\temp\userlist.txt -groupname "My Distro List group"
 
#>

Monday, June 4, 2012

Trinity - summed up in one verse

 
I have seen a lot of attempts to wrap the idea of trinity (God being 3 in 1), by projecting this philosophy on to various verses in ways that make the verse mean other than what it obviously means. In other cases, there were fabricated verses inserted into the bible. And in more we have people attempting to explain away glaring contradictions by saying Jesus didn't know he was God, or was only human at that specific time...basically grasping at straws with no knowledge of the incident in question. I thought I would sum up the trinity in one verse using basic logic. The verse:

Mark 10:18       (Comparitive translations)

"Why do you call me good?" Jesus answered. "No one is good--except God alone."

This is in response to a man just calling Jesus "Good teacher" and asking for guidance on how to get eternal life. Since Jesus was a teacher of goodness and called people to the truth, this would be an appropriate title to address him with. But Jesus responds that only God is good. Lets look at this from the perspective of Jesus and God being part of a trinity.

In Trinity: Jesus = God
In Logic: Jesus says only God is good, thus stating that he is not, by his rejection of the man's
               assertion Jesus = Good, he implies Jesus != Good 
               If Jesus = God, Jesus would be the same entity and (Jesus = Good) must also be true.

Since he is rejecting this statement, then this must be true:
               Jesus != God 

Additionally, in the verse, the word used is "God", not "The Father".  So there is no means that anyone could try to say that they are still the same essence, with one being better than the other in some way.

Besides the logical argument, look how Jesus reacts to the statement.  He could have ignored it, or assumed it was a simple compliment, but he instead immediately redirected the focus to the One that is worthy of all praise...OUR LORD.  Jesus stated that the most important commandment is the first commandment; the oneness of God.  This is a perfect demonstation of giving God what is due to Him, as Jesus said, I of myself can do nothing.


There are many obvious verses that point to this truth. Even verses used to "prove" the trinity, do more to disprove it than they do to support it. I hope the Christians of the world contemplate deeply about the nature of their faith and the source of their book. Look deep for truth.  Ask yourself why none of the messengers talked about trinity or God being multiple parts.  When asked what is the most important of commandments, Jesus stated in Mark 12:29 that is the first: "Hear, O Israel: The Lord our God, the Lord is one."  Jesus points out that he is an example to follow, yet none follow his ways of doing things. For the sincere of faith, and the one that truly wants success in thereafter, pray as Jesus prayed (Matthew 26:39) and ask our Lord (the father) for guidance to see truth and to know the way to return to him with success.  It would be a tragedy if the good works you do are in vain because you haven't applied the first commandment.

Start looking for answers with sincerity.
A good place to start, The true message of Jesus


For some more points to consider, please view some points from my next post.