powershell authentication to Bamboo error - powershell

I am having a problem updating the release label to show if it is broken or Approved etc. I have got this working through postman so I know that the problem is not through that. I am using basic authentication with my username and password being entered and trying to get access to the uri using them details but for the powershell it is not working. It works fine with Postman so it's not the credentials. Here is what I am doing:
$user = Read-Host -Prompt "Enter Bamboo Username"
$pass =  Read-Host -Prompt "Enter password" -AsSecureString
$secpass = ConvertTo-SecureString $user -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($pass,$secpass)
$baseuri = "http://bamboo.uk.myNetwork.net/rest/api/latest/deploy/version/VersionNumber/status/Approved"
$Headers = #{
'X-Atlassian-Token' = 'nochecK'
};
$json = "application/json"
Invoke-RestMethod -Uri $baseuri -Method Post -Credential $credential -Headers $Headers -ContentType $json
This is not working and I am getting the 401client must be authenticated to access this resource. I have also tried all of the following ways to authenticate the user but none have worked:
<#
$encoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($user+":"+$pass))
$EncodedUsernamePassword = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($('{0}:{1}' -f $Credential.UserName, $Credential.GetNetworkCredential().Password)))
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
#>
Postman with return the following details:
{
"id": theID,
"userName": "myUserName",
"displayName": "myName",
"creationDate": 1481536833693,
"versionState": "APPROVED"
}
This shows that the uri with basic authentication and adding the X-Atlassian-Token: nocheck works but for the powershell I am getting Authentication Errors why is this?

The problem was when I used the password as a SecureString type, when I changed it just a string it would work, so all of these ways including the one Hackerman linked worked when using the credentials without a SecureString type.

Related

Encrypting Password parameters in Powershell for GET request to ServiceNow

has anyone found a good solution to encrypting the password parameters in Powershell for ServiceNow API?
This is the default version :
`$user = "admin"
$pass = "admin"
# Build auth header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))
# Set proper headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))
$headers.Add('Accept','application/json')
$response = Invoke-WebRequest -Header $headers -Method $method -Uri $uri
`
`Then I tried the most common way of encrypting the password using "ConvertTo-SecureString":
`
`# Convert the plain text password to an encrypted secure string
$securePassword = ConvertTo-SecureString '' -AsPlainText -Force
# Convert the encrypted password back to a plain text password
$pass = ConvertFrom-SecureString $securePassword
# Set the username
$username = "admin"
`
But this didnt work. Gave me an unauthorised(401) error.
One method I found that did worked was using CredentialManager but I am hesitant to use it because it is not that secure at all. Anyone here has a better solution? Let me know and thanks for the help

Manage credentials for Invoke-RestMethod request

I'm writing a PowerShell script to query an application API (Qualys), and the first step is to authenticate. I can only do it unsecurely:
[string]$username = "username"
[string]$password = "superpassword"
$hdrs= #{"X-Requested-With"="Powershell"}
$base = "https://application-base-url/api/2.0/fo"
$body= "action=login&username=$username&password=$password"
Invoke-RestMethod -SessionVariable sess -Headers $hdrs -URI "$base/session/" -Method POST -Body $body
It works, but as you can see, the username & password are stored in the file. I would like Powershell to prompt me the username and password, and use it to authenticate while securely manage them.
I tried to use Get-Credential but I couldn't make it work. Could anyone help?
Apparently you need to put the plain-text password in the body.
To retrieve that from a credential object you get from using Get-Credential, use:
$cred = Get-Credential
$username = $cred.UserName
$password = $cred.GetNetworkCredential().Password # --> the password as plain-text

Powershell - Do "Grant Permissions" action on Azure AD Application with Powershell

