/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Signing PowerShell Scripts "," PowerShell and Active Directory Part 7 "," PowerShell and Active Directory Part 6 "," Windows PowerShell Video: Next Generation Command ... "," PowerShell and Active Directory Part 5 "," PowerShell and Active Directory Part 4 (TypeData) "," PowerShell and MOM2005 part 2 : Updating Settings "," PowerShell Boolean FileMode "," Working with Fixed Length delimited Text files in ... "," PowerShell and Active Directory Part 3 (UserProper... "," ")

Friday, August 11, 2006

 


PowerShell and Active Directory Part 8 (ACL's)



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 2

You see there are 2 workarounds,
The First I found was inline VB.NET code MSH access NT provider
The 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 Password

This 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 172006 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 :


Comments: Post a Comment

Links to this post:

Create a Link



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?