Pipelining between two SEPARATE Powershell processes - powershell

Let's say I have two PowerShell programs running: Producer.ps1 and Consumer.ps1.
Is there any way to establish a client-server relationship between the two .ps1 files I have?
Specifically, Producer.ps1 outputs a PSObject containing login info. Is there any way I can establish a listener and named pipe between the two objects to pass this PSObject from Producer.ps1 directly into Consumer.ps1?
(Note: the two files cannot be combined, because they each need to run as different Windows users. I know one possible solution for communicating is to write the PSObject to a text/xml file, then have the client read and erase the file, but I'd rather not do this since it exposes the credentials. I'm open to whatever suggestions you have)

I found this link that describes how to do what you're requesting:
https://gbegerow.wordpress.com/2012/04/09/interprocess-communication-in-powershell/
I tested it and I was able to pass data between two separate Powershell sessions.
Server Side:
$pipe=new-object System.IO.Pipes.NamedPipeServerStream("\\.\pipe\Wulf");
'Created server side of "\\.\pipe\Wulf"'
$pipe.WaitForConnection();
$sr = new-object System.IO.StreamReader($pipe);
while (($cmd= $sr.ReadLine()) -ne 'exit')
{
$cmd
};
$sr.Dispose();
$pipe.Dispose();
Client Side:
$pipe = new-object System.IO.Pipes.NamedPipeClientStream("\\.\pipe\Wulf");
$pipe.Connect();
$sw = new-object System.IO.StreamWriter($pipe);
$sw.WriteLine("Go");
$sw.WriteLine("start abc 123");
$sw.WriteLine('exit');
$sw.Dispose();
$pipe.Dispose();

Related

Difficulty passing a secure string to a system.data.odbc.odbcconnection object

Im trying to pass a secure string to an odbc connection object to save me from passing a plain password over a network but cant quite figure it out. See the current iteration of my script below.
$encryptedPassword = Get-Content "<encrypted password.txt>"
$runPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $encryptedPassword)))
$Db2Connection = new-object system.data.odbc.odbcconnection
$Db2Connection.connectionstring = "DSN=<dsn>;Userid=<user>;Password=$runPassword"
$Db2Connection.open()
$SqlQuery = #"
SELECT *
FROM <database>.<table>
"#
$SqlCmd = New-Object system.Data.Odbc.OdbcCommand($SqlQuery,$Db2Connection)
$DataAdapter = New-Object system.Data.Odbc.OdbcDataAdapter($SqlCmd)
$DataTable = New-Object system.Data.datatable
$RowCount = $DataAdapter.fill($DataTable)
$DataAdapter = new-object System.Data.odbc.odbcDataAdapter($SqlCmd)
$DataSet = new-object System.Data.DataSet
$DataAdapter.Fill($DataSet)
$result = $DataSet.Tables[0].Rows[4]
$result
As you can see, while i have encryption at rest the credentials will be handled in clear text using the following.
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $encryptedPassword)))
Any thoughts or recommendations would be appreciated
As you are using an IBM-supplied Db2-driver, it is the Db2-driver itself that handles encrypting the password before transmission.
The Db2-driver does this encrypting transparently to the application, and the application gives the plain-text password to the Db2-driver which encrypts is before transmission. The Db2-server platform (Z/OS, i-series, Linux/Unix/Windows) determines the configuration details for encrypted passwords.
So the application cannot supply an already-encrpyted password to Db2-driver.
Such transparent password-encryption requires correct configuration of the Db2-server authentication setup, and a suitable (meaning: recent and patch-maintained) Db2-driver at the workstations. Db2-clients also support data-encryption in transit in addition to password encryption, but that is a different matter.
As part of the connection attempt, the Db2-driver will obtain from the Db2-server the names of available encryption algorithms the Db2-server can support, and the Db2-client chooses (by default) the most secure algorithm that it can perform that is also available on the Db2-server. You can influence this choice by further configuration as documented in the Db2-Knowledge-Centre.
You can also write your own security-related plugins, if you have special requirements.

Is there a way to use Powershell to read local IE 11 cookies and replicate their data to other users on the same system?

