From ae6667349237bd7b28f8739afef69930ef3f4524 Mon Sep 17 00:00:00 2001 From: neha-Gupta1 Date: Thu, 28 Sep 2023 10:42:07 +0530 Subject: [PATCH] update kopia password --- src/cli/flags/repo.go | 27 ++++++++++---- src/cli/repo/repo.go | 24 +++++++++++- src/cli/repo/s3.go | 64 ++++++++++++++++++++++++++++++++ src/internal/events/events.go | 1 + src/pkg/repository/repository.go | 39 +++++++++++++++++++ 5 files changed, 146 insertions(+), 9 deletions(-) diff --git a/src/cli/flags/repo.go b/src/cli/flags/repo.go index 44bc3a2a3..172049360 100644 --- a/src/cli/flags/repo.go +++ b/src/cli/flags/repo.go @@ -11,17 +11,19 @@ const ( AWSSessionTokenFN = "aws-session-token" // Corso Flags - CorsoPassphraseFN = "passphrase" - SucceedIfExistsFN = "succeed-if-exists" + CorsoPassphraseFN = "passphrase" + UpdateCorsoPassphraseFN = "update-passphrase" + SucceedIfExistsFN = "succeed-if-exists" ) var ( - BackupIDFV string - AWSAccessKeyFV string - AWSSecretAccessKeyFV string - AWSSessionTokenFV string - CorsoPassphraseFV string - SucceedIfExistsFV bool + BackupIDFV string + AWSAccessKeyFV string + AWSSecretAccessKeyFV string + AWSSessionTokenFV string + CorsoPassphraseFV string + UpdateCorsoPhasephraseFV string + SucceedIfExistsFV bool ) // AddBackupIDFlag adds the --backup flag. @@ -59,6 +61,15 @@ func AddCorsoPassphaseFlags(cmd *cobra.Command) { "Passphrase to protect encrypted repository contents") } +// M365 flags +func AddCorsoUpdatePassphraseFlags(cmd *cobra.Command) { + fs := cmd.Flags() + fs.StringVar(&UpdateCorsoPhasephraseFV, + UpdateCorsoPassphraseFN, + "", + "update kopia passphrase for repo") +} + // --------------------------------------------------------------------------- // Provider // --------------------------------------------------------------------------- diff --git a/src/cli/repo/repo.go b/src/cli/repo/repo.go index f5430613b..0e5d99ba9 100644 --- a/src/cli/repo/repo.go +++ b/src/cli/repo/repo.go @@ -17,6 +17,7 @@ import ( const ( initCommand = "init" connectCommand = "connect" + updateCommand = "update" maintenanceCommand = "maintenance" ) @@ -34,12 +35,14 @@ func AddCommands(cmd *cobra.Command) { initCmd = initCmd() connectCmd = connectCmd() maintenanceCmd = maintenanceCmd() + updateCmd = updateCmd() ) cmd.AddCommand(repoCmd) repoCmd.AddCommand(initCmd) repoCmd.AddCommand(connectCmd) repoCmd.AddCommand(maintenanceCmd) + repoCmd.AddCommand(updateCmd) flags.AddMaintenanceModeFlag(maintenanceCmd) flags.AddForceMaintenanceFlag(maintenanceCmd) @@ -50,6 +53,8 @@ func AddCommands(cmd *cobra.Command) { addRepoTo(initCmd) addRepoTo(connectCmd) } + + addS3Commands(updateCmd) } // The repo category of commands. @@ -58,7 +63,7 @@ func repoCmd() *cobra.Command { return &cobra.Command{ Use: "repo", Short: "Manage your repositories", - Long: `Initialize, configure, and connect to your account backup repositories.`, + Long: `Initialize, configure, connect and update to your account backup repositories.`, RunE: handleRepoCmd, Args: cobra.NoArgs, } @@ -170,3 +175,20 @@ func getMaintenanceType(t string) (repository.MaintenanceType, error) { return res, nil } + +// The repo update subcommand. +// `corso repo update [...]` +func updateCmd() *cobra.Command { + return &cobra.Command{ + Use: updateCommand, + Short: "Update a repository.", + Long: `Update a existing repository to store your backups.`, + RunE: handleUpdateCmd, + Args: cobra.NoArgs, + } +} + +// Handler for calls to `corso repo init`. +func handleUpdateCmd(cmd *cobra.Command, args []string) error { + return cmd.Help() +} diff --git a/src/cli/repo/s3.go b/src/cli/repo/s3.go index 343dddf03..cc0f4b97b 100644 --- a/src/cli/repo/s3.go +++ b/src/cli/repo/s3.go @@ -28,6 +28,12 @@ func addS3Commands(cmd *cobra.Command) *cobra.Command { case connectCommand: c, _ = utils.AddCommand(cmd, s3ConnectCmd()) + + case updateCommand: + update := s3UpdateCmd() + flags.AddCorsoUpdatePassphraseFlags(update) + c, _ = utils.AddCommand(cmd, update) + } c.Use = c.Use + " " + s3ProviderCommandUseSuffix @@ -222,6 +228,10 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error { opts, repoID) if err != nil { + return Only(ctx, clues.Wrap(err, "Failed to create a repository controller")) + } + + if err := r.Connect(ctx); err != nil { return Only(ctx, clues.Wrap(err, "Failed to connect to the S3 repository")) } @@ -235,3 +245,57 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error { return nil } + +// --------------------------------------------------------------------------------------------------------- +// Update Password +// --------------------------------------------------------------------------------------------------------- + +// `corso repo update s3 [...]` +func s3UpdateCmd() *cobra.Command { + return &cobra.Command{ + Use: s3ProviderCommand, + Short: "Update to a S3 repository", + Long: `Update to an existing S3 repository.`, + RunE: updateS3Cmd, + Args: cobra.NoArgs, + Example: s3ProviderCommandConnectExamples, + } +} + +// updates to an existing s3 repo. +// currently just updating Kopia password +func updateS3Cmd(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + cfg, err := config.GetConfigRepoDetails( + ctx, + storage.ProviderS3, + true, + true, + flags.S3FlagOverrides(cmd)) + if err != nil { + return Only(ctx, err) + } + + repoID := cfg.RepoID + if len(repoID) == 0 { + repoID = events.RepoIDNotFound + } + + opts := utils.ControlWithConfig(cfg) + + r, err := repository.New( + ctx, + cfg.Account, + cfg.Storage, + opts, + repoID) + if err != nil { + return Only(ctx, clues.Wrap(err, "Failed to create a repository controller")) + } + + if err := r.UpdatePassword(ctx, flags.UpdateCorsoPhasephraseFV); err != nil { + return Only(ctx, clues.Wrap(err, "Failed to update s3")) + } + + return nil +} diff --git a/src/internal/events/events.go b/src/internal/events/events.go index 99c1651ac..52d3b87ab 100644 --- a/src/internal/events/events.go +++ b/src/internal/events/events.go @@ -31,6 +31,7 @@ const ( CorsoStart = "Corso Start" RepoInit = "Repo Init" RepoConnect = "Repo Connect" + RepoUpdate = "Repo Update" BackupStart = "Backup Start" BackupEnd = "Backup End" RestoreStart = "Restore Start" diff --git a/src/pkg/repository/repository.go b/src/pkg/repository/repository.go index 2f836570c..1b4b00344 100644 --- a/src/pkg/repository/repository.go +++ b/src/pkg/repository/repository.go @@ -6,6 +6,7 @@ import ( "github.com/alcionai/clues" "github.com/google/uuid" + "github.com/kopia/kopia/repo" "github.com/kopia/kopia/repo/manifest" "github.com/pkg/errors" @@ -272,6 +273,44 @@ func (r *repository) Connect(ctx context.Context) (err error) { return nil } +// UpdatePassword updates Kopia password +func (r *repository) UpdatePassword(ctx context.Context, password string) (err error) { + ctx = clues.Add( + ctx, + "acct_provider", r.Account.Provider.String(), + "acct_id", clues.Hide(r.Account.ID()), + "storage_provider", r.Storage.Provider.String()) + + defer func() { + if crErr := crash.Recovery(ctx, recover(), "repo connect"); crErr != nil { + err = crErr + } + }() + + progressBar := observe.MessageWithCompletion(ctx, "Connecting to repository") + defer close(progressBar) + + kopiaRef := kopia.NewConn(r.Storage) + if err := kopiaRef.Connect(ctx, r.Opts.Repo); err != nil { + return clues.Wrap(err, "connecting kopia client") + } + + repository := kopiaRef.Repository.(repo.DirectRepository) + err = repository.FormatManager().ChangePassword(ctx, password) + + if err != nil { + return errors.Wrap(err, "unable to update password") + } + + // kopiaRef comes with a count of 1 and NewWrapper/NewModelStore bumps it again so safe + // to close here. + defer kopiaRef.Close(ctx) + + r.Bus.Event(ctx, events.RepoUpdate, nil) + + return nil +} + func (r *repository) Close(ctx context.Context) error { if err := r.Bus.Close(); err != nil { logger.Ctx(ctx).With("err", err).Debugw("closing the event bus", clues.In(ctx).Slice()...)