Jump to content

Issues adding passwords via webapi


Chris Gribbin

Recommended Posts

I have been running around this for ~3hrs back and forth, combing these forums and google alike -

 

My use case:

having lvl1 users comb our runbooks and enter passwords into .csv file

powershell script to add them to pws.

 

I have built in functions that will GET the list ID's based on a parameter query and normalize AccountTypeID from a static csv list of account types I created, it splits the list into good and bad entries (filters out entries that don't have a username or password or title), and then sends the good list through the add function.

 

Every bit of it is working (including the GET search function for the list ID input in the same script) and all my other testing of various searches using Invoke-Restmethod -Method GET, but I can't get the -Method POST command to work no matter what I do.

 

I end up at the following error for every call.

    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Invoke-Restmethod : [{"errors":[{"message":"Invalid API Call"},{"phrase":"Error = Object reference not set to an instance of an object."}]}]

I have found a few similar things here in the forums and tried those:

  1. I used the IP of the server and port, subsequently finding and including the ignore cert code - which let me through to the same error.
  2. I changed the original $jsonData= '{ }' string to the $body= @{ }; $jsonData= $body | ConvertTo-json method as I believe suggested by Fabian.
  3. I added the charset=utf-8 as found in the keepass script (I looked there for reference too) and in Fabian's scripts.
  4. I checked my Invoke-Restmethod command several times against the documentation examples, different scripts and things here on the forum.. it 'looks' right to me..
  5. I tried removing and re-adding all the different elements (like the url), though the examples look like null/blank entries are OK.
  6. For grins I tried on a remote system outside my network (home PC)
  7. Ran in powershell as admin, ise as admin, debug in visualstudiocode, and (per Mark's suggestion on an email thread about a different/similar issue) I downloaded SAPIEN PSS 2018 and debug in there as well.

 

 

 

I'm hoping that you guys see something I missed..

 

In the below function assume that $globalapi set and confirmed working in my other GET functions and that my $uri is also set and confirmed working. 

Running on PWS Version 8491, just updated the other day.

Parameters are passed via a foreach command:

Foreach ($record in $formattedrecords) {
    Add-PWSRecord $record.list $record.title $record.UserName $record.AccountType $record.Password $record.url
}

$formattedrecords being the output array of my normalizing / accounttypeid lookup function - the output of that array looks like I expect it to when echo'd, as does the $body array and the $jsonPasswordData string when echoed prior to the Invoke-Restmethod command.. though I should note that convertto-json appears to reorder them, not that that should make a difference.

function Add-PWSRecord
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,Position = 0)]
        [ValidateNotNullOrEmpty()][string]$body_list,
        [Parameter(Mandatory = $true,Position = 1)]
        [ValidateNotNullOrEmpty()][string]$body_title,
        [Parameter(Mandatory = $true,Position = 2)]
        [ValidateNotNullOrEmpty()][string]$body_username,
        [Parameter(Mandatory = $true,Position = 3)]
        [ValidateNotNullOrEmpty()][string]$body_accounttype,
        [Parameter(Mandatory = $true,Position = 4)]
        [ValidateNotNullOrEmpty()][string]$body_pw,
        [Parameter(Position = 5)][string]$body_url
    )
    $body= @{
PasswordlistID = $body_list
Title = $body_title
UserName = $body_username
AccountType = $body_accounttype
Password = $body_pw
URL = $body_url
APIKey = $globalapi
}
    $jsonPasswordData = $body | ConvertTo-Json

$uri = "https://$pwsurl/api/passwords"

$result= Invoke-Restmethod -Method Post -Uri $uri -ContentType "application/json; charset=utf-8" -Body $jsonPasswordData
$output= 0
}

Cheers!

-Grib

Link to comment
Share on other sites

Hi Chris,

 

Unfortunately I can't spot anything either, and if the key in the $globalapi is the anonymous API key out of system settings, then this should work for all these requests without issue.

 

Object not set is a very vague message unfortunately.  Would you be able to send your script to our support email address, along with some test data, and I'll try to get it working in my test environment? 

 

Or if any of the other gurus in here have any advice, please help!!!!

 

Cheers,

Support.

Link to comment
Share on other sites

Hi all,

 

Currently I think that there's some kind of bug with this REST method, because I can't see any issues with the script and also other users are reporting the same error

In our company about one month ago one user wannted to use the import script from KeePass, which is using the WinAPI and we got the following error when the REST call tried to add passwords to a Passwordlist. After we stared exactly the same import with another user account it worked fine. The KeePass import script with the WinAPI creates private passwordlists and uses the loggedin users account (instead of shared with the script which uses the Anonymous-API with the Key).

image.thumb.png.24052fd54187ea2aa13d93a1860c6a6b.png

 

Best regards,

 

Fabian

Link to comment
Share on other sites

I have submitted my full code (after I finished all the frills..) to support as of Friday and didn't hear anything yet (which I think is good.. because I reckon that means it's not something simple I should have seen..). 