I have a web based system that is called by a local PC system. The web system allows/controls interaction with a IP accessible device. Due to the simplistic nature of the base application interface to the web system (of which I have no control over), I have had to create a local cookie (using a web based configuration form) that stores site/install specific configuration information that is then used by the web system to interact with the internet accessible device for the installed site. The configuration is somewhat complicated. All of this already works and has been deployed to the initial customer site.
The issue is the PCs that are involved could be used by multiple people (in this instance 10 PCs that can be used by 10 or more employees each) with distinct logins to the PC(s) in question. This means setting up this complicated web configuration on each PC, 10 times. Lots of tedious room for errors.
I understand that I can not just copy a Win10 IE11 cookie from one user to another on a PC BUT is it possible to use Powershell to read the initial cookie that is built, extract the cookie information, and replicate/create a new cookie for all other users on that PC loading the new cookie with the same information in the base cookie?
I understand that I would likely need to run this from a user account with local admin right (in order to access the cookie area of other users) and can live with that if it avoids all the repetitive setup.
Is it possible to use Powershell and .Net to read a local cookie (given the URL) and extract the data from that cookie to be used to build new cookies for all other users on that PC for the initial URL?
Can't use IE plug-ins. Have not tried much else.
No code to show.
I am hoping for some code examples that demonstrate how to read from an existing cookie and how to write/create a cookie and load it with data, from Powershell.
You can refer examples of powershell scripts below will help you to read cookies.
$url = "https://www.linkedin.com"
$webrequest = Invoke-WebRequest -Uri $url -SessionVariable websession
$cookies = $websession.Cookies.GetCookies($url)
# Here, you can output all of $cookies, or you can go through them one by one.
foreach ($cookie in $cookies) {
# You can get cookie specifics, or just use $cookie
# This gets each cookie's name and value
Write-Host "$($cookie.name) = $($cookie.value)"
}
And if you're using PowerShell 2.0 and below, use System.Net.HTTPWebRequest
$url = "https://www.linkedin.com"
$cookiejar = New-Object System.Net.CookieContainer
$webrequest = [System.Net.HTTPWebRequest]::Create($url);
$webrequest.CookieContainer = $cookiejar
$response = $webrequest.GetResponse()
$cookies = $cookiejar.GetCookies($url)
# Here, you can output all of $cookies, or you can go through them one by one.
foreach ($cookie in $cookies) {
# You can get cookie specifics, or just use $cookie
# This gets each cookie's name and value
Write-Host "$($cookie.name) = $($cookie.value)"
}
Reference:
Getting Cookies using PowerShell
I did not get any examples for creating new cookie file from the existing files and share that cookie files with other users.

How to add ADFS Relying Party Trust SAMLAssertionConsumer using New-ADFSSamlEndpoint

I'm trying to build a script with powershell that will ask for a new uri to be added to an existing list of Relying Party Trust SAML Assertion Consumer Endpoints.
I've used this:
$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol 'SAMLAssertionConsumer' -Uri 'https://moo.mydomain.local/samlprp-0/' -Binding 'POST' -IsDefault $false -Index 3
Set-ADFSRelyingPartyTrust -TargetName "ExistingRPT" -SamlEndpoint #($samlEndpoint1)
However this seems to remove the existing ones that are there and just leaves this new one. Therefore I was hoping this just added it to the existing list.
Does anyone please have any suggestions? Do I have to export the existing ones to some kind of array and then add to it?
Thanks for your time

How to use PowerShell to delete specific messages from an MSMQ message queue

