From ced16f247900fdc1913358a275455e93280bb28c Mon Sep 17 00:00:00 2001 From: lenforiee Date: Wed, 19 Apr 2023 21:17:57 +0200 Subject: [PATCH 1/4] infinit -> infinite --- api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.go b/api/api.go index 96a0f41..b2958c4 100644 --- a/api/api.go +++ b/api/api.go @@ -64,7 +64,7 @@ start: } else if res.Header.Status == "error" { if res.Header.Code == 403 && res.Header.URL == "/mfa/verify/error.json" { if !firstTime { - // if we are here this probably means that the MFA callback is broken, to prevent a infinit loop lets error here + // if we are here this probably means that the MFA callback is broken, to prevent a infinite loop lets error here return r, &res, fmt.Errorf("Got MFA challenge twice in a row, is your MFA Callback broken? Bailing to prevent loop...:") } if c.MFACallback != nil { From fd895a9d46ed99469b39f7debf32faf0919debc2 Mon Sep 17 00:00:00 2001 From: lenforiee Date: Wed, 19 Apr 2023 21:24:12 +0200 Subject: [PATCH 2/4] challange -> challenge --- README.md | 32 +++++++++++++++++--------------- api/api.go | 4 ++-- api/client.go | 2 +- api/mfa.go | 4 ++-- api/verify.go | 4 ++-- helper/mfa.go | 14 +++++++------- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index ea15790..0ffc1fe 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # go-passbolt + [![Go Reference](https://pkg.go.dev/badge/github.com/passbolt/go-passbolt.svg)](https://pkg.go.dev/github.com/passbolt/go-passbolt) A Go module to interact with [Passbolt](https://www.passbolt.com/), an open-source password manager for teams @@ -7,11 +8,11 @@ There also is a CLI Tool to interact with Passbolt using this module [here](http This 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) -This module is divided into two packages: API and helper. +This module is divided into two packages: API and helper. -In the API package, you will find everything to directly interact with the API. +In the API package, you will find everything to directly interact with the API. -The helper package has simplified functions that use the API package to perform common but complicated tasks such as sharing a password. +The helper package has simplified functions that use the API package to perform common but complicated tasks such as sharing a password. To 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. @@ -19,12 +20,12 @@ PR's are welcome. But be gentle: if it's something bigger or fundamental: please Disclaimer: This project is community driven and not associated with Passbolt SA - # Install `go get github.com/passbolt/go-passbolt` # Examples + ## Login First, you will need to create a client and then log in on the server using the client: @@ -214,24 +215,25 @@ err = helper.UpdateUser( "lastname", // LastName ) ``` + Note: These helpers will only update fields that are not "". Helper update functions also exists for Folders. ## Sharing -As sharing resources is very complicated there are multiple helper functions. +As sharing resources is very complicated there are multiple helper functions. During sharing you will encounter the [permission type](https://github.com/passbolt/passbolt_api/blob/858971516c5e61e1f1be37b007693f0869a70486/src/Model/Entity/Permission.php#L43-L45). The `permissionType` can be: -| Code | Meaning | -| --- | --- | -| `1` | "Read-only" | -| `7` | "Can update" | -| `15` | "Owner" | -| `-1` | Delete existing permission | +| Code | Meaning | +| ---- | -------------------------- | +| `1` | "Read-only" | +| `7` | "Can update" | +| `15` | "Owner" | +| `-1` | Delete existing permission | The `ShareResourceWithUsersAndGroups` function shares the resource with all provided users and groups with the given `permissionType`. @@ -294,6 +296,7 @@ err := client.MoveFolder(ctx, "folder id", "parent folder id") ## Setup You can setup a Account using a Invite Link like this: + ```go // Get the UserID and Token from the Invite Link userID, token, err := ParseInviteUrl(url) @@ -307,7 +310,7 @@ privkey, err := SetupAccount(ctx, rClient, userID, token, "password123") ## Verification -You 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. +You 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. ```go // Setup the Verification @@ -327,18 +330,17 @@ if err != nil { ## MFA -go-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 challanges. 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`. +go-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`. ## Other These 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. - ## Full Example This example: -1. Creates a resource; +1. Creates a resource; 2. Searches for a user named "Test User"; 3. Checks that it's not itself; and, 4. Shares the password with the "Test User" if necessary: diff --git a/api/api.go b/api/api.go index b2958c4..baba63e 100644 --- a/api/api.go +++ b/api/api.go @@ -72,11 +72,11 @@ start: if err != nil { return r, &res, fmt.Errorf("MFA Callback: %w", err) } - // ok, we got the MFA challange and the callback presumably handeld it so we can retry the original request + // ok, we got the MFA challenge and the callback presumably handeld it so we can retry the original request firstTime = false goto start } else { - return r, &res, fmt.Errorf("Got MFA Challange but the MFA callback is not defined") + return r, &res, fmt.Errorf("Got MFA Challenge but the MFA callback is not defined") } } return r, &res, fmt.Errorf("%w: Message: %v, Body: %v", ErrAPIResponseErrorStatusCode, res.Header.Message, string(res.Body)) diff --git a/api/client.go b/api/client.go index 150d0c7..e08609f 100644 --- a/api/client.go +++ b/api/client.go @@ -31,7 +31,7 @@ type Client struct { userPublicKey string userID string - // used for solving MFA challanges. You can block this to for example wait for user input. + // used for solving MFA challenges. You can block this to for example wait for user input. // You shouden't run any unrelated API Calls while you are in this callback. // You need to Return the Cookie that Passbolt expects to verify you MFA, usually it is called passbolt_mfa MFACallback func(ctx context.Context, c *Client, res *APIResponse) (http.Cookie, error) diff --git a/api/mfa.go b/api/mfa.go index 113e3d3..ceffe22 100644 --- a/api/mfa.go +++ b/api/mfa.go @@ -1,6 +1,6 @@ package api -type MFAChallange struct { +type MFAChallenge struct { Provider MFAProviders `json:"providers,omitempty"` } @@ -8,6 +8,6 @@ type MFAProviders struct { TOTP string `json:"totp,omitempty"` } -type MFAChallangeResponse struct { +type MFAChallengeResponse struct { TOTP string `json:"totp,omitempty"` } diff --git a/api/verify.go b/api/verify.go index b8d42d4..89a15b8 100644 --- a/api/verify.go +++ b/api/verify.go @@ -33,7 +33,7 @@ func (c *Client) SetupServerVerification(ctx context.Context) (string, string, e token := "gpgauthv1.3.0|36|" + uuid.String() + "|gpgauthv1.3.0" encToken, err := c.EncryptMessageWithPublicKey(serverKey, token) if err != nil { - return "", "", fmt.Errorf("Encrypting Challange: %w", err) + return "", "", fmt.Errorf("Encrypting Challenge: %w", err) } err = c.VerifyServer(ctx, token, encToken) if err != nil { @@ -57,7 +57,7 @@ func (c *Client) VerifyServer(ctx context.Context, token, encToken string) error } raw, _, err := c.DoCustomRequestAndReturnRawResponse(ctx, "POST", "/auth/verify.json", "v2", data, nil) if err != nil && !strings.Contains(err.Error(), "The authentication failed.") { - return fmt.Errorf("Sending Verification Challange: %w", err) + return fmt.Errorf("Sending Verification Challenge: %w", err) } if raw.Header.Get("X-GPGAuth-Verify-Response") != token { diff --git a/helper/mfa.go b/helper/mfa.go index 0c834c2..6f553aa 100644 --- a/helper/mfa.go +++ b/helper/mfa.go @@ -14,12 +14,12 @@ import ( // AddMFACallbackTOTP adds a MFA callback to the client that generates OTP Codes on demand using a Token with configurable retries and delay func AddMFACallbackTOTP(c *api.Client, retrys uint, retryDelay, offset time.Duration, token string) { c.MFACallback = func(ctx context.Context, c *api.Client, res *api.APIResponse) (http.Cookie, error) { - challange := api.MFAChallange{} - err := json.Unmarshal(res.Body, &challange) + challenge := api.MFAChallenge{} + err := json.Unmarshal(res.Body, &challenge) if err != nil { - return http.Cookie{}, fmt.Errorf("Parsing MFA Challange") + return http.Cookie{}, fmt.Errorf("Parsing MFA Challenge") } - if challange.Provider.TOTP == "" { + if challenge.Provider.TOTP == "" { return http.Cookie{}, fmt.Errorf("Server Provided no TOTP Provider") } for i := uint(0); i < retrys+1; i++ { @@ -28,14 +28,14 @@ func AddMFACallbackTOTP(c *api.Client, retrys uint, retryDelay, offset time.Dura if err != nil { return http.Cookie{}, fmt.Errorf("Error Generating MFA Code: %w", err) } - req := api.MFAChallangeResponse{ + req := api.MFAChallengeResponse{ TOTP: code, } var raw *http.Response raw, _, err = c.DoCustomRequestAndReturnRawResponse(ctx, "POST", "mfa/verify/totp.json", "v2", req, nil) if err != nil { if errors.Unwrap(err) != api.ErrAPIResponseErrorStatusCode { - return http.Cookie{}, fmt.Errorf("Doing MFA Challange Response: %w", err) + return http.Cookie{}, fmt.Errorf("Doing MFA Challenge Response: %w", err) } // MFA failed, so lets wait just let the loop try again time.Sleep(retryDelay) @@ -49,6 +49,6 @@ func AddMFACallbackTOTP(c *api.Client, retrys uint, retryDelay, offset time.Dura return http.Cookie{}, fmt.Errorf("Unable to find Passbolt MFA Cookie") } } - return http.Cookie{}, fmt.Errorf("Failed MFA Challange 3 times: %w", err) + return http.Cookie{}, fmt.Errorf("Failed MFA Challenge 3 times: %w", err) } } From a86ae886f2a7eaa8c7dfb12782658b0abd70227c Mon Sep 17 00:00:00 2001 From: lenforiee Date: Wed, 19 Apr 2023 21:24:53 +0200 Subject: [PATCH 3/4] handeld -> handled --- api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.go b/api/api.go index baba63e..b45148f 100644 --- a/api/api.go +++ b/api/api.go @@ -72,7 +72,7 @@ start: if err != nil { return r, &res, fmt.Errorf("MFA Callback: %w", err) } - // ok, we got the MFA challenge and the callback presumably handeld it so we can retry the original request + // ok, we got the MFA challenge and the callback presumably handled it so we can retry the original request firstTime = false goto start } else { From 1b178b66345eed6ef660f6eec5cbafda2adbed4c Mon Sep 17 00:00:00 2001 From: lenforiee Date: Wed, 19 Apr 2023 21:25:44 +0200 Subject: [PATCH 4/4] containes -> contains --- helper/group.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper/group.go b/helper/group.go index 329be41..fa70ca2 100644 --- a/helper/group.go +++ b/helper/group.go @@ -14,7 +14,7 @@ type GroupMembershipOperation struct { Delete bool } -// GroupMembership containes who and what kind of membership they have with a group +// GroupMembership contains who and what kind of membership they have with a group type GroupMembership struct { UserID string Username string