github.com/crowdsecurity/crowdsec@v1.6.1/cmd/crowdsec-cli/items.go (about) 1 package main 2 3 import ( 4 "encoding/csv" 5 "encoding/json" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 "slices" 11 "strings" 12 13 "gopkg.in/yaml.v3" 14 15 "github.com/crowdsecurity/crowdsec/pkg/cwhub" 16 ) 17 18 // selectItems returns a slice of items of a given type, selected by name and sorted by case-insensitive name 19 func selectItems(hub *cwhub.Hub, itemType string, args []string, installedOnly bool) ([]*cwhub.Item, error) { 20 itemNames := hub.GetItemNames(itemType) 21 22 notExist := []string{} 23 24 if len(args) > 0 { 25 for _, arg := range args { 26 if !slices.Contains(itemNames, arg) { 27 notExist = append(notExist, arg) 28 } 29 } 30 } 31 32 if len(notExist) > 0 { 33 return nil, fmt.Errorf("item(s) '%s' not found in %s", strings.Join(notExist, ", "), itemType) 34 } 35 36 if len(args) > 0 { 37 itemNames = args 38 installedOnly = false 39 } 40 41 items := make([]*cwhub.Item, 0, len(itemNames)) 42 43 for _, itemName := range itemNames { 44 item := hub.GetItem(itemType, itemName) 45 if installedOnly && !item.State.Installed { 46 continue 47 } 48 49 items = append(items, item) 50 } 51 52 cwhub.SortItemSlice(items) 53 54 return items, nil 55 } 56 57 func listItems(out io.Writer, itemTypes []string, items map[string][]*cwhub.Item, omitIfEmpty bool) error { 58 switch csConfig.Cscli.Output { 59 case "human": 60 nothingToDisplay := true 61 62 for _, itemType := range itemTypes { 63 if omitIfEmpty && len(items[itemType]) == 0 { 64 continue 65 } 66 67 listHubItemTable(out, "\n"+strings.ToUpper(itemType), items[itemType]) 68 69 nothingToDisplay = false 70 } 71 72 if nothingToDisplay { 73 fmt.Println("No items to display") 74 } 75 case "json": 76 type itemHubStatus struct { 77 Name string `json:"name"` 78 LocalVersion string `json:"local_version"` 79 LocalPath string `json:"local_path"` 80 Description string `json:"description"` 81 UTF8Status string `json:"utf8_status"` 82 Status string `json:"status"` 83 } 84 85 hubStatus := make(map[string][]itemHubStatus) 86 for _, itemType := range itemTypes { 87 // empty slice in case there are no items of this type 88 hubStatus[itemType] = make([]itemHubStatus, len(items[itemType])) 89 90 for i, item := range items[itemType] { 91 status := item.State.Text() 92 statusEmo := item.State.Emoji() 93 hubStatus[itemType][i] = itemHubStatus{ 94 Name: item.Name, 95 LocalVersion: item.State.LocalVersion, 96 LocalPath: item.State.LocalPath, 97 Description: item.Description, 98 Status: status, 99 UTF8Status: fmt.Sprintf("%v %s", statusEmo, status), 100 } 101 } 102 } 103 104 x, err := json.MarshalIndent(hubStatus, "", " ") 105 if err != nil { 106 return fmt.Errorf("failed to unmarshal: %w", err) 107 } 108 109 out.Write(x) 110 case "raw": 111 csvwriter := csv.NewWriter(out) 112 113 header := []string{"name", "status", "version", "description"} 114 if len(itemTypes) > 1 { 115 header = append(header, "type") 116 } 117 118 if err := csvwriter.Write(header); err != nil { 119 return fmt.Errorf("failed to write header: %s", err) 120 } 121 122 for _, itemType := range itemTypes { 123 for _, item := range items[itemType] { 124 row := []string{ 125 item.Name, 126 item.State.Text(), 127 item.State.LocalVersion, 128 item.Description, 129 } 130 if len(itemTypes) > 1 { 131 row = append(row, itemType) 132 } 133 134 if err := csvwriter.Write(row); err != nil { 135 return fmt.Errorf("failed to write raw output: %s", err) 136 } 137 } 138 } 139 140 csvwriter.Flush() 141 } 142 143 return nil 144 } 145 146 func inspectItem(item *cwhub.Item, showMetrics bool) error { 147 switch csConfig.Cscli.Output { 148 case "human", "raw": 149 enc := yaml.NewEncoder(os.Stdout) 150 enc.SetIndent(2) 151 152 if err := enc.Encode(item); err != nil { 153 return fmt.Errorf("unable to encode item: %s", err) 154 } 155 case "json": 156 b, err := json.MarshalIndent(*item, "", " ") 157 if err != nil { 158 return fmt.Errorf("unable to marshal item: %s", err) 159 } 160 161 fmt.Print(string(b)) 162 } 163 164 if csConfig.Cscli.Output != "human" { 165 return nil 166 } 167 168 if item.State.Tainted { 169 fmt.Println() 170 fmt.Printf(`This item is tainted. Use "%s %s inspect --diff %s" to see why.`, filepath.Base(os.Args[0]), item.Type, item.Name) 171 fmt.Println() 172 } 173 174 if showMetrics { 175 fmt.Printf("\nCurrent metrics: \n") 176 177 if err := ShowMetrics(item); err != nil { 178 return err 179 } 180 } 181 182 return nil 183 }