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

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/coreos/etcd/pkg/fileutil"
    11  	"github.com/coreos/etcd/wal/walpb"
    12  	"github.com/docker/swarmkit/ca"
    13  	"github.com/docker/swarmkit/manager"
    14  	"github.com/docker/swarmkit/manager/encryption"
    15  	"github.com/docker/swarmkit/manager/state/raft/storage"
    16  	"github.com/docker/swarmkit/node"
    17  )
    18  
    19  func certPaths(swarmdir string) *ca.SecurityConfigPaths {
    20  	return ca.NewConfigPaths(filepath.Join(swarmdir, "certificates"))
    21  }
    22  
    23  func getDEKData(krw *ca.KeyReadWriter) (manager.RaftDEKData, error) {
    24  	h, _ := krw.GetCurrentState()
    25  	dekData, ok := h.(manager.RaftDEKData)
    26  	if !ok {
    27  		return manager.RaftDEKData{}, errors.New("cannot read raft dek headers in TLS key")
    28  	}
    29  
    30  	if dekData.CurrentDEK == nil {
    31  		return manager.RaftDEKData{}, errors.New("no raft DEKs available")
    32  	}
    33  
    34  	return dekData, nil
    35  }
    36  
    37  func getKRW(swarmdir, unlockKey string) (*ca.KeyReadWriter, error) {
    38  	var (
    39  		kek []byte
    40  		err error
    41  	)
    42  	if unlockKey != "" {
    43  		kek, err = encryption.ParseHumanReadableKey(unlockKey)
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  	}
    48  	krw := ca.NewKeyReadWriter(certPaths(swarmdir).Node, kek, manager.RaftDEKData{})
    49  	_, _, err = krw.Read() // loads all the key data into the KRW object
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	return krw, nil
    54  }
    55  
    56  func moveDirAside(dirname string) error {
    57  	if fileutil.Exist(dirname) {
    58  		tempdir, err := ioutil.TempDir(filepath.Dir(dirname), filepath.Base(dirname))
    59  		if err != nil {
    60  			return err
    61  		}
    62  		return os.Rename(dirname, tempdir)
    63  	}
    64  	return nil
    65  }
    66  
    67  func decryptRaftData(swarmdir, outdir, unlockKey string) error {
    68  	krw, err := getKRW(swarmdir, unlockKey)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	deks, err := getDEKData(krw)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	// always use false for FIPS, since we want to be able to decrypt logs written using
    78  	// any algorithm (not just FIPS-compatible ones)
    79  	_, d := encryption.Defaults(deks.CurrentDEK, false)
    80  	if deks.PendingDEK == nil {
    81  		_, d2 := encryption.Defaults(deks.PendingDEK, false)
    82  		d = encryption.NewMultiDecrypter(d, d2)
    83  	}
    84  
    85  	snapDir := filepath.Join(outdir, "snap-decrypted")
    86  	if err := moveDirAside(snapDir); err != nil {
    87  		return err
    88  	}
    89  	if err := storage.MigrateSnapshot(
    90  		filepath.Join(swarmdir, "raft", "snap-v3-encrypted"), snapDir,
    91  		storage.NewSnapFactory(encryption.NoopCrypter, d), storage.OriginalSnap); err != nil {
    92  		return err
    93  	}
    94  
    95  	var walsnap walpb.Snapshot
    96  	snap, err := storage.OriginalSnap.New(snapDir).Load()
    97  	if err != nil && !os.IsNotExist(err) {
    98  		return err
    99  	}
   100  	if snap != nil {
   101  		walsnap.Index = snap.Metadata.Index
   102  		walsnap.Term = snap.Metadata.Term
   103  	}
   104  
   105  	walDir := filepath.Join(outdir, "wal-decrypted")
   106  	if err := moveDirAside(walDir); err != nil {
   107  		return err
   108  	}
   109  	return storage.MigrateWALs(context.Background(),
   110  		filepath.Join(swarmdir, "raft", "wal-v3-encrypted"), walDir,
   111  		storage.NewWALFactory(encryption.NoopCrypter, d), storage.OriginalWAL, walsnap)
   112  }
   113  
   114  func downgradeKey(swarmdir, unlockKey string) error {
   115  	var (
   116  		kek []byte
   117  		err error
   118  	)
   119  	if unlockKey != "" {
   120  		kek, err = encryption.ParseHumanReadableKey(unlockKey)
   121  		if err != nil {
   122  			return err
   123  		}
   124  	}
   125  
   126  	n, err := node.New(&node.Config{
   127  		StateDir:  swarmdir,
   128  		UnlockKey: kek,
   129  	})
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	return n.DowngradeKey()
   135  }