Just don't want to see the thread die - I'm patiently waiting.

Link to comment
Share on other sites

Hi Chris,

 

Sorry for the delay - we did have a quick look, but it is a very large script and will take some time to analyse. Maybe upload the entire script to the forum also, and someone from the community might be able to test it also.

Regards

Click Studios

Link to comment
Share on other sites

Hi Chris,

 

I've had a quick look, and I am a bit confused about your script sorry - it's quite a bit to consume. A couple things I have noticed, and I don't know if this is the issue or not, or just my lack of understanding.

  • You script has functions embedded inside other functions - normally we don't do this, but not sure if this is the cause
  • When adding the password records, you reference $record.list, which I believe is meant to be the PasswordListID - it's best to name the variables properly, do avoid any confusion if your other team members need to use the script. If this variable is meant to be referencing the 'list' column in your sample spreadsheet, then this column is entirely blank
  • In your sample csv file, you also have an account name called 'Misc.', but in your AccountTypes csv lookup file, it's called 'Misc. Account'

I hope this helps a little.

Regards

Click Studios

Link to comment
Share on other sites

The nested functions are just for the testing. One echoes the command and the other sends it. 

 

The record.list is because I’m parsing data and weeding out records that don’t have required fields. Saving good records into $records array and foreach $record in $records to construct the call.

 

That list field is blank in the test data because it calls the API to choose a list and adds it to the array during the parsing. 

 

The Misc. is a purposeful mismatch to test my logic that prompts for a valid entry (alongside the no-type record) during the above mentioned parsing. 

 

I included you a section in the leading comment block describing that stuff. 

 

Also, it’s worth a mention that running the script as-is produces the expected result on the test data, 3 rejects and 3 good records passed. Including one that prompts for an account type. The records that pass are echoed before they send (the nested test function) and appear to be constructed correctly but they fail.

 

Every bit of the script that constructs the calls performs exactly as expected in my testing. The records are constructed consistently and accurately according to the examples, and I used a much larger and more varied data set during construction  with similar result. 

 

I sent a screenshot in the email of the output: echo, fail, repeat x2.  You can see the constructed command there.  

 

Finally, even when I manually construct the command via json or convertto-json the manually created command still fails.

 

The script as a whole does a lot, I know.  Even the basic function in my op doesn’t work though, and that constructs it essentially the same, for a single record instead of an array of records. 

 

I hope that that clears it up.  

Link to comment
Share on other sites

This is the whole folder zip'd.  Called support because it's the same ones I mailed into support.  You really just need to extract wherever, update the TLD and API Key, rename the 'rename-me.csv' to something that'll get a result searching your treepath somewhere (I made a test site  for it in mine) and run.  Should see 3 try to post, and 3 rejects entered in a new csv in the rejects folder.

 

I made what I think are complete, if way too wordy, details in the front of the script, and I commented out the cleanup at the end that deletes the source csv files.. once this thing is humming that's just cleanup for good measure.

 

As I said, the nested functions for the call itself is just to illustrate the call being built properly - can comment out one or the other but as-is I have them both running for testing.  I do eventually intend to eliminate that and just leave the call in that part of the script by itself outside a nested function - it's just easier in testing imo to comment out one line than the whole section back and forth from Write-Host to Invoke-Restmethod during this troubleshooting.

 

Here's hoping it's somewhat readable.  I'm not exactly 'new to powershell', but I do lack any real training on the subject.. aside from what google and examples show me.  I'll be glad to take anything constructive anyone has to offer me. 

 

Cheers!

-Grib

Support.zip

Link to comment
Share on other sites

Sent this to Support this morning but afterthought I'd post it here too.

 

OK so I made a few manual calls and they still fail – this is I believe the core of the issue, and once these can get in a state where they go I can make the script work.

 

I sanitized my Global API key and TLD out of the commands on pasting here – but they were of course in there and working for the test commands.  Other than that this is a direct copy from my powershell window.

 

…and for due diligence’s sake I ran them all manually in :

·         terminal on VisualStudioCode

·         debug on PowerShell Studio

·         F8 runs in ISE

·         2012 RDS Terminal Server Session Powershell as admin

·         Colleague’s PC in-shop

·         Remote (my home) PC

 

Hopefully ruling out any location / PC / Software issues – these runs all had identical results.

 

 

First I used your example text from /api/#addingpassword: (adjusted my list, and removed $ from the password arbitrarily because I don’t like it..)

 

PS H:\> Invoke-Restmethod -Method Post -Uri https://passwordstate.com/api/passwords -ContentType "application/json; charset=utf-8" -Body '{

>>     "PasswordListID":"652",

>>     "Title":"North American Core Router 1",

>>     "UserName":"narouter1",

>>     "password":"StenS-Lun#32^yc",

>>     "APIKey":""

>> }

>> '

