// If we abort in the middle of writing the key and cert, such that only the key is written // to the final location, when we read we can still read the cert from the temporary // location. func TestTwoPhaseReadWrite(t *testing.T) { cert1, _, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) cert2, key2, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir)) krw := ca.NewKeyReadWriter(path.Node, nil, nil) // put a directory in the location where the cert goes, so we can't actually move // the cert from the temporary location to the final location. require.NoError(t, os.Mkdir(filepath.Join(path.Node.Cert), 0755)) require.Error(t, krw.Write(cert2, key2, nil)) // the temp cert file should exist tempCertPath := filepath.Join(filepath.Dir(path.Node.Cert), "."+filepath.Base(path.Node.Cert)) readCert, err := ioutil.ReadFile(tempCertPath) require.NoError(t, err) require.Equal(t, cert2, readCert) // remove the directory, to simulate it failing to write the first time os.RemoveAll(path.Node.Cert) readCert, readKey, err := krw.Read() require.NoError(t, err) require.Equal(t, cert2, readCert) require.Equal(t, key2, readKey) // the cert should have been moved to its proper location _, err = os.Stat(tempCertPath) require.True(t, os.IsNotExist(err)) // If the cert in the proper location doesn't match the key, the temp location is checked require.NoError(t, ioutil.WriteFile(tempCertPath, cert2, 0644)) require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert1, 0644)) readCert, readKey, err = krw.Read() require.NoError(t, err) require.Equal(t, cert2, readCert) require.Equal(t, key2, readKey) // the cert should have been moved to its proper location _, err = os.Stat(tempCertPath) require.True(t, os.IsNotExist(err)) // If the cert in the temp location also doesn't match, the failure matching the // correctly-located cert is returned require.NoError(t, os.Remove(path.Node.Cert)) require.NoError(t, ioutil.WriteFile(tempCertPath, cert1, 0644)) // mismatching cert _, _, err = krw.Read() require.True(t, os.IsNotExist(err)) // the cert should have been removed _, err = os.Stat(tempCertPath) require.True(t, os.IsNotExist(err)) }
func TestKeyReadWriterMigrate(t *testing.T) { cert, key, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir)) // if the key exists in an old location, migrate it from there. tempKeyPath := filepath.Join(filepath.Dir(path.Node.Key), "."+filepath.Base(path.Node.Key)) require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert, 0644)) require.NoError(t, ioutil.WriteFile(tempKeyPath, key, 0600)) krw := ca.NewKeyReadWriter(path.Node, nil, nil) require.NoError(t, krw.Migrate()) _, err = os.Stat(tempKeyPath) require.True(t, os.IsNotExist(err)) // it's been moved to the right place _, _, err = krw.Read() require.NoError(t, err) // migrate does not affect any existing files dirList, err := ioutil.ReadDir(filepath.Dir(path.Node.Key)) require.NoError(t, err) require.NoError(t, krw.Migrate()) dirList2, err := ioutil.ReadDir(filepath.Dir(path.Node.Key)) require.NoError(t, err) require.Equal(t, dirList, dirList2) _, _, err = krw.Read() require.NoError(t, err) }
func TestDecrypt(t *testing.T) { tempdir, err := ioutil.TempDir("", "rafttool") require.NoError(t, err) defer os.RemoveAll(tempdir) kek := []byte("kek") dek := []byte("dek") unlockKey := encryption.HumanReadableKey(kek) // write a key to disk, else we won't be able to decrypt anything paths := certPaths(tempdir) krw := ca.NewKeyReadWriter(paths.Node, kek, manager.RaftDEKData{EncryptionKeys: raft.EncryptionKeys{CurrentDEK: dek}}) cert, key, err := testutils.CreateRootCertAndKey("not really a root, just need cert and key") require.NoError(t, err) require.NoError(t, krw.Write(cert, key, nil)) // create the encrypted v3 directory origSnapshot := raftpb.Snapshot{ Data: []byte("snapshot"), Metadata: raftpb.SnapshotMetadata{ Index: 1, Term: 1, }, } e, d := encryption.Defaults(dek) writeFakeRaftData(t, tempdir, &origSnapshot, storage.NewWALFactory(e, d), storage.NewSnapFactory(e, d)) outdir := filepath.Join(tempdir, "outdir") // if we use the wrong unlock key, we can't actually decrypt anything. The output directory won't get created. err = decryptRaftData(tempdir, outdir, "") require.IsType(t, ca.ErrInvalidKEK{}, err) require.False(t, fileutil.Exist(outdir)) // Using the right unlock key, we produce data that is unencrypted require.NoError(t, decryptRaftData(tempdir, outdir, unlockKey)) require.True(t, fileutil.Exist(outdir)) // The snapshot directory is readable by the regular snapshotter snapshot, err := storage.OriginalSnap.New(filepath.Join(outdir, "snap-decrypted")).Load() require.NoError(t, err) require.NotNil(t, snapshot) require.Equal(t, origSnapshot, *snapshot) // The wals are readable by the regular wal walreader, err := storage.OriginalWAL.Open(filepath.Join(outdir, "wal-decrypted"), walpb.Snapshot{Index: 1, Term: 1}) require.NoError(t, err) metadata, _, entries, err := walreader.ReadAll() require.NoError(t, err) require.Equal(t, []byte("v3metadata"), metadata) require.Len(t, entries, 5) }
func TestKeyReadWriterViewAndRotateKEK(t *testing.T) { cert, key, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir)) // write a key with headers to the key to make sure it gets passed when reading/writing headers keyBlock, _ := pem.Decode(key) require.NotNil(t, keyBlock) keyBlock.Headers = map[string]string{"hello": "world"} key = pem.EncodeToMemory(keyBlock) require.NoError(t, ca.NewKeyReadWriter(path.Node, nil, nil).Write(cert, key, nil)) // if if getting new kek and headers fail, rotating a KEK fails, and the kek does not rotate k := ca.NewKeyReadWriter(path.Node, nil, nil) require.Error(t, k.ViewAndRotateKEK(func(k ca.KEKData, h ca.PEMKeyHeaders) (ca.KEKData, ca.PEMKeyHeaders, error) { require.Equal(t, ca.KEKData{}, k) require.Nil(t, h) return ca.KEKData{}, nil, fmt.Errorf("Nope") })) // writing new headers will write a key that has the headers returned by the header update function k = ca.NewKeyReadWriter(path.Node, []byte("oldKEK"), nil) require.NoError(t, k.ViewAndRotateKEK(func(k ca.KEKData, h ca.PEMKeyHeaders) (ca.KEKData, ca.PEMKeyHeaders, error) { require.Equal(t, ca.KEKData{KEK: []byte("oldKEK")}, k) require.Nil(t, h) return ca.KEKData{KEK: []byte("newKEK"), Version: uint64(2)}, testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) { require.Equal(t, []byte("newKEK"), kek.KEK) return map[string]string{"updated": "headers"}, nil }}, nil })) // ensure the key has been re-encrypted and we can read it k = ca.NewKeyReadWriter(path.Node, nil, nil) _, _, err = k.Read() require.Error(t, err) var headers map[string]string k = ca.NewKeyReadWriter(path.Node, []byte("newKEK"), testHeaders{setHeaders: func(h map[string]string, _ ca.KEKData) (ca.PEMKeyHeaders, error) { headers = h return testHeaders{}, nil }}) _, _, err = k.Read() require.NoError(t, err) require.Equal(t, map[string]string{"updated": "headers"}, headers) }
func TestRaftDEKManagerUpdateKeys(t *testing.T) { tempDir, err := ioutil.TempDir("", "manager-update-keys-") require.NoError(t, err) defer os.RemoveAll(tempDir) paths := ca.NewConfigPaths(tempDir) cert, key, err := cautils.CreateRootCertAndKey("cn") require.NoError(t, err) keys := raft.EncryptionKeys{ CurrentDEK: []byte("key1"), PendingDEK: []byte("key2"), } krw := ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{ EncryptionKeys: keys, NeedsRotation: true, }) require.NoError(t, krw.Write(cert, key, nil)) dekManager, err := NewRaftDEKManager(krw) require.NoError(t, err) newKeys := raft.EncryptionKeys{ CurrentDEK: []byte("new current"), } require.NoError(t, dekManager.UpdateKeys(newKeys)) // don't run GetKeys, because NeedsRotation is true and it'd just generate a new one h, _ := krw.GetCurrentState() dekData, ok := h.(RaftDEKData) require.True(t, ok) require.True(t, dekData.NeedsRotation) // UpdateKeys so there is no CurrentDEK: all the headers should be wiped out require.NoError(t, dekManager.UpdateKeys(raft.EncryptionKeys{})) require.Equal(t, raft.EncryptionKeys{}, dekManager.GetKeys()) require.False(t, dekManager.NeedsRotation()) h, _ = krw.GetCurrentState() require.Nil(t, h) keyBytes, err := ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) keyBlock, _ := pem.Decode(keyBytes) require.NotNil(t, keyBlock) // the only header remaining should be the kek version require.Len(t, keyBlock.Headers, 1) require.Contains(t, keyBlock.Headers, "kek-version") }
// NewRaftDEKManager creates a key if one doesn't exist func TestNewRaftDEKManager(t *testing.T) { tempDir, err := ioutil.TempDir("", "manager-new-dek-manager-") require.NoError(t, err) defer os.RemoveAll(tempDir) paths := ca.NewConfigPaths(tempDir) cert, key, err := cautils.CreateRootCertAndKey("cn") require.NoError(t, err) krw := ca.NewKeyReadWriter(paths.Node, nil, nil) require.NoError(t, krw.Write(cert, key, nil)) keyBytes, err := ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.NotContains(t, string(keyBytes), pemHeaderRaftDEK) // headers are not written dekManager, err := NewRaftDEKManager(krw) // this should create a new DEK and write it to the file require.NoError(t, err) keyBytes, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.Contains(t, string(keyBytes), pemHeaderRaftDEK) // header is written now keys := dekManager.GetKeys() require.NotNil(t, keys.CurrentDEK) require.Nil(t, keys.PendingDEK) require.False(t, dekManager.NeedsRotation()) // If one exists, nothing is updated dekManager, err = NewRaftDEKManager(krw) // this should create a new DEK and write it to the file require.NoError(t, err) keyBytes2, err := ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.Equal(t, keyBytes, keyBytes2) require.Equal(t, keys, dekManager.GetKeys()) require.False(t, dekManager.NeedsRotation()) }
func TestKeyReadWriterViewAndUpdateHeaders(t *testing.T) { cert, key, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir)) // write a key with headers to the key to make sure it gets passed when reading/writing headers keyBlock, _ := pem.Decode(key) require.NotNil(t, keyBlock) keyBlock.Headers = map[string]string{"hello": "world"} key = pem.EncodeToMemory(keyBlock) require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert, 0644)) require.NoError(t, ioutil.WriteFile(path.Node.Key, key, 0600)) // if the update headers callback function fails, updating headers fails k := ca.NewKeyReadWriter(path.Node, nil, nil) err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) { require.Nil(t, h) return nil, fmt.Errorf("nope") }) require.Error(t, err) require.Equal(t, "nope", err.Error()) // updating headers succeed and is called with the latest kek data err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) { require.Nil(t, h) return testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) { return map[string]string{"updated": "headers"}, nil }}, nil }) require.NoError(t, err) k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) { require.Equal(t, map[string]string{"updated": "headers"}, h) require.Equal(t, ca.KEKData{}, k) return testHeaders{}, nil }}) _, _, err = k.Read() require.NoError(t, err) // we can also update headers on an encrypted key k = ca.NewKeyReadWriter(path.Node, []byte("kek"), nil) require.NoError(t, k.Write(cert, key, nil)) err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) { require.Nil(t, h) return testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) { require.Equal(t, ca.KEKData{KEK: []byte("kek")}, kek) return map[string]string{"updated": "headers"}, nil }}, nil }) require.NoError(t, err) k = ca.NewKeyReadWriter(path.Node, []byte("kek"), testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) { require.Equal(t, map[string]string{"updated": "headers"}, h) require.Equal(t, ca.KEKData{KEK: []byte("kek")}, k) return testHeaders{}, nil }}) _, _, err = k.Read() require.NoError(t, err) }
// can read and write tls keys that aren't encrypted, and that are encrypted. without // a pem header manager, the headers are all preserved and not overwritten func TestKeyReadWriter(t *testing.T) { cert, key, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) expectedKey := key tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir, "subdir")) // to make sure subdirectories are created checkCanReadWithKEK := func(kek []byte) *ca.KeyReadWriter { k := ca.NewKeyReadWriter(path.Node, kek, nil) readCert, readKey, err := k.Read() require.NoError(t, err) require.Equal(t, cert, readCert) require.Equal(t, expectedKey, readKey, "Expected %s, Got %s", string(expectedKey), string(readKey)) return k } k := ca.NewKeyReadWriter(path.Node, nil, nil) // can't read things that don't exist _, _, err = k.Read() require.Error(t, err) // can write an unencrypted key with no updates require.NoError(t, k.Write(cert, expectedKey, nil)) // can read unencrypted k = checkCanReadWithKEK(nil) _, kekData := k.GetCurrentState() require.EqualValues(t, 0, kekData.Version) // the first version was 0 // write a key with headers to the key to make sure they're cleaned keyBlock, _ := pem.Decode(expectedKey) require.NotNil(t, keyBlock) keyBlock.Headers = map[string]string{"hello": "world"} expectedKey = pem.EncodeToMemory(keyBlock) // write a version, but that's not what we'd expect back once we read keyBlock.Headers["kek-version"] = "8" require.NoError(t, ioutil.WriteFile(path.Node.Key, pem.EncodeToMemory(keyBlock), 0600)) // if a kek is provided, we can still read unencrypted keys, and read // the provided version k = checkCanReadWithKEK([]byte("original kek")) _, kekData = k.GetCurrentState() require.EqualValues(t, 8, kekData.Version) // we can update the kek and write at the same time require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: []byte("new kek!"), Version: 3})) // the same kek can still read, and will continue to write with this key if // no further kek updates are provided _, _, err = k.Read() require.NoError(t, err) require.NoError(t, k.Write(cert, expectedKey, nil)) expectedKey = key // without the right kek, we can't read k = ca.NewKeyReadWriter(path.Node, []byte("original kek"), nil) _, _, err = k.Read() require.Error(t, err) // same new key, just for sanity k = checkCanReadWithKEK([]byte("new kek!")) _, kekData = k.GetCurrentState() require.EqualValues(t, 3, kekData.Version) // we can also change the kek back to nil, which means the key is unencrypted require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: nil})) k = checkCanReadWithKEK(nil) _, kekData = k.GetCurrentState() require.EqualValues(t, 0, kekData.Version) }
// KeyReaderWriter makes a call to a get headers updater, if write is called, // and set headers, if read is called. The KEK version header is always preserved // no matter what. func TestKeyReadWriterWithPemHeaderManager(t *testing.T) { cert, key, err := testutils.CreateRootCertAndKey("cn") require.NoError(t, err) // write a key with headers to the key to make sure it gets overwritten keyBlock, _ := pem.Decode(key) require.NotNil(t, keyBlock) keyBlock.Headers = map[string]string{"hello": "world"} key = pem.EncodeToMemory(keyBlock) tempdir, err := ioutil.TempDir("", "KeyReadWriter") require.NoError(t, err) defer os.RemoveAll(tempdir) path := ca.NewConfigPaths(filepath.Join(tempdir, "subdir")) // to make sure subdirectories are created // if if getting new headers fail, writing a key fails, and the key does not rotate var count int badKEKData := ca.KEKData{KEK: []byte("failed kek"), Version: 3} k := ca.NewKeyReadWriter(path.Node, nil, testHeaders{newHeaders: func(k ca.KEKData) (map[string]string, error) { if count == 0 { count++ require.Equal(t, badKEKData, k) return nil, fmt.Errorf("fail") } require.Equal(t, ca.KEKData{}, k) return nil, nil }}) // first write will fail require.Error(t, k.Write(cert, key, &badKEKData)) // the stored kek data will be not be updated because the write failed _, kekData := k.GetCurrentState() require.Equal(t, ca.KEKData{}, kekData) // second write will succeed, using the original kek (nil) require.NoError(t, k.Write(cert, key, nil)) var ( headers map[string]string kek ca.KEKData ) // if setting headers fail, reading fails k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(map[string]string, ca.KEKData) (ca.PEMKeyHeaders, error) { return nil, fmt.Errorf("nope") }}) _, _, err = k.Read() require.Error(t, err) k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) { headers = h kek = k return testHeaders{}, nil }}) _, _, err = k.Read() require.NoError(t, err) require.Equal(t, ca.KEKData{}, kek) require.Equal(t, keyBlock.Headers, headers) // writing new headers is called with existing headers, and will write a key that has the headers // returned by the header update function k = ca.NewKeyReadWriter(path.Node, []byte("oldKek"), testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) { require.Equal(t, []byte("newKEK"), kek.KEK) return map[string]string{"updated": "headers"}, nil }}) require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: []byte("newKEK"), Version: 2})) // make sure headers were correctly set k = ca.NewKeyReadWriter(path.Node, []byte("newKEK"), testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) { headers = h kek = k return testHeaders{}, nil }}) _, _, err = k.Read() require.NoError(t, err) require.Equal(t, ca.KEKData{KEK: []byte("newKEK"), Version: 2}, kek) _, kekData = k.GetCurrentState() require.Equal(t, kek, kekData) require.Equal(t, map[string]string{"updated": "headers"}, headers) }
func TestRaftDEKManagerMaybeUpdateKEK(t *testing.T) { tempDir, err := ioutil.TempDir("", "manager-maybe-update-kek-") require.NoError(t, err) defer os.RemoveAll(tempDir) paths := ca.NewConfigPaths(tempDir) cert, key, err := cautils.CreateRootCertAndKey("cn") require.NoError(t, err) keys := raft.EncryptionKeys{CurrentDEK: []byte("current dek")} // trying to update a KEK will error if the version is the same but the kek is different krw := ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{EncryptionKeys: keys}) require.NoError(t, krw.Write(cert, key, nil)) dekManager, err := NewRaftDEKManager(krw) require.NoError(t, err) keyBytes, err := ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) _, _, err = dekManager.MaybeUpdateKEK(ca.KEKData{KEK: []byte("locked now")}) require.Error(t, err) require.False(t, dekManager.NeedsRotation()) keyBytes2, err := ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.Equal(t, keyBytes, keyBytes2) // trying to update a KEK from unlocked to lock will set NeedsRotation to true, as well as encrypt the TLS key updated, unlockedToLocked, err := dekManager.MaybeUpdateKEK(ca.KEKData{KEK: []byte("locked now"), Version: 1}) require.NoError(t, err) require.True(t, updated) require.True(t, unlockedToLocked) // don't run GetKeys, because NeedsRotation is true and it'd just generate a new one h, _ := krw.GetCurrentState() dekData, ok := h.(RaftDEKData) require.True(t, ok) require.Equal(t, keys, dekData.EncryptionKeys) require.True(t, dekData.NeedsRotation) require.NotNil(t, <-dekManager.RotationNotify()) // we are notified of a new pending key keyBytes2, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.NotEqual(t, keyBytes, keyBytes2) keyBytes = keyBytes2 readKRW := ca.NewKeyReadWriter(paths.Node, []byte("locked now"), RaftDEKData{}) _, _, err = readKRW.Read() require.NoError(t, err) // trying to update a KEK of a lower version will not update anything, but will not error updated, unlockedToLocked, err = dekManager.MaybeUpdateKEK(ca.KEKData{}) require.NoError(t, err) require.False(t, unlockedToLocked) require.False(t, updated) // don't run GetKeys, because NeedsRotation is true and it'd just generate a new one h, _ = krw.GetCurrentState() dekData, ok = h.(RaftDEKData) require.True(t, ok) require.Equal(t, keys, dekData.EncryptionKeys) require.True(t, dekData.NeedsRotation) keyBytes2, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.Equal(t, keyBytes, keyBytes2, string(keyBytes), string(keyBytes2)) // updating a kek to a higher version, but with the same kek, will also neither update anything nor error updated, unlockedToLocked, err = dekManager.MaybeUpdateKEK(ca.KEKData{KEK: []byte("locked now"), Version: 100}) require.NoError(t, err) require.False(t, unlockedToLocked) require.False(t, updated) // don't run GetKeys, because NeedsRotation is true and it'd just generate a new one h, _ = krw.GetCurrentState() dekData, ok = h.(RaftDEKData) require.True(t, ok) require.Equal(t, keys, dekData.EncryptionKeys) require.True(t, dekData.NeedsRotation) keyBytes2, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.Equal(t, keyBytes, keyBytes2) // going from locked to unlock does not result in the NeedsRotation flag, but does result in // the key being decrypted krw = ca.NewKeyReadWriter(paths.Node, []byte("kek"), RaftDEKData{EncryptionKeys: keys}) require.NoError(t, krw.Write(cert, key, nil)) dekManager, err = NewRaftDEKManager(krw) require.NoError(t, err) keyBytes, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) updated, unlockedToLocked, err = dekManager.MaybeUpdateKEK(ca.KEKData{Version: 2}) require.NoError(t, err) require.False(t, unlockedToLocked) require.True(t, updated) require.Equal(t, keys, dekManager.GetKeys()) require.False(t, dekManager.NeedsRotation()) keyBytes2, err = ioutil.ReadFile(paths.Node.Key) require.NoError(t, err) require.NotEqual(t, keyBytes, keyBytes2) readKRW = ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{}) _, _, err = readKRW.Read() require.NoError(t, err) }
// NeedsRotate returns true if there is a PendingDEK or a NeedsRotation flag func TestRaftDEKManagerNeedsRotateGetKeys(t *testing.T) { tempDir, err := ioutil.TempDir("", "manager-maybe-get-data-") require.NoError(t, err) defer os.RemoveAll(tempDir) paths := ca.NewConfigPaths(tempDir) // if there is no PendingDEK, and no NeedsRotation flag: NeedsRotation=false keys := raft.EncryptionKeys{CurrentDEK: []byte("hello")} dekManager, err := NewRaftDEKManager( ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{EncryptionKeys: keys})) require.NoError(t, err) require.False(t, dekManager.NeedsRotation()) require.Equal(t, keys, dekManager.GetKeys()) // if there is a PendingDEK, and no NeedsRotation flag: NeedsRotation=true keys = raft.EncryptionKeys{CurrentDEK: []byte("hello"), PendingDEK: []byte("another")} dekManager, err = NewRaftDEKManager( ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{EncryptionKeys: keys})) require.NoError(t, err) require.True(t, dekManager.NeedsRotation()) require.Equal(t, keys, dekManager.GetKeys()) // if there is a PendingDEK, and a NeedsRotation flag: NeedsRotation=true keys = raft.EncryptionKeys{CurrentDEK: []byte("hello"), PendingDEK: []byte("another")} dekManager, err = NewRaftDEKManager( ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{ EncryptionKeys: keys, NeedsRotation: true, })) require.NoError(t, err) require.True(t, dekManager.NeedsRotation()) require.Equal(t, keys, dekManager.GetKeys()) // if there no PendingDEK, and a NeedsRotation flag: NeedsRotation=true and // GetKeys attempts to create a pending key and write it to disk. However, writing // will error (because there is no key on disk atm), and then the original keys will // be returned. keys = raft.EncryptionKeys{CurrentDEK: []byte("hello")} krw := ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{ EncryptionKeys: keys, NeedsRotation: true, }) dekManager, err = NewRaftDEKManager(krw) require.NoError(t, err) require.True(t, dekManager.NeedsRotation()) require.Equal(t, keys, dekManager.GetKeys()) h, _ := krw.GetCurrentState() dekData, ok := h.(RaftDEKData) require.True(t, ok) require.True(t, dekData.NeedsRotation) // if there no PendingDEK, and a NeedsRotation flag: NeedsRotation=true and // GetKeys attempts to create a pending key and write it to disk. If successful, // it returns the new keys keys = raft.EncryptionKeys{CurrentDEK: []byte("hello")} krw = ca.NewKeyReadWriter(paths.Node, nil, RaftDEKData{ EncryptionKeys: keys, NeedsRotation: true, }) dekManager, err = NewRaftDEKManager(krw) require.NoError(t, err) cert, key, err := cautils.CreateRootCertAndKey("cn") require.NoError(t, err) require.NoError(t, krw.Write(cert, key, nil)) require.True(t, dekManager.NeedsRotation()) updatedKeys := dekManager.GetKeys() require.Equal(t, keys.CurrentDEK, updatedKeys.CurrentDEK) require.NotNil(t, updatedKeys.PendingDEK) require.True(t, dekManager.NeedsRotation()) h, _ = krw.GetCurrentState() dekData, ok = h.(RaftDEKData) require.True(t, ok) require.False(t, dekData.NeedsRotation) }