I have written the below function to copy file on a remote server
Function deploy-file{
PARAM(
[Parameter(Mandatory=$true,Position=0)][STRING]$cred,
[Parameter(Mandatory=$true,Position=1)][STRING]$server,
[Parameter(Mandatory=$true,Position=2)][STRING]$destdir,
[Parameter(Mandatory=$true,Position=3)][STRING]$file
)
$parameters = #{
Name = $server
PSProvider = "FileSystem"
Root = $destdir
Credential = $cred
}
new-psdrive #parameters
$d=$server + ":\"
copy-item $file $d -force
remove-psdrive $server -ErrorAction SilentlyContinue
}
Now, I am calling the above function from the main file as below:
$sn=abc.com
$server=($sn -split "\.")[0]
$destdir = 'e:\folder'
$file = 'file.zip'
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $usr, $pa
deploy-file $cred $server $destdir $file
There is no issue with credentials.
My script keeps running and not even throwing any error. What is wrong with the script?
Copying a file to a remote host using a PSSession would be as follows:
function Deploy-File {
[cmdletbinding()]
param(
[Parameter(Mandatory, Position=0)]
[securestring] $cred,
[Parameter(Mandatory, Position=1)]
[string] $server,
[Parameter(Mandatory, Position=2)]
[string] $destdir,
[Parameter(Mandatory, Position=3)]
[string] $file
)
try {
[IO.FileInfo] $file = Get-Item $file
$session = New-PSSession -ComputerName $server -Credential $cred
Copy-Item -Path $file -Destination $destdir -ToSession $session
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
finally {
if($session) {
Remove-PSSession $session
}
}
}
By looking at your code is hard to tell what could be failing aside from what we know for sure is incorrect, the parameter $cred is being constrained to [string] when it actually should be [securestring]. By doing so you're rendering your PS Credential object unusable.
Related
I have to make a script who change users domain of my shared folder and add them in addition to the existing users rights.
1st :
I do a script in PowerShell to get all NTFS rights of my directories (It worked perfectly) :
$FolderPath = Get-ChildItem -Directory -LiteralPath "C:\MYPATH" -Recurse -Force
$Report = #()
Foreach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'Users'=$Access.IdentityReference;'Rights'=$Access.FileSystemRights;'Inherit'=$Access.IsInherited;}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
$Report | Export-Csv -Encoding UTF8 -LiteralPath "E:\MYPATH\FolderPermissions2.csv"
2nd : I modify my CSV to find and replace with my new domain.
There is a part of my CSV :
"E:\test migration\MYPATH\MYPATH à la tireuse plans","BUILTIN\Users","AppendData","True"
"E:\test migration\MYPATH\MYPATH","BUILTIN\Users","CreateFiles","True"
"E:\test migration\MYPATH","OLD_DOMAIN\user_name","FullControl","True"
"E:\test migration\MYPATH","OLD_DOMAIN\user_name","ReadAndExecute, Synchronize","True"
"E:\test migration\MYPATH","BUILTIN\Administrators","FullControl","True"
"E:\test migration\MYPATH","NT AUTHORITY\SYSTEM","FullControl","True"
"E:\test migration\MYPATH","OLD_DOMAIN\a_nbe","FullControl","True"
3rd : And I do another script to re-import all rights from my modified CSV and Set them to the same folder :
Import-Module NTFSSecurity
Import-Module ActiveDirectory
$CSV = Import-Csv -Delimiter "," -LiteralPath "E:\MYPATH\FolderPermissions2.csv"
$CSV | ForEach-Object {
$FolderName = $_.FolderName
$Users = $_.Users
$Rights = $_.Rights
$Inherit = $_.Inherit
Add-NTFSAccess -Path $FolderName -IdentityReference $Users -FileSystemRights $Rights
$acl = Get-Acl $FolderName
if ($Inherit = "True", $acl.SetAccessRuleProtection($false,$True)) {
} else {
$acl.SetAccessRuleProtection($false,$False)
}
}
The first part of this script worked perfectly, all of my folder get the "new users" with my new domain with exactly the same rights.
BUT the part where I define my "IsInherited" don't work, I get the path and not my boolean...
screenshot of the error
Anybody has an idea where I do a mistake, please ?
Thank you !
#Cred= Get-Credential
$FolderPath = dir -Directory -Path "\\abc\dc\da" -Recurse -Force | where {$_.psiscontainer -eq $true}
$Report = #()
Foreach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
# $Name= Get-ChildItem $Folder -Recurse | where {!$_.PSIsContainer} |select-object fullname
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'AD
Group or User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
$Report | Export-Csv -path "C:\Output\Test_16-06-2021.csv"
In the above script, I'm able to get all my folder structure with permission but I want to do with a custom parameter like if I want to only folder level 3 it should get me the output as below
\\abc\a\b\c
\\abc\a\c\d
not like
\\abc\a\b\c\d\text.txt
\\abc\a\c\d\e\f\g\demo.pdf
If you're using PowerShell 5.0, you can use the -Recurse and -Depth parameters combined:
[string]$rootFolder = Read-Host -Prompt "Enter root folder path (no trailing '\')"
[int]$recursionDepth = Read-Host -Prompt "Enter recursion depth"
[string]$outputCsv = Read-Host -Prompt "Enter output .csv file (full path)"
$folders = Get-ChildItem -Directory -Path $rootFolder -Recurse -Depth $recursionDepth -Force | Where-Object { $_.PSIsContainer -eq $true }
[array]$report = #()
foreach ($folder in $folders) {
$acl = Get-Acl -Path $folder.FullName
foreach ($access in $acl.access) {
[hashtable]$properties = [ordered]#{
'FolderName' = $folder.FullName;
'AD Group or User' = $access.IdentityReference;
'Permissions' = $access.FileSystemRights;
'Inherited' = $access.IsInherited
}
$report += New-Object -TypeName PSObject -Property $properties
}
}
Write-Host $report
$report | Export-Csv -Path $outputCsv
If that isn't an option, you can try the following:
[string]$rootFolder = Read-Host -Prompt "Enter root folder path (no trailing '\')"
[int]$recursionDepth = Read-Host -Prompt "Enter recursion depth"
[string]$outputCsv = Read-Host -Prompt "Enter output .csv file (full path)"
[string]$recursionStr = if ($recursionDepth -eq 0) { "\*" } else { ("\*" * ($recursionDepth + 1)) }
$folders = Get-ChildItem -Directory -Path "$rootFolder$recursionStr" -Force | Where-Object { $_.PSIsContainer -eq $true }
[array]$report = #()
foreach ($folder in $folders) {
$acl = Get-Acl -Path $folder.FullName
foreach ($access in $acl.access) {
[hashtable]$properties = [ordered]#{
'FolderName' = $folder.FullName;
'AD Group or User' = $access.IdentityReference;
'Permissions' = $access.FileSystemRights;
'Inherited' = $access.IsInherited
}
$report += New-Object -TypeName PSObject -Property $properties
}
}
Write-Host $report
$report | Export-Csv -Path $outputCsv
See Limit Get-ChildItem recursion depth
I'm using Windows 10 Enterprise 1709 and PowerShell ISE v5. I am trying to get the last write time to the file deployment.properties by checking to see if the testpath holds the file and if it does, write the LastWriteTime of that file. I'm not sure I'm doing this the correct way. Any help showing me how to make this work would be appreciated. I've tried several options but this is the only one that doesn't produce an error. However, the code runs, completes without error but doesn't produce and output. My code is listed below first and then the output I see on the PowerShell ISE screen.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $javauser.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
Below is the output I get which returns no information.
PS C:\WINDOWS\system32> Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$filelist = Join-Path $User.FullName $file
if (Test-Path $filelist) {
$testResult = Get-ChildItem $dateTime | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
PS C:\WINDOWS\system32>
Newly modified code below
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, $DeplPath.LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime
Try this out. Your property select for the get-childitem were mislabeled.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
$test = Test-Path $folderFile
if ($test -eq $True) {
$testResult = Get-ChildItem $folderfile | select -Property Name, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime
I have this script baked into an AWS-AMI, running the script logged into an ec2-instance works, but when calling from userdata the Join AD with newname part gets skipped.
# Get Credentials from SSM
echo $new_name
$domain = "xxxx"
$username = (Get-SSMParameterValue -Name ad_domain_user).Parameters[0].Value
$password = (Get-SSMParameterValue -Name ad_domain_password -WithDecryption $True).Parameters[0].Value | ConvertTo-SecureString -asPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
# Get VPC Tags for OU Name
$vpc_id=(Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/network/interfaces/macs/$mac/vpc-id)
$env_name=(aws ec2 describe-vpcs --vpc-ids $vpc_id --query 'Vpcs[*].[Tags[?Key==`Name`] | [0].Value]' --output text)
echo "Attempting to join AD for env_name:$env_name" | Out-File "C:\Program Files\Amazon\Ec2ConfigService\Logs\pslog.txt" -Append
# Join AD with newname
Try {
if ("$env_name" -match "xxxx*") {
Add-Computer -DomainName $domain -ComputerName $env:computername -newname $new_name -Credential $credential -Force -Restart -ErrorAction 'Stop'
} elseif ("$env_name" -match "xxxx-xxxx-*") {
$oupath = "OU=Member Servers,OU=xxxx-xxxx,OU=xxxx,DC=aws,DC=ABC,DC=ORG"
Add-Computer -DomainName $domain -ComputerName $env:computername -newname $new_name -Credential $credential -Force -Restart -ErrorAction 'Stop' -OUpath$oupath
} elseif ("$env_name" -match "xxxx-xxxx-*") {
$oupath = "OU=Member Servers,OU=xxxx-xxxx,OU=xxxx,DC=aws,DC=ABC,DC=ORG"
Add-Computer -DomainName $domain -ComputerName $env:computername -newname $new_name -Credential $credential -Force -Restart -ErrorAction 'Stop' -OUpath $oupath
}
} Catch {
echo $_.Exception | Out-File "C:\Program Files\Amazon\Ec2ConfigService\Logs\Error-JoinDomain.txt" -Append
}
## If Error File Exists try again
Try{
If (Test-Path "C:\Program Files\Amazon\Ec2ConfigService\Logs\Error-JoinDomain.txt" -PathType Leaf) {
if ("$env_name" -match "xxxx*") {
Add-Computer -DomainName $domain -ComputerName $env:computername -newname $new_name -Credential $credential -Force -Restart -ErrorAction 'Stop'
} else {
Add-Computer -DomainName $domain -ComputerName $env:computername -newname $new_name -Credential $credential -Force -Restart -ErrorAction 'Stop' -OUpath $oupath
}
}
} Catch {
echo $_.Exception | Out-File "C:\Program Files\Amazon\Ec2ConfigService\Logs\Error-JoinDomain.txt" -Append
echo $_.Exception | Out-File "C:\Program Files\Amazon\Ec2ConfigService\Logs\pslog.txt" -Append
}
I am writing a script to get permissions and some other info on shares throughout the a network and I am having trouble getting the shares permissions. I read online that one can use "GetAccessMask" but I thought it was just for the current user.
#loop for each computer in computers file
ForEach ($computer in $allComputers)
{
Write-Host "Checking - $computer"
If($computer -ne '')
{
#check if online, this uses WMI so if you don't have access to the machine it will show as offline
If(Test-Connection -Computername $computer -ErrorAction SilentlyContinue)
{
$shares = Get-WmiObject -Class Win32_share -ComputerName $computer -Credential $uCredentials
ForEach($share in $shares)
{
$sName = $share.Name
$sPath = $share.Path
$sDesc = $share.Description
$objShare = New-Object -TypeName PSObject
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Server -NotePropertyValue $computer
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Online -NotePropertyValue $True
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Share -NotePropertyValue $sName
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Path -NotePropertyValue $sPath
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Description -NotePropertyValue $sDesc
$objShare | Export-CSV -Path $fOutfile -Append -NoClobber -NoTypeInformation
}
}
}
}
Above is a snippet of my script (as a whole it reads server list from a file, lists the share name,path, description) and I am wondering if anyone knows how I could get permissions on a given share for all users/groups with rights to the share.
Thanks in advance!
After you get the Shares from win32_share Class, Get the Share Permissions from the Win32_LogicalShareSecuritySetting Class, like this:
$Shares = Get-WmiObject Win32_Share -ComputerName $computer -Credential $uCredentials |
? {$_.Type -eq 0} ## 0 for Disk Drive shares only see: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-share
$Array = #()
$ACL = #()
Foreach ($Share in $Shares)
{
$ShareName = $share.name
$SharePermissions = Get-WmiObject Win32_LogicalShareSecuritySetting -Filter "name='$ShareName'" -ComputerName $computer
Foreach ($SP in $SharePermissions)
{
$SecDesc = $SP.GetSecurityDescriptor().Descriptor
foreach($ace in $SecDesc.DACL){
$UserName = $ace.Trustee.Name
If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}
If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }
$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)
}
}
$Results = "" | Select Server,Name,Status,Path,Description, ID, Rights
$Results.Server = $Share.__Server
$Results.Name = $Share.Name
$Results.Status = $Share.Status
$Results.Path = $Share.Path
$Results.Description = $Share.Description
$Results.ID = $ACL | % {$_.IdentityReference}
$Results.Rights = $ACL | % {$_.FileSystemRights}
$Results = $Results | ? {$_.id -ne $null}
$Array += $Results
}
$Array