Invoke-Restmethod : [{"errors":[{"message":"Invalid API Call"},{"phrase":"Error = Object reference not set to an

instance of an object."}]}]

At line:1 char:1

+ Invoke-Restmethod -Method Post -Uri https://pws.wenetwork.com/api/pas ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc

   eption

    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

 

Then I did the $jsonBody method with my own data:

 

PS H:\> Invoke-Restmethod -Method Post -Uri https://passwordstate.com/api/passwords -ContentType "application/json; charset=utf-8" -Body '{

>>     "UserName":  "uname6",

>>     "Password":  "pass6",

>>     "APIKey":  "",

>>     "AccountType":  "93",

>>     "PasswordlistID":  "652",

>>     "Title":  "NoUrl",

>>     "URL":  ""

>> }'

Invoke-Restmethod : [{"errors":[{"message":"Invalid API Call"},{"phrase":"Error = Object reference not set to an

instance of an object."}]}]

At line:1 char:1

+ Invoke-Restmethod -Method Post -Uri https://pws.wenetwork.com/api/pas ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc

   eption

    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

 

Then I did the $body |  ConvertTo-Json  method: (changed the list ID in this one in case it was complaining about that list)

 

PS H:\> Invoke-Restmethod -Method Post -Uri https://passwordstate.com/api/passwords -ContentType "application/json; charset=utf-8" -Body '{

>>     "UserName":  "uname6",

>>     "Password":  "pass6",

>>     "APIKey":  "",

>>     "AccountType":  "93",

>>     "PasswordlistID":  "660",

>>     "Title":  "NoUrl",

>>     "URL":  ""

>> }'

Invoke-Restmethod : [{"errors":[{"message":"Invalid API Call"},{"phrase":"Error = Object reference not set to an

instance of an object."}]}]

At line:1 char:1

+ Invoke-Restmethod -Method Post -Uri https://pws.wenetwork.com/api/pas ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc

   eption

    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

 

The only difference I see between the three are subtle spacing issues in the position of the ‘:’  - worth noting that in my VisualStudioCode it sees that colon as an unexpected character if I paste the commands into a .ps1 there, but in a .json of course it’s fine… being json data,

 

Link to comment
Share on other sites

Eureka!

 

It fails going to my test list - which is ID 652 (tried 660 and a few others in that range previously)

 

In wondering if it's the list.. common denominator and whatnot.. I tried against an internal list with ID 30 and it succeeds.

 

More testing shows it fails on each try to a 3 digit list - I found ID 142 and it fails, but on ID 98 it succeeds.

 

I sent an email back with more details too.

 

Also, my script had one bug, in the $body creation I needed to change AccountType to AccountTypeID - then it worked and added all 3 good entries to list ID 30 as expected.

 

See your North American Core Router and my 3: AllAtrib, NoType,NoUrl from the script.

 

image.png.ede1baa3afd3dcff2c2550cbb6ee46ca.png

 

 

So it seems to me that the culprit is the 3 digit list IDs not being accepted.  Wish I'd have thought of that sooner.. I honestly thought it was something simple I was doing wrong.

 

Cheers!

-Grib

Link to comment
Share on other sites

OK it's been a long morning but I believe I have it nailed down -

 

I created a brand new list that mirrors my ListID 30 in every single way - ID 710 - and the test was successful.

I created a brand new list that mirrors those exactly except for a client remote site - and the test fails.

 

I subsequently went hunting for other 3 digit lists under Internal site and those all succeeded, regardless of template link or permissions, and all attempts for any remote site regardless of permissions and template link failed.

 

It just so happens that a majority of my 'internal' lists are 2 digits and the client ones are almost all 3 digits.. in fact I have one client with a 2 digit list only, and for grins I tried that one and it failed.

 

So - not a 3 digit problem - now appearing to be a Remote Site Location Problem.

 

I did try and add "SiteID":"4" to my json body like you use in /api/passwordlists and no luck..

 

I slowly read the documentation (I'm guilty of skimming most of the time) to see if there was mention of this and I didn't see it anywhere in the passwords section - I think it's implied that it should inherit site by the listID like when you add a new record in the webui.. but my new theory is that that is not working.

 

Can anyone corroborate?

 

Works for any list on 'Internal' Site - but not any of the lists tied to a remote site

$jsonData = '
    {
        "PasswordListID":"94",
        "Title": "North American Core Router 1",
        "UserName":"narouter1",
        "password":"StenS-Lun#3$2^yc",
        "APIKey":"putyourownglobalpapikeyhere"
    }
    '

$PasswordstateAPIURL = 'https://yourpwsinstance.com/api/passwords/'
$result = Invoke-Restmethod -Method Post -Uri $PasswordstateAPIURL -ContentType "application/json" -Body $jsonData
Write-Output $result #Return all properties of object(s)
Remove-Variable result

Cheers!

-Grib

 

Link to comment
Share on other sites

Hi Chris,

 

Thanks for your help, and patience, in trying to troubleshoot this, and we can confirm we see the same thing if the Password List is for a Remote Site Location. So we'll look into getting this fixed for the next release, and test all other methods as well to make sure there are no other issues.

Thanks again.

Regards

Click Studios

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...