How to run a web request using default credentials in Powershell - powershell

I am working on the following code.
$HTTP_Request =[System.Net.WebRequest]::Create('http://google.com')
$HTTP_Response = $HTTP_Request.GetResponse()
$HTTP_Status = [int]$HTTP_Response.StatusCode
echo $HTTP_Status
But I want to run it using my default credentials, because there are few URLs which returns 401 ,that is client not authorized and for that I need it to run using my default credentials.
Can anyone help me regarding same, as I want to store the status of some URLs and this code is working fine except for those which are protected.

So the question was to run web request while using default credentials, here are the solutions I found:
for powershell 2.0:-
$req = [system.Net.WebRequest]::Create($uri)
$req.UseDefaultCredentials = $true
try
{
$res = $req.GetResponse()
}
catch [System.Net.WebException]
{
$res = $_.Exception.Response
}
$int = [int]$res.StatusCode
echo $int
For Powershell 3.0:-
try{
$res = Invoke-WebRequest $uri -UseDefaultCredentials
}
catch [System.Net.WebException]
{
$res = $_.Exception.Response
}
$int = [int]$res.StatusCode
echo $int
Both scripts are extremely doing well but if you want to find code status of many URLs, then you should go for powershell 3.0 , it handles web-requests in a much better way.

Related

HTTP Status codes via Powershell

Somehow the below codes works fine for the first few test URLs within C:\testurl.txt then it hung up forever when it is processing the 4th URL from the C:\testurl.txt , no idea why it hangs up?
It is already working fine for up to 3 URLs but stuck up on 4th onward
CLS
$urllist = Get-Content "C:\testurl.txt" # URLs to test one in each line
foreach ($url in $urllist) {
Write-Host $url
$req = [System.Net.WebRequest]::Create($url)
try {
$res = $req.GetResponse()
} catch [System.Net.WebException] {
$res = $_.Exception.Response
}
$res.StatusCode
#Print OK or whatever
[int]$res.StatusCode
#Print 200 or whatever
}
It is working fine for up to 3 URLs but hangs the script on 4th URL without any output or error message. Here is the example of c:\testurl.txt
http://www.google.com
http://www.google.com
http://www.google.com
http://www.google.com
http://www.hotmail.com
http://www.gmail.com
http://www.yahoo.com
http://www.msn.com
Please note each URL will be in a new line, you will see that script will stop at (the 4th one) you may try with your own URLs, etc too
then it hung up forever
No - it's hung until the underlying TCP connections of the previous requests time out.
The .NET CLR will internally pool all WebRequest dispatches so that only a finite number of external requests will be initiated concurrently, and as long as you have a number of un-closed WebResponse objects in memory, your requests will start queuing up.
You can avoid this by closing them (as you should):
foreach ($url in $urllist) {
Write-Host $url
$req = [System.Net.WebRequest]::Create($url)
try {
$res = $req.GetResponse()
}
catch [System.Net.WebException] {
$res = $_.Exception.Response
}
finally {
$res.StatusCode
#Print OK or whatever
[int]$res.StatusCode
#Print 200 or whatever
$res.Dispose()
# close connection, dispose of response stream
}
}

API to remotely upload secret to Thycotic Secret Server

