diff --git a/cmd/stbak/cmd/archive.go b/cmd/stbak/cmd/archive.go index 481c9b8..5b9081d 100644 --- a/cmd/stbak/cmd/archive.go +++ b/cmd/stbak/cmd/archive.go @@ -3,11 +3,9 @@ package cmd import ( "archive/tar" "context" - "errors" "fmt" - "io/ioutil" - "os" + "github.com/pojntfx/stfs/internal/compression" "github.com/pojntfx/stfs/internal/keys" "github.com/pojntfx/stfs/internal/persisters" "github.com/pojntfx/stfs/pkg/config" @@ -23,29 +21,9 @@ const ( fromFlag = "from" overwriteFlag = "overwrite" compressionLevelFlag = "compression-level" - - recipientFlag = "recipient" - identityFlag = "identity" - passwordFlag = "password" -) - -var ( - knownCompressionLevels = []string{config.CompressionLevelFastest, config.CompressionLevelBalanced, config.CompressionLevelSmallest} - - errUnknownCompressionLevel = errors.New("unknown compression level") - errUnsupportedCompressionLevel = errors.New("unsupported compression level") - - errKeyNotAccessible = errors.New("key not found or accessible") - - errMissingTarHeader = errors.New("tar header is missing") - - errRecipientUnparsable = errors.New("recipient could not be parsed") - - errCompressionFormatRequiresLargerRecordSize = errors.New("this compression format requires a larger record size") - - errCompressionFormatOnlyRegularSupport = errors.New("this compression format only supports regular files, not i.e. tape drives") - - errSignatureFormatOnlyRegularSupport = errors.New("this signature format only supports regular files, not i.e. tape drives") + recipientFlag = "recipient" + identityFlag = "identity" + passwordFlag = "password" ) var archiveCmd = &cobra.Command{ @@ -57,15 +35,15 @@ var archiveCmd = &cobra.Command{ return err } - if err := checkCompressionLevel(viper.GetString(compressionLevelFlag)); err != nil { + if err := compression.CheckCompressionLevel(viper.GetString(compressionLevelFlag)); err != nil { return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { if viper.GetBool(verboseFlag) { @@ -89,7 +67,7 @@ var archiveCmd = &cobra.Command{ lastIndexedBlock = b } - pubkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -99,7 +77,7 @@ var archiveCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) if err != nil { return err } @@ -130,6 +108,9 @@ var archiveCmd = &cobra.Command{ viper.GetBool(overwriteFlag), viper.GetString(compressionLevelFlag), ) + if err != nil { + return nil + } return recovery.Index( config.StateConfig{ @@ -159,7 +140,7 @@ var archiveCmd = &cobra.Command{ } if len(hdrs) <= i-1 { - return errMissingTarHeader + return config.ErrMissingTarHeader } *hdr = *hdrs[i-1] @@ -173,47 +154,11 @@ var archiveCmd = &cobra.Command{ }, } -func checkKeyAccessible(encryptionFormat string, pathToKey string) error { - if encryptionFormat == noneKey { - return nil - } - - if _, err := os.Stat(pathToKey); err != nil { - return errKeyNotAccessible - } - - return nil -} - -func readKey(encryptionFormat string, pathToKey string) ([]byte, error) { - if encryptionFormat == noneKey { - return []byte{}, nil - } - - return ioutil.ReadFile(pathToKey) -} - -func checkCompressionLevel(compressionLevel string) error { - compressionLevelIsKnown := false - - for _, candidate := range knownCompressionLevels { - if compressionLevel == candidate { - compressionLevelIsKnown = true - } - } - - if !compressionLevelIsKnown { - return errUnknownCompressionLevel - } - - return nil -} - func init() { archiveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record") archiveCmd.PersistentFlags().StringP(fromFlag, "f", ".", "File or directory to archive") archiveCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Start writing from the start instead of from the end of the tape or tar file") - archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", config.CompressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", config.CompressionLevelBalanced, knownCompressionLevels)) + archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", config.CompressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", config.CompressionLevelBalanced, config.KnownCompressionLevels)) archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key to sign with") archiveCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key") diff --git a/cmd/stbak/cmd/delete.go b/cmd/stbak/cmd/delete.go index a9264b5..90ca702 100644 --- a/cmd/stbak/cmd/delete.go +++ b/cmd/stbak/cmd/delete.go @@ -22,22 +22,18 @@ var deleteCmd = &cobra.Command{ return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - if viper.GetBool(verboseFlag) { boil.DebugMode = true } - pubkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -47,7 +43,7 @@ var deleteCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) if err != nil { return err } diff --git a/cmd/stbak/cmd/drive_eject.go b/cmd/stbak/cmd/drive_eject.go index 4ebb023..98d60a2 100644 --- a/cmd/stbak/cmd/drive_eject.go +++ b/cmd/stbak/cmd/drive_eject.go @@ -4,7 +4,6 @@ import ( "github.com/pojntfx/stfs/pkg/hardware" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/volatiletech/sqlboiler/v4/boil" ) var driveEjectCmd = &cobra.Command{ @@ -15,10 +14,6 @@ var driveEjectCmd = &cobra.Command{ return err } - if viper.GetBool(verboseFlag) { - boil.DebugMode = true - } - return hardware.Eject( hardware.DriveConfig{ Drive: viper.GetString(driveFlag), diff --git a/cmd/stbak/cmd/drive_tell.go b/cmd/stbak/cmd/drive_tell.go index d0666c9..3925ee3 100644 --- a/cmd/stbak/cmd/drive_tell.go +++ b/cmd/stbak/cmd/drive_tell.go @@ -6,7 +6,6 @@ import ( "github.com/pojntfx/stfs/pkg/hardware" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/volatiletech/sqlboiler/v4/boil" ) var driveTellCmd = &cobra.Command{ @@ -17,10 +16,6 @@ var driveTellCmd = &cobra.Command{ return err } - if viper.GetBool(verboseFlag) { - boil.DebugMode = true - } - currentRecord, err := hardware.Tell( hardware.DriveConfig{ Drive: viper.GetString(driveFlag), diff --git a/cmd/stbak/cmd/keygen.go b/cmd/stbak/cmd/keygen.go index 238703f..3f92ebe 100644 --- a/cmd/stbak/cmd/keygen.go +++ b/cmd/stbak/cmd/keygen.go @@ -9,22 +9,17 @@ import ( "github.com/pojntfx/stfs/pkg/utility" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/volatiletech/sqlboiler/v4/boil" ) var keygenCmd = &cobra.Command{ Use: "keygen", Aliases: []string{"key", "k"}, - Short: "Restore a file or directory from tape or tar file", + Short: "Generate a encryption or signature key", RunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { return err } - if viper.GetBool(verboseFlag) { - boil.DebugMode = true - } - pubkey, privkey, err := utility.Keygen( config.PipeConfig{ Compression: viper.GetString(compressionFlag), diff --git a/cmd/stbak/cmd/move.go b/cmd/stbak/cmd/move.go index 5774f19..c55280b 100644 --- a/cmd/stbak/cmd/move.go +++ b/cmd/stbak/cmd/move.go @@ -18,22 +18,18 @@ var moveCmd = &cobra.Command{ return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - if viper.GetBool(verboseFlag) { boil.DebugMode = true } - pubkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -43,7 +39,7 @@ var moveCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) if err != nil { return err } diff --git a/cmd/stbak/cmd/recovery_fetch.go b/cmd/stbak/cmd/recovery_fetch.go index 554fff9..7f868f8 100644 --- a/cmd/stbak/cmd/recovery_fetch.go +++ b/cmd/stbak/cmd/recovery_fetch.go @@ -1,14 +1,12 @@ package cmd import ( - "errors" - "github.com/pojntfx/stfs/internal/keys" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/hardware" "github.com/pojntfx/stfs/pkg/recovery" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/volatiletech/sqlboiler/v4/boil" ) const ( @@ -18,40 +16,22 @@ const ( previewFlag = "preview" ) -var ( - errEmbeddedHeaderMissing = errors.New("embedded header is missing") - - errIdentityUnparsable = errors.New("recipient could not be parsed") - - errInvalidSignature = errors.New("invalid signature") - - errSignatureMissing = errors.New("missing signature") -) - var recoveryFetchCmd = &cobra.Command{ Use: "fetch", - Short: "Fetch a file or directory from tape or tar file by record and block", + Short: "Fetch a file or directory from tape or tar file by record and block without the index", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - - if viper.GetBool(verboseFlag) { - boil.DebugMode = true - } - - pubkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -61,7 +41,7 @@ var recoveryFetchCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) if err != nil { return err } @@ -72,9 +52,8 @@ var recoveryFetchCmd = &cobra.Command{ } return recovery.Fetch( - config.StateConfig{ - Drive: viper.GetString(driveFlag), - Metadata: viper.GetString(metadataFlag), + hardware.DriveConfig{ + Drive: viper.GetString(driveFlag), }, config.PipeConfig{ Compression: viper.GetString(compressionFlag), diff --git a/cmd/stbak/cmd/recovery_index.go b/cmd/stbak/cmd/recovery_index.go index a4c6624..0a92c51 100644 --- a/cmd/stbak/cmd/recovery_index.go +++ b/cmd/stbak/cmd/recovery_index.go @@ -21,22 +21,18 @@ var recoveryIndexCmd = &cobra.Command{ return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - if viper.GetBool(verboseFlag) { boil.DebugMode = true } - pubkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -46,7 +42,7 @@ var recoveryIndexCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) if err != nil { return err } diff --git a/cmd/stbak/cmd/recovery_query.go b/cmd/stbak/cmd/recovery_query.go index 40085f9..f290f45 100644 --- a/cmd/stbak/cmd/recovery_query.go +++ b/cmd/stbak/cmd/recovery_query.go @@ -3,10 +3,10 @@ package cmd import ( "github.com/pojntfx/stfs/internal/keys" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/hardware" "github.com/pojntfx/stfs/pkg/recovery" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/volatiletech/sqlboiler/v4/boil" ) var recoveryQueryCmd = &cobra.Command{ @@ -17,22 +17,14 @@ var recoveryQueryCmd = &cobra.Command{ return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - - if viper.GetBool(verboseFlag) { - boil.DebugMode = true - } - - pubkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -42,7 +34,7 @@ var recoveryQueryCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) if err != nil { return err } @@ -53,9 +45,8 @@ var recoveryQueryCmd = &cobra.Command{ } if _, err := recovery.Query( - config.StateConfig{ - Drive: viper.GetString(driveFlag), - Metadata: viper.GetString(metadataFlag), + hardware.DriveConfig{ + Drive: viper.GetString(driveFlag), }, config.PipeConfig{ Compression: viper.GetString(compressionFlag), diff --git a/cmd/stbak/cmd/restore.go b/cmd/stbak/cmd/restore.go index 4ffd27b..806ddce 100644 --- a/cmd/stbak/cmd/restore.go +++ b/cmd/stbak/cmd/restore.go @@ -22,22 +22,18 @@ var restoreCmd = &cobra.Command{ return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(identityFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - if viper.GetBool(verboseFlag) { boil.DebugMode = true } - pubkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -47,7 +43,7 @@ var restoreCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(identityFlag)) if err != nil { return err } diff --git a/cmd/stbak/cmd/root.go b/cmd/stbak/cmd/root.go index abd21b4..c973b16 100644 --- a/cmd/stbak/cmd/root.go +++ b/cmd/stbak/cmd/root.go @@ -1,75 +1,26 @@ package cmd import ( - "errors" "fmt" "os" "path/filepath" "strings" + "github.com/pojntfx/stfs/internal/compression" + "github.com/pojntfx/stfs/internal/encryption" + "github.com/pojntfx/stfs/internal/signature" + "github.com/pojntfx/stfs/pkg/config" "github.com/spf13/cobra" "github.com/spf13/viper" ) const ( - driveFlag = "drive" - metadataFlag = "metadata" - verboseFlag = "verbose" - + driveFlag = "drive" + metadataFlag = "metadata" + verboseFlag = "verbose" compressionFlag = "compression" - - noneKey = "none" - - compressionFormatGZipKey = "gzip" - compressionFormatGZipSuffix = ".gz" - - compressionFormatParallelGZipKey = "parallelgzip" - - compressionFormatLZ4Key = "lz4" - compressionFormatLZ4Suffix = ".lz4" - - compressionFormatZStandardKey = "zstandard" - compressionFormatZStandardSuffix = ".zst" - - compressionFormatBrotliKey = "brotli" - compressionFormatBrotliSuffix = ".br" - - compressionFormatBzip2Key = "bzip2" - compressionFormatBzip2Suffix = ".bz2" - - compressionFormatBzip2ParallelKey = "parallelbzip2" - - encryptionFlag = "encryption" - - encryptionFormatAgeKey = "age" - encryptionFormatAgeSuffix = ".age" - - encryptionFormatPGPKey = "pgp" - encryptionFormatPGPSuffix = ".pgp" - - signatureFlag = "signature" - - signatureFormatMinisignKey = "minisign" - - signatureFormatPGPKey = "pgp" -) - -var ( - knownCompressionFormats = []string{noneKey, compressionFormatGZipKey, compressionFormatParallelGZipKey, compressionFormatLZ4Key, compressionFormatZStandardKey, compressionFormatBrotliKey, compressionFormatBzip2Key, compressionFormatBzip2ParallelKey} - - errUnknownCompressionFormat = errors.New("unknown compression format") - errUnsupportedCompressionFormat = errors.New("unsupported compression format") - - knownEncryptionFormats = []string{noneKey, encryptionFormatAgeKey, encryptionFormatPGPKey} - - errUnknownEncryptionFormat = errors.New("unknown encryption format") - errUnsupportedEncryptionFormat = errors.New("unsupported encryption format") - errKeygenForFormatUnsupported = errors.New("can not generate keys for this format") - - knownSignatureFormats = []string{noneKey, signatureFormatMinisignKey, signatureFormatPGPKey} - - errUnknownSignatureFormat = errors.New("unknown signature format") - errUnsupportedSignatureFormat = errors.New("unsupported signature format") + encryptionFlag = "encryption" + signatureFlag = "signature" ) var rootCmd = &cobra.Command{ @@ -83,46 +34,15 @@ https://github.com/pojntfx/stfs`, viper.SetEnvPrefix("stbak") viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) - compressionFormatIsKnown := false - compressionFormat := viper.GetString(compressionFlag) - - for _, candidate := range knownCompressionFormats { - if compressionFormat == candidate { - compressionFormatIsKnown = true - } + if err := compression.CheckCompressionFormat(viper.GetString(compressionFlag)); err != nil { + return err } - if !compressionFormatIsKnown { - return errUnknownCompressionFormat + if err := encryption.CheckEncryptionFormat(viper.GetString(encryptionFlag)); err != nil { + return err } - encryptionFormatIsKnown := false - encryptionFormat := viper.GetString(encryptionFlag) - - for _, candidate := range knownEncryptionFormats { - if encryptionFormat == candidate { - encryptionFormatIsKnown = true - } - } - - if !encryptionFormatIsKnown { - return errUnknownEncryptionFormat - } - - signatureFormatIsKnown := false - signatureFormat := viper.GetString(signatureFlag) - - for _, candidate := range knownSignatureFormats { - if signatureFormat == candidate { - signatureFormatIsKnown = true - } - } - - if !signatureFormatIsKnown { - return errUnknownSignatureFormat - } - - return nil + return signature.CheckSignatureFormat(viper.GetString(signatureFlag)) }, } @@ -137,9 +57,9 @@ func Execute() { rootCmd.PersistentFlags().StringP(driveFlag, "d", "/dev/nst0", "Tape or tar file to use") rootCmd.PersistentFlags().StringP(metadataFlag, "m", metadataPath, "Metadata database to use") rootCmd.PersistentFlags().BoolP(verboseFlag, "v", false, "Enable verbose logging") - rootCmd.PersistentFlags().StringP(compressionFlag, "c", noneKey, fmt.Sprintf("Compression format to use (default %v, available are %v)", noneKey, knownCompressionFormats)) - rootCmd.PersistentFlags().StringP(encryptionFlag, "e", noneKey, fmt.Sprintf("Encryption format to use (default %v, available are %v)", noneKey, knownEncryptionFormats)) - rootCmd.PersistentFlags().StringP(signatureFlag, "s", noneKey, fmt.Sprintf("Signature format to use (default %v, available are %v)", noneKey, knownSignatureFormats)) + rootCmd.PersistentFlags().StringP(compressionFlag, "c", config.NoneKey, fmt.Sprintf("Compression format to use (default %v, available are %v)", config.NoneKey, config.KnownCompressionFormats)) + rootCmd.PersistentFlags().StringP(encryptionFlag, "e", config.NoneKey, fmt.Sprintf("Encryption format to use (default %v, available are %v)", config.NoneKey, config.KnownEncryptionFormats)) + rootCmd.PersistentFlags().StringP(signatureFlag, "s", config.NoneKey, fmt.Sprintf("Signature format to use (default %v, available are %v)", config.NoneKey, config.KnownSignatureFormats)) if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil { panic(err) diff --git a/cmd/stbak/cmd/update.go b/cmd/stbak/cmd/update.go index 78e90ab..af48e4a 100644 --- a/cmd/stbak/cmd/update.go +++ b/cmd/stbak/cmd/update.go @@ -5,6 +5,7 @@ import ( "context" "fmt" + "github.com/pojntfx/stfs/internal/compression" "github.com/pojntfx/stfs/internal/keys" "github.com/pojntfx/stfs/internal/persisters" "github.com/pojntfx/stfs/pkg/config" @@ -24,15 +25,15 @@ var updateCmd = &cobra.Command{ return err } - if err := checkCompressionLevel(viper.GetString(compressionLevelFlag)); err != nil { + if err := compression.CheckCompressionLevel(viper.GetString(compressionLevelFlag)); err != nil { return err } - if err := checkKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { + if err := keys.CheckKeyAccessible(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)); err != nil { return err } - return checkKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + return keys.CheckKeyAccessible(viper.GetString(signatureFlag), viper.GetString(identityFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { @@ -53,7 +54,7 @@ var updateCmd = &cobra.Command{ return err } - pubkey, err := readKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) + pubkey, err := keys.ReadKey(viper.GetString(encryptionFlag), viper.GetString(recipientFlag)) if err != nil { return err } @@ -63,7 +64,7 @@ var updateCmd = &cobra.Command{ return err } - privkey, err := readKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) + privkey, err := keys.ReadKey(viper.GetString(signatureFlag), viper.GetString(identityFlag)) if err != nil { return err } @@ -126,7 +127,7 @@ var updateCmd = &cobra.Command{ } if len(hdrs) <= i-1 { - return errMissingTarHeader + return config.ErrMissingTarHeader } *hdr = *hdrs[i-1] @@ -144,7 +145,7 @@ func init() { updateCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record") updateCmd.PersistentFlags().StringP(fromFlag, "f", "", "Path of the file or directory to update") updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file") - updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", config.CompressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", config.CompressionLevelBalanced, knownCompressionLevels)) + updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", config.CompressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", config.CompressionLevelBalanced, config.KnownCompressionLevels)) updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") updateCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key to sign with") updateCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key") diff --git a/internal/compression/check.go b/internal/compression/check.go new file mode 100644 index 0000000..8581a23 --- /dev/null +++ b/internal/compression/check.go @@ -0,0 +1,37 @@ +package compression + +import ( + "github.com/pojntfx/stfs/pkg/config" +) + +func CheckCompressionFormat(compressionFormat string) error { + compressionFormatIsKnown := false + + for _, candidate := range config.KnownCompressionFormats { + if compressionFormat == candidate { + compressionFormatIsKnown = true + } + } + + if !compressionFormatIsKnown { + return config.ErrCompressionFormatUnknown + } + + return nil +} + +func CheckCompressionLevel(compressionLevel string) error { + compressionLevelIsKnown := false + + for _, candidate := range config.KnownCompressionLevels { + if compressionLevel == candidate { + compressionLevelIsKnown = true + } + } + + if !compressionLevelIsKnown { + return config.ErrCompressionLevelUnknown + } + + return nil +} diff --git a/internal/encryption/check.go b/internal/encryption/check.go new file mode 100644 index 0000000..cf2cf16 --- /dev/null +++ b/internal/encryption/check.go @@ -0,0 +1,19 @@ +package encryption + +import "github.com/pojntfx/stfs/pkg/config" + +func CheckEncryptionFormat(encryptionFormat string) error { + encryptionFormatIsKnown := false + + for _, candidate := range config.KnownEncryptionFormats { + if encryptionFormat == candidate { + encryptionFormatIsKnown = true + } + } + + if !encryptionFormatIsKnown { + return config.ErrEncryptionFormatUnknown + } + + return nil +} diff --git a/internal/encryption/encrypt.go b/internal/encryption/encrypt.go index 437eeee..52c9b92 100644 --- a/internal/encryption/encrypt.go +++ b/internal/encryption/encrypt.go @@ -8,10 +8,10 @@ import ( "io" "filippo.io/age" + "github.com/ProtonMail/go-crypto/openpgp" "github.com/pojntfx/stfs/internal/noop" "github.com/pojntfx/stfs/internal/pax" "github.com/pojntfx/stfs/pkg/config" - "golang.org/x/crypto/openpgp" ) func Encrypt( diff --git a/internal/keys/check.go b/internal/keys/check.go new file mode 100644 index 0000000..f4695b7 --- /dev/null +++ b/internal/keys/check.go @@ -0,0 +1,24 @@ +package keys + +import ( + "errors" + "os" + + "github.com/pojntfx/stfs/pkg/config" +) + +var ( + ErrKeyNotAccessible = errors.New("key not found or accessible") +) + +func CheckKeyAccessible(encryptionFormat string, pathToKey string) error { + if encryptionFormat == config.NoneKey { + return nil + } + + if _, err := os.Stat(pathToKey); err != nil { + return ErrKeyNotAccessible + } + + return nil +} diff --git a/internal/keys/read.go b/internal/keys/read.go new file mode 100644 index 0000000..acded85 --- /dev/null +++ b/internal/keys/read.go @@ -0,0 +1,15 @@ +package keys + +import ( + "io/ioutil" + + "github.com/pojntfx/stfs/pkg/config" +) + +func ReadKey(encryptionFormat string, pathToKey string) ([]byte, error) { + if encryptionFormat == config.NoneKey { + return []byte{}, nil + } + + return ioutil.ReadFile(pathToKey) +} diff --git a/internal/signature/check.go b/internal/signature/check.go new file mode 100644 index 0000000..424babf --- /dev/null +++ b/internal/signature/check.go @@ -0,0 +1,19 @@ +package signature + +import "github.com/pojntfx/stfs/pkg/config" + +func CheckSignatureFormat(signatureFormat string) error { + signatureFormatIsKnown := false + + for _, candidate := range config.KnownSignatureFormats { + if signatureFormat == candidate { + signatureFormatIsKnown = true + } + } + + if !signatureFormatIsKnown { + return config.ErrSignatureFormatUnknown + } + + return nil +} diff --git a/pkg/config/constants.go b/pkg/config/constants.go index 531203b..5ac73ee 100644 --- a/pkg/config/constants.go +++ b/pkg/config/constants.go @@ -21,3 +21,13 @@ const ( CompressionLevelBalanced = "balanced" CompressionLevelSmallest = "smallest" ) + +var ( + KnownCompressionLevels = []string{CompressionLevelFastest, CompressionLevelBalanced, CompressionLevelSmallest} + + KnownCompressionFormats = []string{NoneKey, CompressionFormatGZipKey, CompressionFormatParallelGZipKey, CompressionFormatLZ4Key, CompressionFormatZStandardKey, CompressionFormatBrotliKey, CompressionFormatBzip2Key, CompressionFormatBzip2ParallelKey} + + KnownEncryptionFormats = []string{NoneKey, EncryptionFormatAgeKey, EncryptionFormatPGPKey} + + KnownSignatureFormats = []string{NoneKey, SignatureFormatMinisignKey, SignatureFormatPGPKey} +) diff --git a/pkg/config/error.go b/pkg/config/error.go index 0c70f80..e82374d 100644 --- a/pkg/config/error.go +++ b/pkg/config/error.go @@ -3,6 +3,7 @@ package config import "errors" var ( + ErrEncryptionFormatUnknown = errors.New("unknown encryption format") ErrEncryptionFormatUnsupported = errors.New("unsupported encryption format") ErrIdentityUnparsable = errors.New("recipient could not be parsed") @@ -10,6 +11,7 @@ var ( ErrEmbeddedHeaderMissing = errors.New("embedded header is missing") + ErrSignatureFormatUnknown = errors.New("unknown signature format") ErrSignatureFormatUnsupported = errors.New("unsupported signature format") ErrSignatureFormatOnlyRegularSupport = errors.New("this signature format only supports regular files, not i.e. tape drives") ErrSignatureInvalid = errors.New("signature is invalid") @@ -17,10 +19,12 @@ var ( ErrKeygenForFormatUnsupported = errors.New("can not generate keys for this format") + ErrCompressionFormatUnknown = errors.New("unknown compression format") ErrCompressionFormatUnsupported = errors.New("unsupported compression format") ErrCompressionFormatOnlyRegularSupport = errors.New("this compression format only supports regular files, not i.e. tape drives") ErrCompressionFormatRequiresLargerRecordSize = errors.New("this compression format requires a larger record size") ErrCompressionLevelUnsupported = errors.New("compression level is unsupported") + ErrCompressionLevelUnknown = errors.New("unknown compression level") ErrMissingTarHeader = errors.New("tar header is missing") ) diff --git a/pkg/operations/restore.go b/pkg/operations/restore.go index 6012a41..e429092 100644 --- a/pkg/operations/restore.go +++ b/pkg/operations/restore.go @@ -13,6 +13,7 @@ import ( "github.com/pojntfx/stfs/internal/formatting" "github.com/pojntfx/stfs/internal/persisters" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/hardware" "github.com/pojntfx/stfs/pkg/recovery" ) @@ -88,7 +89,9 @@ func Restore( } if err := recovery.Fetch( - state, + hardware.DriveConfig{ + Drive: state.Drive, + }, pipes, crypto, diff --git a/pkg/recovery/fetch.go b/pkg/recovery/fetch.go index 09446dd..7b18e7a 100644 --- a/pkg/recovery/fetch.go +++ b/pkg/recovery/fetch.go @@ -15,10 +15,11 @@ import ( "github.com/pojntfx/stfs/internal/signature" "github.com/pojntfx/stfs/internal/tape" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/hardware" ) func Fetch( - state config.StateConfig, + state hardware.DriveConfig, pipes config.PipeConfig, crypto config.CryptoConfig, diff --git a/pkg/recovery/query.go b/pkg/recovery/query.go index e47b23f..dfaa1fd 100644 --- a/pkg/recovery/query.go +++ b/pkg/recovery/query.go @@ -14,10 +14,11 @@ import ( "github.com/pojntfx/stfs/internal/signature" "github.com/pojntfx/stfs/internal/tape" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/hardware" ) func Query( - state config.StateConfig, + state hardware.DriveConfig, pipes config.PipeConfig, crypto config.CryptoConfig,