Skip to content

Commit

Permalink
keyring: Fix a panic when decrypting aead with empty RSA block. (#24442)
Browse files Browse the repository at this point in the history
Clusters that have gone through several upgrades have be found
to include keyring material which has an empty RSA block.

In more recent versions of Nomad, an empty RSA block is omitted
from being written to disk. This results in the panic not being
present. Older versions, however, did not have this struct tag
meaning we wrote an empty JSON block which is not accounted for
in the current version.
  • Loading branch information
jrasell authored Nov 12, 2024
1 parent 7a9e3d2 commit 4e7496d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/24442.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
keyring: Fixed a bug when decrypting aead with an empty RSA block on state upserts
```
2 changes: 1 addition & 1 deletion nomad/encrypter.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ func (e *Encrypter) decryptWrappedKeyTask(ctx context.Context, cancel context.Ca
// Decrypt RSAKey for Workload Identity JWT signing if one exists. Prior to
// 1.7 an ed25519 key derived from the root key was used instead of an RSA
// key.
if wrappedKey.WrappedRSAKey != nil {
if wrappedKey.WrappedRSAKey != nil && len(wrappedKey.WrappedRSAKey.Ciphertext) > 0 {
rsaKey, err = wrapper.Decrypt(e.srv.shutdownCtx, wrappedKey.WrappedRSAKey)
if err != nil {
err := fmt.Errorf("%w (rsa key): %w", ErrDecryptFailed, err)
Expand Down
40 changes: 40 additions & 0 deletions nomad/encrypter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"github.com/go-jose/go-jose/v3/jwt"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc/v2"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/helper/pointer"
Expand Down Expand Up @@ -834,3 +835,42 @@ func TestEncrypter_TransitConfigFallback(t *testing.T) {
fallbackVaultConfig(providers[2], &config.VaultConfig{})
must.Eq(t, expect, providers[2].Config, must.Sprint("expected fallback to env"))
}

func TestEncrypter_decryptWrappedKeyTask(t *testing.T) {
ci.Parallel(t)

srv := &Server{
logger: testlog.HCLogger(t),
config: &Config{},
}

tmpDir := t.TempDir()

key, err := structs.NewUnwrappedRootKey(structs.EncryptionAlgorithmAES256GCM)
must.NoError(t, err)

encrypter, err := NewEncrypter(srv, tmpDir)
must.NoError(t, err)

wrappedKey, err := encrypter.encryptDEK(key, &structs.KEKProviderConfig{})
must.NotNil(t, wrappedKey)
must.NoError(t, err)

// Purposely empty the RSA key, but do not nil it, so we can test for a
// panic where the key doesn't contain the ciphertext.
wrappedKey.WrappedRSAKey = &wrapping.BlobInfo{}

provider, ok := encrypter.providerConfigs[string(structs.KEKProviderAEAD)]
must.True(t, ok)
must.NotNil(t, provider)

KMSWrapper, err := encrypter.newKMSWrapper(provider, key.Meta.KeyID, wrappedKey.KeyEncryptionKey)
must.NoError(t, err)
must.NotNil(t, KMSWrapper)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

err = encrypter.decryptWrappedKeyTask(ctx, cancel, KMSWrapper, provider, key.Meta, wrappedKey)
must.NoError(t, err)
}

0 comments on commit 4e7496d

Please sign in to comment.