LastPass Enterprise API New User Request - powershell

I am trying to use the LastPass Enterprise API to automate the creation of new users in our system using Powershell. I cannot seem to get the call to the API correct in my code. I am almost certain it has something to do with the "data" object. This is the batch object I am passing through the body.
$lastPassObject = #{
cid = "G1TUROWN";
provhash = "N0TM!NE";
cmd = "batchadd";
data = #(
{
username = $email;
fullname = $firstName + " " + $lastName;
password = "Toys4Trucks22!";
password_reset_required = "true";
}
)
}
Here is my API call
Invoke-RestMethod -Uri "https://lastpass.com/enterpriseapi.php" -Method Post -Body $lastPassObject -ContentType "application/json"
Followed by the Error I am receiving
Reference to the API: https://support.lastpass.com/help/add-new-users-via-lastpass-api

You need to convert your body to json before sending it.
Also, you put your Data section in a scriptblock within an array.
This need to be a hashtable, not a scriptblock.
$lastPassObject = #{
cid = "G1TUROWN";
provhash = "N0TM!NE";
cmd = "batchadd";
data = #(
# This need to be an hashtable. You were missing the #
#{
username = $email;
fullname = $firstName + " " + $lastName;
password = "Toys4Trucks22!";
password_reset_required = $true;
}
)
}
$Body = $lastPassObject | ConvertTo-Json
Invoke-RestMethod -Uri "https://lastpass.com/enterpriseapi.php" -Method Post -Body $Body -ContentType "application/json"
If you still have issues after that, make sure to check what the actual json look like (after ConvertTo-Json) so you know exactly what you are sending and can spot more easily discrepancies. For instance, when I first did it, I immediately saw that the data section was all wrong, formatting wise and spotted the missing # because of that.
Also, still by looking at the converted json and the example from their doc, you can see that password_reset_required is a boolean. I changed your "true" to $true so that the correlating json would be what was expected.

Related

Get SPO sites using MS Graph API powershell not working

I'm trying to get all SharePoint Online sites' name and url via PowerShell using MS Graph API, but it's not seem to be working. That's all I get from the request:
#{#odata.context=https://graph.microsoft.com/v1.0/$metadata#sites; value=System.Object[]}
The application I use have all the needed Application type API permissions (Sites.Read, Sites.ReadWrite.All) with admin consent.
Do you have any idea why my script not working?
The code:
$TenantID = 'xxxxxxxxx.ONMICROSOFT.COM'
$ApplicationId = "xxxxx-xxxxxx-xxxx-xxxx"
$ApplicationSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$body = #{
'resource' = 'https://graph.microsoft.com'
'client_id' = $ApplicationId
'client_secret' = $ApplicationSecret
'grant_type' = "client_credentials"
'scope' = "openid"
}
$ClientToken = Invoke-RestMethod -Method post -Uri "https://login.microsoftonline.com/$($tenantid)/oauth2/token" -Body $body -ErrorAction Stop
$headers = #{ "Authorization" = "Bearer $($ClientToken.access_token)" }
$AllSites = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites?search=*" -Headers $headers -Method Get
Write-Host $AllSites
I've also tried these URIs:
https://graph.microsoft.com/v1.0/sites?search=*
https://graph.microsoft.com/v1.0/sites
https://graph.microsoft.com/v1.0/sites$select=siteCollection,webUrl&$filter=siteCollection/root%20ne%20null
The Write-Host cmdlet's primary purpose is to produce
for-(host)-display-only output, such as printing colored text like
when prompting the user for input in conjunction with Read-Host.
Write-Host uses the ToString() method to write the output. By
contrast, to output data to the pipeline, use Write-Output or implicit
output.
reference
This mean that your output is transformed for display purposes. Where you see System.Object[], there is actually data in there just waiting for you.
Based on your current results, your query look good.
Just do not use Write-Host and dig into the object as needed.
To get the site names, just use $AllSites.Value.Name
$AllSites = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites?search=*" -Headers $headers -Method Get
# Return site names
$AllSites.Value.Name
If you need to get additional information from each return you can loop into them, like this to do whatever you need. Here is a custom display of the site name along with an arbitrary index and the associated URL
$index = 0
# Will display results like
# 0: SiteName - www.contoso.sharepoint.com/SiteUrl
foreach ($Site in $AllSites.Value) {
Write-Host "$($index.ToString().PadRight(3,' ')): $($Site.Name) - " -NoNewline
Write-Host $site.webUrl -ForegroundColor Cyan
$index += 1
}
Also, here is an additional reference when working with Azure Graph API that will confirm your requests are working as expected: https://developer.microsoft.com/en-us/graph/graph-explorer

