package main import ( "fmt" "nadir/internal/auth" ) // tokenDBPath holds machine credentials, alongside the other SQLite stores. The // running server and this CLI both open it (WAL handles the sharing). const tokenDBPath = "/var/lib/nadir/tokens.db" // tokenCmd implements `nadir token add|rm|ls`, the mint/revoke surface for // machine credentials. Minting and revoking take effect immediately - the // server reads tokenDBPath live, so no restart is needed. Granting access is a // separate step: assign the token name a role in config.yaml (see `add` output). func tokenCmd(args []string) error { store, err := auth.NewTokenStore(tokenDBPath) if err != nil { return err } defer store.Close() if len(args) == 0 { return fmt.Errorf("usage: nadir token add | rm | ls") } switch args[0] { case "add": if len(args) != 2 { return fmt.Errorf("usage: nadir token add ") } name := args[1] raw, err := store.Create(name) if err != nil { return err } fmt.Printf("Token created for %q. Copy it now - it is not stored or shown again:\n\n %s\n\n", name, raw) fmt.Printf("Use it as a header: Authorization: Bearer nad_***\n") fmt.Printf("Grant it access by assigning a role in config.yaml, then restart nadir:\n\n assignments:\n %s: [auditor]\n", name) return nil case "rm": if len(args) != 2 { return fmt.Errorf("usage: nadir token rm ") } if err := store.Delete(args[1]); err != nil { return err } fmt.Printf("Revoked token %q (effective immediately).\n", args[1]) return nil case "ls": infos, err := store.List() if err != nil { return err } if len(infos) == 0 { fmt.Println("no tokens") return nil } for _, t := range infos { fmt.Printf("%-30s created %s\n", t.Name, t.Created.Format("2006-01-02 15:04:05 UTC")) } return nil default: return fmt.Errorf("unknown token subcommand %q (want add|rm|ls)", args[0]) } }