update/create TFS Server variable group using REST API with powershell gives object reference not set - rest

Allright i have been fiddling with this for a few hours now and i can't seem to find any resources online or solve the issue.
Looking at the api documentation at https://learn.microsoft.com/en-us/rest/api/azure/devops/distributedtask/variablegroups/get?view=azure-devops-rest-6.0
I can get info regarding the variable group that i created as a test:
$invRestMethParams = #{
Uri = "https://xxx.xxx.nl/tfs/DefaultCollection/$($project)/_apis/distributedtask/variablegroups/242/?api-version=6.0-preview.2"
Method = 'GET'
ContentType = 'application/json'
}
Invoke-RestMethod #invRestMethParams -UseDefaultCredentials
I then convert the result to json to get the required values for the PUT or POST to update or create:
{
"variables": {
"check": {
"value": "value"
}
},
"id": 242,
"type": "Vsts",
"name": "TestUpdate",
"description": "",
"isShared": false,
"variableGroupProjectReferences": [
{
"projectReference": "#{id=0add8cd8-0fc8-4aca-8eb4-164cd8d09c9d; name=AutoUpdateVariableGroups}",
"name": "TestUpdate",
"description": ""
}
]
}
The documentation states the update url is:
PUT https://{instance}/{collection}/_apis/distributedtask/variablegroups/{groupId}?api-version=6.0-preview.2
With request body having the above json values (without the ID as this is in the URI). So my update json becomes:
$body = #"
{
"variables": {
"checkupdated": {
"value": "valueupdated"
}
},
"type": "Vsts",
"name": "TestUpdate",
"description": "",
"isShared": false,
"variableGroupProjectReferences": [
{
"projectReference": "#{id=0add8cd8-0fc8-4aca-8eb4-164cd8d09c9d; name=AutoUpdateVariableGroups}",
"name": "TestUpdate",
"description": ""
}
]
}
"#
i convert it from json to see if its valid (no errors).
and use it in my PUT request:
$invRestMethParams = #{
Uri = "https://xxx.xxx.nl/tfs/DefaultCollection/_apis/distributedtask/variablegroups/242/?&api-version=6.0-preview.2"
Method = 'PUT'
ContentType = 'application/json'
Body = $body
}
Invoke-RestMethod #invRestMethParams -UseDefaultCredentials
The error i receive is:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Object reference not set to an instance of an object.","typeName":"System.NullReferenceException, mscorlib","typeKey":"NullReferenceException","errorCode":0,"eventId":0}
At line:32 char:1
+ Invoke-RestMethod #invRestMethParams -UseDefaultCredentials
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Not sure how to troubleshoot this, does anyone know how to fix this issue? seems i am forgetting a value but im kinda lost as to what is the issue here.

From your script, it seems that it has issue with your request body.
In projectReference field, you need to use , to replace the ; and you need to modify the format.
"projectReference": {"id":"projectID", "name":"projectname"},
Refer to my sample:
$JSON = #"
{
"variables": {
"checkupdate": {
"value": "vaslueupdate"
}
},
"type": "Vsts",
"name": "AA",
"description": "",
"isShared": false,
"variableGroupProjectReferences": [
{
"projectReference": {"id":"108e4d7c-0bf3-4940-80da-4793f83def92", "name":"kevin1012"},
"name": "AA",
"description": ""
}
]
}
"#

Related

Graph send mail with attachment

