hub.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/fatih/color"
  6. log "github.com/sirupsen/logrus"
  7. "github.com/spf13/cobra"
  8. "gopkg.in/yaml.v3"
  9. "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
  10. "github.com/crowdsecurity/crowdsec/pkg/cwhub"
  11. )
  12. type cliHub struct {
  13. cfg configGetter
  14. }
  15. func NewCLIHub(cfg configGetter) *cliHub {
  16. return &cliHub{
  17. cfg: cfg,
  18. }
  19. }
  20. func (cli *cliHub) NewCommand() *cobra.Command {
  21. cmd := &cobra.Command{
  22. Use: "hub [action]",
  23. Short: "Manage hub index",
  24. Long: `Hub management
  25. List/update parsers/scenarios/postoverflows/collections from [Crowdsec Hub](https://hub.crowdsec.net).
  26. The Hub is managed by cscli, to get the latest hub files from [Crowdsec Hub](https://hub.crowdsec.net), you need to update.`,
  27. Example: `cscli hub list
  28. cscli hub update
  29. cscli hub upgrade`,
  30. Args: cobra.ExactArgs(0),
  31. DisableAutoGenTag: true,
  32. }
  33. cmd.AddCommand(cli.newListCmd())
  34. cmd.AddCommand(cli.newUpdateCmd())
  35. cmd.AddCommand(cli.newUpgradeCmd())
  36. cmd.AddCommand(cli.newTypesCmd())
  37. return cmd
  38. }
  39. func (cli *cliHub) list(all bool) error {
  40. hub, err := require.Hub(cli.cfg(), nil, log.StandardLogger())
  41. if err != nil {
  42. return err
  43. }
  44. for _, v := range hub.Warnings {
  45. log.Info(v)
  46. }
  47. for _, line := range hub.ItemStats() {
  48. log.Info(line)
  49. }
  50. items := make(map[string][]*cwhub.Item)
  51. for _, itemType := range cwhub.ItemTypes {
  52. items[itemType], err = selectItems(hub, itemType, nil, !all)
  53. if err != nil {
  54. return err
  55. }
  56. }
  57. err = listItems(color.Output, cwhub.ItemTypes, items, true)
  58. if err != nil {
  59. return err
  60. }
  61. return nil
  62. }
  63. func (cli *cliHub) newListCmd() *cobra.Command {
  64. var all bool
  65. cmd := &cobra.Command{
  66. Use: "list [-a]",
  67. Short: "List all installed configurations",
  68. Args: cobra.ExactArgs(0),
  69. DisableAutoGenTag: true,
  70. RunE: func(_ *cobra.Command, _ []string) error {
  71. return cli.list(all)
  72. },
  73. }
  74. flags := cmd.Flags()
  75. flags.BoolVarP(&all, "all", "a", false, "List disabled items as well")
  76. return cmd
  77. }
  78. func (cli *cliHub) update() error {
  79. local := cli.cfg().Hub
  80. remote := require.RemoteHub(cli.cfg())
  81. // don't use require.Hub because if there is no index file, it would fail
  82. hub, err := cwhub.NewHub(local, remote, true, log.StandardLogger())
  83. if err != nil {
  84. return fmt.Errorf("failed to update hub: %w", err)
  85. }
  86. for _, v := range hub.Warnings {
  87. log.Info(v)
  88. }
  89. return nil
  90. }
  91. func (cli *cliHub) newUpdateCmd() *cobra.Command {
  92. cmd := &cobra.Command{
  93. Use: "update",
  94. Short: "Download the latest index (catalog of available configurations)",
  95. Long: `
  96. Fetches the .index.json file from the hub, containing the list of available configs.
  97. `,
  98. Args: cobra.ExactArgs(0),
  99. DisableAutoGenTag: true,
  100. RunE: func(_ *cobra.Command, _ []string) error {
  101. return cli.update()
  102. },
  103. }
  104. return cmd
  105. }
  106. func (cli *cliHub) upgrade(force bool) error {
  107. hub, err := require.Hub(cli.cfg(), require.RemoteHub(cli.cfg()), log.StandardLogger())
  108. if err != nil {
  109. return err
  110. }
  111. for _, itemType := range cwhub.ItemTypes {
  112. items, err := hub.GetInstalledItems(itemType)
  113. if err != nil {
  114. return err
  115. }
  116. updated := 0
  117. log.Infof("Upgrading %s", itemType)
  118. for _, item := range items {
  119. didUpdate, err := item.Upgrade(force)
  120. if err != nil {
  121. return err
  122. }
  123. if didUpdate {
  124. updated++
  125. }
  126. }
  127. log.Infof("Upgraded %d %s", updated, itemType)
  128. }
  129. return nil
  130. }
  131. func (cli *cliHub) newUpgradeCmd() *cobra.Command {
  132. var force bool
  133. cmd := &cobra.Command{
  134. Use: "upgrade",
  135. Short: "Upgrade all configurations to their latest version",
  136. Long: `
  137. Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if you want the latest versions available.
  138. `,
  139. Args: cobra.ExactArgs(0),
  140. DisableAutoGenTag: true,
  141. RunE: func(_ *cobra.Command, _ []string) error {
  142. return cli.upgrade(force)
  143. },
  144. }
  145. flags := cmd.Flags()
  146. flags.BoolVar(&force, "force", false, "Force upgrade: overwrite tainted and outdated files")
  147. return cmd
  148. }
  149. func (cli *cliHub) types() error {
  150. switch cli.cfg().Cscli.Output {
  151. case "human":
  152. s, err := yaml.Marshal(cwhub.ItemTypes)
  153. if err != nil {
  154. return err
  155. }
  156. fmt.Print(string(s))
  157. case "json":
  158. jsonStr, err := json.Marshal(cwhub.ItemTypes)
  159. if err != nil {
  160. return err
  161. }
  162. fmt.Println(string(jsonStr))
  163. case "raw":
  164. for _, itemType := range cwhub.ItemTypes {
  165. fmt.Println(itemType)
  166. }
  167. }
  168. return nil
  169. }
  170. func (cli *cliHub) newTypesCmd() *cobra.Command {
  171. cmd := &cobra.Command{
  172. Use: "types",
  173. Short: "List supported item types",
  174. Long: `
  175. List the types of supported hub items.
  176. `,
  177. Args: cobra.ExactArgs(0),
  178. DisableAutoGenTag: true,
  179. RunE: func(_ *cobra.Command, _ []string) error {
  180. return cli.types()
  181. },
  182. }
  183. return cmd
  184. }