Access ASANA via windows powershell using APIKEY - api-key

I have created this following two codes in powershell to access ASANA.
But both of them dont work. I always get this error
"The remote server returned an error: (401) Unauthorized."
Any help appreciated. If you have a working C# code that can connect to any secure server with only APIKey, please post it. I could convert it to powershell code.
Code 1
Function Get-WebResponseString
{
param (
[Parameter(Mandatory=$true)]
[String]$Url,
[Parameter(Mandatory=$true)]
[String]$Method,
[Parameter(Mandatory=$false)]
[System.Net.NetworkCredential]$Credential
)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.Method = $Method
$Request.ContentType = "application/x-www-form-urlencoded";
if ($Credential -ne $null)
{
$Request.Credentials = $credential
write-host "****" -foregroundcolor blue
}
$Response = $Request.GetResponse()
$StreamReader = New-Object System.IO.StreamReader $Response.GetResponseStream()
$StreamReader.ReadToEnd()
}
$Url = "https://app.asana.com/api/1.0/tasks"
$Username = "MMuthusamy#xxxxxx.xom"
$apikey="xxxxxxxxx"
$credential = New-Object System.Net.NetworkCredential #($Username, $apikey)
Get-WebResponseString -Url $Url -Credential $credential -Method "GET"
Code 2
$sha = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$apikey="xxxxxxx"
#Add colon
$authinfo=$apikey+":";
$string1 = $authinfo
Write-Host $string1 -ForeGroundColor Green
#Encoding format
$enc = [system.Text.Encoding]::UTF8
#get bytes
$data1 = $enc.GetBytes($string1)
#Encode
$result1 = $sha.ComputeHash($data1)
#convert to 64 bit
$mykey=[System.Convert]::ToBase64String($result1)
Write-Host $mykey -ForeGroundColor Green
$url = "https://app.asana.com/api/1.0/tasks"
$url="https://app.asana.com/api/1.0/users"
$request = [System.Net.WebRequest]::Create($url)
$authorization = "Authorization: Basic " + $myKey
Write-Host $authorization -ForeGroundColor Green
$request.Headers.Add($authorization)
#$request.Headers.Add("Authorization: BASIC $mykey")
$response = $request.GetResponse()
Write-Host $Response -ForeGroundColor Green

(I work at Asana)
The 401 header is a clue that the problem lies somewhere in your authorization header.
The HTTP Basic Auth spec does not call for a SHA1 hash of the username:password. It's just straight base64 encoding of that string. Try passing $authinfo to your call to ToBase64String instead of hashed data.

Related

how to increment and save variable in azure devops pipeline

Anyone know how can I increment the value of a variable under some conditions, (for example only if the pipeline succeeded) and save it for next build?
Example:
I set a variable: number=5.
If the pipeline succeeded and job number 2 ran, I want number=6 on the next build.
Is this possible?
You can set the value of your variable by using following command:
Bash
echo "##vso[task.setvariable variable=number;]newValue"
PowerShell
Write-Host "##vso[task.setvariable variable=number;]newValue"
Basically, your number will be set to the newValue after running this command.
how to increment and save variable in azure devops pipeline
Since you could not use the counter, you could try to use the REST API Definitions - Update to update the variable:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.0
The test scripts:
$url = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$counter = [int]$pipeline.variables.Test.value
$counter++
$pipeline.variables.Test.value = $counter
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'Test' is updated to" $updatedef.variables.Test.value
Note: We neeed to declare the variable type as int before we can use ++
$counter = [int]$pipeline.variables.Test.value
$counter++
If you met any premission issue, please refer this thead for some more details.

How to get Build Successes details including Associated Changes and Associated Work Items from TFS 2015 in .txt file? Which API should I have to use

