Manage domain permissions using PowerShell and ADSI APIs

Hello! Consider a way to automate the assignment of user rights to resources using the ADSI and PowerShell interface. Initially, the problem arose when using old Windows 2003 domain controllers and limited Internet access. This topic was raised on Habré earlier. In the case described by me, the transition to the Windows 2008 OS took place only partially, but in terms of complexity and length of the process, it is comparable, perhaps, with the mission to Mars.
Problem statement:
When creating a new user in a large organization, a document is created that describes all the privileges of this account, including the AD groups in which it is a member.
There is a storage system used as a file storage of users with a large number of shared resources. Each shared resource (or just a ball) on the storage system contains an Access Control List (ACL) that includes at least two AD access groups - user (with read and execute permissions) and administrative (edit and delete). The name of both groups in AD includes the name of the resource itself for ease of search. Thus, for full access to the resource, the user needs membership in both groups.
The storage system also has a directory with shortcuts to links to resources in the public domain. When a new entry in the domain is logged in, the group policy containing Startup.script is processed. The script copies all the necessary shortcuts to the user's desktop. The user does not search for anything and immediately gets access to all the documents he needs.
Our task includes:
- Create user.
- Define a list of directories that the user must have access to.
- Create groups with a name containing the directory name.
- Add groups to the ACL directory. Assign the appropriate NTFS rights for each group.
- Include the user in the created groups.
- Create shortcuts with the directory name in the title.
- Update Startup.script, if the user is present in one of the groups, copy the corresponding shortcut to his desktop.
- Use available technical means.
There are at least four ways to do the above actions on Windows systems. Needless to say, performing these actions through the standard snap-ins even for one new user, you will not meet a hundred clicks of the mouse. If there are a lot of users of fifty and privileges of access, you definitely can’t do it in a day. We will try to automate each item separately. We will not describe in detail the creation of the user, this is easily accessible information.
Point 7 is also beyond the scope of the article, in fact it is an administrative template in the GPO policy. The contents of the script are as follows: if the user is in a group, you need to copy the corresponding shortcuts from a certain directory to the desktop. Everything else is also pretty automated in PowerShell.
We will write a test script without checking errors and other nuances.
Manually determine the variables for the test. The user's full name and lists of resources available to him will be obtained from the account creation document:
$server_name = read-host -prompt "Enter fileserver"
$share_name = read-host -prompt "Enter share_name"
$UNC="\\$server_name"+"\$share_name"+"$"If you entered everything correctly, first create a directory and a shortcut that refers to it:
if ($server_name -eq "S182froc152"){
$path = "\\$server_name" +"\vol1$\projetspec2\"
#Check if the directory exists. Skip if true.
if(!(Test-Path($UNC))) {
#Create directories
Write-Host "Creating $share_name"
New-Item -path $path -name $share_name -Type directoryCreate the shortcut through the COM object:
Write-Host "Creating shortcut"
New-Item -path $path\E182_P_GroupWare\Projets_Specifiques\$share_name -Type directory
$wsh = New-Object -com 'WScript.Shell'
$dir = "$path\E182_P_GroupWare\Projets_Specifiques\$share_name"
$sct = $wsh.CreateShortcut("$dir" +"\$share_name.lnk")
$sct.TargetPath =$UNC
$sct.Save()Create a security group.
First, a little theory:
There are security and distribution groups in AD. Distribution groups are used for mailing lists, mostly for MS Exchange.
Groups are also divided into local, global and universal.
- Local groups - manage permissions in the domain. May include objects from other domains.
- Global - give access to the object in any domain, but include only users from one domain.
- Universal - used in forests for multiple domains and greatly confuse everything. I did not have to use them.
Having rummaged in attributes, it is possible to find that local groups have identifier groupType -2147483644, and global - -2147483646.
It seems that the purpose of the group itself is determined by some bit in the number. If you are too lazy to look, you can see the identifier on TechNet.
Specify and create a local group in our domain - specify additional information in the comment: the path to the group resource, and what rights the group itself gives.
Add user:
#Create security_group
$ADS_GROUP_TYPE_LOCAL_GROUP = -2147483644
$objOU = [ADSI]"LDAP: //OU=Groups,OU=MPC,OU=E182,DC=emea,DC=corpdir,DC=net"
$GroupName = "$share_name"
$objGroup = $objOU.Create("group", "CN=" + $GroupName)
$objGroup.Put("groupType", $ADS_GROUP_TYPE_LOCAL_GROUP )
$objGroup.Put("description", $UNC )
$objGroup.Put("sAMAccountName", $GroupName )
$objGroup.SetInfo()
}}Resource rights are divided into SMB permissions and NTFS. This, respectively, access at the folder level and access at the file system level. In fact, they are independent. If you use FAT, you will only have to handle SMB permissions. Access to the resource finally consists of the sum of the SMB + NTFS permissions.
To avoid confusion with the rights to resources, we operate only on NTFS-rights. In SMB-rights we set up general access for all users. Recall the theory:
Each user in the system has an access token with security information for a given login session. The system itself creates an access token at login. Each process that runs on behalf of the user has a copy of this access token. The token identifies the user, user groups, and privileges. The token also contains a login SID (security identifier) that identifies the current login session. When a user tries to access the protected object, authorization in the system occurs and, as a result, he gets permission or denial of access. In this case, authorization is based on a search in the ACL (access control list).
Each entry (or ACE - Access Control Entry) in the object ACL defines access rights. The entry contains three elements:
- SID - the identifier of the user or group to which the entry applies.
- Type of access - reading, writing, etc.
- Record type - allow or deny.
If the owner of the object has not created any entries in the object ACL, the system provides access immediately. Thus, all SID entries in the access token are compared. The order of the entries is also important.
The system stops checking ACE entries when the requested access is explicitly allowed or denied. For example, explicit access denial takes precedence over inherited permission from the parent directory. In second place are inherited permissions from parent directories, followed by all permissions up the directory tree. This also means that the owner of the object can determine their own permissions on the object, which allow access to a group of users and deny access to a subgroup of the group. Inheritance parameters for an object can take the following values:
| Value | Description |
|---|---|
| "None", "None" | Rights apply only to this folder. |
| ContainerInherit, None | Rights apply to this folder and its subfolders |
| ObjectInherit, None | Rights apply to this folder and its files. |
| “ContainerInherit, ObjectInherit”, “None” | Rights apply to this folder of its subfolders and files. |
| ContainerInherit, InheritOnly | Rights apply only to subfolders. |
| “ObjectInherit”, “InheritOnly” | Permissions apply only to files. |
| “ContainerInherit, ObjectInherit”, “InheritOnly” | Rights apply only to subfolders and files. |
The test revealed that the group is not always created in the domain before the next step is performed. I have not done a check yet, so just set a sufficient pause of 5 seconds. Next, we get the directory ACL. Create a new entry in the ACL access list and save it:
start-sleep 5
$dirpath=$path+$share_name
$acl = get-acl $dirpath
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$share_name","ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.SetAccessRuleProtection($True, $True)
$acl.AddAccessRule($rule)
Set-Acl $dirpath $aclWe repeat the same for the second group, administrative, with different access rights:
start-sleep 5
#$objOU = [ADSI]"LDAP://OU=Groups,OU=MPC,OU=E182,DC=emea,DC=corpdir,DC=net"
$GroupName = "$share_name"+"_ADM"
$objGroup = $objOU.Create("group", "CN=" + $GroupName)
$objGroup.Put("groupType", $ADS_GROUP_TYPE_LOCAL_GROUP )
$objGroup.Put("description", $UNC )
$objGroup.Put("sAMAccountName", $GroupName )
$objGroup.SetInfo()
start-sleep 20
$dirpath=$path+$share_name
$acl = get-acl $dirpath
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$GroupName","Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.SetAccessRuleProtection($True, $True)
$acl.AddAccessRule($rule)
Set-Acl $dirpath $acl
Write-Host " $share_name created"It remains to simply "share" the directory:
$dirpath=$path+"\$sharename"
$Shares=[WMICLASS]”WIN32_Share”
If (!(GET-WMIOBJECT Win32_Share -filter “name=’$share_name’”) {
$Shares.Create(“$dirpath”,”$share_name”,0)
}Conclusion
PowerShell has additional convenient Active Directory and File System Security PowerShell Module modules. A normal administrator may not even think of messing with the jungle of object classes when assigning rights in PowerShell, otherwise he would not be an administrator, but a programmer. A list of local groups using the AD module can be obtained, for example, as follows:
get-qadgroup -GroupScope DomainLocal | Get-QADGroupMember -Type group | Where{$_.GroupScope -eq "Local"}Using ADSI, on the other hand, is a more universal approach. There are a large number of conservative customers who, by the way, cannot be convinced to refuse from Windows XP.
Cloning all permissions of one user to another, in this case, can be done from the command line using standard utilities:
dsquery user -samid Person |dsget user -memberof |dsmod group -addmbr "CN=Some Other Person(222),OU=Users,OU=_GlobalResources,OU=222,OU=E777,DC=emea,DC=corpdir,DC=net" –cSuccessful automation!