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

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	log "github.com/sirupsen/logrus"
     8  	"github.com/spf13/cobra"
     9  	"gopkg.in/tomb.v2"
    10  
    11  	"github.com/crowdsecurity/go-cs-lib/ptr"
    12  
    13  	"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
    14  	"github.com/crowdsecurity/crowdsec/pkg/apiserver"
    15  	"github.com/crowdsecurity/crowdsec/pkg/database"
    16  )
    17  
    18  type cliPapi struct {
    19  	cfg configGetter
    20  }
    21  
    22  func NewCLIPapi(cfg configGetter) *cliPapi {
    23  	return &cliPapi{
    24  		cfg: cfg,
    25  	}
    26  }
    27  
    28  func (cli *cliPapi) NewCommand() *cobra.Command {
    29  	cmd := &cobra.Command{
    30  		Use:               "papi [action]",
    31  		Short:             "Manage interaction with Polling API (PAPI)",
    32  		Args:              cobra.MinimumNArgs(1),
    33  		DisableAutoGenTag: true,
    34  		PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
    35  			cfg := cli.cfg()
    36  			if err := require.LAPI(cfg); err != nil {
    37  				return err
    38  			}
    39  			if err := require.CAPI(cfg); err != nil {
    40  				return err
    41  			}
    42  			if err := require.PAPI(cfg); err != nil {
    43  				return err
    44  			}
    45  
    46  			return nil
    47  		},
    48  	}
    49  
    50  	cmd.AddCommand(cli.NewStatusCmd())
    51  	cmd.AddCommand(cli.NewSyncCmd())
    52  
    53  	return cmd
    54  }
    55  
    56  func (cli *cliPapi) NewStatusCmd() *cobra.Command {
    57  	cmd := &cobra.Command{
    58  		Use:               "status",
    59  		Short:             "Get status of the Polling API",
    60  		Args:              cobra.MinimumNArgs(0),
    61  		DisableAutoGenTag: true,
    62  		RunE: func(_ *cobra.Command, _ []string) error {
    63  			var err error
    64  			cfg := cli.cfg()
    65  			dbClient, err = database.NewClient(cfg.DbConfig)
    66  			if err != nil {
    67  				return fmt.Errorf("unable to initialize database client: %s", err)
    68  			}
    69  
    70  			apic, err := apiserver.NewAPIC(cfg.API.Server.OnlineClient, dbClient, cfg.API.Server.ConsoleConfig, cfg.API.Server.CapiWhitelists)
    71  
    72  			if err != nil {
    73  				return fmt.Errorf("unable to initialize API client: %s", err)
    74  			}
    75  
    76  			papi, err := apiserver.NewPAPI(apic, dbClient, cfg.API.Server.ConsoleConfig, log.GetLevel())
    77  
    78  			if err != nil {
    79  				return fmt.Errorf("unable to initialize PAPI client: %s", err)
    80  			}
    81  
    82  			perms, err := papi.GetPermissions()
    83  
    84  			if err != nil {
    85  				return fmt.Errorf("unable to get PAPI permissions: %s", err)
    86  			}
    87  			var lastTimestampStr *string
    88  			lastTimestampStr, err = dbClient.GetConfigItem(apiserver.PapiPullKey)
    89  			if err != nil {
    90  				lastTimestampStr = ptr.Of("never")
    91  			}
    92  			log.Infof("You can successfully interact with Polling API (PAPI)")
    93  			log.Infof("Console plan: %s", perms.Plan)
    94  			log.Infof("Last order received: %s", *lastTimestampStr)
    95  
    96  			log.Infof("PAPI subscriptions:")
    97  			for _, sub := range perms.Categories {
    98  				log.Infof(" - %s", sub)
    99  			}
   100  
   101  			return nil
   102  		},
   103  	}
   104  
   105  	return cmd
   106  }
   107  
   108  func (cli *cliPapi) NewSyncCmd() *cobra.Command {
   109  	cmd := &cobra.Command{
   110  		Use:               "sync",
   111  		Short:             "Sync with the Polling API, pulling all non-expired orders for the instance",
   112  		Args:              cobra.MinimumNArgs(0),
   113  		DisableAutoGenTag: true,
   114  		RunE: func(_ *cobra.Command, _ []string) error {
   115  			var err error
   116  			cfg := cli.cfg()
   117  			t := tomb.Tomb{}
   118  
   119  			dbClient, err = database.NewClient(cfg.DbConfig)
   120  			if err != nil {
   121  				return fmt.Errorf("unable to initialize database client: %s", err)
   122  			}
   123  
   124  			apic, err := apiserver.NewAPIC(cfg.API.Server.OnlineClient, dbClient, cfg.API.Server.ConsoleConfig, cfg.API.Server.CapiWhitelists)
   125  			if err != nil {
   126  				return fmt.Errorf("unable to initialize API client: %s", err)
   127  			}
   128  
   129  			t.Go(apic.Push)
   130  
   131  			papi, err := apiserver.NewPAPI(apic, dbClient, cfg.API.Server.ConsoleConfig, log.GetLevel())
   132  			if err != nil {
   133  				return fmt.Errorf("unable to initialize PAPI client: %s", err)
   134  			}
   135  
   136  			t.Go(papi.SyncDecisions)
   137  
   138  			err = papi.PullOnce(time.Time{}, true)
   139  
   140  			if err != nil {
   141  				return fmt.Errorf("unable to sync decisions: %s", err)
   142  			}
   143  
   144  			log.Infof("Sending acknowledgements to CAPI")
   145  
   146  			apic.Shutdown()
   147  			papi.Shutdown()
   148  			t.Wait()
   149  			time.Sleep(5 * time.Second) //FIXME: the push done by apic.Push is run inside a sub goroutine, sleep to make sure it's done
   150  
   151  			return nil
   152  		},
   153  	}
   154  
   155  	return cmd
   156  }