Download Files with Password in Powershell - windows

I need to download a 51gb zip file from the internet, to open the website you need to enter a password.
I want to do this with a function in PowerShell(PSVersion:5.1.18362.752), but I can't get any further. My function looks like this:
$securepassword = "thepassword"
function Get-Files {
$Properties = #{
URI = "https://theurl"
Credential = $securepassword
}
Invoke-WebRequest #Properties -OutFile "C:\Users\$env:USERNAME\Desktop\thefiles.zip"
}
Can the parameter Credential only be used for Windows Credential?
Many thanks for the help

I think you are using Credentials wrong. Credentials is not password only. It is username plus password, and they should be instance of ICredentials
Please note, that credentials can be passed this way ONLY for web pages that request HTTP 401 authentication. If web page uses form-based authentication, you should process it as non-standard case and credentials will not work, you will need to post data, keep cookies, etc.
$localPath = [System.IO.Path]::Combine(
[System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::DesktopDirectory),
'OutFileName.zip')
$wc = [System.Net.WebClient]::new()
$wc.Credentials = [System.Net.NetworkCredential]::new($username, $plainTextPassword)
$wc.DownloadFile($uri, $localPath)
$wc.Dispose()

Related

ADO CLI can't remove tags

I'm using the Azure CLI with the az boards work-item update command (docs are here). This is part of a larger system that reads the tags on a ticket (amongst other things) and then removes the Ready tag from that list and tries to set the tags back to remove it.
az boards work-item update --organization $ORG --output json --id 12345 --fields System.Tags=Android
When updating the tags field using --fields System.Tags=Android argument, this used to replace existing tags with the tag specified e.g. if a ticket had the Android and Ready tags, this would remove the Ready tag. However recently this seems to only be able to add tags and not remove them.
I've tried various other properties and formats, but nothing seems to work. Does anyone know how I can replace the tags on the ticket with the ones I'm specifying using the CLI?
EDIT: ADO community ticket raised here
I can confirm that the az boards work-item update command is no longer removing/replacing tags with the ones that are passed, and this certainly is a bug. Please report it on Developer Community so it can be fixed.
Meanwhile, as #Fairy Xu mentioned, this behavior leaves you with the only option of making a REST call to update the work item. However, you do not have to swap your entire current setup to REST to work around the issue. The same REST call can be made via Azure CLI as well using the az rest command!
Here is how it can be achieved:
# Get current tags on the work item; Sample response: Tag1; Tag2; Tag3
$Tags = az boards work-item show --id 456 --query 'fields.\"System.Tags\"' -o tsv
# Sample headers.json
# {
# "Authorization":"Basic OmZpYWxreG9xYnBwiZ2IyeDRyZm90d3psNmE=",
# "Content-Type":"application/json-patch+json"
# }
#
# Sample body.json
# [
# {
# "op": "replace",
# "path": "/fields/System.Tags",
# "value": "Tag1; Tag3"
# }
# ]
# Use az rest command to make the Update work item REST call
# In the response you'd see the System.Tags field showing only Tag1; Tag3
az rest --method patch --url https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/456?api-version=5.1 --headers '#headers.json' --body '#body.json'
EDIT:
You can deal with authentication in two ways:
Using AAD Bearer access token
It appears that one can use 499b84ac-1321-427f-aa17-267ca6975798 as the value of --resource to call az rest as follows:
az rest --url 'https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/456?api-version=5.1' --resource 499b84ac-1321-427f-aa17-267ca6975798
Using Basic Authentication with a PAT
For populating the Authorization header, you first have to generate a Personal Access Token (PAT) for your organization with the appropriate scope. Once you have it, you have to convert it to a Base64 string as follows:
$Username=""
$Password="<PAT>"
$Token = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Username,$Password)))
Also, be sure to include and set Content-Type to application/json-patch+json as one of the headers as az rest defaults it to application/json.
References:
az rest - Azure CLI
Work Items - Update REST API
When using PowerShell, pay attention to quoting rules
az curl or az rest for custom REST support (coverage) #7618
As far as I know, there is no such method could delete specific work item tag with Rest API or Azure CLI currently.
For a work around, we need to use Azure CLI/ Rest API to get the work item tags list first. Then we could modify the tags field and update the field.
Here is my powershell example to run the Rest APIs.
$token = "PAT"
$url=" https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{workitemid}?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$tags = $response.fields.'System.Tags'
echo $tags
$New = $tags -replace "tagname" -replace ""
echo $new
$url1 ="https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{workitemid}?api-version=6.0"
$body = "[
{
`"From`" : null,
`"op`": `"replace`",
`"path`": `"/fields/System.Tags`",
`"value`" : `"$new`"
}
]"
$response = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method PATCH -Body $body -ContentType application/json-patch+json
Here is the docs about Rest APIs: Work Items - Get Work Item and Work Items - Update

Add Windows Credentials using PowerShell & cmdkey

I am trying to use credentials from some UI prompted to add Windows credentials using cmdkey:
$sessionCredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "Server Crdentials")
$ps = ConvertFrom-SecureString -SecureString $sessionCredential.password
cmdkey.exe /add:server1 /user:$($sessionCredential.UserName) /pass:$($ps)
The credentials are added correctly, but the password is not.
What can I do?
Use the CredentialManager PowerShell module. It saves the password in the same place as cmdkey, but it can take PSCredential objects directly without needing to convert to text.
Import-Module CredentialManager
# Get the credential from the user with a windows credentials prompt:
$SessionCredential = Get-Credential -Message 'Please enter your server credentials'
# Save the credential object directly without unwrapping it:
New-StoredCredential -Credentials $SessionCredential -Target ServerCredentials -Persist Enterprise `
-Comment "Server Credentials for $($SessionCredential.UserName)" > $null
# Open the credential later
$SavedCred = Get-StoredCredential -Target ServerCredentials
# Delete if needed
Remove-StoredCredential -Target ServerCredentials
cmdkey /pass:$($ps) is prone to errors due to PowerShell garbling password characters.
Apparently, the problem is ConvertFrom-SecureString is returning an encrypted standard string, ConvertFrom-SecureString.
And the option to get plain text is not available on PowerShell 5.1.
I found the correct convert here.
I understand it is not secured. It is used inside secured clients.
See fixed code below:
$sessionCredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "Server Crdentials")
$mpass = [System.Net.NetworkCredential]::new("",$sessionCredential.password).Password
cmdkey.exe /add:server1 /user:$($sessionCredential.UserName) /pass:$($mpass)
Cpt.Whale's answer worked like a charm. The only caveat was the need to copy/distribute the CredentialManager module before using it.

