Powershell - Save encrypted user and pass in a script? - powershell

I have using a script in Powershell, which make a web request with user and password from an API. Since is a shared computer, for security reason, i want to encrypt the user and password.
this is the basic web request i have using (that i obtain from other question in stack overflow ):
$user = 'user'
$pass = 'pass'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = #{
Authorization = $basicAuthValue
}
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
My issue is that i do not found a way to encrypt the user and password variables, try to use the ConvertTo-SecureString and convertTFrom-SecureString, but it does not work. i wanna know if there is a way to save the encrypted credentials in a file or other way. without need to saved as an environment variable and avoid getting credentials, since i wanna automatizes the script as a task.
Please comment any doubt.
Thanks for looking, happy coding.
Regards

If anyone in the future have the same issue as me, you can use the next tool in powershell, Export-Clixml and Import-Clixml:
$cred = Get-Credential | Export-CliXml -Path ..\cred.ps1.credentials
and then use import to access the credentials
$Credential = Import-CliXml -Path "..\cred.ps1.credentials"
now you have to added to the invoke-webrequest
Invoke-WebRequest -Uri 'https://whatever' -credentials $credential
Happy coding!

Related

Powershell7 proxy authentication

I'm a PowerShell novice and I inherited some code that's forced me to use Powershell7 over 5.1 on my Windows Server 2012 and now I can't get my credentials to authenticate across the organisation's proxy. I'm thinking there's something in the Powershell7 environment that's not installed/no longer supported/not configured correctly. The code below works in 5.1 but in 7, I get a message back from our proxy saying it's missing credentials. Can anyone shed light on what to do?
#*************************************************************************
# Proxy Credentials
#*************************************************************************
[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://proxy.############')
$username ="###################"
$password ="###################"
$securePwd = $password| convertto-securestring -AsPlainText -Force
$Creds=new-object System.Management.Automation.PSCredential ($username,$securePwd)
$Wcl=New-Object System.Net.WebClient
$Wcl.Proxy.Credentials=$Creds
#*************************************************************************
# Authentication Call
#*************************************************************************
$uri = 'https://testapi.com/web/authenticate'
$params = '{"userName": "######",
"password": "########"
}'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$token =Invoke-Webrequest -Method Post -Uri $uri -body $params -ContentType "application/json" -UseBasicParsing |ConvertFrom-Json | Select AuthenticateResult
write-host $token
#*************************************************************************
This was something specific to the service account I was using to log in to the server. Changed the account and it worked on both versions. No idea what the difference was but I got what I needed.

Invoke-RestMethod PowerShell Google DDNS

