This blog has moved to http://ThePowerShellGuy.com
Greetings /\/\o\/\/
This eighth part of the AD series is the
*Edit* change of plans, see rest of blogentry, there will be one more, (one before) last about creating users in Active Directory,
in this post we will transform the filter used in last post to a more robust function, and transform it in a more production quality script.
*Note* Disclaimer, while I discus the posibilities for making a production quality script the example script I provide in this post is only a example on how to start, not complete and tested script, so only use this in a test environment also be sure to have a basic understanding
of how the script works, better yet read the other posts in this series first!
Part 1 to 3 of this series handle the making of a user from the start from the commandline, an overview what you can find where you can find in the beginning of part 4 ,
Part 5 - 7 handle the way to use CSV files or any other way to fill the PSObject with the needed properties, and this function.
PowerShell and Active Directory Part 7 PowerShell and Active Directory Part 6 PowerShell and Active Directory Part 5 PowerShell and Active Directory Part 4 (TypeData) PowerShell and Active Directory Part 3 (UserProperties) PowerShell and Active Directory Part 2 PowerShel and Active Directory Part 1 First about the change to a script, the Filter I used is easy to test with as you can just past it to the commandline, this version is a script that you can run directly.
for another example see the changes
Mike Hodnick made to an out-zip function I made before
MSH out-zip Function in his blogpost here
Create zip/compressed folders with Powershell to make it into a scriptas it was
"but it wasn't exactly 100% usable out of the box".The only thing that needed changing is the extension (MSH to PS1) and it works,
only this script was made to create / load the function :
. c:\powershell\fuctions\out-zip.ps1
note the [dot][space] before the scriptpath, that makes that the function is loaded into the $global scope, otherwise it is gone again after the script ends.
It is gone also if you close the PowerShell console but I load this in my profile to keep it handy.
As I mostly test by pasting code into the console most of my examples are like this, so you can just past them in from my blog to test.
So it both handy out-of-the box I think but in an other way and / or a different purpose.
it's good to compare the 2 scripts to see wat I mean.
In this case I also did choose to switch to a scriptfile to run and let it call internal functions.
for some more info and another example see also :
PowerShell AD site Finder this script has the same form, also the switch parameter and byRef I discuss there.
For the setting "User can not change password" I did not yet discuss that in Part 3 about setting the special properties, this is actualy a ACL on the directoryentry and you can not set it using ADSI, only with the NT provider.
You can not use the WinNT provider with a DirectoryEntry Object, but there are some workarounds see also :
Access ADSI WinNT provider from Monad Part 2You see there are 2 workarounds,
The First I found was inline VB.NET code
MSH access NT providerThe second was the Reflection example in part 2,that way, Importing the VisualBasic namespace , I show here :
# Setting User can not change password with NT provider using the VisualBasic namespace
[System.Reflection.Assembly]::LoadWithPartialName('microsoft.visualbasic')
$winNT = [microsoft.visualbasic.interaction]::GetObject("WinNT://mow/mow",$null)
$Type = $winNT.gettype()
$Type.invokemember("userFlags",'GetProperty',$null,$winNT,$null) -band 0x40
$new = $Type.invokemember("userFlags",'GetProperty',$null,$winNT,$null) -bor 0x40
$Type.invokemember("userFlags",'SetProperty',$null,$winNT,$new)
# Save the changes
$Type.invokemember("setinfo",'invokemethod',$null,$winNT,$null)
But as it is actualy an ACL on the directory object we can also change the security on the User object ourself, see for more information here :
MDSN User Cannot Change Password (LDAP Provider) (Be sure to follow the links to the different examples )
for a VbScript see example :
HilltopLabs : cannot Change PasswordThis looks very difficult and big scripts are needed, but we have powershell ;-)
So this looks like this in the script :
# Set User Cannot Change Password Property
if ($_.CantChangePassword) {
$everyOne = [System.Security.Principal.SecurityIdentifier]'S-1-1-0'
$EveryoneDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($Everyone,'ExtendedRight','Deny','ab721a53-1e2f-11d0-9819-00aa0040529b')
$self = [System.Security.Principal.SecurityIdentifier]'S-1-5-10'
$SelfDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($self,'ExtendedRight','Deny','ab721a53-1e2f-11d0-9819-00aa0040529b')
$newUser.get_ObjectSecurity().AddAccessRule($selfDeny)
$newUser.get_ObjectSecurity().AddAccessRule($EveryoneDeny)
$newUser.CommitChanges()
}
Not to Bad right, but note that the other examples do some more checking and can set it back also, as we create new users here we do not need all this.
*Edit* I decided this subject was important enough to get his own blogentry and found back some old material from when I did not have internet I did not post yet, so I will post that material here and will continue the script in next post.In the samples below you can also see how to explore the AD security from the commandline and also to check the current ACL's and remove the Access denied rules.
you can see that it is also very easy, also I will discuss the User must change password at next logon property in this examples, setting pwdLastset to -1 or 0
will switch that (it can not be set in combination the the User can not change password)
# Remove Access denied from commandline
$mow.get_ObjectSecurity().GetAccessRules($true,$false, [System.Security.Principal.SecurityIdentifier] )
$mow.get_ObjectSecurity().GetAccessRules($true,$false, [System.Security.Principal.NTAccount]) |? {$_.ObjectType -eq 'ab721a53-1e2f-11d0-9819-00aa0040529b'}
$mr = $mow.get_ObjectSecurity().GetAccessRules($true,$false, [System.Security.Principal.NTAccount]) |? {$_.ObjectType -eq 'ab721a53-1e2f-11d0-9819-00aa0040529b'} |? {$_.AccessControlType -eq 'Deny'}
$mow.get_ObjectSecurity().RemoveAccessRule($mr[0])
$mow.get_ObjectSecurity().RemoveAccessRule($mr[1])
$mow.CommitChanges()
########################################
PoSH>$mr[0].IdentityReference | gm
TypeName: System.Security.Principal.NTAccount
[System.Security.Principal.SecurityIdentifier].GetConstructors() |% {"$_"}
##############
# Make SID Objects
$everyOne = [System.Security.Principal.SecurityIdentifier]'S-1-1-0'
$self = [System.Security.Principal.SecurityIdentifier]'S-1-5-10'
# you can use NTAccount but thats localized
# translate
PoSH>$self.Translate( [System.Security.Principal.NTAccount])
Value
-----
NT AUTHORITY\SELF
# get the consructors
[System.DirectoryServices.ActiveDirectoryAccessRule].GetConstructors() |% {"$_"}
# we are going to use this one :
Void .ctor(System.Security.Principal.IdentityReference, System.DirectoryServices.ActiveDirectoryRights, System.Security
.AccessControl.AccessControlType, System.Guid)
new System.DirectoryServices.ActiveDirectoryAccessRule ($self,'ExtendedRight','Deny','ab721a53-1e2f-11d0-9819-00aa0040529b')
ActiveDirectoryRights : ExtendedRight
InheritanceType : None
ObjectType : ab721a53-1e2f-11d0-9819-00aa0040529b
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Deny
IdentityReference : S-1-5-10
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
$SelfDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($self,'ExtendedRight','Deny','ab721a53-1e2f-11d0-9819-00aa0040529b')
$SelfAllow = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($self,'ExtendedRight','Allow','ab721a53-1e2f-11d0-9819-00aa0040529b')
$EveryoneDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($Everyone,'ExtendedRight','Deny','ab721a53-1e2f-11d0-9819-00aa0040529b')
$EveryOneAllow = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($Everyone,'ExtendedRight','Allow','ab721a53-1e2f-11d0-9819-00aa0040529b')
$mow.get_ObjectSecurity().AddAccessRule($selfDeny)
$mow.get_ObjectSecurity().AddAccessRule($EveryoneDeny)
$mow.CommitChanges()
#########################################
# Setting User must change password at next Logon
$user.pwdLastSet = -1
# Reading password last set value
$ds = New-Object directoryservices.directorysearcher($user)
MowPS>[datetime]::fromfiletime(($ds.findone().properties.pwdlastset)[0])
Monday, July 17, 2006 5:07:05 PM
# Un-setting user must chage password at next logon
$user.pwdLastSet = 0
MowPS>$user.InvokeGet('PasswordLastChanged')
***************************
MowPS>[datetime]::fromfiletime(($ds.findone().properties.pwdlastset)[0])
Next post I will go on with the script, but I'm still a bit thinging about it and as said did think the ACL material was worth a own "extra" part in this series.
Enjoy,
Greetings /\/\o\/\/
Tags :
Monad msh PowerShell