TFS build successes URL
I have to write AssocoatedChanges and Associated WorkItems in txt file after build success. Team foundation providing any API which will give build details response?
You can use the REST API to get build details including Associated Changes and Associated Work Items:
Associated Changes:
GET https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/changes?api-version={version}
Associated Work Items:
POST https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/workitems?api-version={version}
Please see Get build details for details.
UPDATE:
You can use below PowerShell script to get the build details including Associated Changes and Associated Work Items from TFS 2015 in .txt file (Just specify the correct parameters):
Param(
[string]$collectionurl = "http://server:8080/tfs/defaultcollection",
[string]$project = "0323ScrumTFVC",
[string]$BuildID = "1",
[string]$user = "username",
[string]$token = "password",
[string]$FilePath = 'C:\temp.txt'
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#BaseUrl
$WITbaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/workitems"
$ChangebaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/changes"
#Response
$WITresponse = (Invoke-RestMethod -Uri $WITbaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
$Changeresponse = (Invoke-RestMethod -Uri $ChangebaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
#Output the Associated Work items to a text file.
$WITrequests = #()
foreach($WITrequest in $WITresponse){
$customObject = new-object PSObject -property #{
"WorkitemID" = $WITrequest.id
"WorkitemURL" = $WITrequest.url
}
$WITrequests += $customObject
}
$WITrequests | Select `
WorkitemID,
WorkitemURL | Out-File -FilePath $FilePath -Width 200
#Output the Associated Changes to the text file.
$Changerequests = #()
foreach($Changerequest in $Changeresponse){
$customObject = new-object PSObject -property #{
"ChangesetID" = $Changerequest.id
"Comments" = $Changerequest.message
"Author" = $Changerequest.author.uniqueName
"Timestamp" = $Changerequest.timestamp
"Location" = $Changerequest.location
}
$Changerequests += $customObject
}
$Changerequests | Select `
ChangesetID,
Comments,
Author,
Timestamp,
Location | Out-File -FilePath $FilePath -Width 200 -Append # (with -Append, the contents will increment to txt file )

Powershell how to store and ID giving back from a post method

Okay i wrote the following code to post to an API. The API then returns back an ID that i need to store back into a database. How would i go in doing this i am so confused or is better to store it in memory? I feel that sending it back to sql will be much better. So to be clear again once i run the script i will get back a response back saying that it added what i wanted and it will give me back an ID basically tagging what was added. I need to grab that ID and send it back to a database simultaneously after it is added to the API
$DBServer = "xxxxx"
$DataBaseName = "xxxxxx"
$Connection = new-object system.data.sqlclient.sqlconnection #Set new object to connect to sql database
$Connection.ConnectionString ="server=$DBServer;database=$databasename;trusted_connection=True" # Connection string setting for local machine database with window authentication
Write-host "Connection Information:" -foregroundcolor yellow -backgroundcolor black
$Connection #List connection information to screen
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand #setting object to use sql commands
############ MAIN ####################################
$SqlQuery = #"
SELECT [DeviceId]
,[DeviceName]
FROM [xxx].[dbo].[xxx]
order by 2
"#
$Connection.open()
Write-host "Connection to the $DatabaseName DB was successful." -foregroundcolor green -backgroundcolor black
$SqlCmd.CommandText = $SqlQuery
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$SqlCmd.Connection = $Connection
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$Connection.Close()
###### Will Creds be required??
#Web Client connection
$WebClient = New-Object net.webclient
Add-Type -AssemblyName System.Web.Extensions
#Credentials
$userName ="xxxxxxx"
$password = "xxxxxxxx"
$pair = "$($userName):$($password)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = #{
Authorization = $basicAuthValue
}
#ConvertFromJson
$webclient.Credentials = new-object System.Net.NetworkCredential($username, $password)
foreach ($Row in $DataSet.Tables[0].Rows)
{
#Note sure of the URL at this point..
$URL = "https://xxxxxxxxx/xxxx/xx"
$Endpoint = "/devices.json/$($Row[0])/xxxxxxxxx"
$URLSvc = "$URL$Endpoint"
#write-host $URLSvc + " - " + $($Row[1])
########### TEST ####################
# Create JSON Hash
$JsonTemplate = ConvertTo-Json #{
"applicationName"= "xxx-$($Row[1])";
"applicationType"= "xxxxx";
"description1"= "xxxxx";
"description2"= "";
"passwordCompositionPolicyId"= "xxxxx"
}
## Write out for Display
#ConvertFromJson!!!!!!!!!!!!!!!!!!!!
Write-Host $JsonTemplate -foregroundcolor Red -backgroundcolor White
$xxx = Invoke-RestMethod -Method Post -Headers $Headers -Uri $URLSvc -Body $JsonTemplate -ContentType application/json
Write-Host $xxx
}

How to delete mail items using office 365 REST API in provided powershell script sample

