Invoke-WebRequest equivalent in PowerShell v2 - powershell

Can some one help me with the powershell v2 version of the below cmdlet.
$body =
"<wInput>
<uInputValues>
<uInputEntry value='$arg' key='stringArgument'/>
</uInputValues>
<eDateAndTime></eDateAndTime>
<comments></comments>
</wInput>"
$password = ConvertTo-SecureString $wpassword -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($wusername, $password)
$output = Invoke-WebRequest -Uri $URI1 -Credential $credential -Method Post -ContentType application/xml -Body $body

$URI1 = "<your uri>"
$password = ConvertTo-SecureString $wpassword -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($wusername, $password)
$request = [System.Net.WebRequest]::Create($URI1)
$request.ContentType = "application/xml"
$request.Method = "POST"
$request.Credentials = $credential
# $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()

Here, give this a shot. I provided some in-line comments. Bottom line, you're going to want to use the HttpWebRequest class from the .NET Base Class Library (BCL) to achieve what you're after.
$Body = #"
<wInput>
<uInputValues>
<uInputEntry value='$arg' key='stringArgument'/>
</uInputValues>
<eDateAndTime></eDateAndTime>
<comments></comments>
</wInput>
"#;
# Convert the message body to a byte array
$BodyBytes = [System.Text.Encoding]::UTF8.GetBytes($Body);
# Set the URI of the web service
$URI = [System.Uri]'http://www.google.com';
# Create a new web request
$WebRequest = [System.Net.HttpWebRequest]::CreateHttp($URI);
# Set the HTTP method
$WebRequest.Method = 'POST';
# Set the MIME type
$WebRequest.ContentType = 'application/xml';
# Set the credential for the web service
$WebRequest.Credentials = Get-Credential;
# Write the message body to the request stream
$WebRequest.GetRequestStream().Write($BodyBytes, 0, $BodyBytes.Length);

This method downloads binary content:
# PowerShell 2 version
$WebRequest=New-Object System.Net.WebClient
$WebRequest.UseDefaultCredentials=$true
#$WebRequest.Credentials=(Get-Credential)
$Data=$WebRequest.DownloadData("http://<url>")
[System.IO.File]::WriteAllBytes("<full path of file>",$Data)
# PowerShell 5 version
Invoke-WebRequest -Uri "http://<url>" -OutFile "<full path of file>" -UseDefaultCredentials -ContentType

Related

How to create a Microsoft Teams team using a PowerShell Azure function and the Graph API?

