feat: Allow automatic re-indexing without private key

This commit is contained in:
Felicitas Pojtinger
2021-12-02 12:16:05 +01:00
parent f4dc9f9f52
commit b5a99751de
3 changed files with 88 additions and 54 deletions

View File

@@ -54,6 +54,8 @@ var (
errRecipientNotAccessible = errors.New("recipient/public key not found or accessible") errRecipientNotAccessible = errors.New("recipient/public key not found or accessible")
errIdentityNotAccessible = errors.New("identity/private key not found or accessible") errIdentityNotAccessible = errors.New("identity/private key not found or accessible")
errMissingTarHeader = errors.New("tar header is missing")
) )
type flusher interface { type flusher interface {
@@ -99,10 +101,6 @@ var archiveCmd = &cobra.Command{
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil { if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
return errRecipientNotAccessible return errRecipientNotAccessible
} }
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
return errIdentityNotAccessible
}
} }
return nil return nil
@@ -130,7 +128,6 @@ var archiveCmd = &cobra.Command{
} }
pubkey := []byte{} pubkey := []byte{}
privkey := []byte{}
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey { if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
p, err := ioutil.ReadFile(viper.GetString(recipientFlag)) p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
if err != nil { if err != nil {
@@ -138,14 +135,9 @@ var archiveCmd = &cobra.Command{
} }
pubkey = p pubkey = p
privkey, err = ioutil.ReadFile(viper.GetString(identityFlag))
if err != nil {
return err
}
} }
if err := archive( hdrs, err := archive(
viper.GetString(tapeFlag), viper.GetString(tapeFlag),
viper.GetInt(recordSizeFlag), viper.GetInt(recordSizeFlag),
viper.GetString(srcFlag), viper.GetString(srcFlag),
@@ -154,7 +146,8 @@ var archiveCmd = &cobra.Command{
viper.GetString(compressionLevelFlag), viper.GetString(compressionLevelFlag),
viper.GetString(encryptionFlag), viper.GetString(encryptionFlag),
pubkey, pubkey,
); err != nil { )
if err != nil {
return err return err
} }
@@ -167,7 +160,17 @@ var archiveCmd = &cobra.Command{
viper.GetBool(overwriteFlag), viper.GetBool(overwriteFlag),
viper.GetString(compressionFlag), viper.GetString(compressionFlag),
viper.GetString(encryptionFlag), viper.GetString(encryptionFlag),
privkey, []byte{},
func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error {
if len(hdrs) <= i {
return errMissingTarHeader
}
*hdr = *hdrs[i]
return nil
},
0,
) )
}, },
} }
@@ -181,67 +184,68 @@ func archive(
compressionLevel string, compressionLevel string,
encryptionFormat string, encryptionFormat string,
pubkey []byte, pubkey []byte,
) error { ) ([]*tar.Header, error) {
dirty := false dirty := false
tw, isRegular, cleanup, err := openTapeWriter(tape) tw, isRegular, cleanup, err := openTapeWriter(tape)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
if overwrite { if overwrite {
if isRegular { if isRegular {
if err := cleanup(&dirty); err != nil { // dirty will always be false here if err := cleanup(&dirty); err != nil { // dirty will always be false here
return err return []*tar.Header{}, err
} }
f, err := os.OpenFile(tape, os.O_WRONLY|os.O_CREATE, 0600) f, err := os.OpenFile(tape, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
// Clear the file's content // Clear the file's content
if err := f.Truncate(0); err != nil { if err := f.Truncate(0); err != nil {
return err return []*tar.Header{}, err
} }
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
return err return []*tar.Header{}, err
} }
tw, isRegular, cleanup, err = openTapeWriter(tape) tw, isRegular, cleanup, err = openTapeWriter(tape)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
} else { } else {
if err := cleanup(&dirty); err != nil { // dirty will always be false here if err := cleanup(&dirty); err != nil { // dirty will always be false here
return err return []*tar.Header{}, err
} }
f, err := os.OpenFile(tape, os.O_WRONLY, os.ModeCharDevice) f, err := os.OpenFile(tape, os.O_WRONLY, os.ModeCharDevice)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
// Seek to the start of the tape // Seek to the start of the tape
if err := controllers.SeekToRecordOnTape(f, 0); err != nil { if err := controllers.SeekToRecordOnTape(f, 0); err != nil {
return err return []*tar.Header{}, err
} }
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
return err return []*tar.Header{}, err
} }
tw, isRegular, cleanup, err = openTapeWriter(tape) tw, isRegular, cleanup, err = openTapeWriter(tape)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
} }
} }
defer cleanup(&dirty) defer cleanup(&dirty)
headers := []*tar.Header{}
first := true first := true
return filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { return headers, filepath.Walk(src, func(path string, info fs.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
@@ -343,6 +347,9 @@ func archive(
return err return err
} }
hdrToAppend := *hdr
headers = append(headers, &hdrToAppend)
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
return err return err
} }
@@ -657,7 +664,6 @@ func init() {
archiveCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Start writing from the start instead of from the end of the tape or tar file") 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", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels)) archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
viper.AutomaticEnv() viper.AutomaticEnv()

View File