I have been trying to find a solution to this problem for quite a while now and nothing I've found seems to work. I am hoping to use this script:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
#$password = ConvertTo-SecureString "xxx" -AsPlainText -Force
#$cred = New-Object System.Management.Automation.PSCredential "xxx#xxx.onmicrosofot.com",$password
## USER PROMPT PSW ##
#$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$date = "2014-11-21"
## Get all messages that have attachments where received date is greater than $date
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived ge " + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "c:\Temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
}
That I found from link - TechNet Office 365 Scripts
I can get the script to work fine, it connects to mailbox and downloads the attachments for emails specified after the date variable. Problem is that I would like to run this on an hourly schedule and delete previously processed emails so that their attachments are not stripped on consecutive runs.
I've tried lots of different commands to delete the email with no success and also tried altering the $messageQuery to include only items within a specific date range but can't get anything working.
Can anyone provide the correct syntax for the delete command in powershell and an example of how to use it in this context please?
Thanks
Rich
UPDATE - I think adding in:
$query2 = $url + "/" + $message.Id
And
Invoke-RestMethod $query2 -Credential $cred -Method Delete
Is getting me closer but I now get operation timed out.
UPDATE - Full code as it stands and as requested:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "email#address.co.uk",$password
## USER PROMPT PSW ##
##$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
#$url = "https://outlook.office365.com/api/v1.0/me/messages"
$url = "https://outlook.office365.com/EWS/ODATA/me/messages"
$today = Get-Date -format yyyy-MM-dd
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "\\SomePath\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
#Move pdf files to another folder
#Move-Item '\\SomePath\*.pdf' '\\SomePath'
#Then delete any existing files from directory
#Remove-Item '\\SomePath\*'
I tried to alter the date section to allow for a start and end date so the script could be run once a day, do the extraction but not reprocess attachments from previous days but ran into issues working out the syntax to alter the $messageQuery.
Response from running the script is:
Invoke-RestMethod : The operation has timed out.
At C:\Scripts\EmailExtractServiceContract365.ps1:26 char:13
+ $messages = Invoke-RestMethod $messageQuery -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Not an answer
Use Fiddler to capture the request. Use the https://outlook.office365.com/api/v1.0/me/messages endpoint. The other one has been deprecated (I think). Post your sanitized request/response here.
Your script is probably not the problem
I got the script to work fine; it finds an email with attachment, saves the attachment, then deletes the email. I'm not sure what is going on in your environment until I see the requests (remove the auth headers if you post the request). I only changed the $today value to capture emails with attachments today.
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "user#contoso.com",$password
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$today = (Get-Date).AddDays(1).ToString("yyyy-MM-dd")
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "C:\temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
REQUEST
Here's what the request and response should look like to delete the email.
DELETE https://outlook.office365.com/api/v1.0/me/messages/AAMkADBjYXXXXXXXXXX= HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.0.10586.0
Authorization: XXXXXXXXXXXXXXXXXXXXXXXXX
Host: outlook.office365.com
Cookie: ClientId=CQA
Content-Length: 0
RESPONSE
HTTP/1.1 204 No Content

How to schedule automatic backups in teamcity?

