logging: report issues in rbdImage.DEKStore API with stacks

It helps to get a stack trace when debugging issues. Certain things are
considered bugs in the code (like missing attributes in a struct), and
might cause a panic in certain occasions.

In this case, a missing string will not panic, but the behaviour will
also not be correct (DEKs getting encrypted, but unable to decrypt).
Clearly logging this as a BUG is probably better than calling panic().

Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
Niels de Vos 2021-04-09 14:04:38 +02:00 committed by mergify[bot]
parent 35d58a7d5a
commit 8b8480017b
2 changed files with 31 additions and 5 deletions

View File

@ -116,6 +116,11 @@ func (ri *rbdImage) setupEncryption(ctx context.Context) error {
// from the original, so that both encrypted passphrases (potentially, depends
// on the DEKStore) have different contents.
func (ri *rbdImage) copyEncryptionConfig(cp *rbdImage) error {
if ri.VolID == cp.VolID {
return fmt.Errorf("BUG: %q and %q have the same VolID (%s) "+
"set!? Call stack: %s", ri, cp, ri.VolID, util.CallStack())
}
// get the unencrypted passphrase
passphrase, err := ri.encryption.GetCryptoPassphrase(ri.VolID)
if err != nil {
@ -281,8 +286,12 @@ func (ri *rbdImage) configureEncryption(kmsID string, credentials map[string]str
// StoreDEK saves the DEK in the metadata, overwrites any existing contents.
func (ri *rbdImage) StoreDEK(volumeID, dek string) error {
if ri.VolID != volumeID {
return fmt.Errorf("volume %q can not store DEK for %q", ri.String(), volumeID)
if ri.VolID == "" {
return fmt.Errorf("BUG: %q does not have VolID set, call "+
"stack: %s", ri, util.CallStack())
} else if ri.VolID != volumeID {
return fmt.Errorf("volume %q can not store DEK for %q",
ri.String(), volumeID)
}
return ri.SetMetadata(metadataDEK, dek)
@ -290,7 +299,10 @@ func (ri *rbdImage) StoreDEK(volumeID, dek string) error {
// FetchDEK reads the DEK from the image metadata.
func (ri *rbdImage) FetchDEK(volumeID string) (string, error) {
if ri.VolID != volumeID {
if ri.VolID == "" {
return "", fmt.Errorf("BUG: %q does not have VolID set, call "+
"stack: %s", ri, util.CallStack())
} else if ri.VolID != volumeID {
return "", fmt.Errorf("volume %q can not fetch DEK for %q", ri.String(), volumeID)
}
@ -300,8 +312,12 @@ func (ri *rbdImage) FetchDEK(volumeID string) (string, error) {
// RemoveDEK does not need to remove the DEK from the metadata, the image is
// most likely getting removed.
func (ri *rbdImage) RemoveDEK(volumeID string) error {
if ri.VolID != volumeID {
return fmt.Errorf("volume %q can not remove DEK for %q", ri.String(), volumeID)
if ri.VolID == "" {
return fmt.Errorf("BUG: %q does not have VolID set, call "+
"stack: %s", ri, util.CallStack())
} else if ri.VolID != volumeID {
return fmt.Errorf("volume %q can not remove DEK for %q",
ri.String(), volumeID)
}
return nil

View File

@ -22,6 +22,7 @@ import (
"fmt"
"math"
"os"
"runtime"
"strconv"
"strings"
"time"
@ -333,3 +334,12 @@ func getKeys(m map[string]interface{}) []string {
return keys
}
// CallStack returns the stack of the calls in the current goroutine. Useful
// for debugging or reporting errors. This is a friendly alternative to
// assert() or panic().
func CallStack() string {
stack := make([]byte, 2048)
_ = runtime.Stack(stack, false)
return string(stack)
}