I am total newbie to PowerShell, Thycotic Secret Server and writing APIs. I have been tasked with writing an API to remotely access Thycotic Secret Server and upload a secret together with attached files. Unfortunately, I haven’t gotten off the starting block. I am following the code here:
https://thycotic.force.com/support/s/article/REST-API-PowerShell-Scripts-Getting-Started
I have copied down:
3 – Searching Secrets
4 – Create Secret and
Get-Token from here:
https://thycotic.force.com/support/s/article/Secret-Server-Trial-Using-the-API
and have created functions for each one. The only changes I made are to change myurl, myusername and mypassword.
This is my PowerShell script:
$myUrl = "mysecretserver/Login.aspx?ReturnUrl=%2f"
$application = "https://mysecretserver/Login.aspx?ReturnUrl=%2fsecretserver"
# Ask for user name
$userName = Read-Host -Prompt "Please enter user name"
$userPassword = Read-Host -AsSecureString "Password"
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
Get-Token
Search-Secrets $userName,$userPassword
Create-Secret $userName,$userPassword
When I run Get-Token (no changes made to downloaded code)
function Get-Token
{
[CmdletBinding()]
Param(
[Switch] $UseTwoFactor
)
$creds = #{
username = $userName
password = $userPassword
grant_type = "password"
};
$headers = $null
If ($UseTwoFactor) {
$headers = #{
"OTP" = (Read-Host -Prompt "Enter your OTP for 2FA (displayed in your 2FA app): ")
}
}
try
{
$response = Invoke-RestMethod "$application/oauth2/token" -Method Post -Body $creds -Headers $headers;
$token = $response.access_token;
return $token;
}
catch
{
$result = $_.Exception.Response.GetResponseStream();
$reader = New-Object System.IO.StreamReader($result);
$reader.BaseStream.Position = 0;
$reader.DiscardBufferedData();
$responseBody = $reader.ReadToEnd() | ConvertFrom-Json
Write-Host "ERROR: $($responseBody.error)"
return;
}
}
It seems to run ok but when I display $token, it is empty.
I'm not 100% sure what this is doing and have looked at a lot of examples but seem to be missing the basic steps for reading the token and using it to access the secret server. Any help would be greatly appreciated.
Replace your Secret Server URL with the Server's FQDN, not the web URL you get in a browser. You need to make sure the Secret Server address is correct otherwise it won't be hitting the API (and maybe failing gracefully which is why you don't see any errors from the Get-Token function).
For example, instead of:
$application = "https://mysecretserver/Login.aspx?ReturnUrl=%2fsecretserver"
It may be something like:
$application = "https://mysecretserver.mydomain.com"

Trying to do a simple post request in powershell v2.0, no luck

I'm simply trying to do a HTTP POST request with some keys and values. I can't get this to work for the life of me and yes I know this should be simple.
Here's what I've tried:
$Body = [byte[]][char[]]'username=asdf';
$Request = [System.Net.HttpWebRequest]::CreateHttp('http://mysite/test.php');
$Request.Method = 'POST';
$Stream = $Request.GetRequestStream();
$Stream.Write($Body, 0, $Body.Length);
$Request.GetResponse();
This doesn't work in Powershell v2.0 because I get the error
Method
invocation failed because [System.Net.HttpWebRequest] doesn't contain
a method named 'CreateHttp'.
Next, I've taken someone else's example of:
$URI1 = "http://mysite/test.php"
$request = [System.Net.WebRequest]::Create($URI1)
$request.ContentType = "application/xml"
$request.Method = "POST"
$body = "username=test"
# $request | Get-Member for a list of methods and properties
try
{
$requestStream = $request.GetRequestStream()
$streamWriter = New-Object System.IO.StreamWriter($requestStream)
$streamWriter.Write($body)
}
finally
{
if ($null -ne $streamWriter) { $streamWriter.Dispose() }
if ($null -ne $requestStream) { $requestStream.Dispose() }
}
$res = $request.GetResponse()
but for some reason "username" doesn't get noticed when test.php echos $_POST['username']
Can someone please help tell me what I'm missing here? I've been googling for hours and everything I try isn't working for some reason. Works fine on Powershell versions greater than 2.0, but not 2.0 (default in Windows 7).
Invoke-WebRequest and Invoke-RestMethod do not work on Powershell v2.0, so I'm forced to find all these annoying alternatives.
* EDIT *
I got it working after finding another HTTP POST request example:
$url = "http://mysite/test.php"
$postData = "username=test"
$buffer = [text.encoding]::ascii.getbytes($postData)
[net.httpWebRequest] $req = [net.webRequest]::create($url)
$req.method = "POST"
$req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
$req.Headers.Add("Accept-Language: en-US")
$req.Headers.Add("Accept-Encoding: gzip,deflate")
$req.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7")
$req.AllowAutoRedirect = $false
$req.ContentType = "application/x-www-form-urlencoded"
$req.ContentLength = $buffer.length
$req.TimeOut = 50000
$req.KeepAlive = $true
$req.Headers.Add("Keep-Alive: 300");
$reqst = $req.getRequestStream()
$reqst.write($buffer, 0, $buffer.length)
$reqst.flush()
$reqst.close()
[net.httpWebResponse] $res = $req.getResponse()
$resst = $res.getResponseStream()
$sr = new-object IO.StreamReader($resst)
$result = $sr.ReadToEnd()
$res.close()
This was discovered on another site before additional comments came here; however, I've tried the solutions from people's suggestions below and also was able to get this working.
In the first example code, the method should be named Create, Not CreateHttp
In the second block of code, you set the content-type to 'application/xml', but the body is plain-text.
This method, and your initial example itself, would work in a newer version of PowerShell. Try installing dotnet 4.5 on your system, then WMF 4.0, and this should work with no issue.
The dotnet class of [System.Net.HttpWebRequest] didn't have the static method CreateHttp() until dotnet 4.5, as seen here on MSDN Docs.
Why not just update this one machine to a newer version of PowerShell? It will be a LOT less pain.

Restart application pool based on http response code

I am trying to write a PowerShell script that will restart an application pool in IIS if a 503 response code is received.
So far I have managed to retrieve the response code for every crm application under the default website in IIS. However I am unsure how I would go about finding the application pool name. I've tried the below, but it returns the same application pool for each site. Can anyone help?
$getSite = (Get-WebApplication -Site 'Default Web Site')
$SiteURL = ForEach ($site in $getSite.path) {("http://localhost")+$site}
ForEach ($crm in $SiteURL){
$req = [system.Net.WebRequest]::Create($crm)
try {
$res = $req.GetResponse()
} catch [System.Net.WebException] {
$res = $_.Exception.Response
}
$ApplicationPool = ForEach ($app in $getSite.applicationpool) {$app}
if([int]$res.StatusCode -eq 503) {write-host ($crm + ' ' + [int]$res.StatusCode) + $app}
}
I think you need to access $_.Exception.InnerException for the the Response property.
Your $ApplicationPool assignment doesn't make much sense, as you would only need one applicationPool name per $crm app you test:
foreach($App in #(Get-WebApplication -Site 'Default Web Site')){
# Uri for the application
$TestUri = 'http://localhost{0}' -f $App.path
# Create WebRequest
$Request = [system.Net.WebRequest]::Create($TestUri)
try {
# Get the response
$Response = $Request.GetResponse()
} catch [System.Net.WebException] {
# If it fails, get Response from the Exception
$Response = $_.Exception.InnerException.Response
}
# The numerical value of the StatusCode value is the HTTP status code, ie. 503
if(503 -eq ($Response.StatusCode -as [int])){
# Restart the app pool
Restart-WebAppPool -Name $App.applicationPool
}
}

How to make an authenticated web request in Powershell?

In C#, I might do something like this:
System.Net.WebClient w = new System.Net.WebClient();
w.Credentials = new System.Net.NetworkCredential(username, auth, domain);
string webpage = w.DownloadString(url);
Is there a Powershell version of this, or should I just call through to the CLR?
The PowerShell is almost exactly the same.
$webclient = new-object System.Net.WebClient
$webclient.Credentials = new-object System.Net.NetworkCredential($username, $password, $domain)
$webpage = $webclient.DownloadString($url)
For those that need Powershell to return additional information like the Http StatusCode, here's an example. Included are the two most likely ways to pass in credentials.
Its a slightly modified version of this SO answer:
How to obtain numeric HTTP status codes in PowerShell
$req = [system.Net.WebRequest]::Create($url)
# method 1 $req.UseDefaultCredentials = $true
# method 2 $req.Credentials = New-Object System.Net.NetworkCredential($username, $pwd, $domain);
try
{
$res = $req.GetResponse()
}
catch [System.Net.WebException]
{
$res = $_.Exception.Response
}
$int = [int]$res.StatusCode
$status = $res.StatusCode
return "$int $status"
In some case NTLM authentication still won't work if given the correct credential.
There's a mechanism which will void NTLM auth within WebClient, see here for more information: System.Net.WebClient doesn't work with Windows Authentication
If you're trying above answer and it's still not working, follow the above link to add registry to make the domain whitelisted.
Post this here to save other's time ;)