diff --git a/pkg/cmd/fcs/iom/list.go b/pkg/cmd/fcs/iom/list.go index a9d7fd3..71b6842 100644 --- a/pkg/cmd/fcs/iom/list.go +++ b/pkg/cmd/fcs/iom/list.go @@ -21,6 +21,7 @@ package iom import ( + "fmt" "github.com/crowdstrike/falcon-cli/pkg/cmdutil" "github.com/crowdstrike/falcon-cli/pkg/factory" "github.com/crowdstrike/falcon-cli/pkg/output" @@ -73,6 +74,11 @@ func NewCmdList(f *factory.Factory) *cobra.Command { } func runList(opts *listOptions) error { + const maxLimit = int64(100) + if opts.Limit > maxLimit { + return fmt.Errorf("--limit %d exceeds the maximum of %d for iom list", opts.Limit, maxLimit) + } + client, err := opts.Factory.FalconClient() if err != nil { return err diff --git a/pkg/cmd/fcs/risks/list.go b/pkg/cmd/fcs/risks/list.go index 13985af..b276265 100644 --- a/pkg/cmd/fcs/risks/list.go +++ b/pkg/cmd/fcs/risks/list.go @@ -54,11 +54,16 @@ func NewCmdList(f *factory.Factory) *cobra.Command { # List cloud risks falcon fcs risks list - # Filter by severity - falcon fcs risks list --filter "severity:'High'" + # Filter by severity (values: LOW, MEDIUM, HIGH, CRITICAL — uppercase) + falcon fcs risks list --filter "severity:'HIGH'" + falcon fcs risks list --filter "severity:'CRITICAL'" - # Sort and limit results - falcon fcs risks list --sort "severity.desc" --limit 50 + # Filter by cloud provider — use --grep (the cloud_provider filter field is not reliable) + falcon fcs risks list --grep aws + falcon fcs risks list --output json | jq '[.[] | select(.provider == "aws")]' + + # Sort descending (note: pipe separator, not dot) + falcon fcs risks list --sort "severity|desc" --limit 50 `), RunE: func(_ *cobra.Command, _ []string) error { return runList(opts) diff --git a/pkg/cmdutil/errors.go b/pkg/cmdutil/errors.go index 726df2e..dec6628 100644 --- a/pkg/cmdutil/errors.go +++ b/pkg/cmdutil/errors.go @@ -101,11 +101,27 @@ var cwppOperations = map[string]bool{ } // featureRequirements maps operations to features that must be tenant-provisioned. +// Keys are the human-readable operation strings passed to HandleAPIError. var featureRequirements = map[string]string{ + // Compliance posture — both the ID-discovery query and the posture summary fetch + // return 404 when the Compliance posture feature is not provisioned. + "query compliance frameworks": "CSPM Compliance posture feature (contact your Falcon admin to enable)", + "get compliance framework posture summaries": "CSPM Compliance posture feature (contact your Falcon admin to enable)", + "query compliance controls": "CSPM Compliance posture feature (contact your Falcon admin to enable)", + "get compliance rule posture summaries": "CSPM Compliance posture feature (contact your Falcon admin to enable)", + // Legacy gofalcon operation-name keys kept for backward compatibility. "CloudComplianceFrameworkPostureSummaries": "CSPM Compliance posture feature (contact your Falcon admin to enable)", "CloudComplianceRulePostureSummaries": "CSPM Compliance posture feature (contact your Falcon admin to enable)", } +// filterHints provides known filter field names for APIs whose 400 responses +// do not include a machine-readable field list. Keyed by the operation string +// passed to HandleAPIError. +var filterHints = map[string]string{ + "ContainerCombined": "cluster_name, namespace, cloud, container_id, " + + "privileged, running_as_root, allow_privilege_escalation, image_name", +} + // HandleAPIError wraps a gofalcon API error with an actionable message. // It inspects the HTTP status code via runtime.APIError and maps errors // to the specific API scope required or missing tenant features. @@ -156,6 +172,9 @@ func HandleAPIError(err error, operation string) error { return fmt.Errorf("%s: resource not found (HTTP 404)", operation) case apiErr.Code == 400: + if hint, ok := filterHints[operation]; ok && strings.Contains(err.Error(), "{}") { + return fmt.Errorf("%s: invalid filter expression\n Known filter fields: %s", operation, hint) + } return fmt.Errorf("%s: bad request (HTTP 400) — %s", operation, FirstLine(err.Error())) case apiErr.Code == 429: