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

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/coreos/etcd/raft/raftpb"
    11  	"github.com/coreos/etcd/snap"
    12  	"github.com/coreos/etcd/wal/walpb"
    13  	"github.com/docker/swarmkit/api"
    14  	"github.com/docker/swarmkit/manager/encryption"
    15  	"github.com/docker/swarmkit/manager/state/raft/storage"
    16  	"github.com/docker/swarmkit/manager/state/store"
    17  	"github.com/gogo/protobuf/proto"
    18  )
    19  
    20  func loadData(swarmdir, unlockKey string) (*storage.WALData, *raftpb.Snapshot, error) {
    21  	snapDir := filepath.Join(swarmdir, "raft", "snap-v3-encrypted")
    22  	walDir := filepath.Join(swarmdir, "raft", "wal-v3-encrypted")
    23  
    24  	var (
    25  		snapFactory storage.SnapFactory
    26  		walFactory  storage.WALFactory
    27  	)
    28  
    29  	_, err := os.Stat(walDir)
    30  	if err == nil {
    31  		// Encrypted WAL is present
    32  		krw, err := getKRW(swarmdir, unlockKey)
    33  		if err != nil {
    34  			return nil, nil, err
    35  		}
    36  		deks, err := getDEKData(krw)
    37  		if err != nil {
    38  			return nil, nil, err
    39  		}
    40  
    41  		// always set FIPS=false, because we want to decrypt logs stored using any
    42  		// algorithm, not just FIPS-compatible ones
    43  		_, d := encryption.Defaults(deks.CurrentDEK, false)
    44  		if deks.PendingDEK == nil {
    45  			_, d2 := encryption.Defaults(deks.PendingDEK, false)
    46  			d = encryption.NewMultiDecrypter(d, d2)
    47  		}
    48  
    49  		walFactory = storage.NewWALFactory(encryption.NoopCrypter, d)
    50  		snapFactory = storage.NewSnapFactory(encryption.NoopCrypter, d)
    51  	} else {
    52  		// Try unencrypted WAL
    53  		snapDir = filepath.Join(swarmdir, "raft", "snap")
    54  		walDir = filepath.Join(swarmdir, "raft", "wal")
    55  
    56  		walFactory = storage.OriginalWAL
    57  		snapFactory = storage.OriginalSnap
    58  	}
    59  
    60  	var walsnap walpb.Snapshot
    61  	snapshot, err := snapFactory.New(snapDir).Load()
    62  	if err != nil && err != snap.ErrNoSnapshot {
    63  		return nil, nil, err
    64  	}
    65  	if snapshot != nil {
    66  		walsnap.Index = snapshot.Metadata.Index
    67  		walsnap.Term = snapshot.Metadata.Term
    68  	}
    69  
    70  	wal, walData, err := storage.ReadRepairWAL(context.Background(), walDir, walsnap, walFactory)
    71  	if err != nil {
    72  		return nil, nil, err
    73  	}
    74  	wal.Close()
    75  
    76  	return &walData, snapshot, nil
    77  }
    78  
    79  func dumpWAL(swarmdir, unlockKey string, start, end uint64, redact bool) error {
    80  	walData, _, err := loadData(swarmdir, unlockKey)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	for _, ent := range walData.Entries {
    86  		if (start == 0 || ent.Index >= start) && (end == 0 || ent.Index <= end) {
    87  			fmt.Printf("Entry Index=%d, Term=%d, Type=%s:\n", ent.Index, ent.Term, ent.Type.String())
    88  			switch ent.Type {
    89  			case raftpb.EntryConfChange:
    90  				cc := &raftpb.ConfChange{}
    91  				err := proto.Unmarshal(ent.Data, cc)
    92  				if err != nil {
    93  					return err
    94  				}
    95  
    96  				fmt.Println("Conf change type:", cc.Type.String())
    97  				fmt.Printf("Node ID: %x\n\n", cc.NodeID)
    98  
    99  			case raftpb.EntryNormal:
   100  				r := &api.InternalRaftRequest{}
   101  				err := proto.Unmarshal(ent.Data, r)
   102  				if err != nil {
   103  					return err
   104  				}
   105  
   106  				if redact {
   107  					// redact sensitive information
   108  					for _, act := range r.Action {
   109  						target := act.GetTarget()
   110  						switch actype := target.(type) {
   111  						case *api.StoreAction_Cluster:
   112  							actype.Cluster.UnlockKeys = []*api.EncryptionKey{}
   113  							actype.Cluster.NetworkBootstrapKeys = []*api.EncryptionKey{}
   114  							actype.Cluster.RootCA = api.RootCA{}
   115  							actype.Cluster.Spec.CAConfig = api.CAConfig{}
   116  						case *api.StoreAction_Secret:
   117  							actype.Secret.Spec.Data = []byte("SECRET REDACTED")
   118  						case *api.StoreAction_Config:
   119  							actype.Config.Spec.Data = []byte("CONFIG REDACTED")
   120  						case *api.StoreAction_Task:
   121  							if container := actype.Task.Spec.GetContainer(); container != nil {
   122  								container.Env = []string{"ENVVARS REDACTED"}
   123  								if container.PullOptions != nil {
   124  									container.PullOptions.RegistryAuth = "REDACTED"
   125  								}
   126  							}
   127  						case *api.StoreAction_Service:
   128  							if container := actype.Service.Spec.Task.GetContainer(); container != nil {
   129  								container.Env = []string{"ENVVARS REDACTED"}
   130  								if container.PullOptions != nil {
   131  									container.PullOptions.RegistryAuth = "REDACTED"
   132  								}
   133  							}
   134  						}
   135  					}
   136  				}
   137  
   138  				if err := proto.MarshalText(os.Stdout, r); err != nil {
   139  					return err
   140  				}
   141  				fmt.Println()
   142  			}
   143  		}
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  func dumpSnapshot(swarmdir, unlockKey string, redact bool) error {
   150  	_, snapshot, err := loadData(swarmdir, unlockKey)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	if snapshot == nil {
   156  		return errors.New("no snapshot found")
   157  	}
   158  
   159  	s := &api.Snapshot{}
   160  	if err := proto.Unmarshal(snapshot.Data, s); err != nil {
   161  		return err
   162  	}
   163  	if s.Version != api.Snapshot_V0 {
   164  		return fmt.Errorf("unrecognized snapshot version %d", s.Version)
   165  	}
   166  
   167  	fmt.Println("Active members:")
   168  	for _, member := range s.Membership.Members {
   169  		fmt.Printf(" NodeID=%s, RaftID=%x, Addr=%s\n", member.NodeID, member.RaftID, member.Addr)
   170  	}
   171  	fmt.Println()
   172  
   173  	fmt.Println("Removed members:")
   174  	for _, member := range s.Membership.Removed {
   175  		fmt.Printf(" RaftID=%x\n", member)
   176  	}
   177  	fmt.Println()
   178  
   179  	if redact {
   180  		for _, cluster := range s.Store.Clusters {
   181  			if cluster != nil {
   182  				// expunge everything that may have key material
   183  				cluster.RootCA = api.RootCA{}
   184  				cluster.NetworkBootstrapKeys = []*api.EncryptionKey{}
   185  				cluster.UnlockKeys = []*api.EncryptionKey{}
   186  				cluster.Spec.CAConfig = api.CAConfig{}
   187  			}
   188  		}
   189  		for _, secret := range s.Store.Secrets {
   190  			if secret != nil {
   191  				secret.Spec.Data = []byte("SECRET REDACTED")
   192  			}
   193  		}
   194  		for _, config := range s.Store.Configs {
   195  			if config != nil {
   196  				config.Spec.Data = []byte("CONFIG REDACTED")
   197  			}
   198  		}
   199  		for _, task := range s.Store.Tasks {
   200  			if task != nil {
   201  				if container := task.Spec.GetContainer(); container != nil {
   202  					container.Env = []string{"ENVVARS REDACTED"}
   203  					if container.PullOptions != nil {
   204  						container.PullOptions.RegistryAuth = "REDACTED"
   205  					}
   206  				}
   207  			}
   208  		}
   209  		for _, service := range s.Store.Services {
   210  			if service != nil {
   211  				if container := service.Spec.Task.GetContainer(); container != nil {
   212  					container.Env = []string{"ENVVARS REDACTED"}
   213  					if container.PullOptions != nil {
   214  						container.PullOptions.RegistryAuth = "REDACTED"
   215  					}
   216  				}
   217  			}
   218  		}
   219  	}
   220  
   221  	fmt.Println("Objects:")
   222  	if err := proto.MarshalText(os.Stdout, &s.Store); err != nil {
   223  		return err
   224  	}
   225  	fmt.Println()
   226  
   227  	return nil
   228  }
   229  
   230  // objSelector provides some criteria to select objects.
   231  type objSelector struct {
   232  	all  bool
   233  	id   string
   234  	name string
   235  }
   236  
   237  func bySelection(selector objSelector) store.By {
   238  	if selector.all {
   239  		return store.All
   240  	}
   241  	if selector.name != "" {
   242  		return store.ByName(selector.name)
   243  	}
   244  
   245  	// find nothing
   246  	return store.Or()
   247  }
   248  
   249  func dumpObject(swarmdir, unlockKey, objType string, selector objSelector) error {
   250  	memStore := store.NewMemoryStore(nil)
   251  	defer memStore.Close()
   252  
   253  	walData, snapshot, err := loadData(swarmdir, unlockKey)
   254  	if err != nil {
   255  		return err
   256  	}
   257  
   258  	if snapshot != nil {
   259  		var s api.Snapshot
   260  		if err := s.Unmarshal(snapshot.Data); err != nil {
   261  			return err
   262  		}
   263  		if s.Version != api.Snapshot_V0 {
   264  			return fmt.Errorf("unrecognized snapshot version %d", s.Version)
   265  		}
   266  
   267  		if err := memStore.Restore(&s.Store); err != nil {
   268  			return err
   269  		}
   270  	}
   271  
   272  	for _, ent := range walData.Entries {
   273  		if snapshot != nil && ent.Index <= snapshot.Metadata.Index {
   274  			continue
   275  		}
   276  
   277  		if ent.Type != raftpb.EntryNormal {
   278  			continue
   279  		}
   280  
   281  		r := &api.InternalRaftRequest{}
   282  		err := proto.Unmarshal(ent.Data, r)
   283  		if err != nil {
   284  			return err
   285  		}
   286  
   287  		if r.Action != nil {
   288  			if err := memStore.ApplyStoreActions(r.Action); err != nil {
   289  				return err
   290  			}
   291  		}
   292  	}
   293  
   294  	var objects []proto.Message
   295  	memStore.View(func(tx store.ReadTx) {
   296  		switch objType {
   297  		case "node":
   298  			if selector.id != "" {
   299  				object := store.GetNode(tx, selector.id)
   300  				if object != nil {
   301  					objects = append(objects, object)
   302  				}
   303  			}
   304  
   305  			var results []*api.Node
   306  			results, err = store.FindNodes(tx, bySelection(selector))
   307  			if err != nil {
   308  				return
   309  			}
   310  			for _, o := range results {
   311  				objects = append(objects, o)
   312  			}
   313  		case "service":
   314  			if selector.id != "" {
   315  				object := store.GetService(tx, selector.id)
   316  				if object != nil {
   317  					objects = append(objects, object)
   318  				}
   319  			}
   320  
   321  			var results []*api.Service
   322  			results, err = store.FindServices(tx, bySelection(selector))
   323  			if err != nil {
   324  				return
   325  			}
   326  			for _, o := range results {
   327  				objects = append(objects, o)
   328  			}
   329  		case "task":
   330  			if selector.id != "" {
   331  				object := store.GetTask(tx, selector.id)
   332  				if object != nil {
   333  					objects = append(objects, object)
   334  				}
   335  			}
   336  
   337  			var results []*api.Task
   338  			results, err = store.FindTasks(tx, bySelection(selector))
   339  			if err != nil {
   340  				return
   341  			}
   342  			for _, o := range results {
   343  				objects = append(objects, o)
   344  			}
   345  		case "network":
   346  			if selector.id != "" {
   347  				object := store.GetNetwork(tx, selector.id)
   348  				if object != nil {
   349  					objects = append(objects, object)
   350  				}
   351  			}
   352  
   353  			var results []*api.Network
   354  			results, err = store.FindNetworks(tx, bySelection(selector))
   355  			if err != nil {
   356  				return
   357  			}
   358  			for _, o := range results {
   359  				objects = append(objects, o)
   360  			}
   361  		case "cluster":
   362  			if selector.id != "" {
   363  				object := store.GetCluster(tx, selector.id)
   364  				if object != nil {
   365  					objects = append(objects, object)
   366  				}
   367  			}
   368  
   369  			var results []*api.Cluster
   370  			results, err = store.FindClusters(tx, bySelection(selector))
   371  			if err != nil {
   372  				return
   373  			}
   374  			for _, o := range results {
   375  				objects = append(objects, o)
   376  			}
   377  		case "secret":
   378  			if selector.id != "" {
   379  				object := store.GetSecret(tx, selector.id)
   380  				if object != nil {
   381  					objects = append(objects, object)
   382  				}
   383  			}
   384  
   385  			var results []*api.Secret
   386  			results, err = store.FindSecrets(tx, bySelection(selector))
   387  			if err != nil {
   388  				return
   389  			}
   390  			for _, o := range results {
   391  				objects = append(objects, o)
   392  			}
   393  		case "config":
   394  			if selector.id != "" {
   395  				object := store.GetConfig(tx, selector.id)
   396  				if object != nil {
   397  					objects = append(objects, object)
   398  				}
   399  			}
   400  
   401  			var results []*api.Config
   402  			results, err = store.FindConfigs(tx, bySelection(selector))
   403  			if err != nil {
   404  				return
   405  			}
   406  			for _, o := range results {
   407  				objects = append(objects, o)
   408  			}
   409  		case "resource":
   410  			if selector.id != "" {
   411  				object := store.GetResource(tx, selector.id)
   412  				if object != nil {
   413  					objects = append(objects, object)
   414  				}
   415  			}
   416  
   417  			var results []*api.Resource
   418  			results, err = store.FindResources(tx, bySelection(selector))
   419  			if err != nil {
   420  				return
   421  			}
   422  			for _, o := range results {
   423  				objects = append(objects, o)
   424  			}
   425  		case "extension":
   426  			if selector.id != "" {
   427  				object := store.GetExtension(tx, selector.id)
   428  				if object != nil {
   429  					objects = append(objects, object)
   430  				}
   431  			}
   432  
   433  			var results []*api.Extension
   434  			results, err = store.FindExtensions(tx, bySelection(selector))
   435  			if err != nil {
   436  				return
   437  			}
   438  			for _, o := range results {
   439  				objects = append(objects, o)
   440  			}
   441  		default:
   442  			err = fmt.Errorf("unrecognized object type %s", objType)
   443  		}
   444  	})
   445  
   446  	if err != nil {
   447  		return err
   448  	}
   449  
   450  	if len(objects) == 0 {
   451  		return fmt.Errorf("no matching objects found")
   452  	}
   453  
   454  	for _, object := range objects {
   455  		if err := proto.MarshalText(os.Stdout, object); err != nil {
   456  			return err
   457  		}
   458  		fmt.Println()
   459  	}
   460  
   461  	return nil
   462  }