My ultimate goal is to create a MS Teams team with channels and tabs of applications.
But first, I need to properly format my request. I dont know what I'm doing wrong.
Obviously I found this topic (https://learn.microsoft.com/en-us/graph/api/team-post?view=graph-rest-1.0) Example n°3 that looks promising but I dont know how to use it. I started with the code bellow:
$password = "stackexchange"
$login = "stackexchange#stackexchange.onmicrosoft.com"
$ownerEmail = "stackexchange#stackexchange.onmicrosoft.com"
$url = "https://graph.microsoft.com/v1.0/teams"
$securedPassword = convertto-securestring -String $password -AsPlainText -Force
$creds = new-object -typename System.Management.Automation.PSCredential -argumentlist $login, $securedPassword
$GraphAppId = "stackexchange-guid"
$GraphAppSecret = "stackexchange"
$AADDomain = "stackexchange.onmicrosoft.com"
Connect-AzureAD -Credential $creds
$userId = (Get-AzureADUser -ObjectId $ownerEmail).ObjectId
write-output $userId # Here the userId is actually displayed
Connect-PnPOnline -ClientId $GraphAppId -ClientSecret $GraphAppSecret -AADDomain $AADDomain
$accessToken = Get-PnPGraphAccessToken
$header = #{
"Content-Type" = "application/json"
Authorization = "Bearer $accessToken"
}
$body = #{
displayName = "Test"
"owners#odata.bind" = "https://graph.microsoft.com/v1.0/users('$userId')"
"template#odata.bind" = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"
memberSettings = #{
allowCreateUpdateChannels = $true
}
messagingSettings = #{
allowUserEditMessages = $true
allowUserDeleteMessages = $true
}
funSettings = #{
allowGiphy = $true
giphyContentRating = "strict"
}
}
$Body = ConvertTo-Json -InputObject $body
Invoke-RestMethod -Uri $url -Body $Body -Method 'Post' -Headers $header -UseBasicParsing -Credential $creds
I get the following message in my PowerShell terminal :
Invoke-RestMethod : {
"error": {
"code": "BadRequest",
"message": "Invalid bind property name owners in request.",
"innerError": {
"date": "2020-09-03T15:40:53",
"request-id": "fef8bd7e-3143-4ea9-bcf6-a87702a488b8"
}
}
}
At character Line:36 : 5
+ Invoke-RestMethod -Uri $url -Body $Body -Method 'Post' -Headers $ ...
+ CategoryInfo : InvalidOperation : (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Instead of doing this all "by hand", I'd suggest looking at the Graph SDK for PowerShell. It's still 'officially' in beta, but that's this PowerShell SDK, not the Graph itself of course.
you could also use the PS nuget "MicrosoftTeams"
for example:
# ===========================================
# this Script creates a new project environment containing:
# - a new TEAMs channel
# ===========================================
Install-Module MicrosoftTeams -Force # -AllowClobber
## parameters
$TeamDisplayName='contoso'
$ProjectName='Contoso-Reporting'
$TEAMS_ChannelName=$ProjectName
## connect to TEAMS
Connect-MicrosoftTeams
## Get the Opslogix TEAM
$team = Get-Team | foreach {if ( $_.DisplayName -eq $TeamDisplayName ) { $_ }}
## create a new project channel
$team | new-TeamChannel -DisplayName $TEAMS_ChannelName
#$team | Get-TeamChannel
## disconnect TEAMS
Disconnect-MicrosoftTeams
Try changing:
"owners#odata.bind" = "https://graph.microsoft.com/v1.0/users('$userId')"
to:
members = #(
#{
'#odata.type' = "#microsoft.graph.aadUserConversationMember"
roles = #(
'owner'
)
'user#odata.bind' = "https://graph.microsoft.com/v1.0/users('$userId')"
}
)

How can I download a folder from a webserver with authentication?

I need a script that downloads a certain folder and all its subfolders + files to my pc from a webserver. It needs to be in powershell. I searched a bit and found this:
Invoke-WebRequest http://www.example.com/package.zip -OutFile package.zip
I get this error when I try to run it. But I can't figure out how I can pass the username and password with it. If anyone can help me that would be greatly appreciated! Also how can I specify the folder it should be saved to? Thanks in advance
Following up regarding my comment.
I ask that question because some sites require you to be specific in the credential presentation vs just one blob of stuff. For example:
$credentials = Get-Credential
$webServerUrl = 'http://SomeWebSite'
$r = Invoke-WebRequest $webServerUrl -SessionVariable my_session
$form = $r.Forms[0]
$form.fields['Username'] = $credentials.GetNetworkCredential().UserName
$form.fields['Password'] = $credentials.GetNetworkCredential().Password
$InvokeWebRequestSplat = #{
Uri = $($webServerUrl + $form.Action)
WebSession = $my_session
Method = 'GET '
Body = $form.Fields
}
$r = Invoke-WebRequest #InvokeWebRequestSplat
Update
The follow-up to the comment. This is using IE with PowerShell for site automation.
# Scrape the site to find form data
$url = 'https://pwpush.com'
($FormElements = Invoke-WebRequest -Uri $url -SessionVariable fe)
($Form = $FormElements.Forms[0]) | Format-List -Force
$Form | Get-Member
$Form.Fields
# Use the info on the site
$IE = New-Object -ComObject "InternetExplorer.Application"
$FormElementsequestURI = "https://pwpush.com"
$Password = "password_payload"
$SubmitButton = "submit"
$IE.Visible = $true
$IE.Silent = $true
$IE.Navigate($FormElementsequestURI)
While ($IE.Busy) {
Start-Sleep -Milliseconds 100
}
$Doc = $IE.Document
$Doc.getElementsByTagName("input") | ForEach-Object {
if ($_.id -ne $null){
if ($_.id.contains($SubmitButton)) {$SubmitButton = $_}
if ($_.id.contains($Password)) {$Password = $_}
}
}
$Password.value = "1234"
$SubmitButton.click()
Invoke-WebRequest is Powershell's version of curl. Its alias is even named curl.
SO, in the IVR use case, all you really need to do something like the Facebook and Linkedin examples:
$cred = Get-Credential
$login = Invoke-WebRequest 'facebook.com/login.php' -SessionVariable 'fb'
$login.Forms[0].Fields.email = $cred.UserName
$login.Forms[0].Fields.pass = $cred.GetNetworkCredential().Password
$mainPage = Invoke-WebRequest $login.Forms[0].Action -WebSession $fb -Body $login -Method Post
$cred = Get-Credential
$login = Invoke-WebRequest 'https://www.linkedin.com/uas/login?goback=&trk=hb_signin' -SessionVariable 'li'
$login.Forms[0].Fields.email = $cred.UserName
$login.Forms[0].Fields.pass = $cred.GetNetworkCredential().Password
$mainPage = Invoke-WebRequest $login.Forms[0].Action -WebSession $LI -Body $login -Method Post
Yet, notice I on the FB/LI login page, and I'd need to know that even existed before trying this. Note this is old code, That I've not used in a very long while and I don't have a FB account. I passed this on to someone who did.
$cred = Get-Credential
Invoke-WebRequest http://www.example.com/package.zip -OutFile package.zip -Credential $cred

