github.com/crowdsecurity/crowdsec@v1.6.1/cmd/crowdsec-cli/hub.go (about)

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