I'm trying to send a e-mail with attachment with powershell, as soon as I add in the attachment, I get a 400 Bad Request error, while it works find without attachment. Hope someone has a clue...
Part added:
"attachments": [
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "attachment.txt",
"contentType": "text/plain",
"contentBytes": "SGVsbG8gV29ybGQh"
}
]
Full request:
$Subject = "Subject2"
$Message = "Message2"
$Recipient = "testemailaddress"
$SaveToSentItems = $false
$Request=#"
{
"Message": {
"Subject": $(Escape-StringToJson $Subject),
"Body": {
"ContentType": "HTML",
"Content": $(Escape-StringToJson $Message)
},
"ToRecipients": [
{
"EmailAddress": {
"Address": "$Recipient"
}
}
],
"attachments": [
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "attachment.txt",
"contentType": "text/plain",
"contentBytes": "SGVsbG8gV29ybGQh"
}
]
},
"SaveToSentItems": "$(if($SaveToSentItems){"true"}else{"false"})"
}
"#
# Convert to UTF-8 bytes
$Request_bytes = [system.Text.Encoding]::UTF8.getBytes($Request)
$headers = #{
"Authorization" = "Bearer $($attributes.EXO)"
"Accept" = "text/*, multipart/mixed, application/xml, application/json; odata.metadata=none"
"Content-Type" = "application/json; charset=utf-8"
"X-AnchorMailbox" = (Read-AADIntAccesstoken $attributes.EXO).upn
"Prefer" = 'exchange.behavior="ActivityAccess"'
}
$url="https://outlook.office.com/api/v2.0/me/sendmail"
Invoke-RestMethod -UseBasicParsing -Uri $Url -Method Post -Headers $headers -Body $Request_bytes
Error:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At line:47 char:1
Invoke-RestMethod -UseBasicParsing -Uri $Url -Method Post -Headers $h ...
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I use this for send attachs in mails with ms graph in powershell
$attach = "C:\file.pdf"
$fileName = (Get-Item -Path $attach).Name
$base64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes($attach))
$message = '{
"message": {
"subject": "subject",
"body": {
"contentType": "HTML",
"content": "'+$body+'"
},
"importance": "high",
"toRecipients": [
{
"emailAddress": {
"address": "'+$mail+'"
}
}
],
"attachments": [
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "'+$fileName+'",
"contentType": "text/plain",
"contentBytes": "'+$base64string+'"
}
],
},
"saveToSentItems": "true"
}'
$URL = "https://graph.microsoft.com/v1.0/users/xxxxxxxxxxxxxxxxxxxx/sendMail"
Invoke-RestMethod -Method POST -Uri $URL -Headers $headers -Body $message
Convert to Base64 string before insert in the request.
I guess you have your own "body"!
Regards.

Error while trying to create a release definition using Azure DevOps Rest API

I am using below script to create a release definition in Azure DveOps with a PowerShell script, but its failing with error message as below. Not sure where am giving incorrect details.
Invoke-RestMethod :
{"$id":"1","innerException":null,"message":"VS402903: The specified
value is not convertible to type ReleaseDefinition. Make sure it is
convertible to type ReleaseDefinition and try again."
Code snippet is:
Param(
[string]$organisation = "ORGNAME",
[string]$project = "PROJECTNAME",
[string]$keepForever = "true",
[string]$user = "userid",
[string]$token = "tokenID" )
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
Write-host $base64AuthInfo
$postresults = "https://vsrm.dev.azure.com/$organisation/$project/_apis/release/definitions?api-version=6.0"
Write-host $postresults
$body =
#"
{ "name": "New release pipeline ",
"comment": "test",
"definitionId": 860,
"description": "Create Release from PowerShell",
"artifacts": [],
"isDraft": false,
"reason": "Demo purpose",
"manualEnvironments": null,
"environmentsMetadata": null,
"properties": null,
"variables": null
"environments": [
{
"name": "PROD",
"preDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": false,
"isNotificationOn": false,
"approver": {
"displayName": null,
"id": ""
},
"id": 0
}
]
},
"postDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": true,
"isNotificationOn": false,
"id": 0
}
]
},
"deployPhases": [
{
"deploymentInput": {
"parallelExecution": {
"parallelExecutionType": "none"
},
"skipArtifactsDownload": false,
"artifactsDownloadInput": {},
"queueId": 391,
"demands": [],
"enableAccessToken": false,
"timeoutInMinutes": 0,
"jobCancelTimeoutInMinutes": 1,
"condition": "succeeded()",
"overrideInputs": {}
},
"rank": 1,
"phaseType": "agentBasedDeployment",
"name": "Run on agent",
"workflowTasks": []
}
],
"retentionPolicy": {
"daysToKeep": 30,
"releasesToKeep": 3,
"retainBuild": true
}
}
],
"path": "\\",
"releaseNameFormat": "Release",
"description": ""
}
"# | ConvertTo-Json -Depth 100
$result = Invoke-RestMethod -Uri $postresults -Method Post -Body $body -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
if ($result.count -eq 0)
{
throw "Unable to locate Release Definition Id $($definitionId)"
}
else
{
Write-host "Success!!!"
}
You have few issues in the json body:
The description exist twice.
You have missing , near the "variables": null.
You need to specify a valid id in the preDeployApprovals:
"approver": {
"displayName": null,
"id": "PUT-HERE-ID"
},
Add the above section also to the
You don't need to convert it again to json, remove the | ConvertTo-Json -Depth 100 from the code.

Query MSGraph API with PowerShell Invoke-RestMethod does not return same amount of details as MSGraph Explorer