I'm trying to delete specific messages from an MSMQ message queue using PowerShell. I'm aware that several new cmdlets for managing MSMQ queues & messages were introduced in PowerShell 4+, but from what I can tell, these still don't help me achieve my goal of deleting specific messages.
What I'm trying to achieve is a simple script that connects to a specified queue, then loops through every message in that queue, looks for a specified search string in the message body, and then MOVES any matching messages to another queue on the same server. I have this working very nicely for searching messages, and can COPY any matching using using the Send method:
$source = new-object System.Messaging.MessageQueue($sourcequeuename)
$destination = new-object System.Messaging.MessageQueue($destinationqueuename)
$msgs = $source.GetAllMessages()
foreach ( $msg in $msgs )
{
#Extra logic here - check message body for search string etc...
$destination.Send($msg)
}
But - once copied, my only option to delete the original message from the source queue seems to be purging the entire source queue, which will delete all other messages as well, which I don't want to do!
$source.Purge()
I thought I was onto something with the new (PowerShell 4+) 'Move-MsmqMessage' cmdlet...
Move-MsmqMessage -DestinationQueue $d -InputObject $q -Message $msg
But I'm struggling to get this to work - I'm unclear if I can pass it specific message objects to move. Can anyone give me a working example of using PowerShell (any version) to loop through messages in a queue and move specific messages using this Move-MsmqMessage cmdlet?
Not tested but you should be able to delete the message using the ReceiveById function:
foreach ( $msg in $msgs )
{
#Extra logic here - check message body for search string etc...
$source.ReceiveById($msg.Id, [timespan]::FromMinutes(1))
}
The question and answer do not contain the full scripts used. Here's the full script I used to remove a single message from the queue, once I knew the Id of the message.
[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$queuePath = "FormatName:DIRECT=OS:MachineName\private$\NameOfQueue"
$queue = New-Object System.Messaging.MessageQueue $queuePath
$poisonMessageId = "d53df8ba-3b6a-418b-ab27-198655534253\39996"
$queue.ReceiveById($poisonMessageId)
Btw, to find the message Id is easy, btw.
Go find the message in:
Computer Management -> Services and Applications -> Message Queueing -> Private Queues. Open up your private queue containing the message you want to get rid of
Select 'Properties' and in the 'General' tab is the message id.
Extended version of script from Jay Dubya with deletion by pattern
$StringToFind = "AMS1-COMET5"
$QueueName = "AMS1-COMET5"
[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$queuePath = "FormatName:DIRECT=OS:"+ [System.Net.Dns]::GetHostName() + "\private$\" + $QueueName
$queue = New-Object System.Messaging.MessageQueue $queuePath
$SrcQueue = Get-MsmqQueue($QueueName)
$Messages = $SrcQueue | Receive-MsmqQueue -Peek -Count 10000000
$Messages |foreach {
if ($_.Label -match $StringToFind) {
$_.Label
$queue.ReceiveById($_.Id)
}
}

New LDAP User with Powershell

I have the challenge to create new LDAP Users with a Powershell Script.
I have googled a lot but I found no good results...
This is my Code to get Users from the LDAP...
$authenticationType = [System.DirectoryServices.AuthenticationTypes]::ServerBind
$objSearcherRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://***.local.com:777/ou=user,o=company", "uid=testuser,ou=system,o=company", "password" , $authenticationType)
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SizeLimit= 0
$objSearcher.PageSize = 1000
$objSearcher.SearchRoot = $objSearcherRoot
$objSearcher.Filter = "cn=$cn"
$result = $objSearcher.FindAll()
My Problem is, I don't know how to insert a new LDAP User (not Active Directory)
It would be really nice if someone could help me... ;)
Thanks
Yes, it's possible, I've done it. You need to bind to the LDAP server using a System.DirectoryServices.Protocols.LdapConnection object (let's say $c) and then create a System.DirectoryServices.Protocols.AddRequest object and populate its attributes (I'm only showing a couple in this example):
[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")
[System.Reflection.Assembly]::LoadWithPartialName("System.Net")
$c = New-Object -TypeName System.DirectoryServices.Protocols.LdapConnection -ArgumentList "***.local.com:777,uid=testuser,ou=system,o=company", "password" , $authenticationType"
$c.Bind()
$r = New-Object -TypeName System.DirectoryServices.Protocols.AddRequest
$r.DistinguishedName = "uid= xxxx, ou=user, o=company"
$r.Attributes.Add((New-Object -TypeName System.DirectoryServices.Protocols.DirectoryAttribute -ArgumentList "objectclass",#("top","organizationalPerson","person","inetorgperson","inetuser","mailrecipient","pwmuser","posixAccount"))) | Out-Null
$r.Attributes.Add((New-Object -TypeName System.DirectoryServices.Protocols.DirectoryAttribute -ArgumentList "cn",($FirstName+" "+$LastName))) | Out-Null
Then just send the request:
$c.SendRequest($r)
LDAP does not support "inserts", but supports "adds". The LDAP client must create an entry and transmit that entry to the directory server using the ADD request. The server returns an ADD result to the LDAP client which contains information about the success or failure of the ADD request. So, check the documentation for information on transmitting an ADD request to the directory server and interpreting the subsequent response.
The LDAP client must have permission to ADD an entry (a user in this case). This involves using the BIND request to change the authorization state of the connection to one which permits adding an entry at the designated place in the directory information tree.
Perhaps this link will help.
You say "create new LDAP Users" but you could create AD users and then they would be available Using LDAP.
I used a script from Microsoft to do something similar.
If you look through the code, you should be able to see how they did it. We used their code with a few tweaks to do what we needed.
-jim