Invoke-WebRequest GetSystemWebProxy() - powershell

Under PowerShell 2.0 I know that you can set the proxy you would like to use without knowing the exact proxy settings by doing something like the following:
$proxy = [System.Net.WebRequest]::GetSystemWebproxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
Now, my question is if I don't know the proxy settings can I use the above and combine it with a PowerShell 3.0 Invoke-WebRequest. Here's what I was hoping to be able to do:
$proxy = [System.Net.WebRequest]::GetSystemWebproxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$WS.Proxy = $proxy
$login = Invoke-WebRequest https://website.com/login_form.html -SessionVariable WS
However, when I attempt to do this I get an error, (apparently from my company proxy) indicating that my credentials cannot be verified. I'm hoping that this will ultimately work, but perhaps I'm just making a simple mistake.

Maybe this can help, I keep it in my profile. It is using the new the $PSDefaultParameterValues preference variable to set the default proxy values for the new web cmdlets. The code detects if I'm in my office environment and set the settings accordingly. This saves me specifying the settings each time I use those commands.
if(Test-Connection myCorpProxy -Count 1 -Quiet)
{
$global:PSDefaultParameterValues = #{
'Invoke-RestMethod:Proxy'='http://myCorpProxy:8080'
'Invoke-WebRequest:Proxy'='http://myCorpProxy:8080'
'*:ProxyUseDefaultCredentials'=$true
}
}

Use can use this code :
$dest = "http://www.google.fr"
$proxyurl = ([System.Net.WebRequest]::GetSystemWebproxy()).GetProxy($dest)
Invoke-WebRequest $dest -Proxy $proxyurl -ProxyUseDefaultCredentials

The actual problem with your code above (even though Shay's is more elegant) is that you're trying to set a property on a variable before it exists. The SessionVariable "$WS" doesn't exist before you call Invoke-WebRequest but you're trying to set the .Proxy property above it.
If it worked at one point, you had probably created an instance of $WS previously and therefore were able to work with the object during testing but on a fresh/dry run when the script was processing top-down, it didn't yet exist.

Related

Powershell - Invoke-RestMethod with multiple headers

I am trying to use Invoke-Restmethod in Powershell to call an API (I'm fairly new to this). I can get it to POST and return the jwt access token. I can also use that token to return an id via GET, however I'm then having trouble with the next step of returning the next set of data. I can get it to work manually via curl. I believe the issue may be because multiple headers are required to return the tenant list and I'm unsure of the format to get this to work.
The curl script looks as follows, and works as expected:
curl -XGET -H "Authorization: Bearer <jwt access token>" -H "ID: <id>" https://theapiurl.com/.......
I've tried multiple ways to do this in powershell, most recently as below, but nothing I'm trying works. I've tried returning the individual $headers contents and building a string (i.e. $headers2 = $.headers.Item(Authorization) + ......) but that doesn't work either. To be honest, I've tried so many different things I've forgotten what I have and haven't tried
$headers = #{
'ID' = $id
'Authorization' = $auth_string
}
$response = Invoke-RestMethod -Method Get -Headers $headers -Uri $url
Please could you let me know the correct way to add multiple headers (which I think is the problem and what I'm getting wrong)?
In case it's useful to anyone else, another syntax for setting the parameters of this commandlet is as follows (real working example for uploading to the GitHub release repository). It's usful to set all the switches (without prepending a hyphen) in the parameters object like so:
$upload_params = #{
Uri = $upload_uri + "?name=$asset_name"
Method = 'POST'
Headers = #{
'Authorization' = "token $github_token"
'Accept' = 'application/vnd.github.everest-preview+json'
}
InFile = $asset
ContentType = 'application/octet-stream'
}
"Uploading $asset..."
$upload = Invoke-RestMethod #upload_params
"The server returned:"
echo $upload
The variable $upload contains the full object returned from the server (converted from json to a PowerShell object). So, for example, you can also get properties of this obect like so:
"Upload successfully posted as " + $upload.url
Thanks for all the responses - none of them were really the answer but they did give me the confidence I was doing it the right way.
I'd been using PS Write-Host to check the data returned - this was working for the tokens and ID's, but wasn't working for next step. I wasn't getting an error, just no data. (I did see the returned data when testing manually in a command prompt window).
As soon as I added an -OutFile to the PS and checked the file, I realised it was working all along and PS just wasn't showing me the results. 2 hours wasted, although I've learnt more as a result!

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

Need to get URL HTTP request is being redirected to

