{"id":19879981,"url":"https://github.com/passbolt/go-passbolt","last_synced_at":"2025-05-02T13:31:55.448Z","repository":{"id":42082409,"uuid":"401305925","full_name":"passbolt/go-passbolt","owner":"passbolt","description":"A Go Library to interact with Passbolt, the open source password manager for teams!","archived":false,"fork":false,"pushed_at":"2024-08-13T10:00:53.000Z","size":120,"stargazers_count":24,"open_issues_count":2,"forks_count":7,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-08-14T11:06:51.477Z","etag":null,"topics":["go","golang","passbolt"],"latest_commit_sha":null,"homepage":"https://passbolt.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/passbolt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-30T10:38:51.000Z","updated_at":"2024-08-13T09:58:52.000Z","dependencies_parsed_at":"2023-11-24T11:28:46.778Z","dependency_job_id":"8ac0bd3c-1b0c-4941-8b18-e5b523b80a10","html_url":"https://github.com/passbolt/go-passbolt","commit_stats":null,"previous_names":["speatzle/go-passbolt"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/passbolt%2Fgo-passbolt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/passbolt%2Fgo-passbolt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/passbolt%2Fgo-passbolt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/passbolt%2Fgo-passbolt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/passbolt","download_url":"https://codeload.github.com/passbolt/go-passbolt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224315249,"owners_count":17290992,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","passbolt"],"created_at":"2024-11-12T17:09:55.149Z","updated_at":"2024-11-12T17:09:55.619Z","avatar_url":"https://github.com/passbolt.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-passbolt\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/passbolt/go-passbolt.svg)](https://pkg.go.dev/github.com/passbolt/go-passbolt)\n\nA Go module to interact with [Passbolt](https://www.passbolt.com/), an open-source password manager for teams\n\nThere also is a CLI Tool to interact with Passbolt using this module [here](https://github.com/passbolt/go-passbolt-cli).\n\nThis module tries to support the latest Passbolt Community/PRO server release, PRO Features such as folders are supported. Older versions of Passbolt such as v2 are unsupported (it's a password manager, please update it)\n\nThis module is divided into two packages: API and helper.\n\nIn the API package, you will find everything to directly interact with the API.\n\nThe helper package has simplified functions that use the API package to perform common but complicated tasks such as sharing a password.\n\nTo use the API package, please read the [Passbolt API docs](https://help.passbolt.com/api). Sadly the docs aren't complete so many things here have been found by looking at the source of Passbolt or through trial and error. If you have a question just ask.\n\nPR's are welcome. But be gentle: if it's something bigger or fundamental: please [create an issue](https://github.com/passbolt/go-passbolt/issues/new) and ask first.\n\nDisclaimer: This project is community driven and not associated with Passbolt SA\n\n# Install\n\n`go get github.com/passbolt/go-passbolt`\n\n# Examples\n\n## Login\n\nFirst, you will need to create a client and then log in on the server using the client:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/passbolt/go-passbolt/api\"\n)\n\nconst address = \"https://passbolt.example.com\"\nconst userPassword = \"aStrongPassword\"\nconst userPrivateKey = `\n-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: OpenPGP.js v4.6.2\nComment: https://openpgpjs.org\nklasd...\n-----END PGP PRIVATE KEY BLOCK-----`\n\nfunc main() {\n\tclient, err := api.NewClient(nil, \"\", address, userPrivateKey, userPassword)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n    \tctx := context.TODO()\n\n\terr = client.Login(ctx)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(\"Logged in!\")\n}\n```\n\nNote: if you want to use the client for a long time then you'll have to make sure it is still logged in.\n\nYou can do this using the `client.CheckSession()` function.\n\n## Create a Resource\n\nCreating a resource using the helper package is simple. First, add `\"github.com/passbolt/go-passbolt/helper\"` to your imports.\n\nThen you can simply:\n\n```go\nresourceID, err := helper.CreateResource(\n\tctx,                        // Context\n\tclient,                     // API Client\n\t\"\",                         // ID of Parent Folder (PRO only)\n\t\"Example Account\",          // Name\n\t\"user123\",                  // Username\n\t\"https://test.example.com\", // URI\n\t\"securePassword123\",        // Password\n\t\"This is an Account for the example test portal\", // Description\n)\n```\n\nCreating a (legacy) resource without the helper package would look like this:\n\n```go\nenc, err := client.EncryptMessage(\"securePassword123\")\nif err != nil {\n\tpanic(err)\n}\n\nres := api.Resource{\n\tName:           \"Example Account\",\n\tUsername:       \"user123\",\n\tURI:            \"https://test.example.com\",\n\tDescription:    \"This is an Account for the example test portal\",\n\tSecrets: []api.Secret{\n\t\t{Data: enc},\n\t},\n}\n\nresource, err := client.CreateResource(ctx, res)\nif err != nil {\n\tpanic(err)\n}\n```\n\nNote: Since Passbolt v3 there are resource types. This manual example creates a \"password-string\" type password where the description is unencrypted. Read more [here](https://help.passbolt.com/api/resource-types).\n\n## Getting\n\nGenerally, API GET calls will have parameters that allow specifying `filters` and `contains`, if you don't want to define those parameters just pass nil.\n\n`Filters` just filter by whatever is given, `contains` on the other hand specify what information you want to include in the response. Many `filters` and `contains` are undocumented in the Passbolt docs.\n\nHere we specify that we want to filter by favorites and that the response should contain the permissions for each resource:\n\n```go\nfavorites, err := client.GetResources(ctx, \u0026api.GetResourcesOptions{\n\tFilterIsFavorite: true,\n    ContainPermissions: true,\n})\n```\n\nWe can do the same for users:\n\n```go\nusers, err := client.GetUsers(ctx, \u0026api.GetUsersOptions{\n\tFilterSearch:        \"Samuel\",\n\tContainLastLoggedIn: true,\n})\n```\n\nGroups:\n\n```go\ngroups, err := client.GetGroups(ctx, \u0026api.GetGroupsOptions{\n    FilterHasUsers: []string{\"id of user\", \"id of other user\"},\n\tContainUser: true,\n})\n```\n\nAnd also for folders (PRO only):\n\n```go\nfolders, err := client.GetFolders(ctx, \u0026api.GetFolderOptions{\n\tFilterSearch:             \"Test Folder\",\n\tContainChildrenResources: true,\n})\n```\n\nGetting by ID is also supported using the singular form:\n\n```go\nresource, err := client.GetResource(ctx, \"resource ID\")\n```\n\nSince the password is encrypted (and sometimes the description too) the helper package has a function to decrypt all encrypted fields automatically:\n\n```go\nfolderParentID, name, username, uri, password, description, err := helper.GetResource(ctx, client, \"resource id\")\n```\n\n## Updating\n\nThe helper package has a function to save you from dealing with resource types when updating a resource:\n\n```go\nerr = helper.UpdateResource(\n\tctx,           // Context\n\tclient,        // API Client\n\t\"id\",          // Resource ID\n\t\"name\",        // Name\n\t\"username\",    // Username\n\t\"url\",         // URI\n\t\"strong\",      // Password\n\t\"very strong\", // Description\n)\n```\n\nThe same goes for Groups:\n\n```go\nerr = helper.UpdateGroup(\n\tctx,    // Context\n\tclient, // API Client\n\t\"id\",   // Group ID\n\t\"name\", // Group Name\n\t[]helper.GroupMembershipOperation{\n\t\t{\n\t\t\tUserID:         \"id\",  // ID of User to Add/Modify/Delete\n\t\t\tIsGroupManager: true,  // Should User be a Group Manager\n\t\t\tDelete:         false, // Should this User be Remove from the Group\n\t\t},\n\t}\n)\n```\n\nAnd for Users:\n\n```go\nerr = helper.UpdateUser(\n\tctx,         // Context\n\tclient,      // API Client\n\t\"id\",        // User ID\n\t\"user\",      // Role (user or admin)\n\t\"firstname\", // FirstName\n\t\"lastname\",  // LastName\n)\n```\n\nNote: These helpers will only update fields that are not \"\".\n\nHelper update functions also exists for Folders.\n\n## Sharing\n\nAs sharing resources is very complicated there are multiple helper functions.\n\nDuring sharing you will encounter the [permission type](https://github.com/passbolt/passbolt_api/blob/858971516c5e61e1f1be37b007693f0869a70486/src/Model/Entity/Permission.php#L43-L45).\n\nThe `permissionType` can be:\n\n| Code | Meaning                    |\n| ---- | -------------------------- |\n| `1`  | \"Read-only\"                |\n| `7`  | \"Can update\"               |\n| `15` | \"Owner\"                    |\n| `-1` | Delete existing permission |\n\nThe `ShareResourceWithUsersAndGroups` function shares the resource with all provided users and groups with the given `permissionType`.\n\n```go\nerr := helper.ShareResourceWithUsersAndGroups(ctx, client, \"resource id\", []string{\"user 1 id\"}, []string{\"group 1 id\"}, 7)\n```\n\nNote: Existing permission of users and groups will be adjusted to be of the provided `permissionType`.\n\nIf you need to do something more complicated like setting users/groups to different types then you can use `ShareResource` directly:\n\n```go\nchanges := []helper.ShareOperation{}\n\n// Make this user Owner\nchanges = append(changes, ShareOperation{\n\tType:  15,\n\tARO:   \"User\",\n\tAROID: \"user 1 id\",\n})\n\n// Make this user \"Can Update\"\nchanges = append(changes, ShareOperation{\n\tType:  5,\n\tARO:   \"User\",\n\tAROID: \"user 2 id\",\n})\n\n// Delete this users current permission\nchanges = append(changes, ShareOperation{\n\tType:  -1,\n\tARO:   \"User\",\n\tAROID: \"user 3 id\",\n})\n\n// Make this group \"Read-only\"\nchanges = append(changes, ShareOperation{\n\tType:  1,\n\tARO:   \"Group\",\n\tAROID: \"group 1 id\",\n})\n\nerr := helper.ShareResource(ctx, c, resourceID, changes)\n```\n\nNote: These functions are also available for folders (PRO)\n\n## Moving (PRO)\n\nIn Passbolt PRO there are folders, during the creation of resources and folders you can specify in which folder you want to create the resource/folder inside. But if you want to change which folder the resource/folder is in then you can't use the `Update` function (it is/was possible to update the parent folder using the `Update` function but that breaks things). Instead, you use the `Move` function.\n\n```go\nerr := client.MoveResource(ctx, \"resource id\", \"parent folder id\")\n```\n\n```go\nerr := client.MoveFolder(ctx, \"folder id\", \"parent folder id\")\n```\n\n## Setup\n\nYou can setup a Account using a Invite Link like this:\n\n```go\n// Get the UserID and Token from the Invite Link\nuserID, token, err := ParseInviteUrl(url)\n\n// Make a Client for Registration\nrClient, err := api.NewClient(nil, \"\", \"https://localhost\", \"\", \"\")\n\n// Complete Account Setup\nprivkey, err := SetupAccount(ctx, rClient, userID, token, \"password123\")\n```\n\n## Verification\n\nYou can Verify that the Server hasen't changed, for that you need to initially setup the Verification and save the returned values. Then you can Verify that the serverkey hasen't changed since you setup the Verification. Note this Only Works if the client is not logged in.\n\n```go\n// Setup the Verification\ntoken, encToken, err := client.SetupServerVerification(ctx)\nif err != nil {\n\tpanic(err)\n}\n// You Need to save these\nfmt.Println(\"Token: \", token)\nfmt.Println(\"enc Token: \", encToken)\n// Now you can Verify the Server\nerr = client.VerifyServer(ctx, token, encToken)\nif err != nil {\n\tpanic(err)\n}\n```\n\n## MFA\n\ngo-passbolt now supports MFA! You can set it up using the Client's `MFACallback` function, it will provide everything you need to complete any MFA challenges. When your done you just need to return the new MFA Cookie (usually called passbolt_mfa). The helper package has a example implementation for a noninteractive TOTP Setup under helper/mfa.go in the function `AddMFACallbackTOTP`.\n\n## Other\n\nThese examples are just the main use cases of these Modules, many more API calls are supported. Look at the [reference](https://pkg.go.dev/github.com/passbolt/go-passbolt) for more information.\n\n## Full Example\n\nThis example:\n\n1. Creates a resource;\n2. Searches for a user named \"Test User\";\n3. Checks that it's not itself; and,\n4. Shares the password with the \"Test User\" if necessary:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/passbolt/go-passbolt/api\"\n\t\"github.com/passbolt/go-passbolt/helper\"\n)\n\nconst address = \"https://passbolt.example.com\"\nconst userPassword = \"aStrongPassword\"\nconst userPrivateKey = `\n-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: OpenPGP.js v4.6.2\nComment: https://openpgpjs.org\nklasd...\n-----END PGP PRIVATE KEY BLOCK-----`\n\nfunc main() {\n\tctx := context.TODO()\n\n\tclient, err := api.NewClient(nil, \"\", address, userPrivateKey, userPassword)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\terr = client.Login(ctx)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(\"Logged in!\")\n\n\tresourceID, err := helper.CreateResource(\n\t\tctx,                        // Context\n\t\tclient,                     // API Client\n\t\t\"\",                         // ID of Parent Folder (PRO only)\n\t\t\"Example Account\",          // Name\n\t\t\"user123\",                  // Username\n\t\t\"https://test.example.com\", // URI\n\t\t\"securePassword123\",        // Password\n\t\t\"This is an Account for the example test portal\", // Description\n\t)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(\"Created Resource\")\n\n\tusers, err := client.GetUsers(ctx, \u0026api.GetUsersOptions{\n\t\tFilterSearch: \"Test User\",\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tif len(users) == 0 {\n\t\tpanic(\"Cannot Find Test User\")\n\t}\n\n\tif client.GetUserID() == users[0].ID {\n\t\tfmt.Println(\"I am the Test User, No Need to Share Password With myself\")\n        \tclient.Logout(ctx)\n\t\treturn\n\t}\n\n\thelper.ShareResourceWithUsersAndGroups(ctx, client, resourceID, []string{users[0].ID}, []string{}, 7)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Shared Resource With Test User %v\\n\", users[0].ID)\n\n    \tclient.Logout(ctx)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpassbolt%2Fgo-passbolt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpassbolt%2Fgo-passbolt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpassbolt%2Fgo-passbolt/lists"}