feat: improve security
This commit is contained in:
parent
99fb97dff3
commit
5b16cef525
8 changed files with 181 additions and 46 deletions
69
cmd.go
69
cmd.go
|
|
@ -9,6 +9,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -30,12 +31,70 @@ and other utilities.`,
|
|||
rootCmd.AddCommand(a.connectCommands())
|
||||
rootCmd.AddCommand(a.wakeCommand())
|
||||
rootCmd.AddCommand(a.importTimewarriorCommand())
|
||||
rootCmd.AddCommand(a.configCommand())
|
||||
|
||||
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func (a *App) configCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage configuration and secrets",
|
||||
}
|
||||
|
||||
cmd.AddCommand(&cobra.Command{
|
||||
Use: "set-secrets",
|
||||
Short: "Interactively set passwords in the system keyring",
|
||||
Long: "Prompts for SSH and RDP passwords and stores them securely in the operating system's keychain/keyring.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var sshPw, rdpPw string
|
||||
|
||||
form := huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewInput().
|
||||
Title("SSH Password").
|
||||
Description("Leave empty to keep existing").
|
||||
EchoMode(huh.EchoModePassword).
|
||||
Value(&sshPw),
|
||||
huh.NewInput().
|
||||
Title("RDP Password").
|
||||
Description("Leave empty to keep existing").
|
||||
EchoMode(huh.EchoModePassword).
|
||||
Value(&rdpPw),
|
||||
),
|
||||
)
|
||||
|
||||
if err := form.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if sshPw != "" {
|
||||
if err := setSecret(keySSHPassword, sshPw); err != nil {
|
||||
return fmt.Errorf("failed to save SSH password: %w", err)
|
||||
}
|
||||
fmt.Println("✓ SSH password saved to keyring.")
|
||||
}
|
||||
|
||||
if rdpPw != "" {
|
||||
if err := setSecret(keyRDPPassword, rdpPw); err != nil {
|
||||
return fmt.Errorf("failed to save RDP password: %w", err)
|
||||
}
|
||||
fmt.Println("✓ RDP password saved to keyring.")
|
||||
}
|
||||
|
||||
if sshPw == "" && rdpPw == "" {
|
||||
fmt.Println("No changes made.")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (a *App) startCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "start",
|
||||
|
|
@ -73,7 +132,7 @@ Use --background (-b) to keep tunnels running in the background without auto-con
|
|||
|
||||
fmt.Println("\nINFO: Received interrupt signal. Shutting down background process...")
|
||||
slog.Info("Received signal, cleanup via defer sshCon.Close() will run.")
|
||||
if err := a.timeStore.StopTracking(withoutTimew); err != nil {
|
||||
if err := a.StopTracking(withoutTimew); err != nil {
|
||||
slog.Warn(fmt.Sprintf("Failed to stop time tracking: %v", err))
|
||||
} else {
|
||||
slog.Info("Time tracking stopped.")
|
||||
|
|
@ -86,7 +145,7 @@ Use --background (-b) to keep tunnels running in the background without auto-con
|
|||
|
||||
fmt.Println("Workstation SSH session finished.")
|
||||
slog.Info("Foreground session ended, cleanup via defer sshCon.Close() will run.")
|
||||
if err := a.timeStore.StopTracking(withoutTimew); err != nil {
|
||||
if err := a.StopTracking(withoutTimew); err != nil {
|
||||
slog.Warn(fmt.Sprintf("Failed to stop time tracking: %v", err))
|
||||
} else {
|
||||
slog.Info("Time tracking stopped.")
|
||||
|
|
@ -110,7 +169,7 @@ func (a *App) stopCommand() *cobra.Command {
|
|||
Long: "Stops the current time tracking entry and attempts to kill active SSH tunnels.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Stopping workday procedures...")
|
||||
if err := a.timeStore.StopTracking(withoutTimew); err != nil {
|
||||
if err := a.StopTracking(withoutTimew); err != nil {
|
||||
slog.Error(fmt.Sprintf("Failed to stop time tracking: %v", err))
|
||||
} else {
|
||||
fmt.Println("Time tracking stopped.")
|
||||
|
|
@ -164,7 +223,7 @@ This also stops any currently running timer.`,
|
|||
|
||||
default:
|
||||
fmt.Printf("Attempting to start tracking interval '%s'...\n", tag)
|
||||
if err := a.timeStore.StartTracking(tag, withoutTimew); err != nil {
|
||||
if err := a.StartTracking(tag, withoutTimew); err != nil {
|
||||
slog.Error(fmt.Sprintf("Failed to start tracking '%s': %v", tag, err))
|
||||
return fmt.Errorf("could not start tracking '%s': %w", tag, err)
|
||||
}
|
||||
|
|
@ -178,7 +237,7 @@ This also stops any currently running timer.`,
|
|||
Short: "Start tracking 'break'",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Println("Starting break...")
|
||||
if err := a.timeStore.StartTracking(TagBreak, withoutTimew); err != nil {
|
||||
if err := a.StartTracking(TagBreak, withoutTimew); err != nil {
|
||||
slog.Error(fmt.Sprintf("Failed to start break tracking: %v", err))
|
||||
return fmt.Errorf("could not start break: %w", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue