58 lines
1.8 KiB
Go
58 lines
1.8 KiB
Go
// Package backup dumps and restores a whole Vantage MongoDB database.
|
|
//
|
|
// The archive never contains KEY_ENCRYPTION_KEY. It contains a fingerprint of
|
|
// it, which is enough to answer "will this archive restore into this
|
|
// deployment" and is not a hint at the value.
|
|
package backup
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"gitea.hostxtra.co.uk/vantage/vantage-shared/cryptobox"
|
|
)
|
|
|
|
// ErrNoKey is returned when no key was supplied at all. It is distinct from
|
|
// ErrBadKey because the operator remedies are different: one is "set the
|
|
// variable", the other is "the value you set is wrong".
|
|
var ErrNoKey = errors.New("KEY_ENCRYPTION_KEY is not set")
|
|
|
|
// ErrBadKey is returned when a key was supplied but is not 64 hex characters.
|
|
var ErrBadKey = errors.New("KEY_ENCRYPTION_KEY must be a 64-character hex string (32 bytes)")
|
|
|
|
// ParseKey decodes the hex form used by KEY_ENCRYPTION_KEY.
|
|
func ParseKey(hexKey string) ([]byte, error) {
|
|
if hexKey == "" {
|
|
return nil, ErrNoKey
|
|
}
|
|
key, err := hex.DecodeString(hexKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: not hexadecimal", ErrBadKey)
|
|
}
|
|
if len(key) != cryptobox.KeySize {
|
|
return nil, fmt.Errorf("%w: decoded to %d bytes", ErrBadKey, len(key))
|
|
}
|
|
return key, nil
|
|
}
|
|
|
|
// Fingerprint is the SHA-256 of the raw key bytes, hex encoded.
|
|
//
|
|
// Of the raw bytes rather than of the hex string, so an operator who writes the
|
|
// key in uppercase in one deployment and lowercase in another still gets one
|
|
// fingerprint for one key.
|
|
func Fingerprint(key []byte) string {
|
|
sum := sha256.Sum256(key)
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// FingerprintHex parses and fingerprints in one step.
|
|
func FingerprintHex(hexKey string) (string, error) {
|
|
key, err := ParseKey(hexKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return Fingerprint(key), nil
|
|
}
|