crowdsec/cmd/crowdsec-cli/clilapi/status.go
mmetc b12ade27f4
cscli: review/update argument number checking (#3490)
* cscsli: remove unused Command.Args setting

* cscli: review/update argument number checking

cscli will consistently print the help text if the number of arguments is
wrong for the command, but not for other types of errors.

* fix func tests

* lint
2025-03-04 12:21:27 +01:00

116 lines
3 KiB
Go

package clilapi
import (
"context"
"errors"
"fmt"
"io"
"net/url"
"strings"
"github.com/fatih/color"
"github.com/go-openapi/strfmt"
"github.com/spf13/cobra"
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/args"
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
"github.com/crowdsecurity/crowdsec/pkg/models"
)
const LAPIURLPrefix = "v1"
// queryLAPIStatus checks if the Local API is reachable, and if the credentials are correct.
func queryLAPIStatus(ctx context.Context, hub *cwhub.Hub, credURL string, login string, password string) (bool, error) {
apiURL, err := url.Parse(credURL)
if err != nil {
return false, err
}
client, err := apiclient.NewDefaultClient(apiURL,
LAPIURLPrefix,
"",
nil)
if err != nil {
return false, err
}
pw := strfmt.Password(password)
itemsForAPI := hub.GetInstalledListForAPI()
t := models.WatcherAuthRequest{
MachineID: &login,
Password: &pw,
Scenarios: itemsForAPI,
}
_, _, err = client.Auth.AuthenticateWatcher(ctx, t)
if err != nil {
return false, err
}
return true, nil
}
func (cli *cliLapi) Status(ctx context.Context, out io.Writer, hub *cwhub.Hub) error {
cfg := cli.cfg()
cred := cfg.API.Client.Credentials
fmt.Fprintf(out, "Loaded credentials from %s\n", cfg.API.Client.CredentialsFilePath)
fmt.Fprintf(out, "Trying to authenticate with username %s on %s\n", cred.Login, cred.URL)
_, err := queryLAPIStatus(ctx, hub, cred.URL, cred.Login, cred.Password)
if err != nil {
return fmt.Errorf("failed to authenticate to Local API (LAPI): %w", err)
}
fmt.Fprintf(out, "You can successfully interact with Local API (LAPI)\n")
return nil
}
// prepareAPIURL checks/fixes a LAPI connection url (http, https or socket) and returns an URL struct
func prepareAPIURL(clientCfg *csconfig.LocalApiClientCfg, apiURL string) (*url.URL, error) {
if apiURL == "" {
if clientCfg == nil || clientCfg.Credentials == nil || clientCfg.Credentials.URL == "" {
return nil, errors.New("no Local API URL. Please provide it in your configuration or with the -u parameter")
}
apiURL = clientCfg.Credentials.URL
}
// URL needs to end with /, but user doesn't care
if !strings.HasSuffix(apiURL, "/") {
apiURL += "/"
}
// URL needs to start with http://, but user doesn't care
if !strings.HasPrefix(apiURL, "http://") && !strings.HasPrefix(apiURL, "https://") && !strings.HasPrefix(apiURL, "/") {
apiURL = "http://" + apiURL
}
return url.Parse(apiURL)
}
func (cli *cliLapi) newStatusCmd() *cobra.Command {
cmdLapiStatus := &cobra.Command{
Use: "status",
Short: "Check authentication to Local API (LAPI)",
Args: args.NoArgs,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, _ []string) error {
hub, err := require.Hub(cli.cfg(), nil)
if err != nil {
return err
}
return cli.Status(cmd.Context(), color.Output, hub)
},
}
return cmdLapiStatus
}