Error Creating Resource via the Api in Golang

Hi,

Im having trouble creating a resource via the Api.

This is the Json i send:

{ 
                "name": "Test001",
                "description": "GoTestEntry",
                "secrets": [{
                  "user_id": "4d73053c-a01f-49b3-9203-9cffd522aecc",
                  "data": "-----BEGIN PGP MESSAGE-----
Comment: https://gopenpgp.org
Version: GopenPGP 0.0.1 (ddacebe0)

wcBMA1i15jHaQQryAQf8DbnbzN92yW3FCszc+0Rp09cQ9MqEccxcTqWnbm4pCbXc
pne3xJaUTiq0biDws/v6VpeEhbqdD8bURN/aGwz1gu5SLpaPnR7GBDC9ta1aY3kf
edohVM9VYUTxVsCKGRjS1A+3NfcrHHVqNMf7Kp3yuZIXX+e36wx9ZiTvDExqbenx
1S9T9xnyyktPNFyT1z61Aldq+QKS0P5bhVtcx5MGDcAMSTgYKi//q42Wew+GJl73
UkvtpgMcnwMzH/atK1hGlIl7lRq4zyEENhEkPXrpSBW+41NRRpbiXNoCUxtkn8qX
3J4HU2yox/qVOkzJfUQCECXFqTOEA5LyrzGP+0ZLW9LAowE+bHMA9rvEoNGFv0vW
VRqUn4zJnW+GV3AgnwR0hQKw/hKyv85AgO+HUH/Dzmpzi8Gld67fz8i679Th5byz
nM1lWk8HpwDyDaUlQRslTW3GlsNSefvlJwpJ8bl/5Ds83UMsbunwvgdMyPEn53KF
QT+uROTkl1KLizyVlQiNzbL4ja365fu/RiOhvXPeMb/nW/geVd4++5dIBgJKn/uB
HykCej45fGPk4pKilBAZlUAicujgRVnJxc9wQFOGZZBvX0oILyGPrrZ3s1j3PVVO
HOQuvWGNM5C/IFtEoy7WVcuEWn0po83YiCzY0qMJBCirkrSZihhhYzWmarFL8LWj
PSpc21dPq7/dIS8FovMSZfntTqG6eYPeSONoy6AVS/PI3APFlGY7DVEeiVnjO9Gz
dtQr5ZhnZLuOQHjsBf/IN5CMNTKW3eMD1ocYI8T/x/n5ZgDE66TPGYHbhVWMSzHN
ilt2OSU=
=i/iS
-----END PGP MESSAGE-----"
                }]
}

’ And i receive the following error:

{
  "header": {
    "id": "e30c7024-1a0c-47b6-9199-9379071a29ae",
    "status": "error",
    "servertime": 1586359272,
    "title": "app_resources_add_error",
    "action": "ad8bbc35-6435-538e-b1a7-80b87bcedb6a",
    "message": "Not Found",
    "url": "\\/resources.json?api-version=v2",
    "code": 400
  },
  "body": {
    "name": {
      "_required": "A name is required."
    },
    "secrets": {
      "_required": "A secret is required."
    }
  }
}

Do i have to do something specific to the message? And why is it telling me that i need a Name?
I have tried to send the PGP Message signed and unsigned with the same Error. The Api documentation is unclear about if it needs to be signed as it is mentioned for updating but not for creating.

-Sammy

Hello @Speatzle,

It looks like the API doesn’t detect any data.
Can you share with us the code you wrote?

Hi @cedric ,

Sure i can share my Go code. Please keep in mind that i just started working on this today and everything is just a proof of concept without any real error checking.

Here is the create Resource function:

func createResource(cookies []http.Cookie, name, password string) (string, error) {

    fmt.Println("Creating Resource...")

    myPubkey, myUserUUID, err := getCurrentUser(cookies)
    if err != nil {
        return "", err
    }

    encPassword, err := helper.EncryptMessageArmored(myPubkey, password)
    if err != nil {
        return "", err
    }

    jsonRequest := `{ 
        "name": "` + name + `",
        "description": "GoTestEntry",
        "secrets": [{
          "user_id": "` + myUserUUID + `",
          "data": "` + encPassword + `"
        }]
      }`
    fmt.Println("Json: ", jsonRequest)

    tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
    client := &http.Client{Transport: tr}

    req, err := http.NewRequest("POST", passboltURL+"/resources.json?api-version=v2", strings.NewReader(jsonRequest))
    if err != nil {
        return "", err
    }

    req.AddCookie(&cookies[0])
    req.AddCookie(&cookies[1])
    req.Header.Add("Content-Type", "application/json")
    req.Header.Add("X-CSRF-Token", cookies[1].Value)

    resp, err := client.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    bodyBytes, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    bodyString := string(bodyBytes)
    fmt.Println(bodyString)

    apires := apiResponse{}
    err = json.Unmarshal(bodyBytes, &apires)
    if err != nil {
        return "", err
    }

    return apires.Body.ResourceID, nil
}