I used MSGraph Explorer and PowerShell Invoke-RestMethod to query the same MSGraph API, but MSGraph Explorer returns way more details than the PowerShell command. Could this be a permission issue or I missed something in the PowerShell command.
Here is the URI, it is to retrieve the audit log for a particular directory change.
https://graph.microsoft.com/beta/auditLogs/directoryAudits/Directory_029A8_49125229
This is the output from MSGraph Explorer:
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#auditLogs/directoryAudits/$entity",
"id": "Directory_029A8_49125229",
"category": "Core Directory",
"correlationId": "d534994f-61f4-4015-8040-c16f728ec8b3",
"result": "success",
"resultReason": "",
"activityDisplayName": "Update user",
"activityDateTime": "2018-10-04T05:41:19.9668303Z",
"loggedByService": null,
"initiatedBy": {
"app": null,
"user": {
"id": "1f5c2159-f515-4cea-a99c-11c6ce1f7a5e",
"displayName": null,
"userPrincipalName": "tom-admin#contoso.onmicrosoft.com",
"ipAddress": "<null>"
}
},
"targetResources": [
{
"#odata.type": "#microsoft.graph.targetResourceUser",
"id": "498b3884-f723-444c-9c01-b75ec2c0ef08",
"displayName": null,
"userPrincipalName": "Tom.Real#contoso.com",
"modifiedProperties": [
{
"displayName": "AssignedLicense",
"oldValue": "[\"[SkuName=ENTERPRISEPACK, AccountId=cdc4b90d-7fa9-4a, SkuId=6f94b900, DisabledPlans=[]]\"]",
"newValue": "[]"
},
{
"displayName": "AssignedPlan",
"oldValue": "[{\"SubscribedPlanId\":..., \"ServicePlanId\":\"50e68c76-46c6-4674-81f9-75456511b170\"}]",
"newValue": "[{\"SubscribedPlanId\":... 50e68c76-46c6-4674-81f9-75456511b170\"}]"
},
{
"displayName": "Included Updated Properties",
"oldValue": null,
"newValue": "\"AssignedLicense, AssignedPlan\""
},
{
"displayName": "TargetId.UserType",
"oldValue": null,
"newValue": "\"Member\""
}
]
}
],
"additionalDetails": [
{
"key": "UserType",
"value": "Member"
}
]
}
This is the output from Invoke-RestMethod:
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#auditLogs/directoryAudits/$entity",
"id": "Directory_029A8_49125229",
"category": "Core Directory",
"correlationId": "d534994f-61f4-4015-8040-c16f728ec8b3",
"result": "success",
"resultReason": "",
"activityDisplayName": "Update user",
"activityDateTime": "2018-10-04T05:41:19.9668303Z",
"loggedByService": null,
"initiatedBy": {
"app": null,
"user": {
"id": "1f5c2159-f515-4cea-a99c-11c6ce1f7a5e",
"displayName": null,
"userPrincipalName": "tom-admin#contoso.onmicrosoft.com",
"ipAddress": "\u003cnull\u003e"
}
},
"targetResources": [
{
"#odata.type": "#microsoft.graph.targetResourceUser",
"id": "498b3884-f723-444c-9c01-b75ec2c0ef08",
"displayName": null,
"userPrincipalName": "Tom.Real#contos.com",
"modifiedProperties": " "
}
],
"additionalDetails": [
{
"key": "UserType",
"value": "Member"
}
]
}
As you can see Invoke-RestMethod does not return any details under "additionalDetails".
This is my PowerShell script
Function GetAuthToken
{
param
(
[Parameter(Mandatory=$true)]
$TenantName
)
Import-Module Azure
$clientId = "ef9bcdf0-a675-4cd5-9ec3-fa549f9ee4cf"
$redirectUri = "https://RedirectURI.com"
$resourceAppIdURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/$TenantName"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$Credential = Import-Clixml -Path "C:\MIMA\tom_admin_cred.xml"
$AADCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $credential.UserName,$credential.Password
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,$AADCredential)
return $authResult
}
if($Version -eq $null) {$Version='Beta'}
#------Get the authorization token------#
$token = GetAuthToken -TenantName $tenant
#------Building Rest Api header with authorization token------#
$authHeader = #{
'Content-Type'='application\json'
'Authorization'=$token.CreateAuthorizationHeader()
}
$uri = "https://graph.microsoft.com/beta/auditlogs/directoryAudits/Directory_029A8_49125229"
$results = Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get
$results |ConvertTo-Json
I believe everything is fine with your query and permissions, the results are different since for ConvertTo-Json cmdlet by default 2 levels of contained objects are included in the JSON representation.
So, if you want directoryAudit all properties to be included in result, Depth parameter needs to be specified explicitly, for example:
$results |ConvertTo-Json -Depth 3 #at least 3 levels for directoryAudit entry