using Invoke-RestMethod to post to a cosmosDB Returns a 400

I am trying to post a document to cosmosdb using powershell, I have followed the steps in this post https://www.systemcenterautomation.com/2018/06/cosmos-db-rest-api-powershell/ and I am still getting a 400 error everytime
Add-Type -AssemblyName System.Web
# generate authorization key
Function Generate-MasterKeyAuthorizationSignature
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$verb,
[Parameter(Mandatory=$true)][String]$resourceLink,
[Parameter(Mandatory=$true)][String]$resourceType,
[Parameter(Mandatory=$true)][String]$dateTime,
[Parameter(Mandatory=$true)][String]$key,
[Parameter(Mandatory=$true)][String]$keyType,
[Parameter(Mandatory=$true)][String]$tokenVersion
)
$hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacSha256.Key = [System.Convert]::FromBase64String($key)
$payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n"
$hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad))
$signature = [System.Convert]::ToBase64String($hashPayLoad);
[System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature")
}
Function Post-CosmosDocuments{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$EndPoint,
[Parameter(Mandatory=$true)][String]$DBName,
[Parameter(Mandatory=$true)][String]$CollectionName,
[Parameter(Mandatory=$true)][String]$MasterKey,
[String]$Verb="POST",
[Parameter(Mandatory=$true)][String]$JSON
)
$Verb = "POST"
$ResourceType = "docs";
$ResourceLink = "dbs/$DBName/colls/$CollectionName"
$dateTime = [DateTime]::UtcNow.ToString("r")
$authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $ResourceLink -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime
$header = #{authorization=$authHeader;"x-ms-version"="2017-02-22";"x-ms-date"=$dateTime}
$contentType= "application/json"
$queryUri = "$EndPoint$ResourceLink/docs"
$result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $JSON
return $result.statuscode
}
$CosmosDBEndPoint = "https://<omitted>.documents.azure.com:443/"
$DBName = "database"
$CollectionName = "container"
$MasterKey = "<omitted>=="
$SomeObject = [PSObject]#{ id = 1 ; Application = "Ops"; Environment = "Dev"; adKey = "555-555-5555"; }
Post-CosmosDocuments -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DBName $DBName -CollectionName $CollectionName -JSON ($SomeObject | ConvertTo-Json)
returns a 400 every time, I am not sure what is wrong with the request.
Based on the Powershell script samples, I see you are missing the headers:
x-ms-documentdb-partitionkey
User-Agent
2018-12-31 as x-ms-version
Adding the response body that you are getting would also help.
it is working now
I am not sure why I was getting a 400. perhaps I the timing on when I created the collection was off.

Problem to connect to TFS with user/password

