Using Powershell, how do I connect to a WCF web service using New-WebServiceProxy, and retrieve the response header information including cookie data? I have scoured the net and can't find any relevant information, other than stepping away from use of New-WebServiceProxy.
My current PS script looks like...
$authSvc = New-WebServiceProxy –Uri ‘http://myserver/Services/AuthenticationService.svc?WSDL’
$LoginResults = $true
$authSvc.Login('user1', 'abc123', $null, $true, $true, [ref] $LoginResults, [ref] $null)
... Seems there must be additional hooks into the New-WebServiceProxy that expose the header data, but I can't seem to identify it. Using C# (just a test console app), I have been able to invoke this web service and retrieve cookie data, so I know the service is functioning correctly.
Thoughts?
OK - I think I have an answer to my own question. Placing here for others trying the same thing.
The trick is to use the CookieContainer object which is intrinsic to the New-WebServiceProxy object. The CookieContainer has a CookieCollection in it. This collection can be enumerated. Elaborating on my example in the question, I show how to expose cookie information returned from the web service call...
$authSvc = New-WebServiceProxy –Uri ‘http://myserver/Services/AuthenticationService.svc?WSDL’
$authSvc.CookieContainer = New-Object System.Net.CookieContainer
$LoginResults = $true
$authSvc.Login('user1', 'abc123', $null, $true, $true, [ref] $LoginResults, [ref] $null)
$CookieCollection = $authSvc.CookieContainer.GetCookies(‘http://myserver/Services/AuthenticationService.svc?WSDL’)
foreach($cookie in $CookieCollection)
{
echo $cookie.Name
echo $cookie.Value
}
If I use the Get-Member method of the service...
$authSvc | Get-Member
... I then can see all the exposed methods the service allows. The CookieContainer happens to be one of these. Other relevant properties exposed are (but not limited to)...
ClientCertificates
Credentials
RequestEncoding
SoapVersion
Url
UserAgent
Related
I have a PowerShell script that uses Az PowerShell modules to retrieve properties of all webapps within a resource group. Now, I also need to fetch the MinTlsVersion property as in below. Can I do it using one of Az modules?
When a call to Get-AzWebApp command is made in the script, a request is sent to /subscriptions/<s>/resourceGroups/<rg>/providers/Microsoft.Web/sites endpoint. The response object has property siteConfig set to null. Is there a way to call Get-AzWebApp such that the property is not null so I can use the minTlsVersion sub-property under the siteConfig object?
If there's no way to above:
I see that the client receives minTlsVersion by sending a GET request to /subscriptions/<s>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<st>/config/web endpoint. Can we hit the same endpoint by using one of the Az PowerShell modules? Though, I would prefer a request that can return minTlsVersion of all webapps in a resource group in a single call.
You need to iterate through each app, try the command as below, it works on my side.
$grouname = "<resource-group-name>"
$apps = Get-AzWebApp -ResourceGroupName $grouname
$names = $apps.Name
foreach($name in $names){
$tls = (Get-AzWebApp -ResourceGroupName $grouname -Name $name).SiteConfig.MinTlsVersion
Write-Host "minTlsVersion of web app" $name "is" $tls
}
I am using the below command,
$SQLServerPSCred = Get-Credential
to get the credential object.
How can I get the Creds object without the Prompt?
I have tried below code, but it is failing.
$SQLServerPSCred = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $Password
You haven't included much information about what your actual problem with the code is. it's correct that you're prompted with your first example. As you explicitly tell it to ask you.
With your second example it's incomplete.
PowerShell – How to create a PSCredential object by koteshblog has an example on how to do it:
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
As you can see you first need to convert the password into a SecureString which you can pass to the credential object. It also shows a slightly different syntax but that shouldn't matter.
Depending on what you're doing and where that script resides it can also be worth it to look into some form of "more secure" storage for your secrets. As it is everyone who would have access to the script could extract the username and password from it.
One option is to store the secure string. But keep in mind a secure string is somewhat tied to the users. So You won't be able to easily just pass along a text file that contains the password.
For an example on how to do that check Powershell Tip – Storing and Using Password Credentials by robcost. It's a basic solutions there might be better ones available depending on your needs.
In the SolarWinds user interface, there is a button you can click within a switch or interface view to "Poll Now", instead of waiting for the regularly scheduled poll. I have been trying to figure out a way to recreate this functionality using the SolarWinds API. I've looked through this page, and it seems like I will need to use either the 'invoke' or 'update' operations, but there is almost no information on the actual usage. I have also tried examining the Javascript in the user interface, and can't make heads or tails of it.
I'm wondering if someone can point me towards some useful documentation as to what operations are actually available in the API (the 'invoke' operation requires you to give a 'verb' as an argument, but I can't find any kind of list or documentation as to what verbs are available). Does anyone know of any resources?
If you look at Orion.Nodes SWIS Entity you can see in the bottom "PollNow" SWIS Verb. Unfortunatelly it is not so well documented what parameters it actually has (it can be seen in SWQL Studio though). But you should be able to do it this way using Powershell:
$orionHost = "<hostname where orion is installed>"
$orionUsername = "Admin" # fill login username to orion
$orionPassword = "Pass" # fill login password to orion, this example counts that this is not empty string
$nodeIdToPoll = 1; # put id of the node
$Entity = "Orion.Nodes"
$Verb = "PollNow"
$Data = #($nodeIdToPoll)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$credentials = new-object PSCredential ($orionUsername , (ConvertTo-SecureString $orionPassword -AsPlainText -Force))
Invoke-RestMethod "https://$($orionHost):17778/SolarWinds/InformationService/v3/Json/Invoke/$Entity/$Verb" `
-Method POST `
-Body (ConvertTo-Json -InputObject $Data) `
-Credential $credentials `
-ContentType "application/json"
I wish to check content of one database on server where I'm able to log into by means of Windows Authentication. Sounds really simple and many examples are provided over the Internet.
I tried few examples and each fails on my machine. I suspect, that there might be problem during credentials conversion.
My code (shortened) is as follows:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")
$User=[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$credentials = Get-Credential $saUser | Select-Object *
$Pwd = $credentials.Password | ConvertFrom-SecureString
$targetConn = New-Object ('Microsoft.SqlServer.Management.Common.ServerConnection') ('myServer', $User, $Pwd)
$targetServer = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $targetConn
till now there's no error message.
When I type $targetServer, I don't see any objects listed (no Databases as well).
When I tried to check $targetServer.Databases, I received:
The following exception was thrown when trying to enumerate the collection: "Failed to connect to server mmyServer."
ConvertFrom-SecureString converts a secure string into an "encrypted standard string" (a hash, which is intended to store the encrypted string in text format). So, you're providing a password hash ($Pwd) as the password argument when creating the $targetConn object, which is invalid.
You can get the plaintext password from the PSCredential object $credentials this way:
$Pwd = $credentials.GetNetworkCredential().Password
However, according to the documentation for the contructors for the ServerConnection class, you can also provide a secure string as the password argument. So it should work if you simply leave out the | ConvertFrom-SecureString, i.e.
$Pwd = $credentials.Password
That's probably a better idea, since it's a little more secure. If you use the first method to get the plaintext password, there's a possibility that the RAM location that stores the $Pwd variable will be paged out while the script is running, resulting in the plaintext password being written to the disk.
I'm writing a client against a vendor's webservice, using WCF in Visual Studio 2010. I have no ability to change their implementation or configuration.
Running against an install on their test server, I had no problems. I added a service reference from their wsdl, set the url in code, and made the call:
var client = new TheirWebservicePortTypeClient();
client.Endpoint.Address = new System.ServiceModel.EndpointAddress(webServiceUrl);
if (webServiceUsername != "")
{
client.ClientCredentials.UserName.UserName = webServiceUsername;
client.ClientCredentials.UserName.Password = webServicePassword;
}
TheirWebserviceResponse response = client.TheirOperation(myRequest);
Simple and straightforward. Until they moved it to their production server and configured it to use https. Then I got this error:
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm='.
So I went looking for help. I found this: Can not call web service with basic authentication using wcf.
The approved answer suggested this:
BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromSeconds(25);
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
EndpointAddress address = new EndpointAddress(your-url-here);
ChannelFactory<MyService> factory =
new ChannelFactory<MyService>(binding, address);
MyService proxy = factory.CreateChannel();
proxy.ClientCredentials.UserName.UserName = "username";
proxy.ClientCredentials.UserName.Password = "password";
Which also seemed simple enough. Except for my trying to figure out which of the multitude of classes and interfaces that were generated from the wsdl to make the service reference I should use in place of the "MyService", above.
My first try was to use "TheirWebservicePortTypeClient" - the class I had instantiated in the previous version. That gave me a runtime error:
The type argument passed to the generic ChannelFactory class must be an interface type.
So I dug into the generated code, a bit more. I saw this:
public partial class TheirWebservicePortTypeClient
:
System.ServiceModel.ClientBase<TheirWebservicePortType>,
TheirWebservicePortType
{
...
}
So I tried instantiating ChannelFactory<> with TheirWebservicePortType.
This gave me compile-time errors. The resulting proxy didn't have a ClientCredentials member, or a TheirOperation() method.
So I tried "System.ServiceModel.ClientBase".
Instantiation ChannelFactory<> with it still gave me compile-time errors. The resulting proxy did have a ClientCredentials member, but it still didn't have a TheirOperation() method.
So, what gives? How do I pass a username/password to an HTTPS webservice, from a WCF client?
==================== Edited to explain the solution ====================
First, as suggested, instantiation the factory with TheirWebservicePortType, adding the username and password to the factory.Credentials, instead of to proxy.ClientCredentials worked fine. Except for one bit of confusion.
Maybe it's something to do with the odd way the wsdl is written, but the client class, TheirWebservicePortTypeClient, defined TheirOperation as taking a Request argument and returning a Response result. The TheirWebservicePortType interface defined TheirOperation as taking a TheirOperation_Input argument and returning a TheirOperation_Output result, where TheirOperation_Input contained a Request member and TheirOperation_Output contained a Response member.
In any case, if I constructed a TheirOperation_Input object from the passed Request, the call to the proxy succeeded, and I could then extract the contained Response object from the returned TheirOperation_Output object:
TheirOperation_Output output = client.TheirOperation(new TheirOperation_Input(request));
TheirWebserviceResponse response = output.TheirWebserviceResponse;
You add the credentials to the ChannelFactory Credentials property