I am trying to write a script to automate my Firewall login process. Here is what my Firewall do-
When I connect to my Wi-Fi and open google.com, it redirects to a URL like:
http://<IP>:<PORT>/fgtauth?<RAND-STRING>
It contains a basic username-password form, along with a hidden field 'magic' with value <RAND-STRING> of the URL. I have to submit this form with username and password to login to Firewall. I want to automate the process (and will schedule it to run every 4 hours to prevent auto-logout of Firewall).
Till now I have done this:
$url = "http://<IP>:<PORT>/fgtauth?04582fd55070345b"
$parameters = "4Tredir=http://google.com&magic=04582fd55070345b&username=<UN>&password=<PASS>"
$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.open('POST', $url, $false)
$http_request.setRequestHeader("Content-type",
"application/x-www-form-urlencoded")
$http_request.setRequestHeader("Content-length", '$parameters.length')
$http_request.setRequestHeader("Connection", "close")
$http_request.send($parameters)
$http_request.statusText
which I copied from here. I have to open google.com manually from web browser, copy that 'magic' string from URL and paste it in script. If I do so, script runs fine and login is successful. I now have to somehow make request to google.com first, it'll get redirected to Firewall login page and extract that 'magic' string from it.
Please help me extracting that 'magic' string.
Normally I would not suggest an answer that uses a different approach to the one in the question, however in this case my suggestion uses so little code I thought it may be appropriate.
The easiest way I know of to do this is using the Invoke-WebRequest cmdlet. If the example url you provide is the actual format of the real url then you can do this:
$url = "https://www.theSiteThatWillRedirectYou.com"
$webResponse = Invoke-webRequest -uri $url
$absoluteUriFromResponse = $webResponse.BaseResponse.AbsoluteUri
$splitUri = $absoluteUriFromResponse.split("?")
$desiredString = $splitUri[1]
If the url is of the form ?parameter=value then you can do the following:
$url = "https://www.theSiteThatWillRedirectYou.com"
$webResponse = Invoke-webRequest -uri $url
$absoluteUriFromResponse = $webResponse.BaseResponse.AbsoluteUri
$splitUri = $absoluteUriFromResponse.split("?")
$desiredKeyValPair = $splitUri[1] | convertFrom-StringData
In this case if the url was, for example, whatever.com?rand=randValue then $desiredKeyValPair would contain:
Name Value
---- -----
rand randValue
Now these examples only work if there is only one parameter in the query string. If there are multiple parameters you would need to do a little extra work. For example if the url was like this: www.whatever.com?rand=randVal&otherParam=otherValue you would need to do something like this:
$splitOnQueryChar = $absoluteUriFromResponse.split("?")
$splitOnAmpersand = $splitOnQueryChar[1].split("&")
$keyValPairs = $splitOnAmpersand | convertFrom-StringData
At this point $keyValPairs would contain something like this:
Name Value
---- -----
rand randVal
otherParam otherValue
These values can be referenced by name like this:
$keyValPairs.rand
*Included from comment:
I wasn't thinking in terms of the form on the page but Invoke-webrequest will capture forms/input fields etc, and these can usually be referenced by name.

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

Test remote server cert against locally stored cert before trusting

I have some code that I use to connect to a web server that we own. The server has a self signed certificate. I am currently connecting with the trust any cert
[System.Net.ServicePointManager]::ServerCertificateValidationCallback {$true}.
How can I change this so that I can either test the remote server with custom code or against a cert in my local store? For example can I change the code above to
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$customValidator}
What I would like to do is, instead of trusting any/all certs, I would like to trust it only if it matches with the public key cer file I have or I would like to test the certificate using custom code. The thing I am not very clear on is how to handle the custom verification and at what point in the code. Do I need to write an entire class to handle custom SSL validation or is there a better way to do this?
$url = "https://myWebServer"
$web = New-Object Net.WebClient
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
//[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { customSslCertValidation } #I would like to do something like this
$output = $web.DownloadString($url)
Write-Host $output
Try something like this:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {
$c = [System.Security.Cryptography.X509Certificates.X509Certificate2]$args[1]
($c.Thumbprint -eq "StoredOrRetrievedHash")
}
This checks the Thumbprint of the certificate returned as part of the request against the string "StoredOrRetrievedHash". You would want to replace that with the details from your certificate loaded in dynamically. It is worth noting that the first line of the scriptblock delegate casts the second element of the $args array to be an object of type X509Certificate2, as the bare X509Certificate object doesn't expose the Thumbprint property.
Note: this only works in PowerShell v2 and later - in v1 assigning an arbitrary scriptblock to a delegate was a lot of extra work and quite frankly, just not worth the effort typically.