Directory_ExpiredPageToken when looping through response without delay

I am accessing Microsoft Graph using PowerShell which is working like a charm, except paging.
From time to time I get Directory_ExpiredPageToken errors. The errors are mostly gone if I set a 1 sec delay between the requests.
$ReturnObject = #()
while ($Uri.Length -gt 0) {
Add-TraceLine -Type DEBUG -Text "Calling '$($Uri)'"
$Response = Invoke-RestMethod -Method GET -Uri $Uri -Headers $Headers
$ReturnObject += $Response
if ($Response.'#odata.nextlink') {
$Uri = $Response.'#odata.nextlink'
#Delay needed, otherwise Directory_ExpiredPageToken errors occured
Start-Sleep -Milliseconds 1000
}
else {
$Uri = $null
}
}
Any idea whats going on here?
The delay is a workaround to get the workflow running which is using this module. But I want to get rid of it because of performance reason.
EDIT:
This is a JSON response simplified (value is not only one object, but an array) and changed a little bit because of privacy/security reasons:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(department,displayName,ext2j5y6eqq_linkeduser,givenName,id,jobTitle,mail,mailNickname,surname,userPrincipalName)",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/users?$filter=userType+eq+%27Guest%27\u0026$select=department%2cdisplayName%2cext2j5y6eqq_linkeduser%2cgivenName%2cid%2cjobTitle%2cmail%2cmailNickname%2csurname%2cuserPrincipalName\u0026$skiptoken=RFNwdAkAAQAAAAAAAAAAFAAAADzX_JYCsThFmyry6_Ndz8kBAAAAAAAAAAAAAAAAAAAXMS4yLjg0MC4xMTM1NTYuMS40LjIzMzECAAAAAAABJruiMN_CtUmk63sXDRMMdg",
"value": [
{
"id": "80f7fa19-2669-470d-86ac-ee4c052a5186",
"department": null,
"displayName": "XC Admin",
"givenName": "XC",
"jobTitle": null,
"mail": null,
"mailNickname": "xcadmin",
"surname": "Admin",
"userPrincipalName": "xcadmin#domain.onmicrosoft.com"
}
]
}
EDIT:
This is the error response
+ ERROR { throw $Line }
+ ~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (11.04.2018-06:5...
}
}
}:String) [], RuntimeException
+ FullyQualifiedErrorId : 11.04.2018-06:50:13: <ERROR> - Get-User: {
"error": {
"code": "Directory_ExpiredPageToken",
"message": "The specified page token value has expired and can no longer be included in your request.",
"innerError": {
"request-id": "13ecca81-2d8c-4d0f-a58e-4a9cdd72e100",
"date": "2018-04-11T04:50:15"
}
}
}

Error when creating a blob storage output for Stream Analytics using Powershell

I'm trying to create a Stream Analytics blob storage output using powershell.
This is the command I'm using:
New-AzureRMStreamAnalyticsOutput -ResourceGroupName $ResourceGroupName -JobName $JobName –File soutput.json" -Force
and the output.json file looks like this:
{
"name": "test",
"properties": {
"datasource": {
"type": "Microsoft.Storage/Blob",
"properties": {
"storageAccounts": ["testStorage"],
"container": "testContainer",
"pathPattern": "",
"accountName": "testStorage",
"accountKey": "storage-key"
}
}
}
}
And I'm getting this error:
New-AzureRMStreamAnalyticsOutput : HTTP Status Code: BadRequest
Error Code: BadRequest
Error Message: The JSON provided in the request body is invalid.
Error converting value "testStorage" to type 'Microsoft.Streaming.Service.Contracts.CSMResourceProvider.BlobConnectionInfo'.
Path 'properties.storageAccounts[0]', line 8, position 106.
What should be in the storageAccounts property?
What should be in the storageAccounts property?
We need to set storageAccounts property:
"StorageAccounts": [
{
"AccountKey": "storagekey",
"AccountName": "storageaccount"
}
]
Property "Serialization" need to be included in the output json file.Please have a try to use output.json file as following. It works correctly for me.
{
"Name": "S3PSAJobOutPut",
"Properties": {
"DataSource": {
"Properties": {
"Container": "s3psaoutput",
"PathPattern": "",
"StorageAccounts": [
{
"AccountKey": "storagekey",
"AccountName": "storageaccount"
}
]
},
"Type": "Microsoft.Storage/Blob"
},
"Serialization": {
"Properties": {
"Encoding": "UTF8",
"Format": "LineSeparated"
},
"Type": "Json"
}
}
}