Alter object value upon assignment to PSCustomObject

I'm creating a log of attempted posts to an API. The API key is stored in a simple hash table and passed via Invoke-WebRequest:
$headers = #{ 'x-api-key' = 'ABC123DEF456GHI789' }
Try {
[Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11'
$apiResponse = Invoke-WebRequest -Uri $url -Method $method -Headers $headers -Body $body
$status = $apiResponse.StatusCode
$statusDescription = $apiResponse.StatusDescription
} Catch {
$status = $_.Exception.Response.StatusCode.value__
$statusDescription = $_.Exception.Response.StatusDescription
}
I want to obscure the header key in the log, so I created and modified a new variable.
$obscured = $headers | ConvertTo-Json -depth 100 | ConvertFrom-Json
$obscured.'x-api-key' = $obscured.'x-api-key'.Substring(0,2) + '...' + $obscured.'x-api-key'.Substring($obscured.'x-api-key'.Length-2,2)
$logresults += [PSCustomObject]#{
status = $status
statusDescription = $statusDescription
url = $url
method = $method
header = $obscured
body = ConvertFrom-JSON $body
}
I want to retain the header's structure as a key/value pair in the log. The extra steps prepping a new variable seem wasteful. Does PowerShell have a way to change the header key value upon assignment to the PSCustomObject?
AFAIK, there is no easy way to obscure strings (or objects) in PowerShell or even .Net, see my related purpose: #16921 Add [HiddenString] Class. The only thing that exists is the gone crazy SecureString Class with difficult methodes to convert from a string and reveal string (as that is not secure). Besides, the SecureString might get obsolete (as it appears less secure than intended) and possibly replaced by a shrouded buffer which is even more difficult to use for obscuring information (if even possible in PowerShell).
Anyways, in the HiddenString idea you might do something like this:
$ApiKey = [HiddenString](Read-Host -AsSecureString 'Enter Api key:')
See also: How to encrypt/hide ClearText password in PowerShell Transcript
$Headers = #{
'Accept' = 'application/json'
'X-My-Header' = 'Hello World'
'x-api-key' = $ApiKey
}
$apiResponse = Invoke-WebRequest -Uri $url -Method $method -Headers $($Headers.'x-api-key' = $ApiKey.Reveal(); $Headers) -Body $body
$logresults += [PSCustomObject]#{ # Avoid +=, see: https://stackoverflow.com/a/60708579/1701026
status = $status
statusDescription = $statusDescription
url = $url
method = $method
header = $Headers
body = ConvertFrom-JSON $body
}

Jira Rest Api in Powershell

Could you help me?
I am trying to create an issue in Jira using the Powershell Invoke-WebRequest cmdlet. And I am getting 400 Bad Request error.
I was able to send a successful request using Postman, so I made sure the body syntax is correct and I have sufficient rights.
My code:
$body = #{
"fields" = #{
"project"=
#{
"key"= "ProjectKey"
}
"summary"= "Test"
"description"= "Test"
"issuetype" =#{
"id"= "10705"
}
"priority"= #{
"id"= "18"
}
"reporter"= #{"name"= "MyName"}
}
}
$Headers = #{
Authorization = "Basic QWxla0Zblablablablablablabla" #I took it from Postman
}
$restapiuri = "https://jira.domain.com/rest/api/2/issue"
Invoke-RestMethod -Uri $restapiuri -ContentType "application/json" -Body $body -Method POST -Headers $Headers
for example, I can successfully execute
Invoke-RestMethod "https://jira.domain.com/rest/api/2/issue/createmeta" -Headers $Headers
I've already spent a lot of time-solving this problem, but still can't create an issue.
Any help, please 🙏🙏🙏
For basic authentication with Jira SERVER, the credentials need to be supplied within the header in Base64 encoding, which you need to do before supplying it via the Powershell Invoke-WebRequest method. Here's how to do it:
$username = "The username here"
$password = "The password or token here"
# Convert the username + password into a Base64 encoded hash for basic authentication
$pair = "${username}:${password}"
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
$headers = #{ Authorization = "Basic $base64" }
Next, in PowerShell, if you build the body of the request as a table, like you've shown, don't don't need to wrap the table elements with inverted commas, just leave them as is, but you do need to convert the table to JSON format before submitting it, like this:
$body = #{
fields = #{
project = #{
key = "ProjectKey"
}
issuetype = #{
id = "10705" # Or refer to the Issue type by its name eg. name = "Story"
}
summary = "Test"
}
}
# Convert the body to JSON format
$body = $body | ConvertTo-Json -Depth 50
I'm assuming your $Uri string contains an actual URL to a Jira Server, not the example 'jira.domain.com'
Start with a simple request in the body, like the one I've shown, that contains only the minimum required to create the Issue, which will check your basic code is working before making the request more complex.