I seem to be having a lot of issues with this seemingly basic script to update my IP with Google's DDNS service.
#Fetch current IP address
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Send fetched IP address to Google Domains through their API
$uri = "https://username:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
Invoke-RestMethod -Method 'Get' -Uri $uri
The first issue is with the $ip variable. It produces no output if I keep the $ip on it but works fine without it (I need it as a variable as I use it later on).
The second issue is with the https://username:password#domains.google.com/nic/update?hostname=home.domain.com&myip="$ip".
It works fine if I dump the exact string into postman (substituting an actual IP address instead of $ip)
but fails to send anything even if I run it with a manually inserted IP (such as https://username:password#domains.google.com/nic/update?hostname=home.domain.com&myip=1.2.3.4) in PowerShell.
P.S. In my actual code I substitute in the correct username and password (as provided by Google) and correct subdomain, domain, top-level domain as it applies to me.
Any thoughts on this?
EDIT:
The updated (and working) code is looks like this:
#Fetches current IPv4 address
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Stores Google-provided username and password
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$credential = New-Object Management.Automation.PSCredential ('username', $password)
#Send fetched IP address to Google Domains through their API
$uri = "https://domains.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Invoke-RestMethod -Method 'POST' -Uri $uri -Credential $credential
First off, that's a neat service, api.ipify.org, I'll have to use that in the future.
Secondly, I think the only issue here is your definition of the $url.
The syntax you had before actually throws an error if you try to run the line on its own, error shown here.
"https://username:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
At line:1 char:81
+ ... e:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
+ ~~~~~
Unexpected token '$ip""' in expression or statement.
In PowerShell you should use string expansion syntax like this, instead of nesting quotes.
$uri = "https://username:password.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Update
Found the API Docs here https://support.google.com/domains/answer/6147083?hl=en. They say to provide your username and password using Basic Auth, which makes a base64 encoded string of your credential. We can do that in PowerShell pretty easily!
You can provide your credentials my using the Get-Credential cmdlet to save them then pass them into Invoke-RestMethod and adding -Credential and -Authentication as parameters. Here is what a completed solution would look like.
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Send fetched IP address to Google Domains through their API
$myCredential = Get-Credential #you'll be prompted to provide your google username and pwd.
$uri = "https://domains.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Invoke-RestMethod -Method 'POST' -Uri $uri -Credential $myCredential -Authentication Basic

Custom Data Refresh in Microsoft Power BI

I have a data source connected to to a dashboard that needs to refreshed without actually opening the power bi account. Currently I am able to figure out the powershell script that help me do it from my powershell promt.
The request is something like this
Invoke-WebRequest -Uri "https://api.powerbi.com/v1.0/myorg/datasets/DATASET_ID/refreshes" -Method "POST" -Headers #{"Sec-Fetch-Mode"="cors"; "Authorization"="Bearer XXXXXXXXXXTOKENXXXXXXXX"} -ContentType "application/json;charset=UTF-8"
Now the Token gets expired after sometime and I again need to open the power bi website to get the new token.
Is there a way for generate token locally without actually open the website? i tried using Login-PowerBI in Powershell to get token but is there any other way also.
you need to get a new token each time or get the refresh token from the API. I have tested getting token everytime and I never have a problem. Check my code here to complete your powershell:
https://github.com/ibarrau/PowerBi-code/blob/master/PowerShell/RefreshPowerBi.ps1
Remember you can always install an On Premise Data Gateway to solve this for you.
https://learn.microsoft.com/en-us/power-bi/service-gateway-onprem
As far as I understood, you want to refresh a dataset with PowerShell, but without prompting for credentials. In this case, you can store them in the script itself and do something like this:
Import-Module MicrosoftPowerBIMgmt
Import-Module MicrosoftPowerBIMgmt.Profile
$password = "xxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "xxxxx#yyyyy.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
Connect-PowerBIServiceAccount -Credential $credential
Invoke-PowerBIRestMethod -Url 'groups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/datasets/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/refreshes' -Method Post
Disconnect-PowerBIServiceAccount

While using REST API in Powershell for TFS 2015.2 how to secure your password without using it in the script

While I use the method mentioned in this thread PowerShell's Invoke-RestMethod equivalent of curl -u (Basic Authentication) I could get connected to REST API without a 401 error.
However currently I am giving my password in Plain Text.
I want a way to use a Hash of my password and then use it in the script.
The script then should be able to decrypt it too. But I don't want others who have access to the script, be able to decrypt it.
So I don't want to expose the decryption algorithm as well to any.
Proposed method I am thinking of:
Combine existing HASH algorithms in a mixed random way (by feeding the HASH of one algorithm to another) which only I know and then have a custom Powershell function/cmdlet/whatever in the script which knows to decrypt.
Is there a simpler and better way?
Before I try the proposed method I would like to hear from others on any better ways.
Entire script is as below.
$User = "domain\userName"
$uri = "https://TeamProjectCollectionURI/TeamProjectName/_apis/build/builds"
$securePassword = ConvertTo-SecureString 'PasswordWhichContains$asWell' -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($User, $securePassword)
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$credential)))
$response = Invoke-RestMethod -Method Get -Uri $uri -Credential $credential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -ContentType application/json
$response
You can pass a username and password (masked as a secret variable) through PowerShell into a PSCredential object and use the -Credential switch when invoking the REST method:
$securePassword = $Password | ConvertTo-SecureString -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($User, $securePassword)
$releaseresponse = Invoke-RestMethod -Method Get -Credential $credential -ContentType application/json -Uri $Uri
More detail info please refer this blog: VSTS/TFS REST API: The basics and working with builds and releases
You can convert your password to encrypted string and use the encrypted string in your PowerShell script.
Convert to encrypted string:
$securePassword = ConvertTo-SecureString "Yourpassword" -AsPlainText -Force
$encryptedPwd = ConvertFrom-SecureString -SecureString $securePassword
Write-Host $encryptedPwd
Record the generated encrypted string and use it in your script.
$securePassword = ConvertTo-SecureString -String "Encrypted String"

Uploading Zip to Phonegap Using PowerShell Invoke-RestMethod

I'm trying to write a PowerShell script to have a one click solution to uploading and building my mobile application. I have successfully done this using cURL but was trying to use native PowerShell commands instead. In cURL I can use the -F (--form) parameter and pass the zip file (e.g. -F file=#C:...\www.zip). I cannot figure out how to achieve this same thing using PowerShell. I am trying to use Invoke-RestMethod but not sure if this is correct. Here's a link to the PhoneGap API:
https://build.phonegap.com/docs/write_api
Any help would much appreciated!
Invoke-RestMethod -Uri https://build.phonegap.com/api/v1/apps/:id -Headers #{Authorization='Basic username-and-password-in-base64'} -Method Put -InFile "www.zip"
username-and-password-in-base64 is your Adobe/PhoneGap Build username and password combined into a string "username:password" and encoded using Base64 (http://www.base64decode.org/).
:id in the url is your app id in phonegap build.
Try something like this:
$pathToZip = "bin/phonegap.zip"
$user = "user"
$pass = "password"
## convert to secure password since we can't use get-credential in non interactive mode
$securepass = ConvertTo-SecureString $pass -AsPlainText -Force
## create a PSCredential object
$credential = New-Object System.Management.Automation.PSCredential($user, $securepass)
$appId = "12345"
$url = "https://build.phonegap.com/api/v1/apps/" + $appId;
Write-Host $url
Invoke-RestMethod -Uri $url -Credential $credential -Method Put -InFile $pathToZip