refactor: rename SEP to Keychain and reorganize import commands - Renamed sepunlock.go to keychainunlock.go - Changed all SEP types to Keychain types (SEPUnlockKey -> KeychainUnlockKey) - Updated type string from 'macos-sep' to 'keychain' - Moved 'secret import' to 'secret vault import' for mnemonic imports - Added new 'secret import <secret-name> --source <filename>' for file imports - Updated README to replace all 'Secure Enclave' references with 'macOS Keychain' - Updated directory structure diagrams and examples - Fixed linter error in MarkFlagRequired call - All tests passing, linter clean
This commit is contained in:
@@ -210,6 +210,7 @@ func newVaultCmd() *cobra.Command {
|
||||
cmd.AddCommand(newVaultListCmd())
|
||||
cmd.AddCommand(newVaultCreateCmd())
|
||||
cmd.AddCommand(newVaultSelectCmd())
|
||||
cmd.AddCommand(newVaultImportCmd())
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -254,6 +255,24 @@ func newVaultSelectCmd() *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func newVaultImportCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "import <vault-name>",
|
||||
Short: "Import a mnemonic into a vault",
|
||||
Long: `Import a BIP39 mnemonic phrase into the specified vault (default if not specified).`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
vaultName := "default"
|
||||
if len(args) > 0 {
|
||||
vaultName = args[0]
|
||||
}
|
||||
|
||||
cli := NewCLIInstance()
|
||||
return cli.Import(vaultName)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newAddCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add <secret-name>",
|
||||
@@ -342,7 +361,7 @@ func newKeysAddCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add <type>",
|
||||
Short: "Add a new unlock key",
|
||||
Long: `Add a new unlock key of the specified type (passphrase, macos-sep, pgp).`,
|
||||
Long: `Add a new unlock key of the specified type (passphrase, keychain, pgp).`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cli := NewCLIInstance()
|
||||
@@ -391,28 +410,31 @@ func newKeySelectSubCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
func newImportCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "import [vault-name]",
|
||||
Short: "Import a mnemonic into a vault",
|
||||
Long: `Import a BIP39 mnemonic phrase into the specified vault (default if not specified).`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
cmd := &cobra.Command{
|
||||
Use: "import <secret-name>",
|
||||
Short: "Import a secret from a file",
|
||||
Long: `Import a secret from a file and store it in the current vault under the given name.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
vaultName := "default"
|
||||
if len(args) > 0 {
|
||||
vaultName = args[0]
|
||||
}
|
||||
sourceFile, _ := cmd.Flags().GetString("source")
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
cli := NewCLIInstance()
|
||||
return cli.Import(vaultName)
|
||||
return cli.ImportSecret(args[0], sourceFile, force)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("source", "s", "", "Source file to import from (required)")
|
||||
cmd.Flags().BoolP("force", "f", false, "Overwrite existing secret")
|
||||
_ = cmd.MarkFlagRequired("source")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newEnrollCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "enroll",
|
||||
Short: "Enroll a macOS Secure Enclave unlock key",
|
||||
Long: `Enroll a macOS Secure Enclave unlock key that uses Touch ID/Face ID for biometric authentication.`,
|
||||
Short: "Enroll a macOS Keychain unlock key",
|
||||
Long: `Enroll a macOS Keychain unlock key that uses Touch ID/Face ID for biometric authentication.`,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cli := NewCLIInstance()
|
||||
@@ -934,8 +956,8 @@ func (cli *CLIInstance) KeysList(jsonOutput bool) error {
|
||||
switch metadata.Type {
|
||||
case "passphrase":
|
||||
unlockKey = NewPassphraseUnlockKey(cli.fs, keyDir, metadata)
|
||||
case "macos-sep":
|
||||
unlockKey = NewSEPUnlockKey(cli.fs, keyDir, metadata)
|
||||
case "keychain":
|
||||
unlockKey = NewKeychainUnlockKey(cli.fs, keyDir, metadata)
|
||||
case "pgp":
|
||||
unlockKey = NewPGPUnlockKey(cli.fs, keyDir, metadata)
|
||||
}
|
||||
@@ -1026,8 +1048,8 @@ func (cli *CLIInstance) KeysAdd(keyType string, cmd *cobra.Command) error {
|
||||
cmd.Printf("Created passphrase unlock key: %s\n", passphraseKey.GetMetadata().ID)
|
||||
return nil
|
||||
|
||||
case "macos-sep":
|
||||
return fmt.Errorf("macOS Secure Enclave unlock keys should be created using 'secret enroll' command")
|
||||
case "keychain":
|
||||
return fmt.Errorf("macOS Keychain unlock keys should be created using 'secret enroll' command")
|
||||
|
||||
case "pgp":
|
||||
// Get GPG key ID from flag or environment variable
|
||||
@@ -1050,7 +1072,7 @@ func (cli *CLIInstance) KeysAdd(keyType string, cmd *cobra.Command) error {
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported key type: %s (supported: passphrase, macos-sep, pgp)", keyType)
|
||||
return fmt.Errorf("unsupported key type: %s (supported: passphrase, keychain, pgp)", keyType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1106,17 +1128,17 @@ func (cli *CLIInstance) Import(vaultName string) error {
|
||||
|
||||
// Enroll enrolls a hardware security module
|
||||
func (cli *CLIInstance) Enroll() error {
|
||||
sepKey, err := CreateSEPUnlockKey(cli.fs, cli.stateDir)
|
||||
keychainKey, err := CreateKeychainUnlockKey(cli.fs, cli.stateDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to enroll macOS SEP unlock key: %w", err)
|
||||
return fmt.Errorf("failed to enroll macOS Keychain unlock key: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("macOS SEP unlock key enrolled successfully!\n")
|
||||
fmt.Printf("Key ID: %s\n", sepKey.GetMetadata().ID)
|
||||
fmt.Printf("Directory: %s\n", sepKey.GetDirectory())
|
||||
fmt.Printf("macOS Keychain unlock key enrolled successfully!\n")
|
||||
fmt.Printf("Key ID: %s\n", keychainKey.GetMetadata().ID)
|
||||
fmt.Printf("Directory: %s\n", keychainKey.GetDirectory())
|
||||
|
||||
// Load the key name to show the keychain key name
|
||||
if keyName, err := sepKey.GetKeyName(); err == nil {
|
||||
if keyName, err := keychainKey.GetKeyName(); err == nil {
|
||||
fmt.Printf("Keychain Key Name: %s\n", keyName)
|
||||
}
|
||||
|
||||
@@ -1497,3 +1519,26 @@ func determineStateDir(customConfigDir string) string {
|
||||
}
|
||||
return filepath.Join(configDir, AppID)
|
||||
}
|
||||
|
||||
// ImportSecret imports a secret from a file
|
||||
func (cli *CLIInstance) ImportSecret(secretName, sourceFile string, force bool) error {
|
||||
// Get current vault
|
||||
vault, err := GetCurrentVault(cli.fs, cli.stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read secret value from the source file
|
||||
value, err := afero.ReadFile(cli.fs, sourceFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read secret from file %s: %w", sourceFile, err)
|
||||
}
|
||||
|
||||
// Store the secret in the vault
|
||||
if err := vault.AddSecret(secretName, value, force); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully imported secret '%s' from file '%s'\n", secretName, sourceFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user