Powershell variables in array

I'm creating a powershell script to add users to a system via API request.
I have defined a variable below, it has a lot of escape characters because it's a json string which goes into the body of the request and otherwise it wasn't possible to define user data as variables in it, but this way it works.
$BODY_USERS = "{`"firstName`":`"${NAME}`", `"lastName`":`"${LASTNAME}`",`"email`":`"${EMAIL}`",`"enabled`":`"true`", `"username`":`"${USERNAME}`",`"credentials`":[{`"type`":`"password`",`"value`":`"Test12345789#`",`"temporary`":true}]}"
The command i execute to add a user is this one:
Invoke-RestMethod -Uri $URI_USERS -Method Post -Headers $HEADERS_USERS -Body $BODY_USERS
I would like to provide user related vars ($NAME, $LASTNAME etc) in a separate file. I did it for one user using dotsource - basically just defined abovementioned variables in a separate .ps1 file and referenced it in the script with . .\vars.ps1 and for one user it works just fine of course.
However if I need to construct a for loop for multiple users, I'm not sure what would be the best approach in this case.
Shall I define in my separate vars.ps1 file something like this:
$var=#($NAME='Jonny'; $LASTNAME='Doe'; $USERNAME='johnnydoe'; $EMAIL='johnny.doe#email.com')
$var#($NAME='Jonny2'; $LASTNAME='Doe2'; $USERNAME='johnnydoe2'; $EMAIL='johnny.doe2#email.com')
and then use something like Get-Content "C:\Users\Desktop\vars.ps1" | ForEach-Object {do blahblah} in my script? But I'm not sure how it will be consumed by my $BODY_USERS variable. So I need to provide an array of variables to a variable, or something like that...
Being novice to powershell, i'm a little bit puzzled here.
Any advice is appreciated!
As noted in comments, you don't need to construct JSON string manually. Create a hashtable for much cleaner syntax and convert to JSON string using ConvertTo-JSON. This also takes care of escaping characters that have special meaning in JSON, like " and \.
$BODY_USERS = #{
firstName = $NAME
lastName = $LASTNAME
email = $EMAIL
enabled = $true
username = $USERNAME
credentials = #(
#{ type = "password"; value = "Test12345789#"; temporary = $true }
)
}
$BODY_USERS_JSON = ConvertTo-JSON $BODY_USERS
Invoke-RestMethod -Uri $URI_USERS -Method Post -Headers $HEADERS_USERS -Body $BODY_USERS_JSON
For multiple users you could store the data in a CSV file, which are quite easy to handle with PowerShell:
Users.csv
name,lastname,username,email
Jonny,Doe,johnnydoe,johnny.doe#email.com
Jonny2,Doe2,johnnydoe2,johnny.doe2#email.com
Now we can process the users.csv like this:
$allUsers = Import-Csv users.csv
$allUsers # List users only for debugging purposes
foreach( $user in $allUsers ) {
$BODY_USERS = #{
firstName = $user.NAME
lastName = $user.LASTNAME
email = $user.EMAIL
enabled = $true
username = $user.USERNAME
credentials = #(
#{ type = "password"; value = "Test12345789#"; temporary = $true }
)
}
$BODY_USERS_JSON = ConvertTo-JSON $BODY_USERS
Invoke-RestMethod -Uri $URI_USERS -Method Post -Headers $HEADERS_USERS -Body $BODY_USERS_JSON
}

Error 400 bad request when creating a group calendar event in powershell with Microsoft Graph API

I'm trying to create an event in a calendar in an Office 365 group via powershell.
This is my first experience to do this type of programming so sorry if my question will be very basic :-)
First, I created a simple json file (calendar.json)
{
"start":
{
"dateTime":"2017-03-12T17:00:00.0000000",
"timeZone":"UTC"
},
"end":
{
"dateTime":"2017-03-12T17:30:00.0000000",
"timeZone":"UTC"
},
"responseStatus": {
"response": "None"
},
"iCalUId": "null",
"isReminderOn": false,
"subject": "Test Event created from API"
}
Then I create the event with these steps:
Use a tested powershell function that give me the token
Add header with this code:
$headers = #{}
$headers.Add('Authorization','Bearer ' + $token.AccessToken)
$headers.Add('Content-Type',"application/json")
Because I'm starting now, I convert the json file in an object and then the object in json (I know, it's quite stupid, but I've done so beacuse I have no knowledge of json and how convert without error in powershell code)
$json = ConvertFrom-Json -InputObject (Gc 'C:\Users\mmangiante\OneDrive - Interactive Media S.p.A\Office 365\calendar.json'-Raw)
$body = ConvertTo-Json $json
Call the Invoke-RestMethod
response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups/768afb0c-bafd-4272-b855-6b317a3a9953/calendar/events' -Method Post -Headers $headers -Body $json
What is returned is a 400 bad request.
It's the same error of Sending Microsoft Graph request events returns 400
Given the answer given to that question I modified my code to return the error:
try{$restp=Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups/768afb0c-bafd-4272-b855-6b317a3a9953/calendar/events' -Method Post -Headers $headers -Body $json
} catch {$err=$_}
$err
like suggested in How do I get the body of a web request that returned 400 Bad Request from Invoke-RestMethod but I found nothing of interest.
The only thing that I found is that, at the time of writing, the Invoke-RestMethod doesn't return the full response as in this https://github.com/PowerShell/PowerShell/issues/2193
I suppose my json is not "well formed", but I don't know why.
Does anyone have a suggestion?
This formatting has worked for me in the past. Let me know if this resolves your issues:
$headers = #{
"Authorization" = ("Bearer {0}" -f $token);
"Content-Type" = "application/json";
}
$body = #{
Name1 = 'Value1';
Name2 = 'Value2';
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri <API HERE> -Headers $headers -Body $bodyJSON -OutFile $output
Thanks Shawn,
I tried your suggestion but without luck; I have done other test with 2 other api and found discordant results.
The first test is to use the graph api related to contact, creating a contact as in https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/user_post_contacts
I created the powershell representation of the sample json:
$contactbody = #{
givenName = 'Ciccio';
surname = 'Patacca';
emailAddresses = #(
#{
address = 'cicciopatacca#cicciociccio.com'
name = 'Ciccio Patacca'
}
)
businessPhones = (
'+39 555 123 4567'
)
}
and then converted in json
$contactbody = $contactbody | ConvertTo-Json
I retrieved from Azure Portal the object ID related to my user in my company and so I call the rest method:
$response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/users/e37d2dbe-bdaf-4098-9bb0-03be8c653f7d/contact' -Method Post -Headers $headers -Body $contactbody
The final result is a 400 bad request error.
So, I tried another example and reused some code retrieved from a google search.
This time I copied the powershell json representation as in the sample and converted:
$body = #{"displayName"="ps-blog"; "mailEnabled"=$false; "groupTypes"=#("Unified"); "securityEnabled"=$false; "mailNickname"="ps1" } | ConvertTo-Json
and, as stated in https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/group_post_groups I called the rest method
$response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups' -Method Post -Headers $headers -Body $body
and this worked.
So I thought that the previously powershell representations of the sample with the error were not correctly formed (even if when I printed it they are equal to the samples on the graph api); for test, I rewritten the last powershell of the body as this:
$body = #{
displayName = 'TestGraphGroup';
mailEnabled = $true;
groupTypes = #('Unified')
securityEnabled = $false;
mailNickname = 'TestGraphGroup'
}
$body = $body | ConvertTo-Json
and invoked last method: it worked again.
So, where I'm doing wrong?
A new SDK was released that makes this easier.
Checkout instructions on how to use it here