// showDifference compares the propose and the config-part func (cfg *ciscConfig) showDifference() { if cfg.Proposed == nil { log.Info("No proposed config found") return } for k, v := range cfg.Proposed.Data { orig, ok := cfg.Config.Data[k] if !ok || v != orig { log.Info("New or changed key:", k) } } for k := range cfg.Config.Data { _, ok := cfg.Proposed.Data[k] if !ok { log.Info("Deleted key:", k) } } for dev, pub := range cfg.Proposed.Device { if _, exists := cfg.Config.Device[dev]; !exists { log.Infof("New device: %s / %s", dev, pub.Point.String()) } } for dev := range cfg.Config.Device { if _, exists := cfg.Proposed.Device[dev]; !exists { log.Info("Deleted device:", dev) } } }
// shows only the keys, but not the data func (cfg *ciscConfig) showKeys() { for d := range cfg.Config.Device { log.Info("Connected device", d) } for k := range cfg.Config.Data { log.Info("Key set", k) } }
func followAdd(c *cli.Context) error { if c.NArg() < 2 { log.Fatal("Please give a group-definition, an ID, and optionally a service-name of the skipchain to follow") } cfg, _ := loadConfig(c) group := getGroup(c) idBytes, err := hex.DecodeString(c.Args().Get(1)) log.ErrFatal(err) id := identity.ID(idBytes) newID, err := identity.NewIdentityFromCothority(group.Roster, id) log.ErrFatal(err) if c.NArg() == 3 { newID.DeviceName = c.Args().Get(2) } else { var err error newID.DeviceName, err = os.Hostname() log.ErrFatal(err) log.Info("Using", newID.DeviceName, "as the device-name.") } cfg.Follow = append(cfg.Follow, newID) cfg.writeAuthorizedKeys(c) // Identity needs to exist, else saving/loading will fail. For // followers it doesn't matter if the identity will be overwritten, // as it is not used. cfg.Identity = newID return cfg.saveConfig(c) }
func configList(c *cli.Context) error { cfg := loadConfigOrFail(c) log.Info("Account name:", cfg.DeviceName) log.Infof("Identity-ID: %x", cfg.ID) if c.Bool("d") { log.Info(cfg.Config.Data) } else { cfg.showKeys() } if c.Bool("p") { if cfg.Proposed != nil { log.Infof("Proposed config: %s", cfg.Proposed) } else { log.Info("No proposed config") } } return nil }
// Config contacts all servers and verifies if it receives a valid // signature from each. // If the roster is empty it will return an error. // If a server doesn't reply in time, it will return an error. func Config(tomlFileName string) error { f, err := os.Open(tomlFileName) log.ErrFatal(err, "Couldn't open group definition file") group, err := config.ReadGroupDescToml(f) log.ErrFatal(err, "Error while reading group definition file", err) if len(group.Roster.List) == 0 { log.ErrFatalf(err, "Empty entity or invalid group defintion in: %s", tomlFileName) } log.Info("Checking the availability and responsiveness of the servers in the group...") return Servers(group) }
/* * Identity-related commands */ func idCreate(c *cli.Context) error { log.Info("Creating id") if c.NArg() == 0 { log.Fatal("Please give at least a group-definition") } group := getGroup(c) name, err := os.Hostname() log.ErrFatal(err) if c.NArg() > 1 { name = c.Args().Get(1) } log.Info("Creating new blockchain-identity for", name) thr := c.Int("threshold") cfg := &ciscConfig{Identity: identity.NewIdentity(group.Roster, thr, name)} log.ErrFatal(cfg.CreateIdentity()) log.Infof("IC is %x", cfg.ID) log.Infof("Config to be saved: %+v", cfg.Identity.Cothority) return cfg.saveConfig(c) }
/* * Commands related to the config in general */ func configUpdate(c *cli.Context) error { cfg := loadConfigOrFail(c) log.ErrFatal(cfg.ConfigUpdate()) log.ErrFatal(cfg.ProposeUpdate()) log.Info("Successfully updated") log.ErrFatal(cfg.saveConfig(c)) if cfg.Proposed != nil { cfg.showDifference() } else { cfg.showKeys() } return nil }
// writes the ssh-keys to an 'authorized_keys'-file func (cfg *ciscConfig) writeAuthorizedKeys(c *cli.Context) { var keys []string dir, _ := sshDirConfig(c) authFile := dir + "/authorized_keys" // Make backup b, err := ioutil.ReadFile(authFile) if err == nil { err = ioutil.WriteFile(authFile+".back", b, 0600) log.ErrFatal(err) } log.Info("Made a backup of your", authFile, "before creating new one.") for _, f := range cfg.Follow { log.Lvlf2("Parsing IC %x", f.ID) for _, s := range f.Config.GetIntermediateColumn("ssh", f.DeviceName) { pub := f.Config.GetValue("ssh", s, f.DeviceName) log.Lvlf2("Value of %s is %s", s, pub) log.Info("Writing key for", s, "to authorized_keys") keys = append(keys, pub+" "+s+"@"+f.DeviceName) } } err = ioutil.WriteFile(authFile, []byte(strings.Join(keys, "\n")), 0600) log.ErrFatal(err) }
func configVote(c *cli.Context) error { cfg := loadConfigOrFail(c) log.ErrFatal(cfg.ConfigUpdate()) log.ErrFatal(cfg.ProposeUpdate()) if cfg.Proposed == nil { log.Info("No proposed config") return nil } if c.NArg() == 0 { cfg.showDifference() if !config.InputYN(true, "Do you want to accept the changes") { return nil } } if strings.ToLower(c.Args().First()) == "n" { return nil } log.ErrFatal(cfg.ProposeVote(true)) return cfg.saveConfig(c) }
func idConnect(c *cli.Context) error { log.Info("Connecting") name, err := os.Hostname() log.ErrFatal(err) switch c.NArg() { case 2: // We'll get all arguments after case 3: name = c.Args().Get(2) default: log.Fatal("Please give the following arguments: group.toml id [hostname]", c.NArg()) } group := getGroup(c) idBytes, err := hex.DecodeString(c.Args().Get(1)) log.ErrFatal(err) id := identity.ID(idBytes) cfg := &ciscConfig{Identity: identity.NewIdentity(group.Roster, 0, name)} cfg.AttachToIdentity(id) log.Infof("Public key: %s", cfg.Proposed.Device[cfg.DeviceName].Point.String()) return cfg.saveConfig(c) }