running part of a script with different credentials.

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
DaveMcDonald
Posts: 11
Joined: Tue Sep 04, 2018 8:41 am

running part of a script with different credentials.

Post by DaveMcDonald » Wed Jun 26, 2019 3:25 am

To help you better we need some information from you.

*** Please fill in the fields below. If you leave fields empty or specify 'latest' rather than the actual version your answer will be delayed as we will be forced to ask you for this information. ***

Product, version and build:Powershell Studio 2019 Version 5.6.164
32 or 64 bit version of product:64
Operating system:Windows 10
32 or 64 bit OS:64

So here's my problem.

I have a form that runs as a service account. This is required due to some issues on our network shares. There are parts of the script I need to run with different credentials, basically to access and change properties and permissions of a security group. For the most part, i can use the Credential switch on the AD cmdlets, but, to change the security permissions on a security group in ad, I am using set-acl (if anyone has a better way to grant and remove "Write-Members" permission, please advise). Set-Acl does not have a credential switch. I have tried invoke-command.

$aclpath - String - "AD:\CN=ETIAll,OU=Security Groups,OU=National Groups,OU=National Objects,OU=Accounts,DC=ENT,DC=dfo-mpo,DC=
ca"

$groupacl - System.DirectoryServices.ActiveDirectorySecurity

So the first try I did this:
Invoke-Command -Credential $admincred -ComputerName localhost -ArgumentList $groupinfo, $GroupACL -ScriptBlock {
Set-Acl -path AD:$args[0] -AclObject $args[1]}

