github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarm-rafttool/common_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	"github.com/coreos/etcd/pkg/fileutil"
    11  	"github.com/coreos/etcd/raft/raftpb"
    12  	"github.com/coreos/etcd/wal/walpb"
    13  	"github.com/docker/swarmkit/ca"
    14  	"github.com/docker/swarmkit/ca/testutils"
    15  	"github.com/docker/swarmkit/manager"
    16  	"github.com/docker/swarmkit/manager/encryption"
    17  	"github.com/docker/swarmkit/manager/state/raft"
    18  	"github.com/docker/swarmkit/manager/state/raft/storage"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  // writeFakeRaftData writes the given snapshot and some generated WAL data to given "snap" and "wal" directories
    23  func writeFakeRaftData(t *testing.T, stateDir string, snapshot *raftpb.Snapshot, wf storage.WALFactory, sf storage.SnapFactory) {
    24  	snapDir := filepath.Join(stateDir, "raft", "snap-v3-encrypted")
    25  	walDir := filepath.Join(stateDir, "raft", "wal-v3-encrypted")
    26  	require.NoError(t, os.MkdirAll(snapDir, 0755))
    27  
    28  	wsn := walpb.Snapshot{}
    29  	if snapshot != nil {
    30  		require.NoError(t, sf.New(snapDir).SaveSnap(*snapshot))
    31  
    32  		wsn.Index = snapshot.Metadata.Index
    33  		wsn.Term = snapshot.Metadata.Term
    34  	}
    35  
    36  	var entries []raftpb.Entry
    37  	for i := wsn.Index + 1; i < wsn.Index+6; i++ {
    38  		entries = append(entries, raftpb.Entry{
    39  			Term:  wsn.Term + 1,
    40  			Index: i,
    41  			Data:  []byte(fmt.Sprintf("v3Entry %d", i)),
    42  		})
    43  	}
    44  
    45  	walWriter, err := wf.Create(walDir, []byte("v3metadata"))
    46  	require.NoError(t, err)
    47  	require.NoError(t, walWriter.SaveSnapshot(wsn))
    48  	require.NoError(t, walWriter.Save(raftpb.HardState{}, entries))
    49  	require.NoError(t, walWriter.Close())
    50  }
    51  
    52  func TestDecrypt(t *testing.T) {
    53  	tempdir, err := ioutil.TempDir("", "rafttool")
    54  	require.NoError(t, err)
    55  	defer os.RemoveAll(tempdir)
    56  
    57  	kek := []byte("kek")
    58  	dek := []byte("dek")
    59  	unlockKey := encryption.HumanReadableKey(kek)
    60  
    61  	// write a key to disk, else we won't be able to decrypt anything
    62  	paths := certPaths(tempdir)
    63  	krw := ca.NewKeyReadWriter(paths.Node, kek,
    64  		manager.RaftDEKData{EncryptionKeys: raft.EncryptionKeys{CurrentDEK: dek}})
    65  	cert, key, err := testutils.CreateRootCertAndKey("not really a root, just need cert and key")
    66  	require.NoError(t, err)
    67  	require.NoError(t, krw.Write(cert, key, nil))
    68  
    69  	// create the encrypted v3 directory
    70  	origSnapshot := raftpb.Snapshot{
    71  		Data: []byte("snapshot"),
    72  		Metadata: raftpb.SnapshotMetadata{
    73  			Index: 1,
    74  			Term:  1,
    75  		},
    76  	}
    77  	e, d := encryption.Defaults(dek, false)
    78  	writeFakeRaftData(t, tempdir, &origSnapshot, storage.NewWALFactory(e, d), storage.NewSnapFactory(e, d))
    79  
    80  	outdir := filepath.Join(tempdir, "outdir")
    81  	// if we use the wrong unlock key, we can't actually decrypt anything.  The output directory won't get created.
    82  	err = decryptRaftData(tempdir, outdir, "")
    83  	require.IsType(t, ca.ErrInvalidKEK{}, err)
    84  	require.False(t, fileutil.Exist(outdir))
    85  
    86  	// Using the right unlock key, we produce data that is unencrypted
    87  	require.NoError(t, decryptRaftData(tempdir, outdir, unlockKey))
    88  	require.True(t, fileutil.Exist(outdir))
    89  
    90  	// The snapshot directory is readable by the regular snapshotter
    91  	snapshot, err := storage.OriginalSnap.New(filepath.Join(outdir, "snap-decrypted")).Load()
    92  	require.NoError(t, err)
    93  	require.NotNil(t, snapshot)
    94  	require.Equal(t, origSnapshot, *snapshot)
    95  
    96  	// The wals are readable by the regular wal
    97  	walreader, err := storage.OriginalWAL.Open(filepath.Join(outdir, "wal-decrypted"), walpb.Snapshot{Index: 1, Term: 1})
    98  	require.NoError(t, err)
    99  	metadata, _, entries, err := walreader.ReadAll()
   100  	require.NoError(t, err)
   101  	require.Equal(t, []byte("v3metadata"), metadata)
   102  	require.Len(t, entries, 5)
   103  }