When I try to connect to tfs the function Get-Data failed with 401 error although the function Get-DataWithCred succeed with the same argument.
And don't understand the difference with this two ?
function Get-Data([string]$username, [string]$password, [string]$url)
{
# Step 1. Create a username:password pair
$credPair = "$($username):$($password)"
# Step 2. Encode the pair to Base64 string
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
# Step 3. Form the header and add the Authorization attribute to it
$headers = #{ Authorization = "Basic $encodedCredentials" }
# Step 4. Make the GET request
$responseData = Invoke-WebRequest -Uri $url -Method Get -Headers $headers
return $responseData
}
function Get-DataWithCred([string]$username, [string]$password, [string]$url)
{
$p = ConvertTo-SecureString -String $password -AsPlainText -Force
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $p
$responseData = Invoke-WebRequest -Uri $url -Method Get -Credential $Cred
return $responseData
}
The purpose is too connect through tfs with python script who failed the same way that the function Get-Data when I use the requests library.
>>> r = requests.get('https://tfs-url.com', auth=('user', 'pass'))
>>> r.status_code
401
Looks like there is a problem with $encodedCredentials.
Take a look at Choosing the right authentication mechanism
For my script who connect to TFS i use the following code :
$strUser = 'domain\userID'
$password = "YOURPASSWORD"
$strPass = ConvertTo-SecureString -String $password -AsPlainText -Force
$cred= New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($strUser, $strPass)
And than connect to the TFS as you did :
$responseData = Invoke-WebRequest -Uri $url -Method Get -Credential $cred
Or, If you would like to connect to the TFS with the user who runs the script you can use
-UseDefaultCredentials
code snippet :
$responseData = Invoke-WebRequest -Uri $url -Method Get -UseDefaultCredentials
You need to use a microsoft way to pass your credential : the ntlm protocol.
This protocol are not supported by default by requests but a library requests_ntlm extend requests by adding support to ntlm.
A simple example:
import os
import requests
from requests_ntlm import HttpNtlmAuth
def main():
user = "user"
password = "password"
session = requests.Session()
session.auth = HttpNtlmAuth(user, password)
url = "https://tfs-url.com"
response = session.get(url)
print(response)
if __name__ == "__main__":
main()

Send email to multiple recipients using REST API and powershell

I'm using the following to send to single recipient, and single Cc recipient.
How do I send to multiple recipients, either in To: and/or Cc: ?
Thanks! I have tried all different combinations but its still not working (still getting as if its no surprise, the usual Invoke-RestMethod :The remote server returned an error: (400) Bad Request.)
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
HelpMessage="Email Address e.g man1#whatever.com")]
[Alias('Email')]
$Subject,
$Content)
UserName = "myUPN#mywork.com"
$Password = cat C:\Creds\mycreds.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -
argumentlist $username,$password
$contentType = "application/json;odata.metadata=full"
$uri = "https://outlook.office365.com/api/v1.0/me/sendmail"
$body = "{
""Message"":{
""Subject"": ""$Subject"",
""Importance"": ""High"",
""Body"": {
""ContentType"": ""HTML"",
""Content"": ""$Content""
},
""ToRecipients"": [
{
""EmailAddress"":{
""Address"": ""man1#whateverdomain.com""
}
}
],
""CcRecipients"": [
{
""EmailAddress"":{
""Address"": ""man2#whateverdomain.com""
}
}
]
}}"
Invoke-RestMethod -Uri $uri -Method Post -Credential $cred`
-Body $Body -ContentType $contentType
You can specify the CC's with an array to feed into this
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
HelpMessage="Email Address e.g man.man#domain.com")]
[Alias('Email')]
$EmailAddress,
$CCEmailAddress,
$Subject,
$Content)
$UserName = "man.man#domain.com"
$Password = cat C:\Creds\regcreds.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password
$CCinJSON = $CCEmailAddress | %{'{"EmailAddress": {"Address": "'+$_+'"}},'}
$CCinJSON = ([string]$CCinJSON).Substring(0, ([string]$CCinJSON).Length - 1)
$contentType = "application/json;odata.metadata=full"
$uri = "https://outlook.office365.com/api/v1.0/me/sendmail"
$body = "{
""Message"":{
""Subject"": ""$Subject"",
""Importance"": ""High"",
""Body"": {
""ContentType"": ""HTML"",
""Content"": ""$Content""
},
""ToRecipients"": [
{
""EmailAddress"":{
""Address"": ""$EmailAddress""
}
}
],
""CcRecipients"": [
$CCinJSON
]
}}"
echo $body
Invoke-RestMethod -Uri $uri -Method Post -Credential $cred -Body $Body -ContentType $contentType