So i have figured out why did didn’t work, the PGP Messages are essentailly base64 encoded bytes and for some reason passbolt doesn’t like some of the character in the base64 string which breaks its JSON parsing. For both the Golang and JS JSON parsers this wasn’t an issue, but this issue can be resolved for passbolt if the PGP Message gets URL escaped by the JSON library on the client side.

But more importantly while looking at the doc for password sharing via the API i noticed that it is impossible to use by employing standart JSON Libraries if the doc is correct.

The doc states that the permissions look like this for sharing:

"permissions": [
    {
      "is_new": true,
      "aro": "Group",
      "aro_foreign_key": "36563004-3f25-50c0-b22e-6554c3ccc4e7",
      "aco": "Resource",
      "aco_foreign_key": "8e3874ae-4b40-590b-968a-418f704b9d9a",
      "type": 7
    }],

How is it possible that 2 fields have the same Name? No normal JSON Library parses this.
The best i could come up with is renaming the second instance of a field before parsing and then rename it back after marshalling.
Can somebody explain to me how this is supposed to be used?

-Sammy

Hello,

How is it possible that 2 fields have the same Name?

Which fields have the same name? There is aRo (groups, users) and aCo (resources, folders, etc).

  • ACO - Access Control Object - Represents something that is wanted
  • ARO - Access Request Object - Represents something that wants something else

Signature on OpenPGP messages are not enforced at this stage, but this will become an option this year, so it’s best to send signed messages now, you’ll be rewarded later. Historically this was a performance trade-off, as user are already authenticated, but we want to go there.

Hi,
sorry I guess i was just to tired yesterday and misread.

So currently ACO’s are always resources? And when folders are released they will also be ACO’s? In that case: What happens if a user has access to a resource but not to the folder the resource is in?

In the API ARO’s and ACO’s are explained in such a way that it seemes like they are Actual objects (maybe a table to map id’s for foreign keys) and not just the id’s of users, groups, Resources and folders. The fact that there is even an endpoint to get ARO’s even thou you can just query for all users and then for all groups and get the same thing makes it even more confusing.

On a other note. When i login via the API. I get the ‘CAKEPHP’ cookie and to do any action that changes something on the passbolt side i also need the ‘csrfToken’ that i can get as a cookie by doing a request to any endpoint that gives me data. Why do i not get the csrfToken during login? Also the ‘CAKEPHP’ cookie. Which is basically your session? Is not mentioned in the API documentation(https://help.passbolt.com/api/authentication) at all. You only talk about the csrfToken.

And lastly. How do i logout via the API? How can i tell the server to make my current session invalid?

-Sammy

Yes currently ACO are always resources. Folders will be ACOs also. Maybe we will introduce more ACOs in the future (reports, files, etc.).

Long story short the resource from the perspective of the user that do not have access to the folder will not be seen as being in a folder. They will be able to move them in one of their own folders. The people who have access will be able to see the folder and the resource in it. It works similarly than google doc (with some differences on how we will handle the numerous edge cases). This is why this feature is taking a lot of time for us to develop.

The CSRF token is to prevent an attacker from sending the user from a third party domain to passbolt and perform an unwanted action. It’s not needed for the login, because the user is not authenticated at that time, so there is no “unwanted action” with meaningful consequences that an attacker can perform.

Yes it’s the session. It’s not mentioned in the doc but it should. We expect the client to behave like a web browser and manage the session / cookies itself, but it should be more explicit I agree.

You can do a GET /auth/logout.

Thank you for your detailed reply.

By

I actually meant to ask why i don’t get the csrfToken at the same time as i get the CAKEPHP session(As soon as im logged in). Right now i have to do an arbitrary read to some endpoint to actually get it.

It’s an implementation detail I think rather than a design choice. Your request makes sense though, i’ll try to squeeze this in the next release or so.

Hi again,
My Passbolt API library is now usable enough to integrate into my current Project at work. But sadly folders aren’t released yet. This is a big deal for us as we are going to automatically generate lots of passwords via the API for assets we manage and sort them based on customer and location. If i where to do this with tags that would spam the global tag list in our Passbolt instance very quickly resulting in a big mess as you cannot search resources by tags(only filter) and you cannot search for tags themselves. This is not a problem if folders are used as we could just fold down the top level folder of this Project and still be able to use Passbolt for other things without having to hunt through hundreds of tags.

So ill ask if you can give me a rough time frame as to when folders will be released. Depending on your answer i can push back this feature and work on other features till the time comes or i may have to think of something completely different.

-Sammy

Hi @Speatzle as mentioned elsewhere we stopped giving timelines for upcoming features as it often backfires. This is our main focus at the moment, but it’s by far more complicated than we anticipated. We are aiming at a release candidate end of the month, early next month and stable release after that.

End of the month sounds good. But how do release candidate work for the pro version? And where do i look for downloads / update procedures?

-Sammy

When it is ready we’ll be announcing it on the release page and on twitter as well. The release will be available on dedicated branch on git (develop or similar), with instructions on how to test and report issues.