I'm creating an Azure AD application using AzureAD module to call Microsoft Graph API. I can successfully generate the access token. But, when I try to call the API I have an error "message": "Invalid scope claims/roles.".
When I click on "Grant Permissions" button in my created application in Azure Portal and retry the call to API, the call is working.
I don't find anywhere how to do this "Grant Permissions" actions with Powershell. Is there a way to do that ?
Thanks
Damien
There is an easy way to do this (as admin), it requires you have the AzureAD and AzureRM modules installed for Powershell and is not supported by Microsoft.
Original post / reference to my blog is here: http://www.lieben.nu/liebensraum/2018/04/how-to-grant-oauth2-permissions-to-an-azure-ad-application-using-powershell-unattended-silently/
The specific code sample that should help you accomplish this:
Function Grant-OAuth2PermissionsToApp{
Param(
[Parameter(Mandatory=$true)]$Username, #global administrator username
[Parameter(Mandatory=$true)]$Password, #global administrator password
[Parameter(Mandatory=$true)]$azureAppId #application ID of the azure application you wish to admin-consent to
)
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
$res = login-azurermaccount -Credential $mycreds
$context = Get-AzureRmContext
$tenantId = $context.Tenant.Id
$refreshToken = #($context.TokenCache.ReadItems() | where {$_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date)})[0].RefreshToken
$body = "grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6"
$apiToken = Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'
$header = #{
'Authorization' = 'Bearer ' + $apiToken.access_token
'X-Requested-With'= 'XMLHttpRequest'
'x-ms-client-request-id'= [guid]::NewGuid()
'x-ms-correlation-id' = [guid]::NewGuid()}
$url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true"
Invoke-RestMethod -Uri $url -Headers $header -Method POST -ErrorAction Stop
}
I came across the same error 'Refresh token is malformed'. When reading out the refreshtoken the token was twice in the string. Resolved it by adding the line
$refreshtoken = $refreshtoken.Split("`n")[0]
If I am not wrong, then it is using "Admin Consent". In that case, you should be using &prompt=admin_consent in the auth request directly.
If your application requests an app-only permission and a user tries to sign in to the application, an error message is displayed saying the user isn’t able to consent.
Whether or not a permission requires admin consent is determined by the developer that published the resource, and can be found in the documentation for the resource.
Link: Multi-tenant App pattern
List of Available permissions for the Azure AD Graph API and Microsoft Graph API are
Graph API Permission Scopes
Consent Framework
Hope it helps.
This answer builds on top of Jos's answer.
Active Directory Authentication library doesn't make the refresh tokens publicly available anymore. More information can be found in github/azure-powershell/7525.
The modified snippet below worked for me
Connect-AzAccount
$context = Get-AzContext
$tenantId = $context.Tenant.TenantId
Connect-AzureAD -TenantId $tenantId -AccountId $context.Account.Id
$appId = 'Your Application ID'
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $tenantId, $null, "Never", $null, "74658136-14ec-4630-ad9b-26e160ff0fc6")
$headers = #{
'Authorization' = 'Bearer ' + $token.AccessToken
'X-Requested-With'= 'XMLHttpRequest'
'x-ms-client-request-id'= [guid]::NewGuid()
'x-ms-correlation-id' = [guid]::NewGuid()}
$url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$appId/Consent?onBehalfOfAll=true"
Invoke-RestMethod -Uri $url -Headers $headers -Method POST -ErrorAction Stop

Jira user creation via REST results in 401 - This resource requires WebSudo

I'm attempting to write a PowerShell script that will automate the process of adding new user accounts to our Jira instance. I've provided my code but I'm honestly not even getting to that point as I am receiving a 401 error:
This resource requires WebSudo.
I have seen these two posts on the Jira support forum but it's not clear to me how I could adapt the code to get and then apply it to my REST call. I would be fine with changing this to use the .Net WebClient class if that would make all of this easier, but right now I'm at a bit of a loss.
$url = "https://devjira.domain.com/rest/api/2/user"
$user = "admin"
$pass = "super secure password"
$secpasswd = ConvertTo-SecureString $user -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($pass, $secpasswd);
$userObject = #{
name = "rkaucher#domain.net";
emailAddress = "robert_kaucher#domain.com";
displayName = "Bob Kaucher";
notification = $true;
}
$restParameters = #{
Uri = $url;
ContentType = "application/json";
Method = "POST";
Body = (ConvertTo-Json $userObject).ToString();
Credential = $cred;
}
Invoke-RestMethod #restParameters
JSON output
{
"name": "rkaucher#domain.net",
"displayName": "Bob Kaucher",
"emailAddress": "robert_kaucher#domain.com",
"notification": true
}
I changed the authentication component of my script to this:
$cred = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$user`:$pass"))
$headers = #{Authorization=("Basic $cred")}
This was based on the selected answer to the following:
PowerShell's Invoke-RestMethod equivalent of curl -u (Basic Authentication)
The final invocation of the method looks like this:
$restParameters = #{
Uri = $url;
ContentType = "application/json";
Method = "POST";
Body = (ConvertTo-Json $userObject).ToString();
Headers = $headers;
}
$response = Invoke-RestMethod #restParameters

How can I correct Invalid CSRF token errors when calling a rest API?

I've got a script that will query a web rest service to find the ID for a specific object. I've gotten the query working fine under Powershell for a single query, but I need to run several hundred queries. It's really slow (And bad practice) to login for every single query.
I have the script logon to the server first and save the session. The I run the rest query using a post operation. First one works fine. Second one bombs out saying:
Invoke-RestMethod : Invalid CSRF Token
Invalid CSRF Token
An invalid cross-site request forgery token was detected in the request.
The code looks like this:
$secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("user", $secpasswd)
$headers = "Content-Type: text/plain","Accept: text/plain"
#Login it the server to store the session to WebSession.
$login = Invoke-WebRequest -Uri "https://devrhapapp01:8444" -Credential $cred -SessionVariable websesssion
#This one returns correctly.
$Results = Invoke-RestMethod -Uri "https://devrhapapp01:8444/api/components/find" -ContentType "text/plain" -Method Post -Body "Search1" -WebSession $websesssion
write-host $Results
#This one will give an error.
$Results = Invoke-RestMethod -Uri "https://devrhapapp01:8444/api/components/find" -ContentType "text/plain" -Method Post -Body "Search1" -WebSession $websesssion
write-host $Results
Not sure what is going on, but try submitting the correct anti-forgery token:
$forgeryToken = ($login.InputFields |
Where { $_.name -eq "__RequestVerificationToken" }).value
$forgeryTokenPostData = "__RequestVerificationToken=$forgeryToken"
Invoke-WebRequest .... -Body $forgeryTokenPostData