From 6070bf3cf485ce0f6ecb78ee162ee2659204f22a Mon Sep 17 00:00:00 2001 From: Paul Mairo Date: Tue, 28 May 2024 11:17:41 +0200 Subject: [PATCH 1/2] Fix typos and improve readability --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8ac580b..87ad5c5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # go-passbolt-cli A CLI tool to interact with Passbolt, an Open source Password Manager for teams. -If you want to do something more complicated: [this Go Module](https://github.com/passbolt/go-passbolt) to Interact with Passbolt from Go might intrest you. +If you want to do something more complicated: [this Go Module](https://github.com/passbolt/go-passbolt) to Interact with Passbolt from Go might interest you. -Disclaimer: This project is community driven and not associated with Passbolt SA +Disclaimer: This project is community-driven and not associated with Passbolt SA # Install ## Via Package (Prefered): @@ -23,7 +23,7 @@ Note: tab completion and manpages will need to be installed manually. Note: this will install the binary as go-passbolt-cli, also tab completion and manpages will be missing. # Getting Started -First you need to Setup basic information: the Server Address, your Private Key and your Password. +First, you need to set up basic information: the Server Address, your Private Key, and your Password. You have these options: - Save it in the config file using ``` @@ -38,23 +38,23 @@ passbolt configure --serverAddress https://passbolt.example.org --userPassword ' Notes: - You can set the Private Key using the flags `--userPrivateKey` or `--userPrivateKeyFile` where `--userPrivateKey` takes the actual private key and `--userPrivateKeyFile` loads the content of a file as the PrivateKey, `--userPrivateKeyFile` overwrites the value of `--userPrivateKey`. -- You can also just store the serverAddress and your Private Key, if your Password is not set it will prompt you for it every time. +- You can also just store the serverAddress and your Private Key, if your Password is not set, it will prompt you for it every time. - Passwordless PrivateKeys are unsupported -- MFA settings can also be save permanently this ways +- MFA settings can also be saved permanently these ways # Usage -Generally the Structure of Commands is like this: +Generally, the Structure of Commands is like this: ```bash passbolt action entity [arguments] ``` -Action is the Action you want to perform like Creating, Updating or Deleting an Entity. +Action is the Action you want to perform, like Creating, Updating, or Deleting an Entity. Entity is a Resource(Password), Folder, User or Group that you want to apply an action to. -In Passbolt a Password is usually revert to as a Resource. +In Passbolt, a Password is usually referred to as a Resource. -To Create a Resource you can do this, it will return the ID of the newly created Resource: +To Create a Resource, you can do this. It will return the ID of the newly created Resource: ```bash passbolt create resource --name "Test Resource" --password "Strong Password" ``` @@ -63,10 +63,10 @@ You can then list all users: ```bash passbolt list user ``` -Note: you can adjust which columns should be listed using the flag `--column` or its short from `-c`, if you want multiple column then you need to specify this flag multiple times. +Note: you can adjust which columns should be listed using the flag `--column` or its short from `-c`, if you want multiple columns then you need to specify this flag multiple times. -For sharing we will need to know how we want to share, for that there are these Permission Types: +For sharing, we will need to know how we want to share. For that, there are these Permission Types: | Code | Meaning | | --- | --- | @@ -75,32 +75,32 @@ For sharing we will need to know how we want to share, for that there are these | `15` | "Owner" | | `-1` | Delete existing permission | -Now that we have a Resource ID, know the ID's of other Users and about know about Permission Types, we can share the Resource with them: +Now that we have a Resource ID, know the ID's of other Users and know about Permission Types, we can share the Resource with them: ```bash passbolt share resource --id id_of_resource_to_share --type type_of_permission --user id_of_user_to_share_with ``` -Note: you can supply the the users argument multiple times to share with multiple users +Note: you can supply the `user` argument multiple times to share with multiple users -For sharing with groups the `--group` argument exists. +For sharing with groups, the `--group` argument exists. # MFA -You can setup MFA also using the configuration sub command, only TOTP is supported, there are multiple modes for MFA: `none`, `interactive-totp` and `noninteractive-totp`. +You can also set up MFA using the configuration subcommand. Only TOTP is supported, and there are multiple modes for MFA: `none`, `interactive-totp`, and `noninteractive-totp`. | Mode | Description | | --- | --- | |`none`|just errors if challenged for MFA. |`interactive-totp` | prompts for interactive entry of TOTP Codes. -|`noninteractive-totp` | automatically generates TOTP Codes when challenged, it requires the `mfaTotpToken` flag to be set to your totp Secret, you can configure the behavior using the `mfaDelay`, `mfaRetrys` and `mfaTotpOffset` flags +|`noninteractive-totp` | automatically generates TOTP Codes when challenged. It requires the `mfaTotpToken` flag to be set to your totp Secret, you can configure the behavior using the `mfaDelay`, `mfaRetrys` and `mfaTotpOffset` flags # Server Verification -To enable Server Verification you need to run `passbolt verify` once, after that the server will always be verified if the same config is used +To enable Server Verification, you need to run `passbolt verify` once. After that, the server will always be verified if the same config is used # Scripting -For Scripting we have a -j or --json flag to convert the Output for the create, get and list commands to JSON for easier Parsing in Scripts. +For Scripting, we have a -j or --json flag to convert the Output for the create, get and list commands to JSON for easier Parsing in Scripts. -Note: The JSON Output does not cover Error Messages, you can detect Errors by checking if the Exitcode is not 0 +Note: The JSON Output does not cover Error Messages. You can detect Errors by checking if the Exitcode is not 0 # Documentation Usage for all Subcommands is [here](https://github.com/passbolt/go-passbolt-cli/wiki/passbolt). -And is also available via `man passbolt` +It is also available via `man passbolt` From 9b2d47fecdbe33808ac539eee07acdde6a5988de Mon Sep 17 00:00:00 2001 From: Filipe Roque Date: Sat, 10 Aug 2024 01:08:44 +0100 Subject: [PATCH 2/2] Adds permission subcommand to get a list of permissions of a resource --- resource/get.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++ resource/json.go | 11 +++++ 2 files changed, 116 insertions(+) diff --git a/resource/get.go b/resource/get.go index 9147280..d27234b 100644 --- a/resource/get.go +++ b/resource/get.go @@ -4,10 +4,14 @@ import ( "context" "encoding/json" "fmt" + "strconv" + "strings" + "time" "github.com/alessio/shellescape" "github.com/passbolt/go-passbolt-cli/util" "github.com/passbolt/go-passbolt/helper" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -19,10 +23,24 @@ var ResourceGetCmd = &cobra.Command{ RunE: ResourceGet, } +// ResourcePermissionCmd Gets Permissions for Passbolt Resource +var ResourcePermissionCmd = &cobra.Command{ + Use: "permission", + Short: "Gets Permissions for a Passbolt Resource", + Long: `Gets Permissions for a Passbolt Resource`, + Aliases: []string{"permissions"}, + RunE: ResourcePermission, +} + func init() { ResourceGetCmd.Flags().String("id", "", "id of Resource to Get") ResourceGetCmd.MarkFlagRequired("id") + + ResourceGetCmd.AddCommand(ResourcePermissionCmd) + ResourcePermissionCmd.Flags().String("id", "", "id of Resource to Get") + ResourcePermissionCmd.Flags().StringArrayP("column", "c", []string{"ID", "Aco", "AcoForeignKey", "Aro", "AroForeignKey", "Type"}, "Columns to return, possible Columns:\nID, Aco, AcoForeignKey, Aro, AroForeignKey, Type, CreatedTimestamp, ModifiedTimestamp") + } func ResourceGet(cmd *cobra.Command, args []string) error { @@ -76,3 +94,90 @@ func ResourceGet(cmd *cobra.Command, args []string) error { } return nil } + +func ResourcePermission(cmd *cobra.Command, args []string) error { + resource, err := cmd.Flags().GetString("id") + if err != nil { + return err + } + columns, err := cmd.Flags().GetStringArray("column") + if err != nil { + return err + } + if len(columns) == 0 { + return fmt.Errorf("You need to specify atleast one column to return") + } + jsonOutput, err := cmd.Flags().GetBool("json") + if err != nil { + return err + } + + ctx := util.GetContext() + + client, err := util.GetClient(ctx) + if err != nil { + return err + } + defer client.Logout(context.TODO()) + cmd.SilenceUsage = true + + permissions, err := client.GetResourcePermissions(ctx, resource) + if err != nil { + return fmt.Errorf("Listing Permission: %w", err) + } + + if jsonOutput { + outputPermissions := []PermissionJsonOutput{} + for i := range permissions { + outputPermissions = append(outputPermissions, PermissionJsonOutput{ + ID: &permissions[i].ID, + Aco: &permissions[i].ACO, + AcoForeignKey: &permissions[i].ACOForeignKey, + Aro: &permissions[i].ARO, + AroForeignKey: &permissions[i].AROForeignKey, + Type: &permissions[i].Type, + CreatedTimestamp: &permissions[i].Created.Time, + ModifiedTimestamp: &permissions[i].Modified.Time, + }) + } + jsonPermissions, err := json.MarshalIndent(outputPermissions, "", " ") + if err != nil { + return err + } + fmt.Println(string(jsonPermissions)) + } else { + data := pterm.TableData{columns} + + for _, permission := range permissions { + entry := make([]string, len(columns)) + for i := range columns { + switch strings.ToLower(columns[i]) { + case "id": + entry[i] = permission.ID + case "aco": + entry[i] = permission.ACO + case "acoforeignkey": + entry[i] = permission.ACOForeignKey + case "aro": + entry[i] = permission.ARO + case "aroforeignkey": + entry[i] = permission.AROForeignKey + case "type": + entry[i] = strconv.Itoa(permission.Type) + case "createdtimestamp": + entry[i] = permission.Created.Format(time.RFC3339) + case "modifiedtimestamp": + entry[i] = permission.Modified.Format(time.RFC3339) + default: + cmd.SilenceUsage = false + return fmt.Errorf("Unknown Column: %v", columns[i]) + } + } + data = append(data, entry) + } + + pterm.DefaultTable.WithHasHeader().WithData(data).Render() + } + + return nil +} diff --git a/resource/json.go b/resource/json.go index 950a109..676dd4e 100644 --- a/resource/json.go +++ b/resource/json.go @@ -13,3 +13,14 @@ type ResourceJsonOutput struct { CreatedTimestamp *time.Time `json:"created_timestamp,omitempty"` ModifiedTimestamp *time.Time `json:"modified_timestamp,omitempty"` } + +type PermissionJsonOutput struct { + ID *string `json:"id,omitempty"` + Aco *string `json:"aco,omitempty"` + AcoForeignKey *string `json:"aco_foreign_key,omitempty"` + Aro *string `json:"aro,omitempty"` + AroForeignKey *string `json:"aro_foreign_key,omitempty"` + Type *int `json:"type,omitempty"` + CreatedTimestamp *time.Time `json:"created_timestamp,omitempty"` + ModifiedTimestamp *time.Time `json:"modified_timestamp,omitempty"` +}