Failed:
[localhost] Connecting to remote server localhost failed with the following error message : Access is
denied. For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (localhost:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken

Then I tried this:

Start-Job -Name "Set Permissions" -Credential $admincred -ArgumentList $aclpath, $GroupACL -ScriptBlock { Set-Acl -path $args[0] -AclObject $args[1] }

That failed.
AclObject
+ CategoryInfo : InvalidArgument: (System.Director...rectorySecurity:PSObject) [Set-Acl],
ArgumentException
+ FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand
+ PSComputerName : localhost

I tried a couple of other things (wrapping the whole function in a start-job, etc) nothing seems to work. Any ideas out there?

Here is the function I built.
Function Change-SecACL
{
<#
.SYNOPSIS
This function will add a secondary person to write members.

.DESCRIPTION
Using get and set acl this script will add a secondary user
to have the ability to modify the membership of a security
group

.PARAMETER User
Username

.PARAMETER Group
Group Name

.PARAMETER AR
Remove or Add user
.EXAMPLE


#>
param (

[Parameter(Mandatory = $true)]
[System.String]$User,
[Parameter(Mandatory = $true)]
[System.String]$Group,
[ValidateSet("ADD", "REMOVE")]
[System.String]$AR
)

$userinfo = get-aduser $User -Credential $admincred
$groupinfo = Get-adgroup $group
Write-Host $user
Write-Host $userinfo
Write-Host $groupinfo
$Sid = New-Object System.Security.Principal.NTAccount($userinfo.SamAccountName)
$sid = $sid.Translate([System.Security.Principal.SecurityIdentifier])
$identity = $sid
$GroupACL = Get-Acl -Path "AD:\$($groupinfo.DistinguishedName)"
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$identity,
[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty,
[System.Security.AccessControl.AccessControlType]::Allow,
"bf9679c0-0de6-11d0-a285-00aa003049e2",
[DirectoryServices.ActiveDirectorySecurityInheritance]::All
)
$aclpath = "AD:\$($groupinfo.DistinguishedName)"
switch ($AR)
{
"ADD" { $GroupACL.AddAccessRule($ACE); break }
"REMOVE" { $GroupACL.RemoveAccessRule($ACE); break }
}

switch ($AR)
{
"ADD" {
Start-Job -Name "Add Permissions" -Credential $admincred -ArgumentList $aclpath,$GroupACL -ScriptBlock { Set-Acl -path $args[0] -AclObject $args[1] }
Wait-Job -Name "Add Permissions"
Receive-Job -Name "Add Permissions"
}
"Remove" {
Start-Job -Name "Remove Permissions" -Credential $admincred -ArgumentList $aclpath,$GroupACL -ScriptBlock { Set-Acl -path $args[0] -AclObject $args[1] }
Wait-Job -Name "Remove Permissions"
Receive-Job -Name "Remove Permissions"
}
}


}

User avatar
davidc
Posts: 5913
Joined: Thu Aug 18, 2011 4:56 am

Re: running part of a script with different credentials.

Post by davidc » Wed Jun 26, 2019 7:43 am

[TOPIC MOVED TO POWERSHELL GUIS FORUM BY MODERATOR]
David
SAPIEN Technologies, Inc.

User avatar
jvierra
Posts: 13681
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: running part of a script with different credentials.

Post by jvierra » Wed Jun 26, 2019 7:46 am

You cannot pass a security object between sessions. Using credentials creates a new security session.

Place the whole script in the job and it should work as expected.

DaveMcDonald
Posts: 11
Joined: Tue Sep 04, 2018 8:41 am

Re: running part of a script with different credentials.

Post by DaveMcDonald » Wed Jun 26, 2019 10:25 am

That worked! Thanks jvierra!!


Function Change-SecACL
{
<#
.SYNOPSIS
This function will add a secondary person to write members.

.DESCRIPTION
Using get and set acl this script will add a secondary user
to have the ability to modify the membership of a security
group

.PARAMETER User
Username

.PARAMETER Group
Group Name

.PARAMETER AR
Remove or Add user
.EXAMPLE


#>
param (

[Parameter(Mandatory = $true)]
[System.String]$User,
[Parameter(Mandatory = $true)]
[System.String]$Group,
[ValidateSet("ADD", "REMOVE")]
[System.String]$AR
)
Start-job -name "Set-ACL" -Credential $admincred -ArgumentList $User, $Group, $AR -ScriptBlock {
$AR = $args[2]
$userinfo = get-aduser $args[0]
$groupinfo = Get-adgroup $args[1]
$Sid = New-Object System.Security.Principal.NTAccount($userinfo.SamAccountName)
$sid = $sid.Translate([System.Security.Principal.SecurityIdentifier])
$identity = $sid
$GroupACL = Get-Acl -Path "AD:\$($groupinfo.DistinguishedName)"
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$identity,
[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty,
[System.Security.AccessControl.AccessControlType]::Allow,
"bf9679c0-0de6-11d0-a285-00aa003049e2",
[DirectoryServices.ActiveDirectorySecurityInheritance]::All
)
$aclpath = "AD:\$($groupinfo.DistinguishedName)"
switch ($AR)
{
"ADD" { $GroupACL.AddAccessRule($ACE); break }
"REMOVE" { $GroupACL.RemoveAccessRule($ACE); break }
}

Set-Acl -path $aclpath -AclObject $GroupACL

}
Wait-job -name "Set-Acl"
}

-------------------------------

Well I learned something new. You can't pass security objects between sessions.

DaveMcDonald
Posts: 11
Joined: Tue Sep 04, 2018 8:41 am

Re: running part of a script with different credentials.

Post by DaveMcDonald » Fri Jul 05, 2019 8:55 am

So now things are getting a bit weird.

Function Change-SecACL
{
<#
.SYNOPSIS
This function will modify a security group ACL.

.DESCRIPTION
This function will run as a job with diffrent credeitanls (supplied at start of the script).
It will ADD or REMOVE an ACE from the ACL. It only currently adds or removes the Write-Members allow
ACE for the User.

.EXAMPLE
PS C:\> Change-SecACL mcdonalddw ETIAll -AR ADD

.NOTES
Since the whole script runs as a service account, this funtion actually runs as a job with diffrent
credentials. We do not want the serivce account modifying AD objects. Admin account credentials must be
supplied at the start of the script.

.PARAMETER $USER
An AD User Account

.PARAMETER $Group
An AD Security Group

.PARAMETER $AR
Add or Remove the user from the group ACL
#>
param (

[Parameter(Mandatory = $true)]
[System.String]$User,
[Parameter(Mandatory = $true)]
[System.String]$Group,
[ValidateSet("ADD", "REMOVE")]
[System.String]$AR
)

# Must be run as a job with diffrent crednetials
Write-Host "Starting Job"
Start-job -name "Set-ACL" -Credential $admincred -ArgumentList $User, $Group, $AR -ScriptBlock {
$AR = $args[2]
$userinfo = get-aduser $args[0]
$groupinfo = Get-adgroup $args[1]
#Create the SID object
$Sid = New-Object System.Security.Principal.NTAccount($userinfo.SamAccountName)
$sid = $sid.Translate([System.Security.Principal.SecurityIdentifier])
$identity = $sid
$aclpath = "AD:\$($groupinfo.DistinguishedName)"
#Get the current ACL
$GroupACL = Get-Acl -Path $aclpath
#Create the access control entry we wish to modify.
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$identity,
[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty,
[System.Security.AccessControl.AccessControlType]::Allow,
"bf9679c0-0de6-11d0-a285-00aa003049e2",
[DirectoryServices.ActiveDirectorySecurityInheritance]::All
)
#Decide if we are going to add the ACE to the ACL or remove the ACE from the ACL.
switch ($AR)
{
"ADD" { $GroupACL.AddAccessRule($ACE); break }
"REMOVE" { $GroupACL.RemoveAccessRule($ACE); break }
}
#Set the ACL with the modifications. This will preserve the original entries other than the one we modified.
Set-Acl -path $aclpath -AclObject $GroupACL

}
#Wait for the job to complete.
Write-Host "Waiting for Job"
Wait-job -name "Set-Acl"
}

The job doesn't run. I get the attached error.
error.pdf
(41.08 KiB) Downloaded 9 times

User avatar
jvierra
Posts: 13681
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: running part of a script with different credentials.

Post by jvierra » Fri Jul 05, 2019 11:25 am

When posting code please post the code as an attachment or use the code posting tool provided on the edit bar. WHat you are posting is hard to read and cannot be easily copied without errors.

When posting errors please post the complete error as text using the posting tools provided. Putting everything in a PDF is not really very helpful in this forum.

Locked