(Get-wmiobject win32_computersystem).username returns invalid value

In windows 8.1 English OS/64-bit PC logged on with Microsoft Account
When i execute the above command the User name format will be as follows
//
In windows 8.1 Japanese OS/64-bit PC logged on with Microsoft Account
When i execute the above command the User name format will be as follows
/
Note:
System Name: lenovo-PC
DomainName: LENOVO-PC
UserName: TestAccount
Why it is returning different format in the different environment PC?
My logic is failing to get the token for the current logged in User.
Please help anyone.
There are many ways to get the username. Here are some examples:
(get-wmiobject Win32_ComputerSystem).username
or
[Environment]::UserName
or
whoami
or
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
For your specific problem, try this:
$domain = $env:UserDomain
$user = $env:UserName
$username = "$domain\$user"

Access Slack files from a slack bot

I need a slack bot that's able to receive and save files send from slack chatrooms.
The problem is: slack doesn't send file contents, but an array of links pointing to the file. Most of them, including download link are private and cannot be accessed via bot. It does send one public link, but that link points at the file preview, which does not have the file itself (here's an example).
How can I access uploaded files via bot?
You can access private URLs from your bot by providing an access token in the HTTP header when you are doing you CURL request.
Your token needs to have the scope files.read in order to get access.
The format is:
Authorization: Bearer A_VALID_TOKEN
Replace A_VALID_TOKEN with your slack access token.
I just tested it with a simple PHP script to retrieve a file by its "url_private" and it works nicely.
Source: Slack API documententation / file object / Authentication
Example for using the Python requests library to fetch an example file:
import requests
url = 'https://slack-files.com/T0JU09BGC-F0UD6SJ21-a762ad74d3'
token = 'xoxp-8853424449-8820034832-8891394196-faf6f0'
requests.get(url, headers={'Authorization': 'Bearer %s' % token})
for those wanting to accomplish this with Bash & cURL, here's a helpful function! It will download the file to the current directory with a filename that uniquely identifies the file, even if the file has the same name as others in your file listing.
function slack_download {
URL="$1";
TOKEN="$2"
FILENAME=`echo "$URL" | sed -r 's/.*\/(T.+)\/([^\/]+)$/\1-\2/'`;
curl -o "$FILENAME" -H "Authorization: Bearer $TOKEN" "$URL";
}
# Usage:
# Downloads as ./TJOLLYDAY-FANGBEARD-NSFW_PIC.jpg
slack_download "https://files.slack.com/files-pri/TJOLLYDAY-FANGBEARD/NSFW_PIC.jpg" xoxp-12345678901-01234567890-123456789012-abcdef0123456789abcdef0123456789
Tested with Python3 - just replace SLACK_TOKEN with your token.
Downloads and creates an output file.
#!/usr/bin/env python3
# Usage: python3 download_files_from_slack.py <URL>
import sys
import re
import requests
url = " ".join(sys.argv[1:])
token = 'SLACK_TOKEN'
resp = requests.get(url, headers={'Authorization': 'Bearer %s' % token})
headers = resp.headers['content-disposition']
fname = re.findall("filename=(.*?);", headers)[0].strip("'").strip('"')
assert not os.path.exists(fname), print("File already exists. Please remove/rename and re-run")
out_file = open(fname, mode="wb+")
out_file.write(resp.content)
out_file.close()

Perl Script to Monitor URL Using proxy credentials?

Please help on the following code, this is not working in our environment.
use LWP;
use strict;
my $url = 'http://google.com';
my $username = 'user';
my $password = 'mypassword';
my $browser = LWP::UserAgent->new('Mozilla');
$browser->credentials("172.18.124.11:80","something.co.in",$username=>$password);
$browser->timeout(10);
my $response=$browser->get($url);
print $response->content;
OUTPUT :
Can't connect to google.com:80 (timeout)
LWP::Protocol::http::Socket: connect: timeout at C:/Perl/lib/LWP/Protocol/http.p m line 51.
OS: windows XP
Regards, Gaurav
Do you have a HTTP proxy at 172.18.124.11? I assume LWP is not using the proxy. You might want to use env_proxy => 1 with the new() call.
You also have a mod-perl2 tag in this question. If this code runs inside mod-perl2, it's possible that the http_proxy env variable is not visible to the code. You can check this eg. by printing $browser->proxy('http').
Or just set the proxy with $browser->proxy('http', '172.18.124.11');
Also, I assume you don't have use warnings on, because new() takes a hash, not just a string. It's a good idea to always enable warnings. That will save you lots of trouble.

Resources