We are using Teamcity 6.5.6 professional version, which gives me the option to run a backup but I do not see any option to schedule it to a particular time.
I am not sure if this version of teamcity even supports scheduled backups. If it is not possible through teamcity GUI, I wonder if there is any other option?
Could someone please help?
Thanks.
I wrote Powershell script for TeamCity auto backups, which you can schedule and run backup.
Here's the code:
function Execute-HTTPPostCommand() {
param(
[string] $url,
[string] $username,
[string] $password
)
$authInfo = $username + ":" + $password
$authInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::Default.GetBytes($authInfo))
$webRequest = [System.Net.WebRequest]::Create($url)
$webRequest.ContentType = "text/html"
$PostStr = [System.Text.Encoding]::Default.GetBytes("")
$webrequest.ContentLength = $PostStr.Length
$webRequest.Headers["Authorization"] = "Basic " + $authInfo
$webRequest.PreAuthenticate = $true
$webRequest.Method = "POST"
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($PostStr, 0, $PostStr.length)
$requestStream.Close()
[System.Net.WebResponse] $resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs;
[string] $results = $sr.ReadToEnd();
return $results;
}
function Execute-TeamCityBackup() {
param(
[string] $server,
[string] $addTimestamp,
[string] $includeConfigs,
[string] $includeDatabase,
[string] $includeBuildLogs,
[string] $includePersonalChanges,
[string] $fileName
)
$TeamCityURL = [System.String]::Format("{0}/httpAuth/app/rest/server/backup?addTimestamp={1}&includeConfigs={2}&includeDatabase={3}&includeBuildLogs={4}&includePersonalChanges={5}&fileName={6}",
$server,
$addTimestamp,
$includeConfigs,
$includeDatabase,
$includeBuildLogs,
$includePersonalChanges,
$fileName);
Execute-HTTPPostCommand $TeamCityURL "USER" "PASSWORD"
}
$server = "http://YOUR_SERVER"
$addTimestamp = $true
$includeConfigs = $true
$includeDatabase = $true
$includeBuildLogs = $true
$includePersonalChanges = $true
$fileName = "TeamCity_Backup_"
Execute-TeamCityBackup $server $addTimestamp $includeConfigs $includeDatabase $includeBuildLogs $includePersonalChanges $fileName
You could use the REST API to run the backup. We actually use TeamCity to run a scheduled build at midnight each day. That build makes a call to the rest api to do the backup.
If you don't want to write programs to perform your task, simply run this command:
wget --user=*** --password=*** "http://localhost:8085/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=ScheduledBackup-" --post-data=
where stars should be replaced with your TeamCity login information.
On Windows, you can get WGET as a part of Cygwin package
For those who wants to trigger builds from Mac OS (use "command line" runner on TeamCity):
curl --basic --user user:password -X POST "http://team.city.server:8111/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=ScheduledBackup"
We run maintainDB.cmd and schedule it with the Windows Task Scheduler, it's a one line command and requires no extra software. maintainDB is fully documented in the TeamCity documentation.
You can also use the environment variable to have the team city server address resolve at build time:
curl --basic --user user:pasword -X POST "%teamcity.serverUrl%/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=ScheduledBackup"
Starting from #Ivan Leonenko script I added some lines of code to wait that the backup ends before exit.
function Execute-HTTPCommand() {
param(
[string] $method,
[string] $url,
[string] $username,
[string] $password
)
$authInfo = $username + ":" + $password
$authInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::Default.GetBytes($authInfo))
$webRequest = [System.Net.WebRequest]::Create($url)
$webRequest.ContentType = "text/html"
$PostStr = [System.Text.Encoding]::Default.GetBytes("")
$webrequest.ContentLength = $PostStr.Length
$webRequest.Headers["Authorization"] = "Basic " + $authInfo
$webRequest.PreAuthenticate = $true
$webRequest.Method = $method
if ($method -ne "GET")
{
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($PostStr, 0, $PostStr.length)
$requestStream.Close()
}
[System.Net.WebResponse] $resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs;
[string] $results = $sr.ReadToEnd();
return $results;
}
function Execute-TeamCityBackup() {
param(
[string] $server,
[string] $addTimestamp,
[string] $includeConfigs,
[string] $includeDatabase,
[string] $includeBuildLogs,
[string] $includePersonalChanges,
[string] $fileName,
[string] $username,
[string] $password
)
$TeamCityURL = [System.String]::Format("{0}/httpAuth/app/rest/server/backup?addTimestamp={1}&includeConfigs={2}&includeDatabase={3}&includeBuildLogs={4}&includePersonalChanges={5}&fileName={6}",
$server,
$addTimestamp,
$includeConfigs,
$includeDatabase,
$includeBuildLogs,
$includePersonalChanges,
$fileName);
Write-Host "Starting TeamCity backup"
Execute-HTTPCommand "POST" $TeamCityURL $username $password
}
function Wait-TeamCityBackup() {
param(
[string] $server,
[string] $username,
[string] $password
)
$GetBackupStatusUrl = [System.String]::Format("{0}/httpAuth/app/rest/server/backup",
$server);
do {
Start-Sleep -Seconds 1
$backupStatus = Execute-HTTPCommand "GET" $GetBackupStatusUrl $username $password
Write-Host $backupStatus
} while ($backupStatus -eq 'Running')
}
$server = "http://YOUR_SERVER"
$addTimestamp = $true
$includeConfigs = $true
$includeDatabase = $true
$includeBuildLogs = $true
$includePersonalChanges = $true
$fileName = "TeamCity_Backup_"
$username = "USERNAME" # Must be a TeamCity Admin
$password = "PASSWORD"
Execute-TeamCityBackup $server $addTimestamp $includeConfigs $includeDatabase $includeBuildLogs $includePersonalChanges $fileName $username $password
Wait-TeamCityBackup $server $username $password