package main import ( "errors" "flag" "fmt" "os" "github.com/loyaly/behavision-server/internal/broker" ) // broker-init converts Mosquitto's passwd file into the dynamic-security // plugin's store, once, at cutover. After it the broker is driven over MQTT // and the passwd and acl files are no longer read. func runBrokerInit(args []string) error { fs := flag.NewFlagSet("broker-init", flag.ExitOnError) passwd := fs.String("passwd", "", "path to the mosquitto passwd file to convert") out := fs.String("out", "", "where to write dynamic-security.json (must be writable by the broker)") backend := fs.String("backend-user", "behavision-backend", "the server's own broker username; becomes the plugin admin") health := fs.String("health-user", "health", "the healthcheck username") fs.Usage = func() { fmt.Fprintf(os.Stderr, `usage: behavision-server broker-init -passwd FILE -out FILE Converts a mosquitto_passwd file into the dynamic-security plugin's store, keeping every password hash exactly as it is, so no shop PC has to be re-claimed. Then in mosquitto.conf replace password_file/acl_file with: per_listener_settings false plugin /usr/lib/mosquitto_dynamic_security.so plugin_opt_config_file /mosquitto/data/dynamic-security.json and restart the broker. From then on 'provision site' and POST /api/sites register a shop's login themselves. `) fs.PrintDefaults() } if err := fs.Parse(args); err != nil { return err } if *passwd == "" || *out == "" { fs.Usage() return errors.New("-passwd and -out are required") } f, err := os.Open(*passwd) if err != nil { return err } defer f.Close() st, err := broker.FromPasswd(f, *backend, *health) if err != nil { return err } if _, err := os.Stat(*out); err == nil { return fmt.Errorf("%s already exists - refusing to overwrite a live store", *out) } w, err := os.OpenFile(*out, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600) if err != nil { return err } defer w.Close() if err := st.Encode(w); err != nil { return err } fmt.Printf("wrote %s: %d clients, %d roles\n", *out, len(st.Clients), len(st.Roles)) for _, c := range st.Clients { fmt.Printf(" %-28s %s\n", c.Username, c.Roles[0].Rolename) } return nil }