@@ -68,6 +68,10 @@ var recoveryIndexCmd = &cobra.Command{
viper.GetString(compressionFlag), viper.GetString(compressionFlag),
viper.GetString(encryptionFlag), viper.GetString(encryptionFlag),
privkey, privkey,
func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error {
return decryptHeader(hdr, encryptionFormat, privkey)
},
0,
) )
}, },
} }
@@ -82,6 +86,13 @@ func index(
compressionFormat string, compressionFormat string,
encryptionFormat string, encryptionFormat string,
privkey []byte, privkey []byte,
decryptHeader func(
hdr *tar.Header,
encryptionFormat string,
privkey []byte,
i int,
) error,
offset int,
) error { ) error {
if overwrite { if overwrite {
f, err := os.OpenFile(metadata, os.O_WRONLY|os.O_CREATE, 0600) f, err := os.OpenFile(metadata, os.O_WRONLY|os.O_CREATE, 0600)
@@ -119,6 +130,7 @@ func index(
record := int64(record) record := int64(record)
block := int64(block) block := int64(block)
i := 0
for { for {
hdr, err := tr.Next() hdr, err := tr.Next()
@@ -169,12 +181,14 @@ func index(
break break
} }
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil { if i >= offset {
return err if err := decryptHeader(hdr, encryptionFormat, privkey, i-offset); err != nil {
} return err
}
if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil {
return nil return nil
}
} }
curr, err := f.Seek(0, io.SeekCurrent) curr, err := f.Seek(0, io.SeekCurrent)
@@ -199,6 +213,8 @@ func index(
record++ record++
block = 0 block = 0
} }
i++
} }
} else { } else {
// Seek to record // Seek to record
@@ -217,6 +233,7 @@ func index(
curr := int64((recordSize * controllers.BlockSize * int(record)) + (int(block) * controllers.BlockSize)) curr := int64((recordSize * controllers.BlockSize * int(record)) + (int(block) * controllers.BlockSize))
counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)} counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)}
i := 0
tr := tar.NewReader(counter) tr := tar.NewReader(counter)
for { for {
@@ -246,12 +263,14 @@ func index(
} }
} }
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil { if i >= offset {
return err if err := decryptHeader(hdr, encryptionFormat, privkey, i-offset); err != nil {
} return err
}
if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil {
return nil return nil
}
} }
curr = int64(counter.BytesRead) curr = int64(counter.BytesRead)
@@ -270,6 +289,8 @@ func index(
record++ record++
block = 0 block = 0
} }
i++
} }
} }

View File

@@ -39,10 +39,6 @@ var updateCmd = &cobra.Command{
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil { if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
return errRecipientNotAccessible return errRecipientNotAccessible
} }
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
return errIdentityNotAccessible
}
} }
return nil return nil
@@ -67,7 +63,6 @@ var updateCmd = &cobra.Command{
} }
pubkey := []byte{} pubkey := []byte{}
privkey := []byte{}
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey { if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
p, err := ioutil.ReadFile(viper.GetString(recipientFlag)) p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
if err != nil { if err != nil {
@@ -75,14 +70,9 @@ var updateCmd = &cobra.Command{
} }
pubkey = p pubkey = p
privkey, err = ioutil.ReadFile(viper.GetString(identityFlag))
if err != nil {
return err
}
} }
if err := update( hdrs, err := update(
viper.GetString(tapeFlag), viper.GetString(tapeFlag),
viper.GetInt(recordSizeFlag), viper.GetInt(recordSizeFlag),
viper.GetString(srcFlag), viper.GetString(srcFlag),
@@ -91,7 +81,8 @@ var updateCmd = &cobra.Command{
viper.GetString(compressionLevelFlag), viper.GetString(compressionLevelFlag),
viper.GetString(encryptionFlag), viper.GetString(encryptionFlag),
pubkey, pubkey,
); err != nil { )
if err != nil {
return err return err
} }
@@ -104,7 +95,17 @@ var updateCmd = &cobra.Command{
false, false,
viper.GetString(compressionFlag), viper.GetString(compressionFlag),
viper.GetString(encryptionFlag), viper.GetString(encryptionFlag),
privkey, []byte{},
func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error {
if len(hdrs) <= i {
return errMissingTarHeader
}
*hdr = *hdrs[i]
return nil
},
1,
) )
}, },
} }
@@ -118,16 +119,17 @@ func update(
compressionLevel string, compressionLevel string,
encryptionFormat string, encryptionFormat string,
pubkey []byte, pubkey []byte,
) error { ) ([]*tar.Header, error) {
dirty := false dirty := false
tw, isRegular, cleanup, err := openTapeWriter(tape) tw, isRegular, cleanup, err := openTapeWriter(tape)
if err != nil { if err != nil {
return err return []*tar.Header{}, err
} }
defer cleanup(&dirty) defer cleanup(&dirty)
headers := []*tar.Header{}
first := true first := true
return filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { return headers, filepath.Walk(src, func(path string, info fs.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
@@ -237,6 +239,9 @@ func update(
return err return err
} }
hdrToAppend := *hdr
headers = append(headers, &hdrToAppend)
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
return err return err
} }
@@ -304,6 +309,9 @@ func update(
return err return err
} }
hdrToAppend := *hdr
headers = append(headers, &hdrToAppend)
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
return err return err
} }
@@ -325,7 +333,6 @@ func init() {
updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file") updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file")
updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels)) updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
updateCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
viper.AutomaticEnv() viper.AutomaticEnv()