main.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "strings"
  7. "apiote.xyz/p/eeze/secrets"
  8. "git.sr.ht/~sircmpwn/getopt"
  9. "git.sr.ht/~sircmpwn/go-bare"
  10. )
  11. type Fields struct {
  12. fields *[]string
  13. }
  14. func (f Fields) String() string {
  15. return strings.Join(*f.fields, ",")
  16. }
  17. func (f Fields) Set(s string) error {
  18. fields := strings.Split(s, ",")
  19. *f.fields = fields
  20. return nil
  21. }
  22. func fullUsage() {
  23. fmt.Fprintln(getopt.CommandLine.Output(), "Usage of eeze:")
  24. fmt.Fprintln(getopt.CommandLine.Output(), `
  25. eeze -A
  26. add secret(s);
  27. reads a
  28. []map[string]struct{
  29. Hidden bool
  30. Value string
  31. }
  32. from stdin as dirty
  33. eeze -D -i <id>
  34. delete a secret by <id>
  35. eeze -E
  36. export all secrets as dirty
  37. eeze -G [-e|-p] [-f <fields>] (-i <id>|-l <label> [-u <username>]|-s <url> [-u <username>])
  38. get secrets
  39. -e export as dirty
  40. -p pretty print
  41. -f <fields> get only fields for secrets; fields are comma separated
  42. -i <id> get secret by id field
  43. -l <label> get secret by label field
  44. -s <url> get secret by url field
  45. -u <username> filter secrets by username field
  46. eeze -L
  47. list all secrets in format "id|label" or "id|label: username"
  48. eeze -Ik
  49. list credentials, name and type
  50. eeze -Ir
  51. recreate secrets index
  52. eeze -Ia -n <name> (-p|-2)
  53. add credential with <name>
  54. -p password credential
  55. -2 FIDO2 credential
  56. eeze -Id -n <name>
  57. delete credential named <name>
  58. eeze -h
  59. show this help and exit`)
  60. os.Exit(0)
  61. }
  62. func shortUsage() {
  63. fmt.Fprintln(getopt.CommandLine.Output(), "Usage of eeze:")
  64. fmt.Fprintln(getopt.CommandLine.Output(), `
  65. eeze -A
  66. eeze -D -i <id>
  67. eeze -E
  68. eeze -G [-e|-p] [-f <fields>] (-i <id>|-l <label> [-u <username>]|-s <url> [-u <username>])
  69. eeze -L
  70. eeze -Ik
  71. eeze -Ir
  72. eeze -Ia -n <name> (-p|-2)
  73. eeze -Id -n <name>
  74. eeze -h`)
  75. os.Exit(0)
  76. }
  77. func main() {
  78. bare.RegisterUnion((*secrets.Credential)(nil)).
  79. Member(*new(secrets.FidoCredential), 0).
  80. Member(*new(secrets.PasswordCredential), 1)
  81. I := getopt.Bool("I", false, "Init")
  82. A := getopt.Bool("A", false, "Add")
  83. G := getopt.Bool("G", false, "Get")
  84. E := getopt.Bool("E", false, "Export")
  85. L := getopt.Bool("L", false, "List")
  86. D := getopt.Bool("D", false, "Delete")
  87. addCred := getopt.Bool("a", false, "in I, add credential")
  88. delCred := getopt.Bool("d", false, "in I, delete credential")
  89. listCreds := getopt.Bool("k", false, "in I, list credentials")
  90. credName := getopt.String("n", "", "in I, credential name")
  91. recreateIndex := getopt.Bool("r", false, "in I, recreate index")
  92. fido2 := getopt.Bool("2", false, "in I, add FIDO2 credential")
  93. p := getopt.Bool("p", false, "in I, add password; in G, add headers")
  94. idGet := getopt.String("i", "", "in G and D, secret ID")
  95. labelGet := getopt.String("l", "", "in G, secret label")
  96. urlGet := getopt.String("s", "", "in G, secret URL")
  97. usernameGet := getopt.String("u", "", "in G, secret username")
  98. fields := &[]string{}
  99. getopt.Var(&Fields{fields}, "f", "in G, comma separated fields to show")
  100. export := getopt.Bool("e", false, "in G, export as dirty")
  101. help := getopt.Bool("h", false, "show help")
  102. err := getopt.Parse()
  103. if err != nil {
  104. log.Println("while parsing opts", err)
  105. os.Exit(1)
  106. }
  107. if *help {
  108. getopt.SetOutput(os.Stdout)
  109. fullUsage()
  110. }
  111. err = secrets.InitialiseCredentials()
  112. if err != nil {
  113. log.Println("while initialising", err)
  114. os.Exit(1)
  115. }
  116. if !(*I || *A || *G || *E || *L || *D) {
  117. shortUsage()
  118. }
  119. key, err := secrets.Open()
  120. if err != nil {
  121. log.Println("while opening credentials:", err)
  122. os.Exit(1)
  123. }
  124. switch {
  125. case *E:
  126. entries, err := secrets.List(key)
  127. if err != nil {
  128. log.Println("while listing secrets", err)
  129. os.Exit(1)
  130. }
  131. ids := []string{}
  132. for _, entry := range entries {
  133. ids = append(ids, entry.ID)
  134. }
  135. secretsArr, err := secrets.Get(ids, key)
  136. if err != nil {
  137. log.Println("while getting secrets:", err)
  138. os.Exit(1)
  139. }
  140. fmt.Print(secrets.Format(secretsArr, []string{}, true, false))
  141. case *I:
  142. switch {
  143. case *addCred:
  144. if *fido2 && *p {
  145. log.Println("Both FIDO2 and password requested")
  146. os.Exit(1)
  147. }
  148. err := secrets.AddCredential(*fido2, *p, *credName)
  149. if err != nil {
  150. log.Println("while adding credential", err)
  151. os.Exit(1)
  152. }
  153. case *recreateIndex:
  154. err := secrets.RecreateIndex(key)
  155. if err != nil {
  156. log.Println("while recreating index", err)
  157. os.Exit(1)
  158. }
  159. case *delCred:
  160. err := secrets.DelCredential(*credName)
  161. if err != nil {
  162. log.Println("while deleting credential", err)
  163. os.Exit(1)
  164. }
  165. case *listCreds:
  166. err := secrets.ListCredentials()
  167. if err != nil {
  168. log.Println("while listing credentials", err)
  169. os.Exit(1)
  170. }
  171. default:
  172. log.Println("No action given")
  173. os.Exit(1)
  174. }
  175. case *A:
  176. err := secrets.Add(key)
  177. if err != nil {
  178. log.Println("while adding secrets", err)
  179. os.Exit(1)
  180. }
  181. case *D:
  182. err := secrets.Delete(*idGet, key)
  183. if err != nil {
  184. log.Println("while deleting secrets", err)
  185. os.Exit(1)
  186. }
  187. case *G:
  188. if *idGet == "" && *labelGet == "" && *urlGet == "" {
  189. log.Println("none of ID, label, URL given")
  190. os.Exit(1)
  191. }
  192. ids, err := secrets.Filter(*idGet, *labelGet, *urlGet, *usernameGet, key)
  193. if err != nil {
  194. log.Println("while filtering secret IDs:", err)
  195. os.Exit(1)
  196. }
  197. secretsArr, err := secrets.Get(ids, key)
  198. if err != nil {
  199. log.Println("while getting secrets:", err)
  200. os.Exit(1)
  201. }
  202. fmt.Print(secrets.Format(secretsArr, *fields, *export, *p))
  203. case *L:
  204. entries, err := secrets.List(key)
  205. if err != nil {
  206. log.Println("while listing secrets", err)
  207. os.Exit(1)
  208. }
  209. for _, entry := range entries {
  210. fmt.Printf("%s|%s", entry.ID, entry.Label)
  211. if entry.Username != "" {
  212. fmt.Printf(": %s", entry.Username)
  213. }
  214. fmt.Println("")
  215. }
  216. default:
  217. shortUsage()
  218. }
  219. }