initial import
This commit is contained in:
parent
36fbed6ee8
commit
2016167654
299 changed files with 21245 additions and 0 deletions
73
Dockerfile
Normal file
73
Dockerfile
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
############################
|
||||||
|
# STEP 1 build executable binary
|
||||||
|
############################
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
RUN apk update && apk add make gettext gcc g++
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR $GOPATH/src/JohnDoeCrowdSec/granola
|
||||||
|
|
||||||
|
# COPY the source
|
||||||
|
COPY ./ .
|
||||||
|
|
||||||
|
RUN make build
|
||||||
|
|
||||||
|
RUN make install
|
||||||
|
|
||||||
|
RUN cp ./docker/docker.yaml /etc/crowdsec/docker.yaml
|
||||||
|
RUN cp ./docker/acquis.yaml /etc/crowdsec/crowdsec/
|
||||||
|
|
||||||
|
############################
|
||||||
|
# STEP 2
|
||||||
|
############################
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
COPY --from=builder /usr/local/bin/crowdsec /usr/local/bin/crowdsec
|
||||||
|
COPY --from=builder /usr/local/bin/cscli /usr/local/bin/cscli
|
||||||
|
|
||||||
|
|
||||||
|
COPY --from=builder /etc/crowdsec /etc/crowdsec
|
||||||
|
COPY --from=builder /var/run/crowdsec /var/run/crowdsec
|
||||||
|
|
||||||
|
RUN apk add --update bash rsyslog && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
###########################
|
||||||
|
##### Prepare rsyslog #####
|
||||||
|
###########################
|
||||||
|
|
||||||
|
RUN mkdir -p /etc/rsyslog.d/
|
||||||
|
RUN mkdir -p /var/spool/rsyslog/
|
||||||
|
RUN mkdir -p /var/log/rsyslog
|
||||||
|
RUN touch /var/log/syslog
|
||||||
|
|
||||||
|
EXPOSE 514 514
|
||||||
|
|
||||||
|
COPY ./docker/rsyslog.conf /etc/rsyslog.conf
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
###### Configure crowdsec ###########
|
||||||
|
###########################################
|
||||||
|
|
||||||
|
RUN cscli config token "6ba94afde0fbf41310f7191934bc1d920245c9f1"
|
||||||
|
RUN cscli config installdir "/etc/crowdsec/crowdsec/"
|
||||||
|
RUN cscli config dbpath "/var/run/crowdsec/crowdsec.db"
|
||||||
|
|
||||||
|
RUN cscli update
|
||||||
|
|
||||||
|
RUN cscli install collection crowdsec/base-http-scenarios
|
||||||
|
RUN cscli install collection crowdsec/linux
|
||||||
|
RUN cscli install collection crowdsec/nginx
|
||||||
|
RUN cscli install collection crowdsec/sshd
|
||||||
|
|
||||||
|
######################################
|
||||||
|
## Wrapper to launch multi services ##
|
||||||
|
######################################
|
||||||
|
|
||||||
|
COPY ./docker/wrapper.sh .
|
||||||
|
RUN chmod +x ./wrapper.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["./wrapper.sh"]
|
||||||
|
|
118
Makefile
Normal file
118
Makefile
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
PREFIX?="/tmp/crowdsec/"
|
||||||
|
CFG_PREFIX = $(PREFIX)"/etc/crowdsec/"
|
||||||
|
BIN_PREFIX = $(PREFIX)"/usr/local/bin/"
|
||||||
|
DATA_PREFIX = $(PREFIX)"/var/run/crowdsec/"
|
||||||
|
|
||||||
|
PLUGIN_FOLDER="./plugins"
|
||||||
|
PID_DIR = $(PREFIX)"/var/run/"
|
||||||
|
CROWDSEC_FOLDER = "./cmd/crowdsec"
|
||||||
|
CSCLI_FOLDER = "./cmd/crowdsec-cli/"
|
||||||
|
CROWDSEC_BIN = "crowdsec"
|
||||||
|
CSCLI_BIN = "cscli"
|
||||||
|
BUILD_CMD="build"
|
||||||
|
|
||||||
|
GOARCH=amd64
|
||||||
|
GOOS=linux
|
||||||
|
REQUIRE_GOVERSION="1.13"
|
||||||
|
|
||||||
|
|
||||||
|
#Current versioning information from env
|
||||||
|
export BUILD_VERSION=$(shell cat RELEASE.json | jq -r .Version)
|
||||||
|
export BUILD_GOVERSION="$(shell go version | cut -d " " -f3 | sed -r 's/[go]+//g')"
|
||||||
|
export BUILD_CODENAME=$(shell cat RELEASE.json | jq -r .CodeName)
|
||||||
|
export BUILD_TIMESTAMP=$(shell date +%F"_"%T)
|
||||||
|
export BUILD_TAG="$(shell git rev-parse HEAD)"
|
||||||
|
export LD_OPTS=-ldflags "-X github.com/crowdsecurity/crowdsec/pkg/cwversion.Version=$(BUILD_VERSION) \
|
||||||
|
-X github.com/crowdsecurity/crowdsec/pkg/cwversion.BuildDate=$(BUILD_TIMESTAMP) \
|
||||||
|
-X github.com/crowdsecurity/crowdsec/pkg/cwversion.Codename=$(BUILD_CODENAME) \
|
||||||
|
-X github.com/crowdsecurity/crowdsec/pkg/cwversion.Tag=$(BUILD_TAG) \
|
||||||
|
-X github.com/crowdsecurity/crowdsec/pkg/cwversion.GoVersion=$(BUILD_GOVERSION)"
|
||||||
|
RELDIR = crowdsec-$(BUILD_VERSION)
|
||||||
|
|
||||||
|
all: clean test build
|
||||||
|
|
||||||
|
build: clean goversion crowdsec cscli
|
||||||
|
|
||||||
|
static: goversion crowdsec_static cscli_static
|
||||||
|
|
||||||
|
goversion:
|
||||||
|
CURRENT_GOVERSION="$(shell go version | cut -d " " -f3 | sed -r 's/[go]+//g')"
|
||||||
|
RESPECT_VERSION="$(shell echo "$(CURRENT_GOVERSION),$(REQUIRE_GOVERSION)" | tr ',' '\n' | sort -V)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@make -C $(CROWDSEC_FOLDER) clean --no-print-directory
|
||||||
|
@make -C $(CSCLI_FOLDER) clean --no-print-directory
|
||||||
|
@rm -f $(CROWDSEC_BIN)
|
||||||
|
@rm -f $(CSCLI_BIN)
|
||||||
|
@rm -f *.log
|
||||||
|
|
||||||
|
cscli:
|
||||||
|
ifeq ($(lastword $(RESPECT_VERSION)), $(CURRENT_GOVERSION))
|
||||||
|
@make -C $(CSCLI_FOLDER) build --no-print-directory
|
||||||
|
else
|
||||||
|
@echo "Required golang version is $(REQUIRE_GOVERSION). The current one is $(CURRENT_GOVERSION). Exiting.."
|
||||||
|
@exit 1;
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
crowdsec:
|
||||||
|
ifeq ($(lastword $(RESPECT_VERSION)), $(CURRENT_GOVERSION))
|
||||||
|
@make -C $(CROWDSEC_FOLDER) build --no-print-directory
|
||||||
|
else
|
||||||
|
@echo "Required golang version is $(REQUIRE_GOVERSION). The current one is $(CURRENT_GOVERSION). Exiting.."
|
||||||
|
@exit 1;
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
cscli_static:
|
||||||
|
ifeq ($(lastword $(RESPECT_VERSION)), $(CURRENT_GOVERSION))
|
||||||
|
@make -C $(CSCLI_FOLDER) static --no-print-directory
|
||||||
|
else
|
||||||
|
@echo "Required golang version is $(REQUIRE_GOVERSION). The current one is $(CURRENT_GOVERSION). Exiting.."
|
||||||
|
@exit 1;
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
crowdsec_static:
|
||||||
|
ifeq ($(lastword $(RESPECT_VERSION)), $(CURRENT_GOVERSION))
|
||||||
|
@make -C $(CROWDSEC_FOLDER) static --no-print-directory
|
||||||
|
else
|
||||||
|
@echo "Required golang version is $(REQUIRE_GOVERSION). The current one is $(CURRENT_GOVERSION). Exiting.."
|
||||||
|
@exit 1;
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#.PHONY: test
|
||||||
|
test:
|
||||||
|
ifeq ($(lastword $(RESPECT_VERSION)), $(CURRENT_GOVERSION))
|
||||||
|
@make -C $(CROWDSEC_FOLDER) test --no-print-directory
|
||||||
|
else
|
||||||
|
@echo "Required golang version is $(REQUIRE_GOVERSION). The current one is $(CURRENT_GOVERSION). Exiting.."
|
||||||
|
@exit 1;
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall:
|
||||||
|
@rm -rf "$(CFG_PREFIX)" || exit
|
||||||
|
@rm -rf "$(DATA_PREFIX)" || exit
|
||||||
|
@rm -rf "$(SYSTEMD_PATH_FILE)" || exit
|
||||||
|
|
||||||
|
.PHONY: check_release
|
||||||
|
check_release:
|
||||||
|
@if [ -d $(RELDIR) ]; then echo "$(RELDIR) already exists, abort" ; exit 1 ; fi
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
release: check_release build
|
||||||
|
@echo Building Release to dir $(RELDIR)
|
||||||
|
@mkdir -p $(RELDIR)/cmd/crowdsec
|
||||||
|
@mkdir -p $(RELDIR)/cmd/crowdsec-cli
|
||||||
|
@cp $(CROWDSEC_FOLDER)/$(CROWDSEC_BIN) $(RELDIR)/cmd/crowdsec
|
||||||
|
@cp $(CSCLI_FOLDER)/$(CSCLI_BIN) $(RELDIR)/cmd/crowdsec-cli
|
||||||
|
@cp -R ./config/ $(RELDIR)
|
||||||
|
@cp -R ./data/ $(RELDIR)
|
||||||
|
@cp wizard.sh $(RELDIR)
|
||||||
|
@cp scripts/test_env.sh $(RELDIR)
|
||||||
|
@bash ./scripts/build_plugins.sh
|
||||||
|
@mkdir -p "$(RELDIR)/plugins/backend"
|
||||||
|
@find ./plugins -type f -name "*.so" -exec install -Dm 644 {} "$(RELDIR)/{}" \; || exiting
|
||||||
|
@tar cvzf crowdsec-release.tgz $(RELDIR)
|
153
README.md
Normal file
153
README.md
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
![Go](https://github.com/crowdsecurity/crowdsec/workflows/Go/badge.svg)
|
||||||
|
![build-binary-package](https://github.com/crowdsecurity/crowdsec/workflows/build-binary-package/badge.svg)
|
||||||
|
|
||||||
|
# CrowdSec project
|
||||||
|
|
||||||
|
Please see [terminology](#terminology) if you're new to the projetct.
|
||||||
|
|
||||||
|
## Foreword
|
||||||
|
|
||||||
|
This repository contains the code for the two main components of crowdsec :
|
||||||
|
- `crowdsec` : the daemon a-la-fail2ban that can read, parse, enrich and apply heuristis to logs. This is the component in charge of "detecting" the attacks
|
||||||
|
- `cscli` : the cli tool mainly used to interact with crowdsec : ban/unban/view current bans, enable/disable parsers and scenarios.
|
||||||
|
|
||||||
|
## Plugins
|
||||||
|
|
||||||
|
The plugins are in charge of blocking that Ip/Ranges that have been tagged as malevolent.
|
||||||
|
They do so by querying a sqlite database when they see a new IP. This SQLite database is being fed by crowdsec.
|
||||||
|
The following plugins are available :
|
||||||
|
- `netfilter-plugin` : an iptables/ipset service that can be deployed by the wizard. it will allow to ban IP/Ranges as you would do with iptables.
|
||||||
|
- `nginx-plugin` : a LUA connector for nginx that can be deployed by the wizard. it will allow to ban ip/ranges at the applicative level (ie. more suitable than iptables if your website is behind a CDN).
|
||||||
|
- `wordpress-plugin` : a Wordpress/php module that can be deployed in Wordpress to block the requests at the applicative level. (it comes as a library for easy re-use).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Software architecture
|
||||||
|
|
||||||
|
|
||||||
|
![global crowdsec architecture](./doc/img/crowdsec-global.png)
|
||||||
|
|
||||||
|
|
||||||
|
**NOTE** the API part isn't enabled by default.
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
**To build crowdsec you need golang >= 1.13.**
|
||||||
|
To build binaries :
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make build
|
||||||
|
```
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
## With the wizard
|
||||||
|
|
||||||
|
The wizard is here is significatively improve the user experience, and aims at providing a _next-next-next-finish_ installer that should work out of the box on most linux flavored systems.
|
||||||
|
|
||||||
|
The wizard will help you in the following steps :
|
||||||
|
- detect running services
|
||||||
|
- detect their log files(by default in `/etc/crowdsec/`)
|
||||||
|
- suggest collections/scenarios according to the detect services
|
||||||
|
- deploy crowdsec service
|
||||||
|
- deploy plugins
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ make build
|
||||||
|
$ sudo ./wizard.sh -i
|
||||||
|
```
|
||||||
|
|
||||||
|
and you're done !
|
||||||
|
|
||||||
|
|
||||||
|
## Without the wizard
|
||||||
|
|
||||||
|
> You man of little faith
|
||||||
|
|
||||||
|
You can install crowdsec and its cli without the wizard :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ make build
|
||||||
|
$ make systemd
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE** if you install without the wizard, it will be your responsability to configure the acquisition (which file to read for which service) and to deploy scenarios and parsers (how to parse logs, and which scenarios should be applied to which services).
|
||||||
|
|
||||||
|
## After the installation
|
||||||
|
|
||||||
|
Services are deployed as systemd units :
|
||||||
|
- `crowdsec` is the detection component
|
||||||
|
- `crowdsec-netfilter` is the netfilter plugin
|
||||||
|
- the nginx, wordpress etc. plugins usually are ran inside said service (ie. nginx plugin is a LUA script, wordpress plugin is a php module)
|
||||||
|
- `cscli` is deployed in standard path.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo systemctl status crowdsec
|
||||||
|
# stop the netfilter plugin. If you didn't install other plugins, decisions won't be 'applied' anymore unless you start it again.
|
||||||
|
$ sudo systemctl stop crowdsec-netfilter
|
||||||
|
```
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
crowdsec relies on the following configuration files (by default in `/etc/crowdsec/`) :
|
||||||
|
|
||||||
|
- default.yaml : The main configuration of crowdsec, you will find here informations about logging, path to sqlite DB etc.
|
||||||
|
- acquis.yaml : Describes the files that will be read (a-la `tail -f`) and which type of logs to expect from it
|
||||||
|
- api.yaml : url & token for api push and pulls (pushes **signal occurences** and fetchs **crowd-sourced reputation**)
|
||||||
|
- profiles.yaml : (you shouldn't modify this one) Describes in which condition crowdsec should insert a ban decision in database. It's usually because a scenario has a `remediation: true` flag in its tags.
|
||||||
|
|
||||||
|
However, the "real" configuration of crowdsec relies on the collections of scenarios and parsers that you have deployed.
|
||||||
|
Those are deployed / upgraded / removed (ideally) with `cscli`, see [its dedicated documentation](./cmd/crowdsec-cli/doc/cscli.md)
|
||||||
|
|
||||||
|
If you used the wizard, chances are that you don't have anything specific to configure.
|
||||||
|
|
||||||
|
# Usage / FAQ
|
||||||
|
|
||||||
|
[See `cscli`dedicated documentation](./cmd/crowdsec-cli/doc/cscli.md)
|
||||||
|
|
||||||
|
## stop the netfilter plugin
|
||||||
|
|
||||||
|
**note** when netfilter plugin is disabled, no bans will be applied if no other plugins are enabled.
|
||||||
|
|
||||||
|
```
|
||||||
|
#view netfilter logs
|
||||||
|
$ journalctl -u -f crowdsec-netfilter
|
||||||
|
#stop service
|
||||||
|
$ systemctl stop crowdsec-netfilter
|
||||||
|
```
|
||||||
|
|
||||||
|
## view/add/remove bans
|
||||||
|
|
||||||
|
```
|
||||||
|
# cscli ban list
|
||||||
|
INFO[0000] 38 non-expired ban applications
|
||||||
|
+-----------------+---------------+--------------------+--------+---------+--------------------------------+--------------+--------------------+
|
||||||
|
| SOURCE | SCENARIO | CURRENT BANS COUNT | ACTION | COUNTRY | AS | EVENTS COUNT | EXPIRATION |
|
||||||
|
+-----------------+---------------+--------------------+--------+---------+--------------------------------+--------------+--------------------+
|
||||||
|
| 37.195.50.41 | ssh_user_enum | 1 | ban | RU | 31200 Novotelecom Ltd | 4 | 3h59m56.337435741s |
|
||||||
|
| 159.203.143.58 | ssh_user_enum | 1 | ban | US | 14061 DigitalOcean, LLC | 4 | 3h59m55.585257629s |
|
||||||
|
...
|
||||||
|
# cscli ban add range 37.139.4.0/24 10m spam
|
||||||
|
# cscli ban add ip 37.139.4.123 10m spam
|
||||||
|
```
|
||||||
|
|
||||||
|
# Terminology
|
||||||
|
|
||||||
|
- **crowdsec** : the daemon that reads log files, parses logs and triggers scenarios, alerts and bans.
|
||||||
|
- **crowdsec database** : a local file that contains at a given time the list of banned ip/ranges.
|
||||||
|
- **plugin** : a software component that can interact with crowdsec database to block/delay attackers.
|
||||||
|
- **parser** : a configuration file that allows crowdsec to 'understand' a specific log file format. Each service will generally require its own parser (nginx, apache, sshd, mysql etc.). parsers are usually found on the **hub** and downloaded via the **cli**.
|
||||||
|
- **scenario** : a leakybucket description that allows to detect a specific attack : _more that 5 failed ssh authentication attempts from the same IP within less than 20 seconds is a ssh bruteforce and should be punished_
|
||||||
|
- **signal** : the information resulting from a scenario being triggered, this information is shared amongst participants and will lead to consensus : _users A, B, C, D all reported that ip 1.2.3.4 targetted them with a ssh bruteforce_
|
||||||
|
- **bucket**, **bucket overflow** : a more technical term referring to a scenario being triggered.
|
||||||
|
- **hub** : the portal on which users can find, share and publish parsers and scenarios.
|
||||||
|
- **cli** : the `cscli` tool.
|
||||||
|
|
||||||
|
# Making a release
|
||||||
|
|
||||||
|
- release-drafter maintains a draft release up-to-date with MRs
|
||||||
|
- when you publish the release with the "pre-release" flag, it's going to launch action to add the built release package to release.
|
||||||
|
- once extra manual steps are done, you can remove the "pre-release" flag from published release "and voila"
|
||||||
|
|
||||||
|
|
4
RELEASE.json
Normal file
4
RELEASE.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"Version": "v0.0.21",
|
||||||
|
"CodeName": "road2beta"
|
||||||
|
}
|
31
cmd/crowdsec-cli/Makefile
Normal file
31
cmd/crowdsec-cli/Makefile
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Go parameters
|
||||||
|
GOCMD=go
|
||||||
|
GOBUILD=$(GOCMD) build
|
||||||
|
GOCLEAN=$(GOCMD) clean
|
||||||
|
GOTEST=$(GOCMD) test
|
||||||
|
GOGET=$(GOCMD) get
|
||||||
|
BINARY_NAME=cscli
|
||||||
|
PREFIX?="/"
|
||||||
|
BIN_PREFIX = $(PREFIX)"/usr/local/bin/"
|
||||||
|
|
||||||
|
all: clean build
|
||||||
|
|
||||||
|
build: clean
|
||||||
|
@$(GOBUILD) $(LD_OPTS) -o $(BINARY_NAME) -v
|
||||||
|
|
||||||
|
static: clean
|
||||||
|
@$(GOBUILD) -o $(BINARY_NAME) -v -a -tags netgo -ldflags '-w -extldflags "-static"'
|
||||||
|
|
||||||
|
install: install-conf install-bin
|
||||||
|
|
||||||
|
install-conf:
|
||||||
|
|
||||||
|
install-bin:
|
||||||
|
@install -v -m 755 -D "$(BINARY_NAME)" "$(BIN_PREFIX)/$(BINARY_NAME)" || exit
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
@rm -rf $(CSCLI_CONFIG)
|
||||||
|
@rm -rf $(BIN_PREFIX)$(BINARY_NAME)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f $(BINARY_NAME)
|
1
cmd/crowdsec-cli/README.md
Normal file
1
cmd/crowdsec-cli/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
see doc in `doc/`
|
271
cmd/crowdsec-cli/api.go
Normal file
271
cmd/crowdsec-cli/api.go
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/sqlite"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
|
||||||
|
"github.com/denisbrodbeck/machineid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
passwordLength = 64
|
||||||
|
upper = "ABCDEFGHIJKLMNOPQRSTUVWXY"
|
||||||
|
lower = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
digits = "0123456789"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
apiConfigFile = "api.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
var userID string // for flag parsing
|
||||||
|
var dbctx *sqlite.Context
|
||||||
|
|
||||||
|
var outputCTX *outputs.Output
|
||||||
|
|
||||||
|
func dumpCredentials() error {
|
||||||
|
if config.output == "json" {
|
||||||
|
credsYaml, err := json.Marshal(&outputCTX.API.Creds)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Can't marshal credentials : %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(credsYaml))
|
||||||
|
} else {
|
||||||
|
credsYaml, err := yaml.Marshal(&outputCTX.API.Creds)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Can't marshal credentials : %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(credsYaml))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generatePassword() string {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
charset := upper + lower + digits
|
||||||
|
|
||||||
|
buf := make([]byte, passwordLength)
|
||||||
|
buf[0] = digits[rand.Intn(len(digits))]
|
||||||
|
buf[1] = upper[rand.Intn(len(upper))]
|
||||||
|
buf[2] = lower[rand.Intn(len(lower))]
|
||||||
|
|
||||||
|
for i := 3; i < passwordLength; i++ {
|
||||||
|
buf[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
rand.Shuffle(len(buf), func(i, j int) {
|
||||||
|
buf[i], buf[j] = buf[j], buf[i]
|
||||||
|
})
|
||||||
|
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pullTOP() error {
|
||||||
|
/*profile from cwhub*/
|
||||||
|
var profiles []string
|
||||||
|
if _, ok := cwhub.HubIdx[cwhub.SCENARIOS]; !ok || len(cwhub.HubIdx[cwhub.SCENARIOS]) == 0 {
|
||||||
|
log.Errorf("no loaded scenarios, can't fill profiles")
|
||||||
|
return fmt.Errorf("no profiles")
|
||||||
|
}
|
||||||
|
for _, item := range cwhub.HubIdx[cwhub.SCENARIOS] {
|
||||||
|
if item.Tainted || !item.Installed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
profiles = append(profiles, item.Name)
|
||||||
|
}
|
||||||
|
outputCTX.API.Creds.Profile = strings.Join(profiles[:], ",")
|
||||||
|
if err := outputCTX.API.Signin(); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := outputCTX.API.PullTop()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
log.Warningf("api pull returned %d entries", len(ret))
|
||||||
|
for _, item := range ret {
|
||||||
|
if _, ok := item["range_ip"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := item["scenario"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
item["scenario"] = fmt.Sprintf("api: %s", item["scenario"])
|
||||||
|
|
||||||
|
if _, ok := item["action"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := item["expiration"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := item["country"]; !ok {
|
||||||
|
item["country"] = ""
|
||||||
|
}
|
||||||
|
if _, ok := item["as_org"]; !ok {
|
||||||
|
item["as_org"] = ""
|
||||||
|
}
|
||||||
|
if _, ok := item["as_num"]; !ok {
|
||||||
|
item["as_num"] = ""
|
||||||
|
}
|
||||||
|
var signalOcc types.SignalOccurence
|
||||||
|
signalOcc, err = simpleBanToSignal(item["range_ip"], item["scenario"], item["expiration"], item["action"], item["as_name"], item["as_num"], item["country"], "api")
|
||||||
|
if err := outputCTX.Insert(signalOcc); err != nil {
|
||||||
|
log.Fatalf("Unable to write pull to sqliteDB : %+s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputCTX.Flush()
|
||||||
|
log.Infof("Wrote %d bans from api to database.", len(ret))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPICmd() *cobra.Command {
|
||||||
|
|
||||||
|
var cmdAPI = &cobra.Command{
|
||||||
|
Use: "api [action]",
|
||||||
|
Short: "Crowdsec API interaction",
|
||||||
|
Long: `
|
||||||
|
Allow to register your machine into crowdsec API to send and receive signal.
|
||||||
|
`,
|
||||||
|
Example: `
|
||||||
|
cscli api register # Register to Crowdsec API
|
||||||
|
cscli api pull # Pull malevolant IPs from Crowdsec API
|
||||||
|
cscli api reset # Reset your machines credentials
|
||||||
|
cscli api enroll # Enroll your machine to the user account you created on Crowdsec backend
|
||||||
|
cscli api credentials # Display your API credentials
|
||||||
|
`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
|
||||||
|
outputConfig := outputs.OutputFactory{
|
||||||
|
BackendFolder: config.BackendPluginFolder,
|
||||||
|
}
|
||||||
|
outputCTX, err = outputs.NewOutput(&outputConfig, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outputCTX.LoadAPIConfig(path.Join(config.InstallFolder, apiConfigFile))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdAPIRegister = &cobra.Command{
|
||||||
|
Use: "register",
|
||||||
|
Short: "Register on Crowdsec API",
|
||||||
|
Long: `This command will register your machine to crowdsec API to allow you to receive list of malveolent IPs.
|
||||||
|
The printed machine_id and password should be added to your api.yaml file.`,
|
||||||
|
Example: `cscli api register`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
id, err := machineid.ID()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to get machine id: %s", err)
|
||||||
|
}
|
||||||
|
password := generatePassword()
|
||||||
|
|
||||||
|
if err := outputCTX.API.RegisterMachine(id, password); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Printf("machine_id: %s\n", outputCTX.API.Creds.User)
|
||||||
|
fmt.Printf("password: %s\n", outputCTX.API.Creds.Password)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdAPIEnroll = &cobra.Command{
|
||||||
|
Use: "enroll",
|
||||||
|
Short: "Associate your machine to an existing crowdsec user",
|
||||||
|
Long: `Enrolling your machine into your user account will allow for more accurate lists and threat detection. See website to create user account.`,
|
||||||
|
Example: `cscli api enroll -u 1234567890ffff`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := outputCTX.API.Signin(); err != nil {
|
||||||
|
log.Fatalf("unable to signin : %s", err)
|
||||||
|
}
|
||||||
|
if err := outputCTX.API.Enroll(userID); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdAPIResetPassword = &cobra.Command{
|
||||||
|
Use: "reset",
|
||||||
|
Short: "Reset password on CrowdSec API",
|
||||||
|
Long: `Attempts to reset your credentials to the API.`,
|
||||||
|
Example: `cscli api reset`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
id, err := machineid.ID()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to get machine id: %s", err)
|
||||||
|
}
|
||||||
|
password := generatePassword()
|
||||||
|
if err := outputCTX.API.ResetPassword(id, password); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Printf("machine_id: %s\n", outputCTX.API.Creds.User)
|
||||||
|
fmt.Printf("password: %s\n", outputCTX.API.Creds.Password)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdAPIPull = &cobra.Command{
|
||||||
|
Use: "pull",
|
||||||
|
Short: "Pull crowdsec API TopX",
|
||||||
|
Long: `Pulls a list of malveolent IPs relevant to your situation and add them into the local ban database.`,
|
||||||
|
Example: `cscli api pull`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
err := pullTOP()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdAPICreds = &cobra.Command{
|
||||||
|
Use: "credentials",
|
||||||
|
Short: "Display api credentials",
|
||||||
|
Long: ``,
|
||||||
|
Example: `cscli api credentials`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := dumpCredentials(); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdAPI.AddCommand(cmdAPICreds)
|
||||||
|
cmdAPIEnroll.Flags().StringVarP(&userID, "user", "u", "", "User ID (required)")
|
||||||
|
cmdAPIEnroll.MarkFlagRequired("user")
|
||||||
|
cmdAPI.AddCommand(cmdAPIEnroll)
|
||||||
|
cmdAPI.AddCommand(cmdAPIResetPassword)
|
||||||
|
cmdAPI.AddCommand(cmdAPIRegister)
|
||||||
|
cmdAPI.AddCommand(cmdAPIPull)
|
||||||
|
return cmdAPI
|
||||||
|
}
|
473
cmd/crowdsec-cli/backup-restore.go
Normal file
473
cmd/crowdsec-cli/backup-restore.go
Normal file
|
@ -0,0 +1,473 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwapi"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
//it's a rip of the cli version, but in silent-mode
|
||||||
|
func silenceInstallItem(name string, obtype string) (string, error) {
|
||||||
|
for _, it := range cwhub.HubIdx[obtype] {
|
||||||
|
if it.Name == name {
|
||||||
|
if download_only && it.Downloaded && it.UpToDate {
|
||||||
|
return fmt.Sprintf("%s is already downloaded and up-to-date", it.Name), nil
|
||||||
|
}
|
||||||
|
it, err := cwhub.DownloadLatest(it, cwhub.Hubdir, force_install)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error while downloading %s : %v", it.Name, err)
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[obtype][it.Name] = it
|
||||||
|
if download_only {
|
||||||
|
return fmt.Sprintf("Downloaded %s to %s", it.Name, cwhub.Hubdir+"/"+it.RemotePath), nil
|
||||||
|
}
|
||||||
|
it, err = cwhub.EnableItem(it, cwhub.Installdir, cwhub.Hubdir)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error while enabled %s : %v", it.Name, err)
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[obtype][it.Name] = it
|
||||||
|
|
||||||
|
return fmt.Sprintf("Enabled %s", it.Name), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("%s not found in hub index", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*help to copy the file, ioutil doesn't offer the feature*/
|
||||||
|
|
||||||
|
func copyFileContents(src, dst string) (err error) {
|
||||||
|
in, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
out, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
cerr := out.Close()
|
||||||
|
if err == nil {
|
||||||
|
err = cerr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if _, err = io.Copy(out, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = out.Sync()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*copy the file, ioutile doesn't offer the feature*/
|
||||||
|
func copyFile(sourceSymLink, destinationFile string) (err error) {
|
||||||
|
|
||||||
|
sourceFile, err := filepath.EvalSymlinks(sourceSymLink)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Not a symlink : %s", err)
|
||||||
|
sourceFile = sourceSymLink
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceFileStat, err := os.Stat(sourceFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !sourceFileStat.Mode().IsRegular() {
|
||||||
|
// cannot copy non-regular files (e.g., directories,
|
||||||
|
// symlinks, devices, etc.)
|
||||||
|
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sourceFileStat.Name(), sourceFileStat.Mode().String())
|
||||||
|
}
|
||||||
|
destinationFileStat, err := os.Stat(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !(destinationFileStat.Mode().IsRegular()) {
|
||||||
|
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", destinationFileStat.Name(), destinationFileStat.Mode().String())
|
||||||
|
}
|
||||||
|
if os.SameFile(sourceFileStat, destinationFileStat) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = os.Link(sourceFile, destinationFile); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = copyFileContents(sourceFile, destinationFile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*given a backup directory, restore configs (parser,collections..) both tainted and untainted.
|
||||||
|
as well attempts to restore api credentials after verifying the existing ones aren't good
|
||||||
|
finally restores the acquis.yaml file*/
|
||||||
|
func restoreFromDirectory(source string) error {
|
||||||
|
var err error
|
||||||
|
/*backup scenarios etc.*/
|
||||||
|
for _, itype := range cwhub.ItemTypes {
|
||||||
|
itemDirectory := fmt.Sprintf("%s/%s/", source, itype)
|
||||||
|
if _, err = os.Stat(itemDirectory); err != nil {
|
||||||
|
log.Infof("no %s in backup", itype)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
/*restore the upstream items*/
|
||||||
|
upstreamListFN := fmt.Sprintf("%s/upstream-%s.json", itemDirectory, itype)
|
||||||
|
file, err := ioutil.ReadFile(upstreamListFN)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error while opening %s : %s", upstreamListFN, err)
|
||||||
|
}
|
||||||
|
var upstreamList []string
|
||||||
|
err = json.Unmarshal([]byte(file), &upstreamList)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling %s : %s", upstreamListFN, err)
|
||||||
|
}
|
||||||
|
for _, toinstall := range upstreamList {
|
||||||
|
label, err := silenceInstallItem(toinstall, itype)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error while installing %s : %s", toinstall, err)
|
||||||
|
} else if label != "" {
|
||||||
|
log.Infof("Installed %s : %s", toinstall, label)
|
||||||
|
} else {
|
||||||
|
log.Printf("Installed %s : ok", toinstall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*restore the local and tainted items*/
|
||||||
|
files, err := ioutil.ReadDir(itemDirectory)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed enumerating files of %s : %s", itemDirectory, err)
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
//dir are stages, keep track
|
||||||
|
if !file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
stage := file.Name()
|
||||||
|
stagedir := fmt.Sprintf("%s/%s/%s/", config.InstallFolder, itype, stage)
|
||||||
|
log.Debugf("Found stage %s in %s, target directory : %s", stage, itype, stagedir)
|
||||||
|
if err = os.MkdirAll(stagedir, os.ModePerm); err != nil {
|
||||||
|
return fmt.Errorf("Error while creating stage directory %s : %s", stagedir, err)
|
||||||
|
}
|
||||||
|
/*find items*/
|
||||||
|
ifiles, err := ioutil.ReadDir(itemDirectory + "/" + stage + "/")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed enumerating files of %s : %s", itemDirectory+"/"+stage, err)
|
||||||
|
}
|
||||||
|
//finaly copy item
|
||||||
|
for _, tfile := range ifiles {
|
||||||
|
log.Infof("Going to restore local/tainted [%s]", tfile.Name())
|
||||||
|
sourceFile := fmt.Sprintf("%s/%s/%s", itemDirectory, stage, tfile.Name())
|
||||||
|
destinationFile := fmt.Sprintf("%s%s", stagedir, tfile.Name())
|
||||||
|
if err = copyFile(sourceFile, destinationFile); err != nil {
|
||||||
|
return fmt.Errorf("failed copy %s %s to %s : %s", itype, sourceFile, destinationFile, err)
|
||||||
|
} else {
|
||||||
|
log.Infof("restored %s to %s", sourceFile, destinationFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*restore api credentials*/
|
||||||
|
//check if credentials exists :
|
||||||
|
// - if no, restore
|
||||||
|
// - if yes, try them :
|
||||||
|
// - if it works, left untouched
|
||||||
|
// - if not, restore
|
||||||
|
// -> try login
|
||||||
|
if err := restoreAPICreds(source); err != nil {
|
||||||
|
return fmt.Errorf("Failed to restore api credentials : %s", err)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Restore acquis
|
||||||
|
*/
|
||||||
|
yamlAcquisFile := fmt.Sprintf("%s/acquis.yaml", config.InstallFolder)
|
||||||
|
bac := fmt.Sprintf("%s/acquis.yaml", source)
|
||||||
|
if err = copyFile(bac, yamlAcquisFile); err != nil {
|
||||||
|
return fmt.Errorf("failed copy %s to %s : %s", bac, yamlAcquisFile, err)
|
||||||
|
}
|
||||||
|
log.Infof("Restore acquis to %s", yamlAcquisFile)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func restoreAPICreds(source string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
/*check existing configuration*/
|
||||||
|
apiyaml := path.Join(config.InstallFolder, apiConfigFile)
|
||||||
|
|
||||||
|
api := &cwapi.ApiCtx{}
|
||||||
|
if err = api.LoadConfig(apiyaml); err != nil {
|
||||||
|
return fmt.Errorf("Unable to load api config %s : %s", apiyaml, err)
|
||||||
|
}
|
||||||
|
if api.Creds.User != "" {
|
||||||
|
log.Infof("Credentials present in existing configuration, try before override")
|
||||||
|
err := api.Signin()
|
||||||
|
if err == nil {
|
||||||
|
log.Infof("Credentials present allow authentication, don't override !")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
log.Infof("Credentials aren't valid : %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*existing config isn't good, override it !*/
|
||||||
|
ret, err := ioutil.ReadFile(path.Join(source, "api_creds.json"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to read api creds from save : %s", err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(ret, &api.Creds); err != nil {
|
||||||
|
return fmt.Errorf("Failed unmarshaling saved credentials : %s", err)
|
||||||
|
}
|
||||||
|
api.CfgUser = api.Creds.User
|
||||||
|
api.CfgPassword = api.Creds.Password
|
||||||
|
/*override the existing yaml file*/
|
||||||
|
if err := api.WriteConfig(apiyaml); err != nil {
|
||||||
|
return fmt.Errorf("Failed writing to %s : %s", apiyaml, err)
|
||||||
|
} else {
|
||||||
|
log.Infof("Overwritting %s with backup info", apiyaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*reload to check everything is safe*/
|
||||||
|
if err = api.LoadConfig(apiyaml); err != nil {
|
||||||
|
return fmt.Errorf("Unable to load api config %s : %s", apiyaml, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := api.Signin(); err != nil {
|
||||||
|
log.Errorf("Failed to authenticate after credentials restaurtion : %v", err)
|
||||||
|
} else {
|
||||||
|
log.Infof("Successfully auth to API after credentials restauration")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func backupToDirectory(target string) error {
|
||||||
|
var itemDirectory string
|
||||||
|
var upstreamParsers []string
|
||||||
|
var err error
|
||||||
|
if target == "" {
|
||||||
|
return fmt.Errorf("target directory can't be empty")
|
||||||
|
}
|
||||||
|
log.Warningf("Starting configuration backup")
|
||||||
|
_, err = os.Stat(target)
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("%s already exists", target)
|
||||||
|
}
|
||||||
|
if err = os.MkdirAll(target, os.ModePerm); err != nil {
|
||||||
|
return fmt.Errorf("Error while creating %s : %s", target, err)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
backup configurations :
|
||||||
|
- parers, scenarios, collections, postoverflows
|
||||||
|
*/
|
||||||
|
|
||||||
|
for _, itemType := range cwhub.ItemTypes {
|
||||||
|
clog := log.WithFields(log.Fields{
|
||||||
|
"type": itemType,
|
||||||
|
})
|
||||||
|
if _, ok := cwhub.HubIdx[itemType]; ok {
|
||||||
|
itemDirectory = fmt.Sprintf("%s/%s/", target, itemType)
|
||||||
|
if err := os.MkdirAll(itemDirectory, os.ModePerm); err != nil {
|
||||||
|
return fmt.Errorf("Error while creating %s : %s", itemDirectory, err)
|
||||||
|
}
|
||||||
|
upstreamParsers = []string{}
|
||||||
|
stage := ""
|
||||||
|
for k, v := range cwhub.HubIdx[itemType] {
|
||||||
|
clog = clog.WithFields(log.Fields{
|
||||||
|
"file": v.Name,
|
||||||
|
})
|
||||||
|
if !v.Installed { //only backup installed ones
|
||||||
|
clog.Debugf("[%s] : not installed", k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//for the local/tainted ones, we backup the full file
|
||||||
|
if v.Tainted || v.Local || !v.UpToDate {
|
||||||
|
//we need to backup stages for parsers
|
||||||
|
if itemType == cwhub.PARSERS || itemType == cwhub.PARSERS_OVFLW {
|
||||||
|
tmp := strings.Split(v.LocalPath, "/")
|
||||||
|
stage = "/" + tmp[len(tmp)-2] + "/"
|
||||||
|
fstagedir := fmt.Sprintf("%s%s", itemDirectory, stage)
|
||||||
|
if err := os.MkdirAll(fstagedir, os.ModePerm); err != nil {
|
||||||
|
return fmt.Errorf("Error while creating stage dir %s : %s", fstagedir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clog.Debugf("[%s] : backuping file (tainted:%t local:%t up-to-date:%t)", k, v.Tainted, v.Local, v.UpToDate)
|
||||||
|
tfile := fmt.Sprintf("%s%s%s", itemDirectory, stage, v.FileName)
|
||||||
|
//clog.Infof("item : %s", spew.Sdump(v))
|
||||||
|
if err = copyFile(v.LocalPath, tfile); err != nil {
|
||||||
|
return fmt.Errorf("failed copy %s %s to %s : %s", itemType, v.LocalPath, tfile, err)
|
||||||
|
}
|
||||||
|
clog.Infof("local/tainted saved %s to %s", v.LocalPath, tfile)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
clog.Debugf("[%s] : from hub, just backup name (up-to-date:%t)", k, v.UpToDate)
|
||||||
|
clog.Infof("saving, version:%s, up-to-date:%t", v.Version, v.UpToDate)
|
||||||
|
upstreamParsers = append(upstreamParsers, v.Name)
|
||||||
|
}
|
||||||
|
//write the upstream items
|
||||||
|
upstreamParsersFname := fmt.Sprintf("%s/upstream-%s.json", itemDirectory, itemType)
|
||||||
|
upstreamParsersContent, err := json.MarshalIndent(upstreamParsers, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed marshaling upstream parsers : %s", err)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(upstreamParsersFname, upstreamParsersContent, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to write to %s %s : %s", itemType, upstreamParsersFname, err)
|
||||||
|
}
|
||||||
|
clog.Infof("Wrote %d entries for %s to %s", len(upstreamParsers), itemType, upstreamParsersFname)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
clog.Infof("No %s to backup.", itemType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Backup acquis
|
||||||
|
*/
|
||||||
|
yamlAcquisFile := fmt.Sprintf("%s/acquis.yaml", config.InstallFolder)
|
||||||
|
bac := fmt.Sprintf("%s/acquis.yaml", target)
|
||||||
|
if err = copyFile(yamlAcquisFile, bac); err != nil {
|
||||||
|
return fmt.Errorf("failed copy %s to %s : %s", yamlAcquisFile, bac, err)
|
||||||
|
}
|
||||||
|
log.Infof("Saved acquis to %s", bac)
|
||||||
|
/*
|
||||||
|
Backup default.yaml
|
||||||
|
*/
|
||||||
|
defyaml := fmt.Sprintf("%s/default.yaml", config.InstallFolder)
|
||||||
|
bac = fmt.Sprintf("%s/default.yaml", target)
|
||||||
|
if err = copyFile(defyaml, bac); err != nil {
|
||||||
|
return fmt.Errorf("failed copy %s to %s : %s", yamlAcquisFile, bac, err)
|
||||||
|
}
|
||||||
|
log.Infof("Saved default yaml to %s", bac)
|
||||||
|
/*
|
||||||
|
Backup API info
|
||||||
|
*/
|
||||||
|
if outputCTX == nil {
|
||||||
|
log.Fatalf("no API output context, won't save api credentials")
|
||||||
|
}
|
||||||
|
outputCTX.API = &cwapi.ApiCtx{}
|
||||||
|
if err = outputCTX.API.LoadConfig(path.Join(config.InstallFolder, apiConfigFile)); err != nil {
|
||||||
|
return fmt.Errorf("unable to load api config %s : %s", path.Join(config.InstallFolder, apiConfigFile), err)
|
||||||
|
}
|
||||||
|
credsYaml, err := json.Marshal(&outputCTX.API.Creds)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("can't marshal credentials : %v", err)
|
||||||
|
}
|
||||||
|
apiCredsDumped := fmt.Sprintf("%s/api_creds.json", target)
|
||||||
|
err = ioutil.WriteFile(apiCredsDumped, credsYaml, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to write credentials to %s : %s", apiCredsDumped, err)
|
||||||
|
}
|
||||||
|
log.Infof("Saved configuration to %s", target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBackupCmd() *cobra.Command {
|
||||||
|
var cmdBackup = &cobra.Command{
|
||||||
|
Use: "backup [save|restore] <directory>",
|
||||||
|
Short: "Backup or restore configuration (api, parsers, scenarios etc.) to/from directory",
|
||||||
|
Long: `This command is here to help you save and/or restore crowdsec configurations to simple replication`,
|
||||||
|
Example: `cscli backup save ./my-backup
|
||||||
|
cscli backup restore ./my-backup`,
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdBackupSave = &cobra.Command{
|
||||||
|
Use: "save <directory>",
|
||||||
|
Short: "Backup configuration (api, parsers, scenarios etc.) to directory",
|
||||||
|
Long: `backup command will try to save all relevant informations to crowdsec config, including :
|
||||||
|
|
||||||
|
- List of scenarios, parsers, postoverflows and collections that are up-to-date
|
||||||
|
|
||||||
|
- Actual backup of tainted/local/out-of-date scenarios, parsers, postoverflows and collections
|
||||||
|
|
||||||
|
- Backup of API credentials
|
||||||
|
|
||||||
|
- Backup of acqusition configuration
|
||||||
|
|
||||||
|
`,
|
||||||
|
Example: `cscli backup save ./my-backup`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
outputConfig := outputs.OutputFactory{
|
||||||
|
BackendFolder: config.BackendPluginFolder,
|
||||||
|
}
|
||||||
|
outputCTX, err = outputs.NewOutput(&outputConfig, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to load output plugins")
|
||||||
|
}
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if err := backupToDirectory(args[0]); err != nil {
|
||||||
|
log.Fatalf("Failed backuping to %s : %s", args[0], err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBackup.AddCommand(cmdBackupSave)
|
||||||
|
|
||||||
|
var cmdBackupRestore = &cobra.Command{
|
||||||
|
Use: "restore <directory>",
|
||||||
|
Short: "Restore configuration (api, parsers, scenarios etc.) from directory",
|
||||||
|
Long: `restore command will try to restore all saved information from <directory> to yor local setup, including :
|
||||||
|
|
||||||
|
- Installation of up-to-date scenarios/parsers/... via cscli
|
||||||
|
|
||||||
|
- Restauration of tainted/local/out-of-date scenarios/parsers/... file
|
||||||
|
|
||||||
|
- Restauration of API credentials (if the existing ones aren't working)
|
||||||
|
|
||||||
|
- Restauration of acqusition configuration
|
||||||
|
`,
|
||||||
|
Example: `cscli backup restore ./my-backup`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
outputConfig := outputs.OutputFactory{
|
||||||
|
BackendFolder: config.BackendPluginFolder,
|
||||||
|
}
|
||||||
|
outputCTX, err = outputs.NewOutput(&outputConfig, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to load output plugins")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if err := restoreFromDirectory(args[0]); err != nil {
|
||||||
|
log.Fatalf("failed restoring from %s : %s", args[0], err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBackup.AddCommand(cmdBackupRestore)
|
||||||
|
|
||||||
|
return cmdBackup
|
||||||
|
}
|
326
cmd/crowdsec-cli/ban.go
Normal file
326
cmd/crowdsec-cli/ban.go
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/parser"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var remediationType string
|
||||||
|
var atTime string
|
||||||
|
var all bool
|
||||||
|
|
||||||
|
func simpleBanToSignal(targetIP string, reason string, expirationStr string, action string, asName string, asNum string, country string, banSource string) (types.SignalOccurence, error) {
|
||||||
|
var signalOcc types.SignalOccurence
|
||||||
|
|
||||||
|
expiration, err := time.ParseDuration(expirationStr)
|
||||||
|
if err != nil {
|
||||||
|
return signalOcc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
asOrgInt := 0
|
||||||
|
if asNum != "" {
|
||||||
|
asOrgInt, err = strconv.Atoi(asNum)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Invalid as value %s : %s", asNum, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
banApp := types.BanApplication{
|
||||||
|
MeasureSource: banSource,
|
||||||
|
MeasureType: action,
|
||||||
|
Until: time.Now().Add(expiration),
|
||||||
|
IpText: targetIP,
|
||||||
|
TargetCN: country,
|
||||||
|
TargetAS: asOrgInt,
|
||||||
|
TargetASName: asName,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
var parsedIP net.IP
|
||||||
|
var parsedRange *net.IPNet
|
||||||
|
if strings.Contains(targetIP, "/") {
|
||||||
|
if parsedIP, parsedRange, err = net.ParseCIDR(targetIP); err != nil {
|
||||||
|
return signalOcc, fmt.Errorf("'%s' is not a valid CIDR", targetIP)
|
||||||
|
}
|
||||||
|
if parsedRange == nil {
|
||||||
|
return signalOcc, fmt.Errorf("Unable to parse network : %s", err)
|
||||||
|
}
|
||||||
|
banApp.StartIp = types.IP2Int(parsedRange.IP)
|
||||||
|
banApp.EndIp = types.IP2Int(types.LastAddress(parsedRange))
|
||||||
|
} else {
|
||||||
|
parsedIP = net.ParseIP(targetIP)
|
||||||
|
if parsedIP == nil {
|
||||||
|
return signalOcc, fmt.Errorf("'%s' is not a valid IP", targetIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var banApps = make([]types.BanApplication, 1)
|
||||||
|
banApps = append(banApps, banApp)
|
||||||
|
signalOcc = types.SignalOccurence{
|
||||||
|
Scenario: reason,
|
||||||
|
Events_count: 1,
|
||||||
|
Start_at: time.Now(),
|
||||||
|
Stop_at: time.Now(),
|
||||||
|
BanApplications: banApps,
|
||||||
|
Source_ip: targetIP,
|
||||||
|
Source_AutonomousSystemNumber: asNum,
|
||||||
|
Source_AutonomousSystemOrganization: asName,
|
||||||
|
Source_Country: country,
|
||||||
|
}
|
||||||
|
return signalOcc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BanList() error {
|
||||||
|
at := time.Now()
|
||||||
|
if atTime != "" {
|
||||||
|
_, at = parser.GenDateParse(atTime)
|
||||||
|
if at.IsZero() {
|
||||||
|
return fmt.Errorf("Unable to parse date '%s'", atTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret, err := outputCTX.ReadAT(at)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get records from sqlite : %v", err)
|
||||||
|
}
|
||||||
|
if config.output == "json" {
|
||||||
|
x, _ := json.MarshalIndent(ret, "", " ")
|
||||||
|
fmt.Printf("%s", string(x))
|
||||||
|
} else if config.output == "human" {
|
||||||
|
|
||||||
|
uniqAS := map[string]bool{}
|
||||||
|
uniqCN := map[string]bool{}
|
||||||
|
|
||||||
|
table := tablewriter.NewWriter(os.Stdout)
|
||||||
|
table.SetHeader([]string{"Source", "Ip", "Reason", "Bans", "Action", "Country", "AS", "Events", "Expiration"})
|
||||||
|
|
||||||
|
dispcount := 0
|
||||||
|
totcount := 0
|
||||||
|
apicount := 0
|
||||||
|
for _, rm := range ret {
|
||||||
|
if !all && rm["source"] == "api" {
|
||||||
|
apicount++
|
||||||
|
if _, ok := uniqAS[rm["as"]]; !ok {
|
||||||
|
uniqAS[rm["as"]] = true
|
||||||
|
}
|
||||||
|
if _, ok := uniqCN[rm["cn"]]; !ok {
|
||||||
|
uniqCN[rm["cn"]] = true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dispcount < 20 {
|
||||||
|
table.Append([]string{rm["source"], rm["iptext"], rm["reason"], rm["bancount"], rm["action"], rm["cn"], rm["as"], rm["events_count"], rm["until"]})
|
||||||
|
}
|
||||||
|
totcount++
|
||||||
|
dispcount++
|
||||||
|
|
||||||
|
}
|
||||||
|
if dispcount > 0 {
|
||||||
|
if !all {
|
||||||
|
fmt.Printf("%d local decisions:\n", totcount)
|
||||||
|
}
|
||||||
|
table.Render() // Send output
|
||||||
|
if dispcount > 20 {
|
||||||
|
fmt.Printf("Additional records stripped.\n")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No local decisions.\n")
|
||||||
|
}
|
||||||
|
if !all {
|
||||||
|
fmt.Printf("And %d records from API, %d distinct AS, %d distinct countries\n", apicount, len(uniqAS), len(uniqCN))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BanAdd(target string, duration string, reason string, action string) error {
|
||||||
|
var signalOcc types.SignalOccurence
|
||||||
|
var err error
|
||||||
|
|
||||||
|
signalOcc, err = simpleBanToSignal(target, reason, duration, action, "", "", "", "cli")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to insert ban : %v", err)
|
||||||
|
}
|
||||||
|
err = outputCTX.Insert(signalOcc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = outputCTX.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Wrote ban to database.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func banFlush() error {
|
||||||
|
allBa := types.BanApplication{}
|
||||||
|
records := dbctx.Db.Delete(&allBa)
|
||||||
|
if records.Error != nil {
|
||||||
|
return records.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBanCmds() *cobra.Command {
|
||||||
|
/*TODO : add a remediation type*/
|
||||||
|
var cmdBan = &cobra.Command{
|
||||||
|
Use: "ban [command] <target> <duration> <reason>",
|
||||||
|
Short: "Manage bans/mitigations",
|
||||||
|
Long: `This is the main interaction point with local ban database for humans.
|
||||||
|
|
||||||
|
You can add/delete/list or flush current bans in your local ban DB.`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before using bans")
|
||||||
|
}
|
||||||
|
|
||||||
|
outputConfig := outputs.OutputFactory{
|
||||||
|
BackendFolder: config.BackendPluginFolder,
|
||||||
|
}
|
||||||
|
|
||||||
|
outputCTX, err = outputs.NewOutput(&outputConfig, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBan.PersistentFlags().StringVar(&config.dbPath, "db", "", "Set path to SQLite DB.")
|
||||||
|
cmdBan.PersistentFlags().StringVar(&remediationType, "remediation", "ban", "Set specific remediation type : ban|slow|captcha")
|
||||||
|
cmdBan.Flags().SortFlags = false
|
||||||
|
cmdBan.PersistentFlags().SortFlags = false
|
||||||
|
|
||||||
|
var cmdBanAdd = &cobra.Command{
|
||||||
|
Use: "add [ip|range] <target> <duration> <reason>",
|
||||||
|
Short: "Adds a ban against a given ip/range for the provided duration",
|
||||||
|
Long: `
|
||||||
|
Allows to add a ban against a specific ip or range target for a specific duration.
|
||||||
|
|
||||||
|
The duration argument can be expressed in seconds(s), minutes(m) or hours (h).
|
||||||
|
|
||||||
|
See [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) for more informations.`,
|
||||||
|
Example: `cscli ban add ip 1.2.3.4 24h "scan"
|
||||||
|
cscli ban add range 1.2.3.0/24 24h "the whole range"`,
|
||||||
|
Args: cobra.MinimumNArgs(4),
|
||||||
|
}
|
||||||
|
cmdBan.AddCommand(cmdBanAdd)
|
||||||
|
var cmdBanAddIp = &cobra.Command{
|
||||||
|
Use: "ip <target> <duration> <reason>",
|
||||||
|
Short: "Adds the specific ip to the ban db",
|
||||||
|
Long: `Duration must be [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration), expressed in s/m/h.`,
|
||||||
|
Example: `cscli ban add ip 1.2.3.4 12h "the scan"`,
|
||||||
|
Args: cobra.ExactArgs(3),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := BanAdd(args[0], args[1], args[2], remediationType); err != nil {
|
||||||
|
log.Fatalf("failed to add ban to sqlite : %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBanAdd.AddCommand(cmdBanAddIp)
|
||||||
|
var cmdBanAddRange = &cobra.Command{
|
||||||
|
Use: "range <target> <duration> <reason>",
|
||||||
|
Short: "Adds the specific ip to the ban db",
|
||||||
|
Long: `Duration must be [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) compatible, expressed in s/m/h.`,
|
||||||
|
Example: `cscli ban add range 1.2.3.0/24 12h "the whole range"`,
|
||||||
|
Args: cobra.ExactArgs(3),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := BanAdd(args[0], args[1], args[2], remediationType); err != nil {
|
||||||
|
log.Fatalf("failed to add ban to sqlite : %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBanAdd.AddCommand(cmdBanAddRange)
|
||||||
|
var cmdBanDel = &cobra.Command{
|
||||||
|
Use: "del [command] <target>",
|
||||||
|
Short: "Delete bans from db",
|
||||||
|
Long: "The removal of the bans can be applied on a single IP address or directly on a IP range.",
|
||||||
|
Example: `cscli ban del ip 1.2.3.4
|
||||||
|
cscli ban del range 1.2.3.0/24`,
|
||||||
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
}
|
||||||
|
cmdBan.AddCommand(cmdBanDel)
|
||||||
|
|
||||||
|
var cmdBanFlush = &cobra.Command{
|
||||||
|
Use: "flush",
|
||||||
|
Short: "Fush ban DB",
|
||||||
|
Example: `cscli ban flush`,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := outputCTX.DeleteAll(); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
log.Printf("Ban DB flushed")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBan.AddCommand(cmdBanFlush)
|
||||||
|
var cmdBanDelIp = &cobra.Command{
|
||||||
|
Use: "ip <target>",
|
||||||
|
Short: "Delete bans for given ip from db",
|
||||||
|
Example: `cscli ban del ip 1.2.3.4`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
count, err := outputCTX.Delete(args[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to delete %s : %v", args[0], err)
|
||||||
|
}
|
||||||
|
log.Infof("Deleted %d entries", count)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBanDel.AddCommand(cmdBanDelIp)
|
||||||
|
var cmdBanDelRange = &cobra.Command{
|
||||||
|
Use: "range <target>",
|
||||||
|
Short: "Delete bans for given ip from db",
|
||||||
|
Example: `cscli ban del range 1.2.3.0/24`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
count, err := outputCTX.Delete(args[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to delete %s : %v", args[0], err)
|
||||||
|
}
|
||||||
|
log.Infof("Deleted %d entries", count)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBanDel.AddCommand(cmdBanDelRange)
|
||||||
|
|
||||||
|
var cmdBanList = &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List local or api bans/remediations",
|
||||||
|
Long: `List the bans, by default only local decisions.
|
||||||
|
|
||||||
|
If --all/-a is specified, api-provided bans will be displayed too.
|
||||||
|
|
||||||
|
Time can be specified with --at and support a variety of date formats:
|
||||||
|
- Jan 2 15:04:05
|
||||||
|
- Mon Jan 02 15:04:05.000000 2006
|
||||||
|
- 2006-01-02T15:04:05Z07:00
|
||||||
|
- 2006/01/02
|
||||||
|
- 2006/01/02 15:04
|
||||||
|
- 2006-01-02
|
||||||
|
- 2006-01-02 15:04
|
||||||
|
`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := BanList(); err != nil {
|
||||||
|
log.Fatalf("failed to list bans : %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdBanList.PersistentFlags().StringVar(&atTime, "at", "", "List bans at given time")
|
||||||
|
cmdBanList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well bans received from API")
|
||||||
|
cmdBan.AddCommand(cmdBanList)
|
||||||
|
return cmdBan
|
||||||
|
}
|
160
cmd/crowdsec-cli/config.go
Normal file
160
cmd/crowdsec-cli/config.go
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*CliCfg is the cli configuration structure, might be unexported*/
|
||||||
|
type cliConfig struct {
|
||||||
|
configured bool
|
||||||
|
simulation bool /*are we in simulation mode*/
|
||||||
|
configFolder string `yaml:"cliconfig,omitempty"` /*overload ~/.cscli/*/
|
||||||
|
output string /*output is human, json*/
|
||||||
|
logLevel log.Level /*debug,info,warning,error*/
|
||||||
|
hubFolder string
|
||||||
|
InstallFolder string `yaml:"installdir"` /*/etc/crowdsec/*/
|
||||||
|
BackendPluginFolder string `yaml:"backend"`
|
||||||
|
dbPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func interactiveCfg() error {
|
||||||
|
var err error
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
fmt.Print("crowdsec installation directory (default: /etc/crowdsec/crowdsec/): ")
|
||||||
|
config.InstallFolder, err = reader.ReadString('\n')
|
||||||
|
config.InstallFolder = strings.Replace(config.InstallFolder, "\n", "", -1) //CRLF to LF (windows)
|
||||||
|
if config.InstallFolder == "" {
|
||||||
|
config.InstallFolder = "/etc/crowdsec/crowdsec/"
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to read input : %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("crowdsec backend plugin directory (default: /etc/crowdsec/plugin/backend): ")
|
||||||
|
config.BackendPluginFolder, err = reader.ReadString('\n')
|
||||||
|
config.BackendPluginFolder = strings.Replace(config.BackendPluginFolder, "\n", "", -1) //CRLF to LF (windows)
|
||||||
|
if config.BackendPluginFolder == "" {
|
||||||
|
config.BackendPluginFolder = "/etc/crowdsec/plugin/backend"
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to read input : %v", err.Error())
|
||||||
|
}
|
||||||
|
if err := writeCfg(); err != nil {
|
||||||
|
log.Fatalf("failed writting configuration file : %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeCfg() error {
|
||||||
|
|
||||||
|
if config.configFolder == "" {
|
||||||
|
return fmt.Errorf("config dir is unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.hubFolder = config.configFolder + "/hub/"
|
||||||
|
if _, err := os.Stat(config.hubFolder); os.IsNotExist(err) {
|
||||||
|
|
||||||
|
log.Warningf("creating skeleton!")
|
||||||
|
if err := os.MkdirAll(config.hubFolder, os.ModePerm); err != nil {
|
||||||
|
return fmt.Errorf("failed to create missing directory : '%s'", config.hubFolder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out := path.Join(config.configFolder, "/config")
|
||||||
|
configYaml, err := yaml.Marshal(&config)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed marshaling config: %s", err)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(out, configYaml, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to write to %s : %s", out, err)
|
||||||
|
}
|
||||||
|
log.Infof("wrote config to %s ", out)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigCmd() *cobra.Command {
|
||||||
|
|
||||||
|
var cmdConfig = &cobra.Command{
|
||||||
|
Use: "config [command] <value>",
|
||||||
|
Short: "Allows to view/edit cscli config",
|
||||||
|
Long: `Allow to configure sqlite path and installation directory.
|
||||||
|
If no commands are specified, config is in interactive mode.`,
|
||||||
|
Example: ` - cscli config show
|
||||||
|
- cscli config prompt`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
}
|
||||||
|
var cmdConfigShow = &cobra.Command{
|
||||||
|
Use: "show",
|
||||||
|
Short: "Displays current config",
|
||||||
|
Long: `Displays the current cli configuration.`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if config.output == "json" {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"installdir": config.InstallFolder,
|
||||||
|
"cliconfig": path.Join(config.configFolder, "/config"),
|
||||||
|
}).Warning("Current config")
|
||||||
|
} else {
|
||||||
|
x, err := yaml.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to marshal current configuration : %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", x)
|
||||||
|
fmt.Printf("#cliconfig: %s", path.Join(config.configFolder, "/config"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdConfig.AddCommand(cmdConfigShow)
|
||||||
|
var cmdConfigInterctive = &cobra.Command{
|
||||||
|
Use: "prompt",
|
||||||
|
Short: "Prompt for configuration values in an interactive fashion",
|
||||||
|
Long: `Start interactive configuration of cli. It will successively ask for install dir, db path.`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
err := interactiveCfg()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to run interactive config : %s", err)
|
||||||
|
}
|
||||||
|
log.Warningf("Configured, please run update.")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdConfig.AddCommand(cmdConfigInterctive)
|
||||||
|
var cmdConfigInstalldir = &cobra.Command{
|
||||||
|
Use: "installdir [value]",
|
||||||
|
Short: `Configure installation directory`,
|
||||||
|
Long: `Configure the installation directory of crowdsec, such as /etc/crowdsec/crowdsec/`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
config.InstallFolder = args[0]
|
||||||
|
if err := writeCfg(); err != nil {
|
||||||
|
log.Fatalf("failed writting configuration: %s", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdConfig.AddCommand(cmdConfigInstalldir)
|
||||||
|
|
||||||
|
var cmdConfigBackendFolder = &cobra.Command{
|
||||||
|
Use: "backend [value]",
|
||||||
|
Short: `Configure installation directory`,
|
||||||
|
Long: `Configure the backend plugin directory of crowdsec, such as /etc/crowdsec/plugins/backend`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
config.BackendPluginFolder = args[0]
|
||||||
|
if err := writeCfg(); err != nil {
|
||||||
|
log.Fatalf("failed writting configuration: %s", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdConfig.AddCommand(cmdConfigBackendFolder)
|
||||||
|
|
||||||
|
return cmdConfig
|
||||||
|
}
|
371
cmd/crowdsec-cli/dashboard.go
Normal file
371
cmd/crowdsec-cli/dashboard.go
Normal file
|
@ -0,0 +1,371 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
|
"github.com/dghubble/sling"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
metabaseImage = "metabase/metabase"
|
||||||
|
metabaseDbURI = "https://crowdsec-statics-assets.s3-eu-west-1.amazonaws.com/metabase.db.zip"
|
||||||
|
metabaseDbPath = "/var/lib/crowdsec/data"
|
||||||
|
/**/
|
||||||
|
metabaseListenAddress = "127.0.0.1"
|
||||||
|
metabaseListenPort = "3000"
|
||||||
|
metabaseContainerID = "/crowdsec-metabase"
|
||||||
|
/*informations needed to setup a random password on user's behalf*/
|
||||||
|
metabaseURI = "http://localhost:3000/api/"
|
||||||
|
metabaseURISession = "session"
|
||||||
|
metabaseURIRescan = "database/2/rescan_values"
|
||||||
|
metabaseURIUpdatepwd = "user/1/password"
|
||||||
|
defaultPassword = "c6cmetabase"
|
||||||
|
defaultEmail = "metabase@crowdsec.net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewDashboardCmd() *cobra.Command {
|
||||||
|
/* ---- UPDATE COMMAND */
|
||||||
|
var cmdDashboard = &cobra.Command{
|
||||||
|
Use: "dashboard",
|
||||||
|
Short: "Start a dashboard (metabase) container.",
|
||||||
|
Long: `Start a metabase container exposing dashboards and metrics.`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Example: `cscli dashboard setup
|
||||||
|
cscli dashboard start
|
||||||
|
cscli dashboard stop
|
||||||
|
cscli dashboard setup --force`,
|
||||||
|
}
|
||||||
|
|
||||||
|
var force bool
|
||||||
|
var cmdDashSetup = &cobra.Command{
|
||||||
|
Use: "setup",
|
||||||
|
Short: "Setup a metabase container.",
|
||||||
|
Long: `Perform a metabase docker setup, download standard dashboards, create a fresh user and start the container`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Example: `cscli dashboard setup
|
||||||
|
cscli dashboard setup --force
|
||||||
|
cscli dashboard setup -l 0.0.0.0 -p 443
|
||||||
|
`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := downloadMetabaseDB(force); err != nil {
|
||||||
|
log.Fatalf("Failed to download metabase DB : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("Downloaded metabase DB")
|
||||||
|
if err := createMetabase(); err != nil {
|
||||||
|
log.Fatalf("Failed to start metabase container : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("Started metabase")
|
||||||
|
newpassword := generatePassword()
|
||||||
|
if err := resetMetabasePassword(newpassword); err != nil {
|
||||||
|
log.Fatalf("Failed to reset password : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("Setup finished")
|
||||||
|
log.Infof("url : http://%s:%s", metabaseListenAddress, metabaseListenPort)
|
||||||
|
log.Infof("username: %s", defaultEmail)
|
||||||
|
log.Infof("password: %s", newpassword)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdDashSetup.Flags().BoolVarP(&force, "force", "f", false, "Force setup : override existing files.")
|
||||||
|
cmdDashSetup.Flags().StringVarP(&metabaseDbPath, "dir", "d", metabaseDbPath, "Shared directory with metabase container.")
|
||||||
|
cmdDashSetup.Flags().StringVarP(&metabaseListenAddress, "listen", "l", metabaseListenAddress, "Listen address of container")
|
||||||
|
cmdDashSetup.Flags().StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container")
|
||||||
|
cmdDashboard.AddCommand(cmdDashSetup)
|
||||||
|
|
||||||
|
var cmdDashStart = &cobra.Command{
|
||||||
|
Use: "start",
|
||||||
|
Short: "Start the metabase container.",
|
||||||
|
Long: `Stats the metabase container using docker.`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := startMetabase(); err != nil {
|
||||||
|
log.Fatalf("Failed to start metabase container : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("Started metabase")
|
||||||
|
log.Infof("url : http://%s:%s", metabaseListenAddress, metabaseListenPort)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdDashboard.AddCommand(cmdDashStart)
|
||||||
|
|
||||||
|
var remove bool
|
||||||
|
var cmdDashStop = &cobra.Command{
|
||||||
|
Use: "stop",
|
||||||
|
Short: "Stops the metabase container.",
|
||||||
|
Long: `Stops the metabase container using docker.`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := stopMetabase(remove); err != nil {
|
||||||
|
log.Fatalf("Failed to stop metabase container : %s", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdDashStop.Flags().BoolVarP(&remove, "remove", "r", false, "remove (docker rm) container as well.")
|
||||||
|
cmdDashboard.AddCommand(cmdDashStop)
|
||||||
|
return cmdDashboard
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadMetabaseDB(force bool) error {
|
||||||
|
|
||||||
|
metabaseDBSubpath := path.Join(metabaseDbPath, "metabase.db")
|
||||||
|
|
||||||
|
_, err := os.Stat(metabaseDBSubpath)
|
||||||
|
if err == nil && force == false {
|
||||||
|
log.Printf("%s exists, skip.", metabaseDBSubpath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(metabaseDBSubpath, 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create %s : %s", metabaseDBSubpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", metabaseDbURI, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to build request to fetch metabase db : %s", err)
|
||||||
|
}
|
||||||
|
//This needs to be removed once we move the zip out of github
|
||||||
|
req.Header.Add("Accept", `application/vnd.github.v3.raw`)
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed request to fetch metabase db : %s", err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return fmt.Errorf("got http %d while requesting metabase db %s, stop", resp.StatusCode, metabaseDbURI)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed request read while fetching metabase db : %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Got %d bytes archive", len(body))
|
||||||
|
if err := extractMetabaseDB(bytes.NewReader(body)); err != nil {
|
||||||
|
return fmt.Errorf("while extracting zip : %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractMetabaseDB(buf *bytes.Reader) error {
|
||||||
|
r, err := zip.NewReader(buf, int64(buf.Len()))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, f := range r.File {
|
||||||
|
tfname := fmt.Sprintf("%s/%s", metabaseDbPath, f.Name)
|
||||||
|
log.Debugf("%s -> %d", f.Name, f.UncompressedSize64)
|
||||||
|
if f.UncompressedSize64 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tfd, err := os.OpenFile(tfname, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed opening target file '%s' : %s", tfname, err)
|
||||||
|
}
|
||||||
|
rc, err := f.Open()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("While opening zip content %s : %s", f.Name, err)
|
||||||
|
}
|
||||||
|
written, err := io.Copy(tfd, rc)
|
||||||
|
if err == io.EOF {
|
||||||
|
log.Printf("files finished ok")
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("While copying content to %s : %s", tfname, err)
|
||||||
|
}
|
||||||
|
log.Infof("written %d bytes to %s", written, tfname)
|
||||||
|
rc.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resetMetabasePassword(newpassword string) error {
|
||||||
|
|
||||||
|
httpctx := sling.New().Base(metabaseURI).Set("User-Agent", fmt.Sprintf("CrowdWatch/%s", cwversion.VersionStr()))
|
||||||
|
|
||||||
|
log.Printf("Waiting for metabase API to be up (can take up to a minute)")
|
||||||
|
for {
|
||||||
|
sessionreq, err := httpctx.New().Post(metabaseURISession).BodyJSON(map[string]string{"username": defaultEmail, "password": defaultPassword}).Request()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("api signin: HTTP request creation failed: %s", err)
|
||||||
|
}
|
||||||
|
httpClient := http.Client{Timeout: 20 * time.Second}
|
||||||
|
resp, err := httpClient.Do(sessionreq)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(".")
|
||||||
|
log.Debugf("While waiting for metabase to be up : %s", err)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
fmt.Printf("\n")
|
||||||
|
log.Printf("Metabase API is up")
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("metabase session unable to read API response body: '%s'", err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return fmt.Errorf("metabase session http error (%d): %s", resp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
log.Printf("Successfully authenticated")
|
||||||
|
jsonResp := make(map[string]string)
|
||||||
|
err = json.Unmarshal(body, &jsonResp)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal metabase api response '%s': %s", string(body), err.Error())
|
||||||
|
}
|
||||||
|
log.Debugf("unmarshaled response : %v", jsonResp)
|
||||||
|
httpctx = httpctx.Set("Cookie", fmt.Sprintf("metabase.SESSION=%s", jsonResp["id"]))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
/*rescan values*/
|
||||||
|
sessionreq, err := httpctx.New().Post(metabaseURIRescan).Request()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("metabase rescan_values http error : %s", err)
|
||||||
|
}
|
||||||
|
httpClient := http.Client{Timeout: 20 * time.Second}
|
||||||
|
resp, err := httpClient.Do(sessionreq)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("While trying to do rescan api call to metabase : %s", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("While reading rescan api call response : %s", err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return fmt.Errorf("Got '%s' (http:%d) while trying to rescan metabase", string(body), resp.StatusCode)
|
||||||
|
}
|
||||||
|
/*update password*/
|
||||||
|
sessionreq, err = httpctx.New().Put(metabaseURIUpdatepwd).BodyJSON(map[string]string{
|
||||||
|
"id": "1",
|
||||||
|
"password": newpassword,
|
||||||
|
"old_password": defaultPassword}).Request()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("metabase password change http error : %s", err)
|
||||||
|
}
|
||||||
|
httpClient = http.Client{Timeout: 20 * time.Second}
|
||||||
|
resp, err = httpClient.Do(sessionreq)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("While trying to reset metabase password : %s", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("while reading from %s: '%s'", metabaseURIUpdatepwd, err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
log.Printf("Got %s (http:%d) while trying to reset password.", string(body), resp.StatusCode)
|
||||||
|
log.Printf("Password has probably already been changed.")
|
||||||
|
log.Printf("Use the dashboard install command to reset existing setup.")
|
||||||
|
return fmt.Errorf("got http error %d on %s : %s", resp.StatusCode, metabaseURIUpdatepwd, string(body))
|
||||||
|
}
|
||||||
|
log.Printf("Changed password !")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startMetabase() error {
|
||||||
|
ctx := context.Background()
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create docker client : %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cli.ContainerStart(ctx, metabaseContainerID, types.ContainerStartOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("Failed while starting %s : %s", metabaseContainerID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopMetabase(remove bool) error {
|
||||||
|
log.Printf("Stop docker metabase %s", metabaseContainerID)
|
||||||
|
ctx := context.Background()
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create docker client : %s", err)
|
||||||
|
}
|
||||||
|
var to time.Duration = 20 * time.Second
|
||||||
|
if err := cli.ContainerStop(ctx, metabaseContainerID, &to); err != nil {
|
||||||
|
return fmt.Errorf("Failed while stopping %s : %s", metabaseContainerID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if remove {
|
||||||
|
log.Printf("Removing docker metabase %s", metabaseContainerID)
|
||||||
|
if err := cli.ContainerRemove(ctx, metabaseContainerID, types.ContainerRemoveOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("Failed remove container %s : %s", metabaseContainerID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMetabase() error {
|
||||||
|
ctx := context.Background()
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to start docker client : %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Pulling docker image %s", metabaseImage)
|
||||||
|
reader, err := cli.ImagePull(ctx, metabaseImage, types.ImagePullOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to pull docker image : %s", err)
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
fmt.Print(".")
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return fmt.Errorf("failed to read imagepull reader: %s", err)
|
||||||
|
}
|
||||||
|
fmt.Print("\n")
|
||||||
|
|
||||||
|
hostConfig := &container.HostConfig{
|
||||||
|
PortBindings: nat.PortMap{
|
||||||
|
"3000/tcp": []nat.PortBinding{
|
||||||
|
{
|
||||||
|
HostIP: metabaseListenAddress,
|
||||||
|
HostPort: metabaseListenPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Mounts: []mount.Mount{
|
||||||
|
{
|
||||||
|
Type: mount.TypeBind,
|
||||||
|
Source: metabaseDbPath,
|
||||||
|
Target: "/metabase-data",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
dockerConfig := &container.Config{
|
||||||
|
Image: metabaseImage,
|
||||||
|
Tty: true,
|
||||||
|
Env: []string{"MB_DB_FILE=/metabase-data/metabase.db"},
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Creating container")
|
||||||
|
resp, err := cli.ContainerCreate(ctx, dockerConfig, hostConfig, nil, metabaseContainerID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create container : %s", err)
|
||||||
|
}
|
||||||
|
log.Printf("Starting container")
|
||||||
|
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("Failed to start docker container : %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
57
cmd/crowdsec-cli/doc/cwcli.md
Normal file
57
cmd/crowdsec-cli/doc/cwcli.md
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
## cscli
|
||||||
|
|
||||||
|
cscli allows you to manage crowdsec
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
cscli is the main command to interact with your crowdsec service, scenarios & db.
|
||||||
|
It is meant to allow you to manage bans, parsers/scenarios/etc, api and generally manage you crowdsec setup.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
View/Add/Remove bans:
|
||||||
|
- cscli ban list
|
||||||
|
- cscli ban add ip 1.2.3.4 24h 'go away'
|
||||||
|
- cscli ban del 1.2.3.4
|
||||||
|
|
||||||
|
View/Add/Upgrade/Remove scenarios and parsers:
|
||||||
|
- cscli list
|
||||||
|
- cscli install collection crowdsec/linux-web
|
||||||
|
- cscli remove scenario crowdsec/ssh_enum
|
||||||
|
- cscli upgrade --all
|
||||||
|
|
||||||
|
API interaction:
|
||||||
|
- cscli api pull
|
||||||
|
- cscli api register
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--info Set logging to info.
|
||||||
|
--warning Set logging to warning.
|
||||||
|
--error Set logging to error.
|
||||||
|
-h, --help help for cscli
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
* [cscli backup](cscli_backup.md) - Backup or restore configuration (api, parsers, scenarios etc.) to/from directory
|
||||||
|
* [cscli ban](cscli_ban.md) - Manage bans/mitigations
|
||||||
|
* [cscli config](cscli_config.md) - Allows to view/edit cscli config
|
||||||
|
* [cscli dashboard](cscli_dashboard.md) - Start a dashboard (metabase) container.
|
||||||
|
* [cscli inspect](cscli_inspect.md) - Inspect configuration(s)
|
||||||
|
* [cscli install](cscli_install.md) - Install configuration(s) from hub
|
||||||
|
* [cscli list](cscli_list.md) - List enabled configs
|
||||||
|
* [cscli metrics](cscli_metrics.md) - Display crowdsec prometheus metrics.
|
||||||
|
* [cscli remove](cscli_remove.md) - Remove/disable configuration(s)
|
||||||
|
* [cscli update](cscli_update.md) - Fetch available configs from hub
|
||||||
|
* [cscli upgrade](cscli_upgrade.md) - Upgrade configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
49
cmd/crowdsec-cli/doc/cwcli_api.md
Normal file
49
cmd/crowdsec-cli/doc/cwcli_api.md
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
## cscli api
|
||||||
|
|
||||||
|
Crowdsec API interaction
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Allow to register your machine into crowdsec API to send and receive signal.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
cscli api register # Register to Crowdsec API
|
||||||
|
cscli api pull # Pull malevolant IPs from Crowdsec API
|
||||||
|
cscli api reset # Reset your machines credentials
|
||||||
|
cscli api enroll # Enroll your machine to the user account you created on Crowdsec backend
|
||||||
|
cscli api credentials # Display your API credentials
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for api
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli api credentials](cscli_api_credentials.md) - Display api credentials
|
||||||
|
* [cscli api enroll](cscli_api_enroll.md) - Associate your machine to an existing crowdsec user
|
||||||
|
* [cscli api pull](cscli_api_pull.md) - Pull crowdsec API TopX
|
||||||
|
* [cscli api register](cscli_api_register.md) - Register on Crowdsec API
|
||||||
|
* [cscli api reset](cscli_api_reset.md) - Reset password on CrowdSec API
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_api_credentials.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_api_credentials.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli api credentials
|
||||||
|
|
||||||
|
Display api credentials
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Display api credentials
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api credentials [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
41
cmd/crowdsec-cli/doc/cwcli_api_enroll.md
Normal file
41
cmd/crowdsec-cli/doc/cwcli_api_enroll.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
## cscli api enroll
|
||||||
|
|
||||||
|
Associate your machine to an existing crowdsec user
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Enrolling your machine into your user account will allow for more accurate lists and threat detection. See website to create user account.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api enroll [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api enroll -u 1234567890ffff
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for enroll
|
||||||
|
-u, --user string User ID (required)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_api_pull.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_api_pull.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli api pull
|
||||||
|
|
||||||
|
Pull crowdsec API TopX
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Pulls a list of malveolent IPs relevant to your situation and add them into the local ban database.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api pull [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api pull
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for pull
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
41
cmd/crowdsec-cli/doc/cwcli_api_register.md
Normal file
41
cmd/crowdsec-cli/doc/cwcli_api_register.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
## cscli api register
|
||||||
|
|
||||||
|
Register on Crowdsec API
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
This command will register your machine to crowdsec API to allow you to receive list of malveolent IPs.
|
||||||
|
The printed machine_id and password should be added to your api.yaml file.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api register [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api register
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for register
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_api_reset.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_api_reset.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli api reset
|
||||||
|
|
||||||
|
Reset password on CrowdSec API
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Attempts to reset your credentials to the API.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api reset [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli api reset
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for reset
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli api](cscli_api.md) - Crowdsec API interaction
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_backup.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_backup.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli backup
|
||||||
|
|
||||||
|
Backup or restore configuration (api, parsers, scenarios etc.) to/from directory
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
This command is here to help you save and/or restore crowdsec configurations to simple replication
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli backup save ./my-backup
|
||||||
|
cscli backup restore ./my-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--cfgdir string Configuration directory (default "/etc/crowdsec/")
|
||||||
|
-h, --help help for backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli backup restore](cscli_backup_restore.md) - Restore configuration (api, parsers, scenarios etc.) from directory
|
||||||
|
* [cscli backup save](cscli_backup_save.md) - Backup configuration (api, parsers, scenarios etc.) to directory
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
50
cmd/crowdsec-cli/doc/cwcli_backup_restore.md
Normal file
50
cmd/crowdsec-cli/doc/cwcli_backup_restore.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
## cscli backup restore
|
||||||
|
|
||||||
|
Restore configuration (api, parsers, scenarios etc.) from directory
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
restore command will try to restore all saved information from <directory> to yor local setup, including :
|
||||||
|
|
||||||
|
- Installation of up-to-date scenarios/parsers/... via cscli
|
||||||
|
|
||||||
|
- Restauration of tainted/local/out-of-date scenarios/parsers/... file
|
||||||
|
|
||||||
|
- Restauration of API credentials (if the existing ones aren't working)
|
||||||
|
|
||||||
|
- Restauration of acqusition configuration
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli backup restore <directory> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli backup restore ./my-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--cfgdir string Configuration directory (default "/etc/crowdsec/")
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli backup](cscli_backup.md) - Backup or restore configuration (api, parsers, scenarios etc.) to/from directory
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
51
cmd/crowdsec-cli/doc/cwcli_backup_save.md
Normal file
51
cmd/crowdsec-cli/doc/cwcli_backup_save.md
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
## cscli backup save
|
||||||
|
|
||||||
|
Backup configuration (api, parsers, scenarios etc.) to directory
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
backup command will try to save all relevant informations to crowdsec config, including :
|
||||||
|
|
||||||
|
- List of scenarios, parsers, postoverflows and collections that are up-to-date
|
||||||
|
|
||||||
|
- Actual backup of tainted/local/out-of-date scenarios, parsers, postoverflows and collections
|
||||||
|
|
||||||
|
- Backup of API credentials
|
||||||
|
|
||||||
|
- Backup of acqusition configuration
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli backup save <directory> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli backup save ./my-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--cfgdir string Configuration directory (default "/etc/crowdsec/")
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli backup](cscli_backup.md) - Backup or restore configuration (api, parsers, scenarios etc.) to/from directory
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
38
cmd/crowdsec-cli/doc/cwcli_ban.md
Normal file
38
cmd/crowdsec-cli/doc/cwcli_ban.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
## cscli ban
|
||||||
|
|
||||||
|
Manage bans/mitigations
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
This is the main interaction point with local ban database for humans.
|
||||||
|
|
||||||
|
You can add/delete/list or flush current bans in your local ban DB.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
-h, --help help for ban
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli ban add](cscli_ban_add.md) - Adds a ban against a given ip/range for the provided duration
|
||||||
|
* [cscli ban del](cscli_ban_del.md) - Delete bans from db
|
||||||
|
* [cscli ban flush](cscli_ban_flush.md) - Fush ban DB
|
||||||
|
* [cscli ban list](cscli_ban_list.md) - List local or api bans/remediations
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
46
cmd/crowdsec-cli/doc/cwcli_ban_add.md
Normal file
46
cmd/crowdsec-cli/doc/cwcli_ban_add.md
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
## cscli ban add
|
||||||
|
|
||||||
|
Adds a ban against a given ip/range for the provided duration
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Allows to add a ban against a specific ip or range target for a specific duration.
|
||||||
|
|
||||||
|
The duration argument can be expressed in seconds(s), minutes(m) or hours (h).
|
||||||
|
|
||||||
|
See [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) for more informations.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban add ip 1.2.3.4 24h "scan"
|
||||||
|
cscli ban add range 1.2.3.0/24 24h "the whole range"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for add
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban](cscli_ban.md) - Manage bans/mitigations
|
||||||
|
* [cscli ban add ip](cscli_ban_add_ip.md) - Adds the specific ip to the ban db
|
||||||
|
* [cscli ban add range](cscli_ban_add_range.md) - Adds the specific ip to the ban db
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_ban_add_ip.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_ban_add_ip.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli ban add ip
|
||||||
|
|
||||||
|
Adds the specific ip to the ban db
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Duration must be [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration), expressed in s/m/h.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban add ip <target> <duration> <reason> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban add ip 1.2.3.4 12h "the scan"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for ip
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban add](cscli_ban_add.md) - Adds a ban against a given ip/range for the provided duration
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_ban_add_range.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_ban_add_range.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli ban add range
|
||||||
|
|
||||||
|
Adds the specific ip to the ban db
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Duration must be [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) compatible, expressed in s/m/h.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban add range <target> <duration> <reason> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban add range 1.2.3.0/24 12h "the whole range"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for range
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban add](cscli_ban_add.md) - Adds a ban against a given ip/range for the provided duration
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
41
cmd/crowdsec-cli/doc/cwcli_ban_del.md
Normal file
41
cmd/crowdsec-cli/doc/cwcli_ban_del.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
## cscli ban del
|
||||||
|
|
||||||
|
Delete bans from db
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
The removal of the bans can be applied on a single IP address or directly on a IP range.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban del ip 1.2.3.4
|
||||||
|
cscli ban del range 1.2.3.0/24
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for del
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban](cscli_ban.md) - Manage bans/mitigations
|
||||||
|
* [cscli ban del ip](cscli_ban_del_ip.md) - Delete bans for given ip from db
|
||||||
|
* [cscli ban del range](cscli_ban_del_range.md) - Delete bans for given ip from db
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_ban_del_ip.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_ban_del_ip.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli ban del ip
|
||||||
|
|
||||||
|
Delete bans for given ip from db
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Delete bans for given ip from db
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban del ip <target> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban del ip 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for ip
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban del](cscli_ban_del.md) - Delete bans from db
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_ban_del_range.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_ban_del_range.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli ban del range
|
||||||
|
|
||||||
|
Delete bans for given ip from db
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Delete bans for given ip from db
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban del range <target> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban del range 1.2.3.0/24
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for range
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban del](cscli_ban_del.md) - Delete bans from db
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_ban_flush.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_ban_flush.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli ban flush
|
||||||
|
|
||||||
|
Fush ban DB
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fush ban DB
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban flush [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban flush
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for flush
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban](cscli_ban.md) - Manage bans/mitigations
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
50
cmd/crowdsec-cli/doc/cwcli_ban_list.md
Normal file
50
cmd/crowdsec-cli/doc/cwcli_ban_list.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
## cscli ban list
|
||||||
|
|
||||||
|
List local or api bans/remediations
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List the bans, by default only local decisions.
|
||||||
|
|
||||||
|
If --all/-a is specified, api-provided bans will be displayed too.
|
||||||
|
|
||||||
|
Time can be specified with --at and support a variety of date formats:
|
||||||
|
- Jan 2 15:04:05
|
||||||
|
- Mon Jan 02 15:04:05.000000 2006
|
||||||
|
- 2006-01-02T15:04:05Z07:00
|
||||||
|
- 2006/01/02
|
||||||
|
- 2006/01/02 15:04
|
||||||
|
- 2006-01-02
|
||||||
|
- 2006-01-02 15:04
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli ban list [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well bans received from API
|
||||||
|
--at string List bans at given time
|
||||||
|
-h, --help help for list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--db string Set path to SQLite DB.
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--remediation string Set specific remediation type : ban|slow|captcha (default "ban")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli ban](cscli_ban.md) - Manage bans/mitigations
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_config.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_config.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli config
|
||||||
|
|
||||||
|
Allows to view/edit cscli config
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Allow to configure sqlite path and installation directory.
|
||||||
|
If no commands are specified, config is in interactive mode.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
- cscli config show
|
||||||
|
- cscli config prompt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for config
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli config backend](cscli_config_backend.md) - Configure installation directory
|
||||||
|
* [cscli config installdir](cscli_config_installdir.md) - Configure installation directory
|
||||||
|
* [cscli config prompt](cscli_config_prompt.md) - Prompt for configuration values in an interactive fashion
|
||||||
|
* [cscli config show](cscli_config_show.md) - Displays current config
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
34
cmd/crowdsec-cli/doc/cwcli_config_backend.md
Normal file
34
cmd/crowdsec-cli/doc/cwcli_config_backend.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
## cscli config backend
|
||||||
|
|
||||||
|
Configure installation directory
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Configure the backend plugin directory of crowdsec, such as /etc/crowdsec/plugins/backend
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli config backend [value] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli config](cscli_config.md) - Allows to view/edit cscli config
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
34
cmd/crowdsec-cli/doc/cwcli_config_installdir.md
Normal file
34
cmd/crowdsec-cli/doc/cwcli_config_installdir.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
## cscli config installdir
|
||||||
|
|
||||||
|
Configure installation directory
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Configure the installation directory of crowdsec, such as /etc/crowdsec/crowdsec/
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli config installdir [value] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for installdir
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli config](cscli_config.md) - Allows to view/edit cscli config
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
34
cmd/crowdsec-cli/doc/cwcli_config_prompt.md
Normal file
34
cmd/crowdsec-cli/doc/cwcli_config_prompt.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
## cscli config prompt
|
||||||
|
|
||||||
|
Prompt for configuration values in an interactive fashion
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Start interactive configuration of cli. It will successively ask for install dir, db path.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli config prompt [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for prompt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli config](cscli_config.md) - Allows to view/edit cscli config
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
34
cmd/crowdsec-cli/doc/cwcli_config_show.md
Normal file
34
cmd/crowdsec-cli/doc/cwcli_config_show.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
## cscli config show
|
||||||
|
|
||||||
|
Displays current config
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Displays the current cli configuration.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli config show [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for show
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli config](cscli_config.md) - Allows to view/edit cscli config
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_dashboard.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_dashboard.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli dashboard
|
||||||
|
|
||||||
|
Start a dashboard (metabase) container.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Start a metabase container exposing dashboards and metrics.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli dashboard setup
|
||||||
|
cscli dashboard start
|
||||||
|
cscli dashboard stop
|
||||||
|
cscli dashboard setup --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli dashboard setup](cscli_dashboard_setup.md) - Setup a metabase container.
|
||||||
|
* [cscli dashboard start](cscli_dashboard_start.md) - Start the metabase container.
|
||||||
|
* [cscli dashboard stop](cscli_dashboard_stop.md) - Stops the metabase container.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
47
cmd/crowdsec-cli/doc/cwcli_dashboard_setup.md
Normal file
47
cmd/crowdsec-cli/doc/cwcli_dashboard_setup.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
## cscli dashboard setup
|
||||||
|
|
||||||
|
Setup a metabase container.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Perform a metabase docker setup, download standard dashboards, create a fresh user and start the container
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli dashboard setup [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli dashboard setup
|
||||||
|
cscli dashboard setup --force
|
||||||
|
cscli dashboard setup -l 0.0.0.0 -p 443
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-d, --dir string Shared directory with metabase container. (default "/var/lib/crowdsec/data")
|
||||||
|
-f, --force Force setup : override existing files.
|
||||||
|
-h, --help help for setup
|
||||||
|
-l, --listen string Listen address of container (default "127.0.0.1")
|
||||||
|
-p, --port string Listen port of container (default "3000")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli dashboard](cscli_dashboard.md) - Start a dashboard (metabase) container.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
34
cmd/crowdsec-cli/doc/cwcli_dashboard_start.md
Normal file
34
cmd/crowdsec-cli/doc/cwcli_dashboard_start.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
## cscli dashboard start
|
||||||
|
|
||||||
|
Start the metabase container.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Stats the metabase container using docker.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli dashboard start [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli dashboard](cscli_dashboard.md) - Start a dashboard (metabase) container.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_dashboard_stop.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_dashboard_stop.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli dashboard stop
|
||||||
|
|
||||||
|
Stops the metabase container.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Stops the metabase container using docker.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli dashboard stop [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for stop
|
||||||
|
-r, --remove remove (docker rm) container as well.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli dashboard](cscli_dashboard.md) - Start a dashboard (metabase) container.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
47
cmd/crowdsec-cli/doc/cwcli_inspect.md
Normal file
47
cmd/crowdsec-cli/doc/cwcli_inspect.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
## cscli inspect
|
||||||
|
|
||||||
|
Inspect configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Inspect give you full detail about local installed configuration.
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net) or locally installed.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect parser crowdsec/xxx
|
||||||
|
cscli inspect collection crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli inspect collection](cscli_inspect_collection.md) - Inspect given collection
|
||||||
|
* [cscli inspect parser](cscli_inspect_parser.md) - Inspect given log parser
|
||||||
|
* [cscli inspect postoverflow](cscli_inspect_postoverflow.md) - Inspect given postoverflow parser
|
||||||
|
* [cscli inspect scenario](cscli_inspect_scenario.md) - Inspect given scenario
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_inspect_collection.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_inspect_collection.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli inspect collection
|
||||||
|
|
||||||
|
Inspect given collection
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Inspect given collection from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect collection [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect collection crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for collection
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli inspect](cscli_inspect.md) - Inspect configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_inspect_parser.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_inspect_parser.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli inspect parser
|
||||||
|
|
||||||
|
Inspect given log parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Inspect given parser from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect parser [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect parser crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for parser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli inspect](cscli_inspect.md) - Inspect configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_inspect_postoverflow.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_inspect_postoverflow.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli inspect postoverflow
|
||||||
|
|
||||||
|
Inspect given postoverflow parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Inspect given postoverflow from hub.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect postoverflow [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect postoverflow crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postoverflow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli inspect](cscli_inspect.md) - Inspect configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
40
cmd/crowdsec-cli/doc/cwcli_inspect_scenario.md
Normal file
40
cmd/crowdsec-cli/doc/cwcli_inspect_scenario.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
## cscli inspect scenario
|
||||||
|
|
||||||
|
Inspect given scenario
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Inspect given scenario from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect scenario [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli inspect scenario crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for scenario
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli inspect](cscli_inspect.md) - Inspect configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
51
cmd/crowdsec-cli/doc/cwcli_install.md
Normal file
51
cmd/crowdsec-cli/doc/cwcli_install.md
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
## cscli install
|
||||||
|
|
||||||
|
Install configuration(s) from hub
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Install configuration from the CrowdSec Hub.
|
||||||
|
|
||||||
|
In order to download latest versions of configuration,
|
||||||
|
you should [update cscli](./cscli_update.md).
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net).
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install [type] [config_name]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-d, --download-only Only download packages, don't enable
|
||||||
|
--force Force install : Overwrite tainted and outdated files
|
||||||
|
-h, --help help for install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli install collection](cscli_install_collection.md) - Install given collection
|
||||||
|
* [cscli install parser](cscli_install_parser.md) - Install given log parser
|
||||||
|
* [cscli install postoverflow](cscli_install_postoverflow.md) - Install given postoverflow parser
|
||||||
|
* [cscli install scenario](cscli_install_scenario.md) - Install given scenario
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_install_collection.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_install_collection.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli install collection
|
||||||
|
|
||||||
|
Install given collection
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fetch and install given collection from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install collection [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install collection crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for collection
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
-d, --download-only Only download packages, don't enable
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Force install : Overwrite tainted and outdated files
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli install](cscli_install.md) - Install configuration(s) from hub
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_install_parser.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_install_parser.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli install parser
|
||||||
|
|
||||||
|
Install given log parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fetch and install given parser from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install parser [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install parser crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for parser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
-d, --download-only Only download packages, don't enable
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Force install : Overwrite tainted and outdated files
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli install](cscli_install.md) - Install configuration(s) from hub
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
43
cmd/crowdsec-cli/doc/cwcli_install_postoverflow.md
Normal file
43
cmd/crowdsec-cli/doc/cwcli_install_postoverflow.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
## cscli install postoverflow
|
||||||
|
|
||||||
|
Install given postoverflow parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fetch and install given postoverflow from hub.
|
||||||
|
As a reminder, postoverflows are parsing configuration that will occur after the overflow (before a decision is applied).
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install postoverflow [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install collection crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postoverflow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
-d, --download-only Only download packages, don't enable
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Force install : Overwrite tainted and outdated files
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli install](cscli_install.md) - Install configuration(s) from hub
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
42
cmd/crowdsec-cli/doc/cwcli_install_scenario.md
Normal file
42
cmd/crowdsec-cli/doc/cwcli_install_scenario.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
## cscli install scenario
|
||||||
|
|
||||||
|
Install given scenario
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fetch and install given scenario from hub
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install scenario [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli install scenario crowdsec/xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for scenario
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
-d, --download-only Only download packages, don't enable
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Force install : Overwrite tainted and outdated files
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli install](cscli_install.md) - Install configuration(s) from hub
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
54
cmd/crowdsec-cli/doc/cwcli_list.md
Normal file
54
cmd/crowdsec-cli/doc/cwcli_list.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
## cscli list
|
||||||
|
|
||||||
|
List enabled configs
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
List enabled configurations (parser/scenarios/collections) on your host.
|
||||||
|
|
||||||
|
It is possible to list also configuration from [Crowdsec Hub](https://hub.crowdsec.net) with the '-a' options.
|
||||||
|
|
||||||
|
[type] must be parsers, scenarios, postoverflows, collections
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list [-a] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list # List all local configurations
|
||||||
|
cscli list [type] # List all local configuration of type [type]
|
||||||
|
cscli list -a # List all local and remote configurations
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well disabled items
|
||||||
|
-h, --help help for list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli list collections](cscli_list_collections.md) - List enabled collections
|
||||||
|
* [cscli list parsers](cscli_list_parsers.md) - List enabled parsers
|
||||||
|
* [cscli list postoverflows](cscli_list_postoverflows.md) - List enabled postoverflow parsers
|
||||||
|
* [cscli list scenarios](cscli_list_scenarios.md) - List enabled scenarios
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_list_collections.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_list_collections.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli list collections
|
||||||
|
|
||||||
|
List enabled collections
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List enabled collections
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list collections [-a] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for collections
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well disabled items
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli list](cscli_list.md) - List enabled configs
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_list_parsers.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_list_parsers.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli list parsers
|
||||||
|
|
||||||
|
List enabled parsers
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List enabled parsers
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list parsers [-a] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for parsers
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well disabled items
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli list](cscli_list.md) - List enabled configs
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_list_postoverflows.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_list_postoverflows.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli list postoverflows
|
||||||
|
|
||||||
|
List enabled postoverflow parsers
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List enabled postoverflow parsers
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list postoverflows [-a] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postoverflows
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well disabled items
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli list](cscli_list.md) - List enabled configs
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_list_scenarios.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_list_scenarios.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli list scenarios
|
||||||
|
|
||||||
|
List enabled scenarios
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List enabled scenarios
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli list scenarios [-a] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for scenarios
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-a, --all List as well disabled items
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli list](cscli_list.md) - List enabled configs
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
35
cmd/crowdsec-cli/doc/cwcli_metrics.md
Normal file
35
cmd/crowdsec-cli/doc/cwcli_metrics.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## cscli metrics
|
||||||
|
|
||||||
|
Display crowdsec prometheus metrics.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Fetch metrics from the prometheus server and display them in a human-friendly way
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli metrics [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for metrics
|
||||||
|
-u, --url string Prometheus url (default "http://127.0.0.1:6060/metrics")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
48
cmd/crowdsec-cli/doc/cwcli_remove.md
Normal file
48
cmd/crowdsec-cli/doc/cwcli_remove.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
## cscli remove
|
||||||
|
|
||||||
|
Remove/disable configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Remove local configuration.
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net) or locally installed.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli remove [type] [config_name]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Delete all the files in selected scope
|
||||||
|
-h, --help help for remove
|
||||||
|
--purge Delete source file in ~/.cscli/hub/ too
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli remove collection](cscli_remove_collection.md) - Remove/disable collection
|
||||||
|
* [cscli remove parser](cscli_remove_parser.md) - Remove/disable parser
|
||||||
|
* [cscli remove postoverflow](cscli_remove_postoverflow.md) - Remove/disable postoverflow parser
|
||||||
|
* [cscli remove scenario](cscli_remove_scenario.md) - Remove/disable scenario
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
36
cmd/crowdsec-cli/doc/cwcli_remove_collection.md
Normal file
36
cmd/crowdsec-cli/doc/cwcli_remove_collection.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## cscli remove collection
|
||||||
|
|
||||||
|
Remove/disable collection
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
<config> must be a valid collection.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli remove collection [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for collection
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Delete all the files in selected scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--purge Delete source file in ~/.cscli/hub/ too
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli remove](cscli_remove.md) - Remove/disable configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
36
cmd/crowdsec-cli/doc/cwcli_remove_parser.md
Normal file
36
cmd/crowdsec-cli/doc/cwcli_remove_parser.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## cscli remove parser
|
||||||
|
|
||||||
|
Remove/disable parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
<config> must be a valid parser.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli remove parser <config> [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for parser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Delete all the files in selected scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--purge Delete source file in ~/.cscli/hub/ too
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli remove](cscli_remove.md) - Remove/disable configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
36
cmd/crowdsec-cli/doc/cwcli_remove_postoverflow.md
Normal file
36
cmd/crowdsec-cli/doc/cwcli_remove_postoverflow.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## cscli remove postoverflow
|
||||||
|
|
||||||
|
Remove/disable postoverflow parser
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
<config> must be a valid collection.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli remove postoverflow [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postoverflow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Delete all the files in selected scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--purge Delete source file in ~/.cscli/hub/ too
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli remove](cscli_remove.md) - Remove/disable configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
36
cmd/crowdsec-cli/doc/cwcli_remove_scenario.md
Normal file
36
cmd/crowdsec-cli/doc/cwcli_remove_scenario.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## cscli remove scenario
|
||||||
|
|
||||||
|
Remove/disable scenario
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
<config> must be a valid scenario.
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli remove scenario [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for scenario
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Delete all the files in selected scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--purge Delete source file in ~/.cscli/hub/ too
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli remove](cscli_remove.md) - Remove/disable configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
36
cmd/crowdsec-cli/doc/cwcli_update.md
Normal file
36
cmd/crowdsec-cli/doc/cwcli_update.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## cscli update
|
||||||
|
|
||||||
|
Fetch available configs from hub
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.index.json) file from hub, containing the list of available configs.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli update [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for update
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
62
cmd/crowdsec-cli/doc/cwcli_upgrade.md
Normal file
62
cmd/crowdsec-cli/doc/cwcli_upgrade.md
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
## cscli upgrade
|
||||||
|
|
||||||
|
Upgrade configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
Upgrade configuration from the CrowdSec Hub.
|
||||||
|
|
||||||
|
In order to upgrade latest versions of configuration,
|
||||||
|
the Hub cache should be [updated](./cscli_update.md).
|
||||||
|
|
||||||
|
Tainted configuration will not be updated (use --force to update them).
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade [type] [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade [type] [config_name]
|
||||||
|
cscli upgrade --all # Upgrade all configurations types
|
||||||
|
cscli upgrade --force # Overwrite tainted configuration
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Upgrade all configuration in scope
|
||||||
|
--force Overwrite existing files, even if tainted
|
||||||
|
-h, --help help for upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli](cscli.md) - cscli allows you to manage crowdsec
|
||||||
|
* [cscli upgrade collection](cscli_upgrade_collection.md) - Upgrade collection configuration(s)
|
||||||
|
* [cscli upgrade parser](cscli_upgrade_parser.md) - Upgrade parser configuration(s)
|
||||||
|
* [cscli upgrade postoverflow](cscli_upgrade_postoverflow.md) - Upgrade postoverflow parser configuration(s)
|
||||||
|
* [cscli upgrade scenario](cscli_upgrade_scenario.md) - Upgrade scenario configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
44
cmd/crowdsec-cli/doc/cwcli_upgrade_collection.md
Normal file
44
cmd/crowdsec-cli/doc/cwcli_upgrade_collection.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
## cscli upgrade collection
|
||||||
|
|
||||||
|
Upgrade collection configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Upgrade one or more collection configurations
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade collection [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
- cscli upgrade collection crowdsec/apache-lamp
|
||||||
|
- cscli upgrade collection -all
|
||||||
|
- cscli upgrade collection crowdsec/apache-lamp --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for collection
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Upgrade all configuration in scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Overwrite existing files, even if tainted
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli upgrade](cscli_upgrade.md) - Upgrade configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
44
cmd/crowdsec-cli/doc/cwcli_upgrade_parser.md
Normal file
44
cmd/crowdsec-cli/doc/cwcli_upgrade_parser.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
## cscli upgrade parser
|
||||||
|
|
||||||
|
Upgrade parser configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Upgrade one or more parser configurations
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade parser [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
- cscli upgrade parser crowdsec/apache-logs
|
||||||
|
- cscli upgrade parser -all
|
||||||
|
- cscli upgrade parser crowdsec/apache-logs --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for parser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Upgrade all configuration in scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Overwrite existing files, even if tainted
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli upgrade](cscli_upgrade.md) - Upgrade configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
44
cmd/crowdsec-cli/doc/cwcli_upgrade_postoverflow.md
Normal file
44
cmd/crowdsec-cli/doc/cwcli_upgrade_postoverflow.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
## cscli upgrade postoverflow
|
||||||
|
|
||||||
|
Upgrade postoverflow parser configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Upgrade one or more postoverflow parser configurations
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade postoverflow [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
- cscli upgrade postoverflow crowdsec/enrich-rdns
|
||||||
|
- cscli upgrade postoverflow -all
|
||||||
|
- cscli upgrade postoverflow crowdsec/enrich-rdns --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postoverflow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Upgrade all configuration in scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Overwrite existing files, even if tainted
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli upgrade](cscli_upgrade.md) - Upgrade configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
43
cmd/crowdsec-cli/doc/cwcli_upgrade_scenario.md
Normal file
43
cmd/crowdsec-cli/doc/cwcli_upgrade_scenario.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
## cscli upgrade scenario
|
||||||
|
|
||||||
|
Upgrade scenario configuration(s)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Upgrade one or more scenario configurations
|
||||||
|
|
||||||
|
```
|
||||||
|
cscli upgrade scenario [config] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
- cscli upgrade scenario -all
|
||||||
|
- cscli upgrade scenario crowdsec/http-404 --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for scenario
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--all Upgrade all configuration in scope
|
||||||
|
-c, --config-dir string Configuration directory to use. (default "/etc/crowdsec/cscli/")
|
||||||
|
--debug Set logging to debug.
|
||||||
|
--error Set logging to error.
|
||||||
|
--force Overwrite existing files, even if tainted
|
||||||
|
--info Set logging to info.
|
||||||
|
-o, --output string Output format : human, json, raw. (default "human")
|
||||||
|
--warning Set logging to warning.
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [cscli upgrade](cscli_upgrade.md) - Upgrade configuration(s)
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 14-May-2020
|
110
cmd/crowdsec-cli/inspect.go
Normal file
110
cmd/crowdsec-cli/inspect.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InspectItem(name string, objectType string) {
|
||||||
|
|
||||||
|
for _, hubItem := range cwhub.HubIdx[objectType] {
|
||||||
|
if hubItem.Name != name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buff, err := yaml.Marshal(hubItem)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to marshal item : %s", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", string(buff))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInspectCmd() *cobra.Command {
|
||||||
|
var cmdInspect = &cobra.Command{
|
||||||
|
Use: "inspect [type] [config]",
|
||||||
|
Short: "Inspect configuration(s)",
|
||||||
|
Long: `
|
||||||
|
Inspect give you full detail about local installed configuration.
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net) or locally installed.
|
||||||
|
`,
|
||||||
|
Example: `cscli inspect parser crowdsec/xxx
|
||||||
|
cscli inspect collection crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdInspectParser = &cobra.Command{
|
||||||
|
Use: "parser [config]",
|
||||||
|
Short: "Inspect given log parser",
|
||||||
|
Long: `Inspect given parser from hub`,
|
||||||
|
Example: `cscli inspect parser crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InspectItem(args[0], cwhub.PARSERS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInspect.AddCommand(cmdInspectParser)
|
||||||
|
var cmdInspectScenario = &cobra.Command{
|
||||||
|
Use: "scenario [config]",
|
||||||
|
Short: "Inspect given scenario",
|
||||||
|
Long: `Inspect given scenario from hub`,
|
||||||
|
Example: `cscli inspect scenario crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InspectItem(args[0], cwhub.SCENARIOS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInspect.AddCommand(cmdInspectScenario)
|
||||||
|
|
||||||
|
var cmdInspectCollection = &cobra.Command{
|
||||||
|
Use: "collection [config]",
|
||||||
|
Short: "Inspect given collection",
|
||||||
|
Long: `Inspect given collection from hub`,
|
||||||
|
Example: `cscli inspect collection crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InspectItem(args[0], cwhub.COLLECTIONS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInspect.AddCommand(cmdInspectCollection)
|
||||||
|
|
||||||
|
var cmdInspectPostoverflow = &cobra.Command{
|
||||||
|
Use: "postoverflow [config]",
|
||||||
|
Short: "Inspect given postoverflow parser",
|
||||||
|
Long: `Inspect given postoverflow from hub.`,
|
||||||
|
Example: `cscli inspect postoverflow crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InspectItem(args[0], cwhub.PARSERS_OVFLW)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInspect.AddCommand(cmdInspectPostoverflow)
|
||||||
|
|
||||||
|
return cmdInspect
|
||||||
|
}
|
150
cmd/crowdsec-cli/install.go
Normal file
150
cmd/crowdsec-cli/install.go
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var download_only, force_install bool
|
||||||
|
|
||||||
|
func InstallItem(name string, obtype string) {
|
||||||
|
for _, it := range cwhub.HubIdx[obtype] {
|
||||||
|
if it.Name == name {
|
||||||
|
if download_only && it.Downloaded && it.UpToDate {
|
||||||
|
log.Warningf("%s is already downloaded and up-to-date", it.Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
it, err := cwhub.DownloadLatest(it, cwhub.Hubdir, force_install)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error while downloading %s : %v", it.Name, err)
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[obtype][it.Name] = it
|
||||||
|
if download_only {
|
||||||
|
log.Infof("Downloaded %s to %s", it.Name, cwhub.Hubdir+"/"+it.RemotePath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
it, err = cwhub.EnableItem(it, cwhub.Installdir, cwhub.Hubdir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error while enabled %s : %v.", it.Name, err)
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[obtype][it.Name] = it
|
||||||
|
log.Infof("Enabled %s", it.Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Warningf("%s not found in hub index", name)
|
||||||
|
/*iterate of pkg index data*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallScenario(name string) {
|
||||||
|
InstallItem(name, cwhub.SCENARIOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallCollection(name string) {
|
||||||
|
InstallItem(name, cwhub.COLLECTIONS)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallParser(name string) {
|
||||||
|
InstallItem(name, cwhub.PARSERS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallPostoverflow(name string) {
|
||||||
|
InstallItem(name, cwhub.PARSERS_OVFLW)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInstallCmd() *cobra.Command {
|
||||||
|
/* ---- INSTALL COMMAND */
|
||||||
|
|
||||||
|
var cmdInstall = &cobra.Command{
|
||||||
|
Use: "install [type] [config]",
|
||||||
|
Short: "Install configuration(s) from hub",
|
||||||
|
Long: `
|
||||||
|
Install configuration from the CrowdSec Hub.
|
||||||
|
|
||||||
|
In order to download latest versions of configuration,
|
||||||
|
you should [update cscli](./cscli_update.md).
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net).
|
||||||
|
`,
|
||||||
|
Example: `cscli install [type] [config_name]`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInstall.PersistentFlags().BoolVarP(&download_only, "download-only", "d", false, "Only download packages, don't enable")
|
||||||
|
cmdInstall.PersistentFlags().BoolVar(&force_install, "force", false, "Force install : Overwrite tainted and outdated files")
|
||||||
|
|
||||||
|
var cmdInstallParser = &cobra.Command{
|
||||||
|
Use: "parser [config]",
|
||||||
|
Short: "Install given log parser",
|
||||||
|
Long: `Fetch and install given parser from hub`,
|
||||||
|
Example: `cscli install parser crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InstallItem(args[0], cwhub.PARSERS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInstall.AddCommand(cmdInstallParser)
|
||||||
|
var cmdInstallScenario = &cobra.Command{
|
||||||
|
Use: "scenario [config]",
|
||||||
|
Short: "Install given scenario",
|
||||||
|
Long: `Fetch and install given scenario from hub`,
|
||||||
|
Example: `cscli install scenario crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InstallItem(args[0], cwhub.SCENARIOS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInstall.AddCommand(cmdInstallScenario)
|
||||||
|
|
||||||
|
var cmdInstallCollection = &cobra.Command{
|
||||||
|
Use: "collection [config]",
|
||||||
|
Short: "Install given collection",
|
||||||
|
Long: `Fetch and install given collection from hub`,
|
||||||
|
Example: `cscli install collection crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InstallItem(args[0], cwhub.COLLECTIONS)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInstall.AddCommand(cmdInstallCollection)
|
||||||
|
|
||||||
|
var cmdInstallPostoverflow = &cobra.Command{
|
||||||
|
Use: "postoverflow [config]",
|
||||||
|
Short: "Install given postoverflow parser",
|
||||||
|
Long: `Fetch and install given postoverflow from hub.
|
||||||
|
As a reminder, postoverflows are parsing configuration that will occur after the overflow (before a decision is applied).`,
|
||||||
|
Example: `cscli install collection crowdsec/xxx`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
InstallItem(args[0], cwhub.PARSERS_OVFLW)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdInstall.AddCommand(cmdInstallPostoverflow)
|
||||||
|
|
||||||
|
return cmdInstall
|
||||||
|
}
|
152
cmd/crowdsec-cli/list.go
Normal file
152
cmd/crowdsec-cli/list.go
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
|
||||||
|
"github.com/enescakir/emoji"
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var listAll bool
|
||||||
|
|
||||||
|
func doListing(ttype string, args []string) {
|
||||||
|
|
||||||
|
var pkgst []map[string]string
|
||||||
|
|
||||||
|
if len(args) == 1 {
|
||||||
|
pkgst = cwhub.HubStatus(ttype, args[0], listAll)
|
||||||
|
} else {
|
||||||
|
pkgst = cwhub.HubStatus(ttype, "", listAll)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.output == "human" {
|
||||||
|
|
||||||
|
table := tablewriter.NewWriter(os.Stdout)
|
||||||
|
table.SetCenterSeparator("")
|
||||||
|
table.SetColumnSeparator("")
|
||||||
|
|
||||||
|
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
|
||||||
|
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||||
|
table.SetHeader([]string{"Name", fmt.Sprintf("%v Status", emoji.Package), "Version", "Local Path"})
|
||||||
|
for _, v := range pkgst {
|
||||||
|
table.Append([]string{v["name"], v["utf8_status"], v["local_version"], v["local_path"]})
|
||||||
|
}
|
||||||
|
table.Render()
|
||||||
|
} else if config.output == "json" {
|
||||||
|
x, err := json.MarshalIndent(pkgst, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to unmarshal")
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", string(x))
|
||||||
|
} else if config.output == "raw" {
|
||||||
|
for _, v := range pkgst {
|
||||||
|
fmt.Printf("%s %s\n", v["name"], v["description"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListCmd() *cobra.Command {
|
||||||
|
/* ---- LIST COMMAND */
|
||||||
|
var cmdList = &cobra.Command{
|
||||||
|
Use: "list [-a]",
|
||||||
|
Short: "List enabled configs",
|
||||||
|
Long: `
|
||||||
|
List enabled configurations (parser/scenarios/collections) on your host.
|
||||||
|
|
||||||
|
It is possible to list also configuration from [Crowdsec Hub](https://hub.crowdsec.net) with the '-a' options.
|
||||||
|
|
||||||
|
[type] must be parsers, scenarios, postoverflows, collections
|
||||||
|
`,
|
||||||
|
Example: `cscli list # List all local configurations
|
||||||
|
cscli list [type] # List all local configuration of type [type]
|
||||||
|
cscli list -a # List all local and remote configurations
|
||||||
|
`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cwhub.DisplaySummary()
|
||||||
|
log.Printf("PARSERS:")
|
||||||
|
doListing(cwhub.PARSERS, args)
|
||||||
|
log.Printf("SCENARIOS:")
|
||||||
|
doListing(cwhub.SCENARIOS, args)
|
||||||
|
log.Printf("COLLECTIONS:")
|
||||||
|
doListing(cwhub.COLLECTIONS, args)
|
||||||
|
log.Printf("POSTOVERFLOWS:")
|
||||||
|
doListing(cwhub.PARSERS_OVFLW, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdList.PersistentFlags().BoolVarP(&listAll, "all", "a", false, "List as well disabled items")
|
||||||
|
|
||||||
|
var cmdListParsers = &cobra.Command{
|
||||||
|
Use: "parsers [-a]",
|
||||||
|
Short: "List enabled parsers",
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
doListing(cwhub.PARSERS, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdList.AddCommand(cmdListParsers)
|
||||||
|
|
||||||
|
var cmdListScenarios = &cobra.Command{
|
||||||
|
Use: "scenarios [-a]",
|
||||||
|
Short: "List enabled scenarios",
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
doListing(cwhub.SCENARIOS, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdList.AddCommand(cmdListScenarios)
|
||||||
|
|
||||||
|
var cmdListCollections = &cobra.Command{
|
||||||
|
Use: "collections [-a]",
|
||||||
|
Short: "List enabled collections",
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
doListing(cwhub.COLLECTIONS, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdList.AddCommand(cmdListCollections)
|
||||||
|
|
||||||
|
var cmdListPostoverflows = &cobra.Command{
|
||||||
|
Use: "postoverflows [-a]",
|
||||||
|
Short: "List enabled postoverflow parsers",
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
doListing(cwhub.PARSERS_OVFLW, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdList.AddCommand(cmdListPostoverflows)
|
||||||
|
|
||||||
|
return cmdList
|
||||||
|
}
|
139
cmd/crowdsec-cli/main.go
Normal file
139
cmd/crowdsec-cli/main.go
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/cobra/doc"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbg_lvl, nfo_lvl, wrn_lvl, err_lvl bool
|
||||||
|
|
||||||
|
var config cliConfig
|
||||||
|
|
||||||
|
func initConfig() {
|
||||||
|
|
||||||
|
if dbg_lvl {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
} else if nfo_lvl {
|
||||||
|
log.SetLevel(log.InfoLevel)
|
||||||
|
} else if wrn_lvl {
|
||||||
|
log.SetLevel(log.WarnLevel)
|
||||||
|
} else if err_lvl {
|
||||||
|
log.SetLevel(log.ErrorLevel)
|
||||||
|
}
|
||||||
|
if config.output == "json" {
|
||||||
|
log.SetLevel(log.WarnLevel)
|
||||||
|
log.SetFormatter(&log.JSONFormatter{})
|
||||||
|
} else if config.output == "raw" {
|
||||||
|
log.SetLevel(log.ErrorLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(config.configFolder, "~/") {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to resolve path ~/ : %s", err)
|
||||||
|
}
|
||||||
|
config.configFolder = usr.HomeDir + "/" + config.configFolder[2:]
|
||||||
|
}
|
||||||
|
/*read config*/
|
||||||
|
buf, err := ioutil.ReadFile(filepath.Clean(config.configFolder + "/config"))
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Failed to open config %s : %s", filepath.Clean(config.configFolder+"/config"), err)
|
||||||
|
} else {
|
||||||
|
err = yaml.UnmarshalStrict(buf, &config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse config %s : %s, please configure", filepath.Clean(config.configFolder+"/config"), err)
|
||||||
|
}
|
||||||
|
config.InstallFolder = filepath.Clean(config.InstallFolder)
|
||||||
|
config.hubFolder = filepath.Clean(config.configFolder + "/hub/")
|
||||||
|
config.BackendPluginFolder = filepath.Clean(config.BackendPluginFolder)
|
||||||
|
//
|
||||||
|
cwhub.Installdir = config.InstallFolder
|
||||||
|
cwhub.Cfgdir = config.configFolder
|
||||||
|
cwhub.Hubdir = config.hubFolder
|
||||||
|
config.configured = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "cscli",
|
||||||
|
Short: "cscli allows you to manage crowdsec",
|
||||||
|
Long: `cscli is the main command to interact with your crowdsec service, scenarios & db.
|
||||||
|
It is meant to allow you to manage bans, parsers/scenarios/etc, api and generally manage you crowdsec setup.`,
|
||||||
|
Example: `View/Add/Remove bans:
|
||||||
|
- cscli ban list
|
||||||
|
- cscli ban add ip 1.2.3.4 24h 'go away'
|
||||||
|
- cscli ban del 1.2.3.4
|
||||||
|
|
||||||
|
View/Add/Upgrade/Remove scenarios and parsers:
|
||||||
|
- cscli list
|
||||||
|
- cscli install collection crowdsec/linux-web
|
||||||
|
- cscli remove scenario crowdsec/ssh_enum
|
||||||
|
- cscli upgrade --all
|
||||||
|
|
||||||
|
API interaction:
|
||||||
|
- cscli api pull
|
||||||
|
- cscli api register
|
||||||
|
`}
|
||||||
|
/*TODO : add a remediation type*/
|
||||||
|
var cmdDocGen = &cobra.Command{
|
||||||
|
Use: "doc",
|
||||||
|
Short: "Generate the documentation in `./doc/`. Directory must exist.",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Hidden: true,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
doc.GenMarkdownTree(rootCmd, "./doc/")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(cmdDocGen)
|
||||||
|
/*usage*/
|
||||||
|
var cmdVersion = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Display version and exit.",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Hidden: true,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cwversion.Show()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(cmdVersion)
|
||||||
|
|
||||||
|
//rootCmd.PersistentFlags().BoolVarP(&config.simulation, "simulate", "s", false, "No action; perform a simulation of events that would occur based on the current arguments.")
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&config.configFolder, "config-dir", "c", "/etc/crowdsec/cscli/", "Configuration directory to use.")
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&config.output, "output", "o", "human", "Output format : human, json, raw.")
|
||||||
|
rootCmd.PersistentFlags().BoolVar(&dbg_lvl, "debug", false, "Set logging to debug.")
|
||||||
|
rootCmd.PersistentFlags().BoolVar(&nfo_lvl, "info", false, "Set logging to info.")
|
||||||
|
rootCmd.PersistentFlags().BoolVar(&wrn_lvl, "warning", false, "Set logging to warning.")
|
||||||
|
rootCmd.PersistentFlags().BoolVar(&err_lvl, "error", false, "Set logging to error.")
|
||||||
|
|
||||||
|
cobra.OnInitialize(initConfig)
|
||||||
|
/*don't sort flags so we can enforce order*/
|
||||||
|
rootCmd.Flags().SortFlags = false
|
||||||
|
rootCmd.PersistentFlags().SortFlags = false
|
||||||
|
|
||||||
|
rootCmd.AddCommand(NewBanCmds())
|
||||||
|
rootCmd.AddCommand(NewConfigCmd())
|
||||||
|
rootCmd.AddCommand(NewInstallCmd())
|
||||||
|
rootCmd.AddCommand(NewListCmd())
|
||||||
|
rootCmd.AddCommand(NewRemoveCmd())
|
||||||
|
rootCmd.AddCommand(NewUpdateCmd())
|
||||||
|
rootCmd.AddCommand(NewUpgradeCmd())
|
||||||
|
rootCmd.AddCommand(NewAPICmd())
|
||||||
|
rootCmd.AddCommand(NewMetricsCmd())
|
||||||
|
rootCmd.AddCommand(NewBackupCmd())
|
||||||
|
rootCmd.AddCommand(NewDashboardCmd())
|
||||||
|
rootCmd.AddCommand(NewInspectCmd())
|
||||||
|
|
||||||
|
rootCmd.Execute()
|
||||||
|
}
|
229
cmd/crowdsec-cli/metrics.go
Normal file
229
cmd/crowdsec-cli/metrics.go
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"github.com/prometheus/prom2json"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*This is a complete rip from prom2json*/
|
||||||
|
func ShowPrometheus(url string) {
|
||||||
|
mfChan := make(chan *dto.MetricFamily, 1024)
|
||||||
|
|
||||||
|
// Start with the DefaultTransport for sane defaults.
|
||||||
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
|
// Conservatively disable HTTP keep-alives as this program will only
|
||||||
|
// ever need a single HTTP request.
|
||||||
|
transport.DisableKeepAlives = true
|
||||||
|
// Timeout early if the server doesn't even return the headers.
|
||||||
|
transport.ResponseHeaderTimeout = time.Minute
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := prom2json.FetchMetricFamilies(url, mfChan, transport)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to fetch prometheus metrics : %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
result := []*prom2json.Family{}
|
||||||
|
for mf := range mfChan {
|
||||||
|
result = append(result, prom2json.NewFamily(mf))
|
||||||
|
}
|
||||||
|
log.Debugf("Finished reading prometheus output, %d entries", len(result))
|
||||||
|
/*walk*/
|
||||||
|
acquis_stats := map[string]map[string]int{}
|
||||||
|
parsers_stats := map[string]map[string]int{}
|
||||||
|
buckets_stats := map[string]map[string]int{}
|
||||||
|
for idx, fam := range result {
|
||||||
|
if !strings.HasPrefix(fam.Name, "cs_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Debugf("round %d", idx)
|
||||||
|
for _, m := range fam.Metrics {
|
||||||
|
metric := m.(prom2json.Metric)
|
||||||
|
name, ok := metric.Labels["name"]
|
||||||
|
if !ok {
|
||||||
|
log.Debugf("no name in Metric")
|
||||||
|
}
|
||||||
|
source, ok := metric.Labels["source"]
|
||||||
|
if !ok {
|
||||||
|
log.Debugf("no source in Metric")
|
||||||
|
}
|
||||||
|
value := m.(prom2json.Metric).Value
|
||||||
|
ival, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unexpected int value %s : %s", value, err)
|
||||||
|
}
|
||||||
|
switch fam.Name {
|
||||||
|
/*buckets*/
|
||||||
|
case "cs_bucket_create":
|
||||||
|
if _, ok := buckets_stats[name]; !ok {
|
||||||
|
buckets_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
buckets_stats[name]["instanciation"] += ival
|
||||||
|
case "cs_bucket_overflow":
|
||||||
|
if _, ok := buckets_stats[name]; !ok {
|
||||||
|
buckets_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
buckets_stats[name]["overflow"] += ival
|
||||||
|
case "cs_bucket_pour":
|
||||||
|
if _, ok := buckets_stats[name]; !ok {
|
||||||
|
buckets_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
if _, ok := acquis_stats[source]; !ok {
|
||||||
|
acquis_stats[source] = make(map[string]int)
|
||||||
|
}
|
||||||
|
buckets_stats[name]["pour"] += ival
|
||||||
|
acquis_stats[source]["pour"] += ival
|
||||||
|
case "cs_bucket_underflow":
|
||||||
|
if _, ok := buckets_stats[name]; !ok {
|
||||||
|
buckets_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
buckets_stats[name]["underflow"] += ival
|
||||||
|
/*acquis*/
|
||||||
|
case "cs_reader_hits":
|
||||||
|
if _, ok := acquis_stats[source]; !ok {
|
||||||
|
acquis_stats[source] = make(map[string]int)
|
||||||
|
}
|
||||||
|
acquis_stats[source]["reads"] += ival
|
||||||
|
case "cs_parser_hits_ok":
|
||||||
|
if _, ok := acquis_stats[source]; !ok {
|
||||||
|
acquis_stats[source] = make(map[string]int)
|
||||||
|
}
|
||||||
|
acquis_stats[source]["parsed"] += ival
|
||||||
|
case "cs_parser_hits_ko":
|
||||||
|
if _, ok := acquis_stats[source]; !ok {
|
||||||
|
acquis_stats[source] = make(map[string]int)
|
||||||
|
}
|
||||||
|
acquis_stats[source]["unparsed"] += ival
|
||||||
|
case "cs_node_hits":
|
||||||
|
if _, ok := parsers_stats[name]; !ok {
|
||||||
|
parsers_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
parsers_stats[name]["hits"] += ival
|
||||||
|
case "cs_node_hits_ok":
|
||||||
|
if _, ok := parsers_stats[name]; !ok {
|
||||||
|
parsers_stats[name] = make(map[string]int)
|
||||||
|
}
|
||||||
|
parsers_stats[name]["parsed"] += ival
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.output == "human" {
|
||||||
|
atable := tablewriter.NewWriter(os.Stdout)
|
||||||
|
atable.SetHeader([]string{"Source", "Lines read", "Lines parsed", "Lines unparsed", "Lines poured to bucket"})
|
||||||
|
for alabel, astats := range acquis_stats {
|
||||||
|
|
||||||
|
if alabel == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
row := []string{}
|
||||||
|
row = append(row, alabel) //name
|
||||||
|
for _, sl := range []string{"reads", "parsed", "unparsed", "pour"} {
|
||||||
|
if v, ok := astats[sl]; ok {
|
||||||
|
row = append(row, fmt.Sprintf("%d", v))
|
||||||
|
} else {
|
||||||
|
row = append(row, "-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
atable.Append(row)
|
||||||
|
}
|
||||||
|
btable := tablewriter.NewWriter(os.Stdout)
|
||||||
|
btable.SetHeader([]string{"Bucket", "Overflows", "Instanciated", "Poured", "Expired"})
|
||||||
|
for blabel, bstats := range buckets_stats {
|
||||||
|
if blabel == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
row := []string{}
|
||||||
|
row = append(row, blabel) //name
|
||||||
|
for _, sl := range []string{"overflow", "instanciation", "pour", "underflow"} {
|
||||||
|
if v, ok := bstats[sl]; ok {
|
||||||
|
row = append(row, fmt.Sprintf("%d", v))
|
||||||
|
} else {
|
||||||
|
row = append(row, "-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btable.Append(row)
|
||||||
|
}
|
||||||
|
ptable := tablewriter.NewWriter(os.Stdout)
|
||||||
|
ptable.SetHeader([]string{"Parsers", "Hits", "Parsed", "Unparsed"})
|
||||||
|
for plabel, pstats := range parsers_stats {
|
||||||
|
if plabel == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
row := []string{}
|
||||||
|
row = append(row, plabel) //name
|
||||||
|
hits := 0
|
||||||
|
parsed := 0
|
||||||
|
for _, sl := range []string{"hits", "parsed"} {
|
||||||
|
if v, ok := pstats[sl]; ok {
|
||||||
|
row = append(row, fmt.Sprintf("%d", v))
|
||||||
|
if sl == "hits" {
|
||||||
|
hits = v
|
||||||
|
} else if sl == "parsed" {
|
||||||
|
parsed = v
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row = append(row, "-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row = append(row, fmt.Sprintf("%d", hits-parsed))
|
||||||
|
ptable.Append(row)
|
||||||
|
}
|
||||||
|
log.Printf("Buckets Metrics:")
|
||||||
|
btable.Render() // Send output
|
||||||
|
log.Printf("Acquisition Metrics:")
|
||||||
|
atable.Render() // Send output
|
||||||
|
log.Printf("Parser Metrics:")
|
||||||
|
ptable.Render() // Send output
|
||||||
|
} else if config.output == "json" {
|
||||||
|
for _, val := range []map[string]map[string]int{acquis_stats, parsers_stats, buckets_stats} {
|
||||||
|
x, err := json.MarshalIndent(val, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to unmarshal metrics : %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(x))
|
||||||
|
}
|
||||||
|
} else if config.output == "raw" {
|
||||||
|
for _, val := range []map[string]map[string]int{acquis_stats, parsers_stats, buckets_stats} {
|
||||||
|
x, err := yaml.Marshal(val)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to unmarshal metrics : %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var purl string
|
||||||
|
|
||||||
|
func NewMetricsCmd() *cobra.Command {
|
||||||
|
/* ---- UPDATE COMMAND */
|
||||||
|
var cmdMetrics = &cobra.Command{
|
||||||
|
Use: "metrics",
|
||||||
|
Short: "Display crowdsec prometheus metrics.",
|
||||||
|
Long: `Fetch metrics from the prometheus server and display them in a human-friendly way`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
ShowPrometheus(purl)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdMetrics.PersistentFlags().StringVarP(&purl, "url", "u", "http://127.0.0.1:6060/metrics", "Prometheus url")
|
||||||
|
|
||||||
|
return cmdMetrics
|
||||||
|
}
|
150
cmd/crowdsec-cli/remove.go
Normal file
150
cmd/crowdsec-cli/remove.go
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var purge_remove, remove_all bool
|
||||||
|
|
||||||
|
func RemoveMany(ttype string, name string) {
|
||||||
|
var err error
|
||||||
|
var disabled int
|
||||||
|
for _, v := range cwhub.HubIdx[ttype] {
|
||||||
|
if name != "" && v.Name == name {
|
||||||
|
v, err = cwhub.DisableItem(v, cwhub.Installdir, cwhub.Hubdir, purge_remove)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to disable %s : %v", v.Name, err)
|
||||||
|
}
|
||||||
|
disabled += 1
|
||||||
|
cwhub.HubIdx[ttype][v.Name] = v
|
||||||
|
return
|
||||||
|
} else if name == "" && remove_all {
|
||||||
|
v, err = cwhub.DisableItem(v, cwhub.Installdir, cwhub.Hubdir, purge_remove)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to disable %s : %v", v.Name, err)
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[ttype][v.Name] = v
|
||||||
|
disabled += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if name != "" && !remove_all {
|
||||||
|
log.Errorf("%s not found", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Infof("Disabled %d items", disabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRemoveCmd() *cobra.Command {
|
||||||
|
|
||||||
|
var cmdRemove = &cobra.Command{
|
||||||
|
Use: "remove [type] <config>",
|
||||||
|
Short: "Remove/disable configuration(s)",
|
||||||
|
Long: `
|
||||||
|
Remove local configuration.
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net) or locally installed.
|
||||||
|
`,
|
||||||
|
Example: `cscli remove [type] [config_name]`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdRemove.PersistentFlags().BoolVar(&purge_remove, "purge", false, "Delete source file in ~/.cscli/hub/ too")
|
||||||
|
cmdRemove.PersistentFlags().BoolVar(&remove_all, "all", false, "Delete all the files in selected scope")
|
||||||
|
var cmdRemoveParser = &cobra.Command{
|
||||||
|
Use: "parser <config>",
|
||||||
|
Short: "Remove/disable parser",
|
||||||
|
Long: `<config> must be a valid parser.`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if remove_all && len(args) == 0 {
|
||||||
|
RemoveMany(cwhub.PARSERS, "")
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
RemoveMany(cwhub.PARSERS, args[0])
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//fmt.Println("remove/disable parser: " + strings.Join(args, " "))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdRemove.AddCommand(cmdRemoveParser)
|
||||||
|
var cmdRemoveScenario = &cobra.Command{
|
||||||
|
Use: "scenario [config]",
|
||||||
|
Short: "Remove/disable scenario",
|
||||||
|
Long: `<config> must be a valid scenario.`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if remove_all && len(args) == 0 {
|
||||||
|
RemoveMany(cwhub.SCENARIOS, "")
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
RemoveMany(cwhub.SCENARIOS, args[0])
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdRemove.AddCommand(cmdRemoveScenario)
|
||||||
|
var cmdRemoveCollection = &cobra.Command{
|
||||||
|
Use: "collection [config]",
|
||||||
|
Short: "Remove/disable collection",
|
||||||
|
Long: `<config> must be a valid collection.`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if remove_all && len(args) == 0 {
|
||||||
|
RemoveMany(cwhub.COLLECTIONS, "")
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
RemoveMany(cwhub.COLLECTIONS, args[0])
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdRemove.AddCommand(cmdRemoveCollection)
|
||||||
|
|
||||||
|
var cmdRemovePostoverflow = &cobra.Command{
|
||||||
|
Use: "postoverflow [config]",
|
||||||
|
Short: "Remove/disable postoverflow parser",
|
||||||
|
Long: `<config> must be a valid collection.`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if remove_all && len(args) == 0 {
|
||||||
|
RemoveMany(cwhub.PARSERS_OVFLW, "")
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
RemoveMany(cwhub.PARSERS_OVFLW, args[0])
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdRemove.AddCommand(cmdRemovePostoverflow)
|
||||||
|
|
||||||
|
return cmdRemove
|
||||||
|
}
|
34
cmd/crowdsec-cli/update.go
Normal file
34
cmd/crowdsec-cli/update.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewUpdateCmd() *cobra.Command {
|
||||||
|
/* ---- UPDATE COMMAND */
|
||||||
|
var cmdUpdate = &cobra.Command{
|
||||||
|
Use: "update",
|
||||||
|
Short: "Fetch available configs from hub",
|
||||||
|
Long: `
|
||||||
|
Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.index.json) file from hub, containing the list of available configs.
|
||||||
|
`,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("You must configure cli before interacting with hub.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.UpdateHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return cmdUpdate
|
||||||
|
}
|
205
cmd/crowdsec-cli/upgrade.go
Normal file
205
cmd/crowdsec-cli/upgrade.go
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
|
|
||||||
|
"github.com/enescakir/emoji"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var upgrade_all, force_upgrade bool
|
||||||
|
|
||||||
|
func UpgradeConfig(ttype string, name string) {
|
||||||
|
var err error
|
||||||
|
var updated int
|
||||||
|
var found bool
|
||||||
|
|
||||||
|
for _, v := range cwhub.HubIdx[ttype] {
|
||||||
|
//name mismatch
|
||||||
|
if name != "" && name != v.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !v.Installed {
|
||||||
|
log.Debugf("skip %s, not installed", v.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !v.Downloaded {
|
||||||
|
log.Warningf("%s : not downloaded, please install.", v.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found = true
|
||||||
|
if v.UpToDate {
|
||||||
|
log.Infof("%s : up-to-date", v.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v, err = cwhub.DownloadLatest(v, cwhub.Hubdir, force_upgrade)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%s : download failed : %v", v.Name, err)
|
||||||
|
}
|
||||||
|
if !v.UpToDate {
|
||||||
|
if v.Tainted {
|
||||||
|
log.Infof("%v %s is tainted, --force to overwrite", emoji.Warning, v.Name)
|
||||||
|
} else if v.Local {
|
||||||
|
log.Infof("%v %s is local", emoji.Prohibited, v.Name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Infof("%v %s : updated", emoji.Package, v.Name)
|
||||||
|
updated += 1
|
||||||
|
}
|
||||||
|
cwhub.HubIdx[ttype][v.Name] = v
|
||||||
|
}
|
||||||
|
if found == false {
|
||||||
|
log.Errorf("Didn't find %s", name)
|
||||||
|
} else if updated == 0 && found == true {
|
||||||
|
log.Errorf("Nothing to update")
|
||||||
|
} else if updated != 0 {
|
||||||
|
log.Infof("Upgraded %d items", updated)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpgradeCmd() *cobra.Command {
|
||||||
|
|
||||||
|
var cmdUpgrade = &cobra.Command{
|
||||||
|
Use: "upgrade [type] [config]",
|
||||||
|
Short: "Upgrade configuration(s)",
|
||||||
|
Long: `
|
||||||
|
Upgrade configuration from the CrowdSec Hub.
|
||||||
|
|
||||||
|
In order to upgrade latest versions of configuration,
|
||||||
|
the Hub cache should be [updated](./cscli_update.md).
|
||||||
|
|
||||||
|
Tainted configuration will not be updated (use --force to update them).
|
||||||
|
|
||||||
|
[type] must be parser, scenario, postoverflow, collection.
|
||||||
|
|
||||||
|
[config_name] must be a valid config name from [Crowdsec Hub](https://hub.crowdsec.net).
|
||||||
|
|
||||||
|
|
||||||
|
`,
|
||||||
|
Example: `cscli upgrade [type] [config_name]
|
||||||
|
cscli upgrade --all # Upgrade all configurations types
|
||||||
|
cscli upgrade --force # Overwrite tainted configuration
|
||||||
|
`,
|
||||||
|
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !config.configured {
|
||||||
|
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if upgrade_all == false && len(args) < 2 {
|
||||||
|
_ = cmd.Help()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if upgrade_all == true && len(args) == 0 {
|
||||||
|
log.Warningf("Upgrade all : parsers, scenarios, collections.")
|
||||||
|
UpgradeConfig(cwhub.PARSERS, "")
|
||||||
|
UpgradeConfig(cwhub.PARSERS_OVFLW, "")
|
||||||
|
UpgradeConfig(cwhub.SCENARIOS, "")
|
||||||
|
UpgradeConfig(cwhub.COLLECTIONS, "")
|
||||||
|
}
|
||||||
|
//fmt.Println("upgrade all ?!: " + strings.Join(args, " "))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdUpgrade.PersistentFlags().BoolVar(&upgrade_all, "all", false, "Upgrade all configuration in scope")
|
||||||
|
cmdUpgrade.PersistentFlags().BoolVar(&force_upgrade, "force", false, "Overwrite existing files, even if tainted")
|
||||||
|
var cmdUpgradeParser = &cobra.Command{
|
||||||
|
Use: "parser [config]",
|
||||||
|
Short: "Upgrade parser configuration(s)",
|
||||||
|
Long: `Upgrade one or more parser configurations`,
|
||||||
|
Example: ` - cscli upgrade parser crowdsec/apache-logs
|
||||||
|
- cscli upgrade parser -all
|
||||||
|
- cscli upgrade parser crowdsec/apache-logs --force`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
UpgradeConfig(cwhub.PARSERS, args[0])
|
||||||
|
//UpgradeConfig(cwhub.PARSERS_OVFLW, "")
|
||||||
|
} else if upgrade_all == true {
|
||||||
|
UpgradeConfig(cwhub.PARSERS, "")
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdUpgrade.AddCommand(cmdUpgradeParser)
|
||||||
|
var cmdUpgradeScenario = &cobra.Command{
|
||||||
|
Use: "scenario [config]",
|
||||||
|
Short: "Upgrade scenario configuration(s)",
|
||||||
|
Long: `Upgrade one or more scenario configurations`,
|
||||||
|
Example: ` - cscli upgrade scenario -all
|
||||||
|
- cscli upgrade scenario crowdsec/http-404 --force `,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
UpgradeConfig(cwhub.SCENARIOS, args[0])
|
||||||
|
} else if upgrade_all == true {
|
||||||
|
UpgradeConfig(cwhub.SCENARIOS, "")
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdUpgrade.AddCommand(cmdUpgradeScenario)
|
||||||
|
var cmdUpgradeCollection = &cobra.Command{
|
||||||
|
Use: "collection [config]",
|
||||||
|
Short: "Upgrade collection configuration(s)",
|
||||||
|
Long: `Upgrade one or more collection configurations`,
|
||||||
|
Example: ` - cscli upgrade collection crowdsec/apache-lamp
|
||||||
|
- cscli upgrade collection -all
|
||||||
|
- cscli upgrade collection crowdsec/apache-lamp --force`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
UpgradeConfig(cwhub.COLLECTIONS, args[0])
|
||||||
|
} else if upgrade_all == true {
|
||||||
|
UpgradeConfig(cwhub.COLLECTIONS, "")
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdUpgrade.AddCommand(cmdUpgradeCollection)
|
||||||
|
|
||||||
|
var cmdUpgradePostoverflow = &cobra.Command{
|
||||||
|
Use: "postoverflow [config]",
|
||||||
|
Short: "Upgrade postoverflow parser configuration(s)",
|
||||||
|
Long: `Upgrade one or more postoverflow parser configurations`,
|
||||||
|
Example: ` - cscli upgrade postoverflow crowdsec/enrich-rdns
|
||||||
|
- cscli upgrade postoverflow -all
|
||||||
|
- cscli upgrade postoverflow crowdsec/enrich-rdns --force`,
|
||||||
|
Args: cobra.MinimumNArgs(0),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cwhub.GetHubIdx(); err != nil {
|
||||||
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
UpgradeConfig(cwhub.PARSERS_OVFLW, args[0])
|
||||||
|
} else if upgrade_all == true {
|
||||||
|
UpgradeConfig(cwhub.PARSERS_OVFLW, "")
|
||||||
|
} else {
|
||||||
|
_ = cmd.Help()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmdUpgrade.AddCommand(cmdUpgradePostoverflow)
|
||||||
|
return cmdUpgrade
|
||||||
|
}
|
68
cmd/crowdsec/Makefile
Normal file
68
cmd/crowdsec/Makefile
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Go parameters
|
||||||
|
GOCMD=go
|
||||||
|
GOBUILD=$(GOCMD) build
|
||||||
|
GOCLEAN=$(GOCMD) clean
|
||||||
|
GOTEST=$(GOCMD) test
|
||||||
|
GOGET=$(GOCMD) get
|
||||||
|
|
||||||
|
CROWDSEC_BIN=crowdsec
|
||||||
|
PREFIX?="/"
|
||||||
|
CFG_PREFIX = $(PREFIX)"/etc/crowdsec/crowdsec/"
|
||||||
|
BIN_PREFIX = $(PREFIX)"/usr/local/bin/"
|
||||||
|
DATA_PREFIX = $(PREFIX)"/var/run/crowdsec/"
|
||||||
|
PID_DIR = $(PREFIX)"/var/run/"
|
||||||
|
|
||||||
|
SYSTEMD_PATH_FILE="/etc/systemd/system/crowdsec.service"
|
||||||
|
|
||||||
|
|
||||||
|
all: clean test build
|
||||||
|
|
||||||
|
build: clean
|
||||||
|
$(GOBUILD) $(LD_OPTS) -o $(CROWDSEC_BIN) -v
|
||||||
|
|
||||||
|
static: clean
|
||||||
|
$(GOBUILD) -o $(CROWDSEC_BIN) -v -a -tags netgo -ldflags '-w -extldflags "-static"'
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(GOTEST) -v ./...
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(CROWDSEC_BIN)
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: install-conf install-bin
|
||||||
|
|
||||||
|
.PHONY: install-conf
|
||||||
|
install-conf:
|
||||||
|
mkdir -p $(DATA_PREFIX) || exit
|
||||||
|
(cd ../.. / && find ./data -type f -exec install -Dm 755 "{}" "$(DATA_PREFIX){}" \; && cd ./cmd/crowdsec) || exit
|
||||||
|
(cd ../../config && find ./patterns -type f -exec install -Dm 755 "{}" "$(CFG_PREFIX){}" \; && cd ../cmd/crowdsec) || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)" || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)/parsers" || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)/scenarios" || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)/postoverflows" || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)/collections" || exit
|
||||||
|
mkdir -p "$(CFG_PREFIX)/patterns" || exit
|
||||||
|
install -v -m 755 -D ../../config/prod.yaml "$(CFG_PREFIX)" || exit
|
||||||
|
install -v -m 755 -D ../../config/dev.yaml "$(CFG_PREFIX)" || exit
|
||||||
|
install -v -m 755 -D ../../config/acquis.yaml "$(CFG_PREFIX)" || exit
|
||||||
|
install -v -m 755 -D ../../config/profiles.yaml "$(CFG_PREFIX)" || exit
|
||||||
|
install -v -m 755 -D ../../config/api.yaml "$(CFG_PREFIX)" || exit
|
||||||
|
mkdir -p $(PID_DIR) || exit
|
||||||
|
PID=$(PID_DIR) DATA=$(DATA_PREFIX)"/data/" CFG=$(CFG_PREFIX) envsubst < ../../config/prod.yaml > $(CFG_PREFIX)"/default.yaml"
|
||||||
|
|
||||||
|
.PHONY: install-bin
|
||||||
|
install-bin:
|
||||||
|
install -v -m 755 -D "$(CROWDSEC_BIN)" "$(BIN_PREFIX)/$(CROWDSEC_BIN)" || exit
|
||||||
|
|
||||||
|
.PHONY: systemd"$(BIN_PREFI"$(BIN_PREFIX)/$(CROWDSEC_BIN)""$(BIN_PREFIX)/$(CROWDSEC_BIN)"X)/$(CROWDSEC_BIN)"
|
||||||
|
systemd: install
|
||||||
|
CFG=$(CFG_PREFIX) PID=$(PID_DIR) BIN=$(BIN_PREFIX)"/"$(CROWDSEC_BIN) envsubst < ../../config/crowdsec.service > "$(SYSTEMD_PATH_FILE)"
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall:
|
||||||
|
rm -rf $(CFG_PREFIX)
|
||||||
|
rm -rf $(DATA_PREFIX)
|
||||||
|
rm -f "$(BIN_PREFIX)/$(CROWDSEC_BIN)"
|
||||||
|
rm -f "$(SYSTEMD_PATH_FILE)"
|
33
cmd/crowdsec/acquisition.go
Normal file
33
cmd/crowdsec/acquisition.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadAcquisition() (*acquisition.FileAcquisCtx, error) {
|
||||||
|
var acquisitionCTX *acquisition.FileAcquisCtx
|
||||||
|
var err error
|
||||||
|
/*Init the acqusition : from cli or from acquis.yaml file*/
|
||||||
|
if cConfig.SingleFile != "" {
|
||||||
|
var input acquisition.FileCtx
|
||||||
|
input.Filename = cConfig.SingleFile
|
||||||
|
input.Mode = acquisition.CATMODE
|
||||||
|
input.Labels = make(map[string]string)
|
||||||
|
input.Labels["type"] = cConfig.SingleFileLabel
|
||||||
|
acquisitionCTX, err = acquisition.InitReaderFromFileCtx([]acquisition.FileCtx{input})
|
||||||
|
} else { /* Init file reader if we tail */
|
||||||
|
acquisitionCTX, err = acquisition.InitReader(cConfig.AcquisitionFile)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to start file acquisition, bailout %v", err)
|
||||||
|
}
|
||||||
|
if acquisitionCTX == nil {
|
||||||
|
return nil, fmt.Errorf("no inputs to process")
|
||||||
|
}
|
||||||
|
if cConfig.Profiling == true {
|
||||||
|
acquisitionCTX.Profiling = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return acquisitionCTX, nil
|
||||||
|
}
|
320
cmd/crowdsec/main.go
Normal file
320
cmd/crowdsec/main.go
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||||
|
config "github.com/crowdsecurity/crowdsec/pkg/config/crowdsec"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
|
leaky "github.com/crowdsecurity/crowdsec/pkg/leakybucket"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/parser"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
"gopkg.in/tomb.v2"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
/*tombs for the parser, buckets and outputs.*/
|
||||||
|
acquisTomb tomb.Tomb
|
||||||
|
parsersTomb tomb.Tomb
|
||||||
|
bucketsTomb tomb.Tomb
|
||||||
|
outputsTomb tomb.Tomb
|
||||||
|
|
||||||
|
holders []leaky.BucketFactory
|
||||||
|
buckets *leaky.Buckets
|
||||||
|
cConfig *config.Crowdwatch
|
||||||
|
|
||||||
|
/*settings*/
|
||||||
|
lastProcessedItem time.Time /*keep track of last item timestamp in time-machine. it is used to GC buckets when we dump them.*/
|
||||||
|
)
|
||||||
|
|
||||||
|
func configureLogger(logMode string, logFolder string, logLevel log.Level) error {
|
||||||
|
/*Configure logs*/
|
||||||
|
if logMode == "file" {
|
||||||
|
log.SetOutput(&lumberjack.Logger{
|
||||||
|
Filename: logFolder + "/crowdsec.log",
|
||||||
|
MaxSize: 500, //megabytes
|
||||||
|
MaxBackups: 3,
|
||||||
|
MaxAge: 28, //days
|
||||||
|
Compress: true, //disabled by default
|
||||||
|
})
|
||||||
|
log.SetFormatter(&log.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true})
|
||||||
|
} else if logMode != "stdout" {
|
||||||
|
return fmt.Errorf("log mode '%s' unknown", logMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("setting loglevel to %s", logLevel)
|
||||||
|
log.SetLevel(logLevel)
|
||||||
|
log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
|
||||||
|
if logLevel >= log.InfoLevel {
|
||||||
|
log.SetFormatter(&log.TextFormatter{TimestampFormat: "02-01-2006 15:04:05", FullTimestamp: true})
|
||||||
|
}
|
||||||
|
if logLevel >= log.DebugLevel {
|
||||||
|
log.SetReportCaller(true)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
p parser.UnixParser
|
||||||
|
parserNodes []parser.Node = make([]parser.Node, 0)
|
||||||
|
postOverflowNodes []parser.Node = make([]parser.Node, 0)
|
||||||
|
nbParser int = 1
|
||||||
|
parserCTX *parser.UnixParserCtx
|
||||||
|
postOverflowCTX *parser.UnixParserCtx
|
||||||
|
acquisitionCTX *acquisition.FileAcquisCtx
|
||||||
|
CustomParsers []parser.Stagefile
|
||||||
|
CustomPostoverflows []parser.Stagefile
|
||||||
|
CustomScenarios []parser.Stagefile
|
||||||
|
outputEventChan chan types.Event
|
||||||
|
)
|
||||||
|
|
||||||
|
inputLineChan := make(chan types.Event)
|
||||||
|
inputEventChan := make(chan types.Event)
|
||||||
|
|
||||||
|
cConfig = config.NewCrowdwatchConfig()
|
||||||
|
|
||||||
|
// Handle command line arguments
|
||||||
|
if err := cConfig.GetOPT(); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = configureLogger(cConfig.LogMode, cConfig.LogFolder, cConfig.LogLevel); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Crowdwatch %s", cwversion.VersionStr())
|
||||||
|
|
||||||
|
if cConfig.Prometheus == true {
|
||||||
|
registerPrometheus()
|
||||||
|
cConfig.Profiling = true
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Loading grok library")
|
||||||
|
/* load base regexps for two grok parsers */
|
||||||
|
parserCTX, err = p.Init(map[string]interface{}{"patterns": cConfig.ConfigFolder + string("/patterns/")})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to initialize parser : %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
postOverflowCTX, err = p.Init(map[string]interface{}{"patterns": cConfig.ConfigFolder + string("/patterns/")})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to initialize postoverflow : %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*enable profiling*/
|
||||||
|
if cConfig.Profiling == true {
|
||||||
|
go runTachymeter(cConfig.HTTPListen)
|
||||||
|
parserCTX.Profiling = true
|
||||||
|
postOverflowCTX.Profiling = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load enrichers
|
||||||
|
*/
|
||||||
|
log.Infof("Loading enrich plugins")
|
||||||
|
parserPlugins, err := parser.Loadplugin(cConfig.DataFolder)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to load plugin geoip : %v", err)
|
||||||
|
}
|
||||||
|
parser.ECTX = append(parser.ECTX, parserPlugins)
|
||||||
|
|
||||||
|
/*parser the validatormode option if present. mostly used for testing purposes*/
|
||||||
|
if cConfig.ValidatorMode != "" {
|
||||||
|
//beurk : provided 'parser:file.yaml,postoverflow:file.yaml,scenario:file.yaml load only those
|
||||||
|
validators := strings.Split(cConfig.ValidatorMode, ",")
|
||||||
|
for _, val := range validators {
|
||||||
|
splittedValidator := strings.Split(val, ":")
|
||||||
|
if len(splittedValidator) != 2 {
|
||||||
|
log.Fatalf("parser:file,scenario:file,postoverflow:file")
|
||||||
|
}
|
||||||
|
|
||||||
|
configType := splittedValidator[0]
|
||||||
|
configFile := splittedValidator[1]
|
||||||
|
|
||||||
|
var parsedFile []parser.Stagefile
|
||||||
|
dataFile, err := ioutil.ReadFile(configFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed opening %s : %s", configFile, err)
|
||||||
|
}
|
||||||
|
if err := yaml.UnmarshalStrict(dataFile, &parsedFile); err != nil {
|
||||||
|
log.Fatalf("failed unmarshalling %s : %s", configFile, err)
|
||||||
|
}
|
||||||
|
switch configType {
|
||||||
|
case "parser":
|
||||||
|
CustomParsers = parsedFile
|
||||||
|
case "scenario":
|
||||||
|
CustomScenarios = parsedFile
|
||||||
|
case "postoverflow":
|
||||||
|
CustomPostoverflows = parsedFile
|
||||||
|
default:
|
||||||
|
log.Fatalf("wrong type, format is parser:file,scenario:file,postoverflow:file")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load the parser nodes */
|
||||||
|
if cConfig.ValidatorMode != "" && len(CustomParsers) > 0 {
|
||||||
|
log.Infof("Loading (validatormode) parsers")
|
||||||
|
parserNodes, err = parser.LoadStages(CustomParsers, parserCTX)
|
||||||
|
} else {
|
||||||
|
log.Infof("Loading parsers")
|
||||||
|
parserNodes, err = parser.LoadStageDir(cConfig.ConfigFolder+"/parsers/", parserCTX)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to load parser config : %v", err)
|
||||||
|
}
|
||||||
|
/* parsers loaded */
|
||||||
|
|
||||||
|
/* load the post-overflow stages*/
|
||||||
|
if cConfig.ValidatorMode != "" && len(CustomPostoverflows) > 0 {
|
||||||
|
log.Infof("Loading (validatormode) postoverflow parsers")
|
||||||
|
postOverflowNodes, err = parser.LoadStages(CustomPostoverflows, postOverflowCTX)
|
||||||
|
} else {
|
||||||
|
log.Infof("Loading postoverflow parsers")
|
||||||
|
postOverflowNodes, err = parser.LoadStageDir(cConfig.ConfigFolder+"/postoverflows/", postOverflowCTX)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to load postoverflow config : %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Loaded Nodes : %d parser, %d postoverflow", len(parserNodes), len(postOverflowNodes))
|
||||||
|
/* post overflow loaded */
|
||||||
|
|
||||||
|
/* Loading buckets / scenarios */
|
||||||
|
if cConfig.ValidatorMode != "" && len(CustomScenarios) > 0 {
|
||||||
|
log.Infof("Loading (validatormode) scenarios")
|
||||||
|
bucketFiles := []string{}
|
||||||
|
for _, scenarios := range CustomScenarios {
|
||||||
|
bucketFiles = append(bucketFiles, scenarios.Filename)
|
||||||
|
}
|
||||||
|
holders, outputEventChan, err = leaky.LoadBuckets(bucketFiles)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.Infof("Loading scenarios")
|
||||||
|
holders, outputEventChan, err = leaky.Init(map[string]string{"patterns": cConfig.ConfigFolder + "/scenarios/"})
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Scenario loading failed : %v", err)
|
||||||
|
}
|
||||||
|
/* buckets/scenarios loaded */
|
||||||
|
|
||||||
|
/*keep track of scenarios name for consensus profiling*/
|
||||||
|
var scenariosEnabled string
|
||||||
|
for _, x := range holders {
|
||||||
|
if scenariosEnabled != "" {
|
||||||
|
scenariosEnabled += ","
|
||||||
|
}
|
||||||
|
scenariosEnabled += x.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets = leaky.NewBuckets()
|
||||||
|
|
||||||
|
/*restore as well previous state if present*/
|
||||||
|
if cConfig.RestoreMode != "" {
|
||||||
|
log.Warningf("Restoring buckets state from %s", cConfig.RestoreMode)
|
||||||
|
if err := leaky.LoadBucketsState(cConfig.RestoreMode, buckets, holders); err != nil {
|
||||||
|
log.Fatalf("unable to restore buckets : %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cConfig.Profiling == true {
|
||||||
|
//force the profiling in all buckets
|
||||||
|
for holderIndex := range holders {
|
||||||
|
holders[holderIndex].Profiling = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load output profiles
|
||||||
|
*/
|
||||||
|
log.Infof("Loading output profiles")
|
||||||
|
outputProfiles, err := outputs.LoadOutputProfiles(cConfig.ConfigFolder + "/profiles.yaml")
|
||||||
|
if err != nil || len(outputProfiles) == 0 {
|
||||||
|
log.Fatalf("Failed to load output profiles : %v", err)
|
||||||
|
}
|
||||||
|
/* Linting is done */
|
||||||
|
if cConfig.Linter {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outputRunner, err := outputs.NewOutput(cConfig.OutputConfig, cConfig.Daemonize)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("output plugins initialization error : %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init the API connector */
|
||||||
|
if cConfig.APIMode {
|
||||||
|
log.Infof("Loading API client")
|
||||||
|
var apiConfig = map[string]string{
|
||||||
|
"path": cConfig.ConfigFolder + "/api.yaml",
|
||||||
|
"profile": scenariosEnabled,
|
||||||
|
}
|
||||||
|
if err := outputRunner.InitAPI(apiConfig); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if the user is in "single file mode" (might be writting scenario or parsers), allow loading **without** parsers or scenarios */
|
||||||
|
if cConfig.SingleFile == "" {
|
||||||
|
if len(parserNodes) == 0 {
|
||||||
|
log.Fatalf("no parser(s) loaded, abort.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(holders) == 0 {
|
||||||
|
log.Fatalf("no bucket(s) loaded, abort.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(outputProfiles) == 0 {
|
||||||
|
log.Fatalf("no output profile(s) loaded, abort.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Starting processing routines")
|
||||||
|
//start go-routines for parsing, buckets pour and ouputs.
|
||||||
|
for i := 0; i < nbParser; i++ {
|
||||||
|
parsersTomb.Go(func() error {
|
||||||
|
return runParse(inputLineChan, inputEventChan, *parserCTX, parserNodes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < nbParser; i++ {
|
||||||
|
bucketsTomb.Go(func() error {
|
||||||
|
return runPour(inputEventChan, holders, buckets)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < nbParser; i++ {
|
||||||
|
outputsTomb.Go(func() error {
|
||||||
|
return runOutput(inputEventChan, outputEventChan, holders, buckets, *postOverflowCTX, postOverflowNodes, outputProfiles, outputRunner)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warningf("Starting processing data")
|
||||||
|
|
||||||
|
//Init the acqusition : from cli or from acquis.yaml file
|
||||||
|
acquisitionCTX, err = loadAcquisition()
|
||||||
|
|
||||||
|
//start reading in the background
|
||||||
|
acquisition.AcquisStartReading(acquisitionCTX, inputLineChan, &acquisTomb)
|
||||||
|
|
||||||
|
if err = serve(*outputRunner); err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
121
cmd/crowdsec/metrics.go
Normal file
121
cmd/crowdsec/metrics.go
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||||
|
leaky "github.com/crowdsecurity/crowdsec/pkg/leakybucket"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/parser"
|
||||||
|
"github.com/jamiealquiza/tachymeter"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
parseStat *tachymeter.Tachymeter
|
||||||
|
bucketStat *tachymeter.Tachymeter
|
||||||
|
outputStat *tachymeter.Tachymeter
|
||||||
|
linesReadOK uint64
|
||||||
|
linesReadKO uint64
|
||||||
|
linesParsedOK uint64
|
||||||
|
linesParsedKO uint64
|
||||||
|
linesPouredOK uint64
|
||||||
|
linesPouredKO uint64
|
||||||
|
)
|
||||||
|
|
||||||
|
/*prometheus*/
|
||||||
|
var globalParserHits = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "cs_parser_hits",
|
||||||
|
Help: "How many time an event entered the parser.",
|
||||||
|
},
|
||||||
|
[]string{"source"},
|
||||||
|
)
|
||||||
|
var globalParserHitsOk = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "cs_parser_hits_ok",
|
||||||
|
Help: "How many time an event was successfully parsed.",
|
||||||
|
},
|
||||||
|
[]string{"source"},
|
||||||
|
)
|
||||||
|
var globalParserHitsKo = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "cs_parser_hits_ko",
|
||||||
|
Help: "How many time an event was unsuccessfully parsed.",
|
||||||
|
},
|
||||||
|
[]string{"source"},
|
||||||
|
)
|
||||||
|
|
||||||
|
var globalBucketPourKo = prometheus.NewCounter(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "cs_bucket_pour_ko",
|
||||||
|
Help: "How many time an event was poured in no bucket.",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
var globalBucketPourOk = prometheus.NewCounter(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "cs_bucket_pour_ok",
|
||||||
|
Help: "How many time an event was poured in at least one bucket.",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
func dumpMetrics() {
|
||||||
|
|
||||||
|
if cConfig.DumpBuckets == true {
|
||||||
|
log.Infof("!! Dumping buckets state")
|
||||||
|
if err := leaky.DumpBucketsStateAt("buckets_state.json", time.Now(), buckets); err != nil {
|
||||||
|
log.Fatalf("Failed dumping bucket state : %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cConfig.Profiling {
|
||||||
|
var memoryStats runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&memoryStats)
|
||||||
|
|
||||||
|
log.Infof("parser evt/s : %s", parseStat.Calc())
|
||||||
|
log.Infof("bucket pour evt/s : %s", bucketStat.Calc())
|
||||||
|
log.Infof("outputs evt/s : %s", outputStat.Calc())
|
||||||
|
log.Infof("Alloc = %v MiB", bToMb(memoryStats.Alloc))
|
||||||
|
log.Infof("TotalAlloc = %v MiB", bToMb(memoryStats.TotalAlloc))
|
||||||
|
log.Infof("Sys = %v MiB", bToMb(memoryStats.Sys))
|
||||||
|
log.Infof("NumGC = %v", memoryStats.NumGC)
|
||||||
|
log.Infof("Lines read ok : %d", linesReadOK)
|
||||||
|
if linesReadKO > 0 {
|
||||||
|
log.Infof("Lines discarded : %d (%.2f%%)", linesReadKO, float64(linesReadKO)/float64(linesReadOK)*100.0)
|
||||||
|
}
|
||||||
|
log.Infof("Lines parsed ok : %d", linesParsedOK)
|
||||||
|
if linesParsedKO > 0 {
|
||||||
|
log.Infof("Lines unparsed : %d (%.2f%%)", linesParsedKO, float64(linesParsedKO)/float64(linesParsedOK)*100.0)
|
||||||
|
}
|
||||||
|
log.Infof("Lines poured ok : %d", linesPouredOK)
|
||||||
|
if linesPouredKO > 0 {
|
||||||
|
log.Infof("Lines never poured : %d (%.2f%%)", linesPouredKO, float64(linesPouredKO)/float64(linesPouredOK)*100.0)
|
||||||
|
}
|
||||||
|
log.Infof("Writting metrics dump to %s", cConfig.WorkingFolder+"/crowdsec.profile")
|
||||||
|
prometheus.WriteToTextfile(cConfig.WorkingFolder+"/crowdsec.profile", prometheus.DefaultGatherer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTachymeter(HTTPListen string) {
|
||||||
|
log.Warningf("Starting profiling and http server")
|
||||||
|
/*Tachymeter for global perfs */
|
||||||
|
parseStat = tachymeter.New(&tachymeter.Config{Size: 100})
|
||||||
|
bucketStat = tachymeter.New(&tachymeter.Config{Size: 100})
|
||||||
|
outputStat = tachymeter.New(&tachymeter.Config{Size: 100})
|
||||||
|
log.Fatal(http.ListenAndServe(HTTPListen, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerPrometheus() {
|
||||||
|
/*Registering prometheus*/
|
||||||
|
log.Warningf("Loading prometheus collectors")
|
||||||
|
prometheus.MustRegister(globalParserHits, globalParserHitsOk, globalParserHitsKo, parser.NodesHits, parser.NodesHitsOk,
|
||||||
|
parser.NodesHitsKo, acquisition.ReaderHits, leaky.BucketsPour, leaky.BucketsUnderflow, leaky.BucketsInstanciation,
|
||||||
|
leaky.BucketsOverflow)
|
||||||
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
|
}
|
54
cmd/crowdsec/output.go
Normal file
54
cmd/crowdsec/output.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
|
leaky "github.com/crowdsecurity/crowdsec/pkg/leakybucket"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/parser"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runOutput(input chan types.Event, overflow chan types.Event, holders []leaky.BucketFactory, buckets *leaky.Buckets,
|
||||||
|
poctx parser.UnixParserCtx, ponodes []parser.Node, outputProfiles []types.Profile, output *outputs.Output) error {
|
||||||
|
var (
|
||||||
|
//action string
|
||||||
|
start time.Time
|
||||||
|
)
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-bucketsTomb.Dying():
|
||||||
|
log.Infof("Exiting output processing")
|
||||||
|
output.FlushAll()
|
||||||
|
break LOOP
|
||||||
|
case event := <-overflow:
|
||||||
|
if cConfig.Profiling {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Overflow.Reprocess {
|
||||||
|
log.Debugf("Overflow being reprocessed.")
|
||||||
|
input <- event
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Overflow.Scenario == "" && event.Overflow.MapKey != "" {
|
||||||
|
//log.Infof("Deleting expired entry %s", event.Overflow.MapKey)
|
||||||
|
buckets.Bucket_map.Delete(event.Overflow.MapKey)
|
||||||
|
} else {
|
||||||
|
/*let's handle output profiles */
|
||||||
|
if err := output.ProcessOutput(event.Overflow, outputProfiles); err != nil {
|
||||||
|
log.Warningf("Error while processing overflow/output : %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cConfig.Profiling {
|
||||||
|
outputStat.AddTime(time.Since(start))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
74
cmd/crowdsec/parse.go
Normal file
74
cmd/crowdsec/parse.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/parser"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runParse(input chan types.Event, output chan types.Event, parserCTX parser.UnixParserCtx, nodes []parser.Node) error {
|
||||||
|
var start time.Time
|
||||||
|
var discardCPT, processCPT int
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-parsersTomb.Dying():
|
||||||
|
log.Infof("Killing parser routines")
|
||||||
|
break LOOP
|
||||||
|
case event := <-input:
|
||||||
|
if cConfig.Profiling {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
|
if event.Process == false {
|
||||||
|
if cConfig.Profiling {
|
||||||
|
atomic.AddUint64(&linesReadKO, 1)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cConfig.Profiling {
|
||||||
|
atomic.AddUint64(&linesReadOK, 1)
|
||||||
|
globalParserHits.With(prometheus.Labels{"source": event.Line.Src}).Inc()
|
||||||
|
|
||||||
|
}
|
||||||
|
/* parse the log using magic */
|
||||||
|
parsed, error := parser.Parse(parserCTX, event, nodes)
|
||||||
|
if error != nil {
|
||||||
|
log.Errorf("failed parsing : %v\n", error)
|
||||||
|
return errors.New("parsing failed :/")
|
||||||
|
}
|
||||||
|
if parsed.Process == false {
|
||||||
|
if cConfig.Profiling {
|
||||||
|
globalParserHitsKo.With(prometheus.Labels{"source": event.Line.Src}).Inc()
|
||||||
|
atomic.AddUint64(&linesParsedKO, 1)
|
||||||
|
}
|
||||||
|
log.Debugf("Discarding line %+v", parsed)
|
||||||
|
discardCPT++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cConfig.Profiling {
|
||||||
|
globalParserHitsOk.With(prometheus.Labels{"source": event.Line.Src}).Inc()
|
||||||
|
atomic.AddUint64(&linesParsedOK, 1)
|
||||||
|
}
|
||||||
|
processCPT++
|
||||||
|
if parsed.Whitelisted == true {
|
||||||
|
log.Debugf("event whitelisted, discard")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if processCPT%1000 == 0 {
|
||||||
|
log.Debugf("%d lines processed, %d lines discarded (unparsed)", processCPT, discardCPT)
|
||||||
|
}
|
||||||
|
output <- parsed
|
||||||
|
if cConfig.Profiling {
|
||||||
|
parseStat.AddTime(time.Since(start))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
65
cmd/crowdsec/pour.go
Normal file
65
cmd/crowdsec/pour.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
leaky "github.com/crowdsecurity/crowdsec/pkg/leakybucket"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runPour(input chan types.Event, holders []leaky.BucketFactory, buckets *leaky.Buckets) error {
|
||||||
|
var (
|
||||||
|
start time.Time
|
||||||
|
count int
|
||||||
|
)
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
//bucket is now ready
|
||||||
|
select {
|
||||||
|
case <-bucketsTomb.Dying():
|
||||||
|
log.Infof("Exiting Bucketify")
|
||||||
|
break LOOP
|
||||||
|
case parsed := <-input:
|
||||||
|
count++
|
||||||
|
if cConfig.Profiling {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
if count%5000 == 0 {
|
||||||
|
log.Warningf("%d existing LeakyRoutine", leaky.LeakyRoutineCount)
|
||||||
|
//when in forensics mode, garbage collect buckets
|
||||||
|
if parsed.MarshaledTime != "" && cConfig.SingleFile != "" {
|
||||||
|
var z *time.Time = &time.Time{}
|
||||||
|
if err := z.UnmarshalText([]byte(parsed.MarshaledTime)); err != nil {
|
||||||
|
log.Warningf("Failed to unmarshal time from event '%s' : %s", parsed.MarshaledTime, err)
|
||||||
|
} else {
|
||||||
|
log.Warningf("Starting buckets garbage collection ...")
|
||||||
|
leaky.GarbageCollectBuckets(*z, buckets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//here we can bucketify with parsed
|
||||||
|
poured, err := leaky.PourItemToHolders(parsed, holders, buckets)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("bucketify failed for: %v", parsed)
|
||||||
|
return fmt.Errorf("process of event failed : %v", err)
|
||||||
|
}
|
||||||
|
if poured {
|
||||||
|
globalBucketPourOk.Inc()
|
||||||
|
atomic.AddUint64(&linesPouredOK, 1)
|
||||||
|
} else {
|
||||||
|
globalBucketPourKo.Inc()
|
||||||
|
atomic.AddUint64(&linesPouredKO, 1)
|
||||||
|
}
|
||||||
|
if cConfig.Profiling {
|
||||||
|
bucketStat.AddTime(time.Since(start))
|
||||||
|
}
|
||||||
|
lastProcessedItem.UnmarshalText([]byte(parsed.MarshaledTime))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Infof("Sending signal Bucketify")
|
||||||
|
return nil
|
||||||
|
}
|
130
cmd/crowdsec/serve.go
Normal file
130
cmd/crowdsec/serve.go
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/outputs"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/sevlyar/go-daemon"
|
||||||
|
)
|
||||||
|
|
||||||
|
func reloadHandler(sig os.Signal) error {
|
||||||
|
dumpMetrics()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func termHandler(sig os.Signal) error {
|
||||||
|
log.Warningf("Shutting down routines")
|
||||||
|
|
||||||
|
acquisTomb.Kill(nil)
|
||||||
|
log.Infof("waiting for acquisition to finish")
|
||||||
|
if err := acquisTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("Acquisition returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("acquisition is finished, wait for parser/bucket/ouputs.")
|
||||||
|
//let's wait more than enough for in-flight events to be parsed.
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
parsersTomb.Kill(nil)
|
||||||
|
if err := parsersTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("Parsers returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("parsers is done")
|
||||||
|
bucketsTomb.Kill(nil)
|
||||||
|
if err := bucketsTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("Buckets returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("buckets is done")
|
||||||
|
outputsTomb.Kill(nil)
|
||||||
|
if err := outputsTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("Ouputs returned error : %s", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
log.Infof("ouputs is done")
|
||||||
|
dumpMetrics()
|
||||||
|
log.Warningf("all routines are done, bye.")
|
||||||
|
return daemon.ErrStop
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveDaemon() error {
|
||||||
|
var daemonCTX *daemon.Context
|
||||||
|
|
||||||
|
daemon.SetSigHandler(termHandler, syscall.SIGTERM)
|
||||||
|
daemon.SetSigHandler(reloadHandler, syscall.SIGHUP)
|
||||||
|
|
||||||
|
daemonCTX = &daemon.Context{
|
||||||
|
PidFileName: cConfig.PIDFolder + "/crowdsec.pid",
|
||||||
|
PidFilePerm: 0644,
|
||||||
|
WorkDir: "./",
|
||||||
|
Umask: 027,
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := daemonCTX.Reborn()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to run daemon: %s ", err.Error())
|
||||||
|
}
|
||||||
|
if d != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer daemonCTX.Release()
|
||||||
|
err = daemon.ServeSignals()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("serveDaemon error : %s", err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveOneTimeRun(outputRunner outputs.Output) error {
|
||||||
|
log.Infof("waiting for acquisition to finish")
|
||||||
|
|
||||||
|
if err := acquisTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("acquisition returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("acquisition is finished, wait for parser/bucket/ouputs.")
|
||||||
|
|
||||||
|
//let's wait more than enough for in-flight events to be parsed.
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
// wait for the parser to parse all events
|
||||||
|
parsersTomb.Kill(nil)
|
||||||
|
if err := parsersTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("parsers returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("parsers is done")
|
||||||
|
|
||||||
|
// wait for the bucket to pour all events
|
||||||
|
bucketsTomb.Kill(nil)
|
||||||
|
if err := bucketsTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("buckets returned error : %s", err)
|
||||||
|
}
|
||||||
|
log.Infof("buckets is done")
|
||||||
|
|
||||||
|
// wait for output to output all event
|
||||||
|
outputsTomb.Kill(nil)
|
||||||
|
if err := outputsTomb.Wait(); err != nil {
|
||||||
|
log.Warningf("ouputs returned error : %s", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
log.Infof("ouputs is done")
|
||||||
|
dumpMetrics()
|
||||||
|
outputRunner.Flush()
|
||||||
|
log.Warningf("all routines are done, bye.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serve(outputRunner outputs.Output) error {
|
||||||
|
var err error
|
||||||
|
if cConfig.Daemonize == true {
|
||||||
|
if err = serveDaemon(); err != nil {
|
||||||
|
return fmt.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = serveOneTimeRun(outputRunner); err != nil {
|
||||||
|
return fmt.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
5
cmd/crowdsec/utils.go
Normal file
5
cmd/crowdsec/utils.go
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
func bToMb(b uint64) uint64 {
|
||||||
|
return b / 1024 / 1024
|
||||||
|
}
|
52
config/acquis.yaml
Normal file
52
config/acquis.yaml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
filenames:
|
||||||
|
- /var/log/nginx/*.log
|
||||||
|
- ./tests/nginx/nginx.log
|
||||||
|
#this is not a syslog log, indicate which kind of logs it is
|
||||||
|
labels:
|
||||||
|
prog_name: nginx
|
||||||
|
type: nginx_raw_log
|
||||||
|
---
|
||||||
|
filenames:
|
||||||
|
- /var/log/auth.log
|
||||||
|
- /var/log/syslog
|
||||||
|
#no need to set the prog_name, syslog format contains this info
|
||||||
|
labels:
|
||||||
|
type: syslog
|
||||||
|
---
|
||||||
|
filename: /var/log/apache2/*.log
|
||||||
|
labels:
|
||||||
|
prog_name: apache2
|
||||||
|
type: nginx_raw_log
|
||||||
|
---
|
||||||
|
filenames:
|
||||||
|
- ./tests/tcpdump.out
|
||||||
|
- /root/granola/tcpdump.out
|
||||||
|
labels:
|
||||||
|
prog_name: tcpdump
|
||||||
|
type: tcpdump_raw_log
|
||||||
|
---
|
||||||
|
filename: ./tests/apache.log
|
||||||
|
labels:
|
||||||
|
prog_name: apache2
|
||||||
|
---
|
||||||
|
filename: ./tests/nginx.log
|
||||||
|
labels:
|
||||||
|
prog_name: nginx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# #list of files to be tailed
|
||||||
|
# #it's ok to add files that don't exist, they will juste be skipped :)
|
||||||
|
# - /var/log/nginx/*.log
|
||||||
|
# - /root/granola/tcpdump.out
|
||||||
|
# - /var/log/auth.log
|
||||||
|
# - tests/*.log
|
||||||
|
# - tests/tcpdump.out
|
||||||
|
# - tests/nginx/nginx.log
|
||||||
|
|
||||||
|
# # for honeypots
|
||||||
|
# - /data/logs/*.log
|
||||||
|
# - /var/log/tcpdump.out
|
||||||
|
# - /var/log/auth.log
|
||||||
|
# - /var/log/syslog
|
8
config/api.yaml
Normal file
8
config/api.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
version: v1
|
||||||
|
url: https://tmsov6x2n9.execute-api.eu-west-1.amazonaws.com
|
||||||
|
signin_path: signin
|
||||||
|
push_path: signals
|
||||||
|
pull_path: pull
|
||||||
|
enroll_path: enroll
|
||||||
|
reset_pwd_path: resetpassword
|
||||||
|
register_path: register
|
13
config/crowdsec.service
Normal file
13
config/crowdsec.service
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Crowdwatch agent
|
||||||
|
After=syslog.target network.target remote-fs.target nss-lookup.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
#PIDFile=${PID}/crowdsec.pid
|
||||||
|
ExecStartPre=${BIN} -c ${CFG}/default.yaml -t
|
||||||
|
ExecStart=${BIN} -c ${CFG}/default.yaml
|
||||||
|
ExecStartPost=/bin/sleep 0.1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
6
config/crowdsec_pull
Normal file
6
config/crowdsec_pull
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# /etc/cron.d/crowdsec_pull: crontab to pull crowdsec API
|
||||||
|
# bad IP in ban DB.
|
||||||
|
|
||||||
|
# Run everyday at 08:00 A.M
|
||||||
|
|
||||||
|
0 8 * * * root /usr/local/bin/cscli api pull >> /var/log/cscli.log 2>&1
|
12
config/dev.yaml
Normal file
12
config/dev.yaml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
working_dir: "."
|
||||||
|
data_dir: "./data"
|
||||||
|
config_dir: "./config"
|
||||||
|
pid_dir: "./"
|
||||||
|
log_dir: "./logs"
|
||||||
|
log_mode: "stdout"
|
||||||
|
log_level: info
|
||||||
|
profiling: false
|
||||||
|
sqlite_path: "./test.db"
|
||||||
|
apimode: false
|
||||||
|
plugin:
|
||||||
|
backend: "./config/plugins/backend"
|
11
config/patterns/aws
Normal file
11
config/patterns/aws
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
S3_REQUEST_LINE (?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})
|
||||||
|
|
||||||
|
S3_ACCESS_LOG %{WORD:owner} %{NOTSPACE:bucket} \[%{HTTPDATE:timestamp}\] %{IP:clientip} %{NOTSPACE:requester} %{NOTSPACE:request_id} %{NOTSPACE:operation} %{NOTSPACE:key} (?:"%{S3_REQUEST_LINE}"|-) (?:%{INT:response:int}|-) (?:-|%{NOTSPACE:error_code}) (?:%{INT:bytes:int}|-) (?:%{INT:object_size:int}|-) (?:%{INT:request_time_ms:int}|-) (?:%{INT:turnaround_time_ms:int}|-) (?:%{QS:referrer}|-) (?:"?%{QS:agent}"?|-) (?:-|%{NOTSPACE:version_id})
|
||||||
|
|
||||||
|
ELB_URIPATHPARAM %{URIPATH:path}(?:%{URIPARAM:params})?
|
||||||
|
|
||||||
|
ELB_URI %{URIPROTO:proto}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST:urihost})?(?:%{ELB_URIPATHPARAM})?
|
||||||
|
|
||||||
|
ELB_REQUEST_LINE (?:%{WORD:verb} %{ELB_URI:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})
|
||||||
|
|
||||||
|
ELB_ACCESS_LOG %{TIMESTAMP_ISO8601:timestamp} %{NOTSPACE:elb} %{IP:clientip}:%{INT:clientport:int} (?:(%{IP:backendip}:?:%{INT:backendport:int})|-) %{NUMBER:request_processing_time:float} %{NUMBER:backend_processing_time:float} %{NUMBER:response_processing_time:float} %{INT:response:int} %{INT:backend_response:int} %{INT:received_bytes:int} %{INT:bytes:int} "%{ELB_REQUEST_LINE}"
|
50
config/patterns/bacula
Normal file
50
config/patterns/bacula
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
BACULA_TIMESTAMP %{MONTHDAY}-%{MONTH} %{HOUR}:%{MINUTE}
|
||||||
|
BACULA_HOST [a-zA-Z0-9-]+
|
||||||
|
BACULA_VOLUME %{USER}
|
||||||
|
BACULA_DEVICE %{USER}
|
||||||
|
BACULA_DEVICEPATH %{UNIXPATH}
|
||||||
|
BACULA_CAPACITY %{INT}{1,3}(,%{INT}{3})*
|
||||||
|
BACULA_VERSION %{USER}
|
||||||
|
BACULA_JOB %{USER}
|
||||||
|
|
||||||
|
BACULA_LOG_MAX_CAPACITY User defined maximum volume capacity %{BACULA_CAPACITY} exceeded on device \"%{BACULA_DEVICE:device}\" \(%{BACULA_DEVICEPATH}\)
|
||||||
|
BACULA_LOG_END_VOLUME End of medium on Volume \"%{BACULA_VOLUME:volume}\" Bytes=%{BACULA_CAPACITY} Blocks=%{BACULA_CAPACITY} at %{MONTHDAY}-%{MONTH}-%{YEAR} %{HOUR}:%{MINUTE}.
|
||||||
|
BACULA_LOG_NEW_VOLUME Created new Volume \"%{BACULA_VOLUME:volume}\" in catalog.
|
||||||
|
BACULA_LOG_NEW_LABEL Labeled new Volume \"%{BACULA_VOLUME:volume}\" on device \"%{BACULA_DEVICE:device}\" \(%{BACULA_DEVICEPATH}\).
|
||||||
|
BACULA_LOG_WROTE_LABEL Wrote label to prelabeled Volume \"%{BACULA_VOLUME:volume}\" on device \"%{BACULA_DEVICE}\" \(%{BACULA_DEVICEPATH}\)
|
||||||
|
BACULA_LOG_NEW_MOUNT New volume \"%{BACULA_VOLUME:volume}\" mounted on device \"%{BACULA_DEVICE:device}\" \(%{BACULA_DEVICEPATH}\) at %{MONTHDAY}-%{MONTH}-%{YEAR} %{HOUR}:%{MINUTE}.
|
||||||
|
BACULA_LOG_NOOPEN \s+Cannot open %{DATA}: ERR=%{GREEDYDATA:berror}
|
||||||
|
BACULA_LOG_NOOPENDIR \s+Could not open directory %{DATA}: ERR=%{GREEDYDATA:berror}
|
||||||
|
BACULA_LOG_NOSTAT \s+Could not stat %{DATA}: ERR=%{GREEDYDATA:berror}
|
||||||
|
BACULA_LOG_NOJOBS There are no more Jobs associated with Volume \"%{BACULA_VOLUME:volume}\". Marking it purged.
|
||||||
|
BACULA_LOG_ALL_RECORDS_PRUNED All records pruned from Volume \"%{BACULA_VOLUME:volume}\"; marking it \"Purged\"
|
||||||
|
BACULA_LOG_BEGIN_PRUNE_JOBS Begin pruning Jobs older than %{INT} month %{INT} days .
|
||||||
|
BACULA_LOG_BEGIN_PRUNE_FILES Begin pruning Files.
|
||||||
|
BACULA_LOG_PRUNED_JOBS Pruned %{INT} Jobs* for client %{BACULA_HOST:client} from catalog.
|
||||||
|
BACULA_LOG_PRUNED_FILES Pruned Files from %{INT} Jobs* for client %{BACULA_HOST:client} from catalog.
|
||||||
|
BACULA_LOG_ENDPRUNE End auto prune.
|
||||||
|
BACULA_LOG_STARTJOB Start Backup JobId %{INT}, Job=%{BACULA_JOB:job}
|
||||||
|
BACULA_LOG_STARTRESTORE Start Restore Job %{BACULA_JOB:job}
|
||||||
|
BACULA_LOG_USEDEVICE Using Device \"%{BACULA_DEVICE:device}\"
|
||||||
|
BACULA_LOG_DIFF_FS \s+%{UNIXPATH} is a different filesystem. Will not descend from %{UNIXPATH} into it.
|
||||||
|
BACULA_LOG_JOBEND Job write elapsed time = %{DATA:elapsed}, Transfer rate = %{NUMBER} (K|M|G)? Bytes/second
|
||||||
|
BACULA_LOG_NOPRUNE_JOBS No Jobs found to prune.
|
||||||
|
BACULA_LOG_NOPRUNE_FILES No Files found to prune.
|
||||||
|
BACULA_LOG_VOLUME_PREVWRITTEN Volume \"%{BACULA_VOLUME:volume}\" previously written, moving to end of data.
|
||||||
|
BACULA_LOG_READYAPPEND Ready to append to end of Volume \"%{BACULA_VOLUME:volume}\" size=%{INT}
|
||||||
|
BACULA_LOG_CANCELLING Cancelling duplicate JobId=%{INT}.
|
||||||
|
BACULA_LOG_MARKCANCEL JobId %{INT}, Job %{BACULA_JOB:job} marked to be canceled.
|
||||||
|
BACULA_LOG_CLIENT_RBJ shell command: run ClientRunBeforeJob \"%{GREEDYDATA:runjob}\"
|
||||||
|
BACULA_LOG_VSS (Generate )?VSS (Writer)?
|
||||||
|
BACULA_LOG_MAXSTART Fatal error: Job canceled because max start delay time exceeded.
|
||||||
|
BACULA_LOG_DUPLICATE Fatal error: JobId %{INT:duplicate} already running. Duplicate job not allowed.
|
||||||
|
BACULA_LOG_NOJOBSTAT Fatal error: No Job status returned from FD.
|
||||||
|
BACULA_LOG_FATAL_CONN Fatal error: bsock.c:133 Unable to connect to (Client: %{BACULA_HOST:client}|Storage daemon) on %{HOSTNAME}:%{POSINT}. ERR=%{GREEDYDATA:berror}
|
||||||
|
BACULA_LOG_NO_CONNECT Warning: bsock.c:127 Could not connect to (Client: %{BACULA_HOST:client}|Storage daemon) on %{HOSTNAME}:%{POSINT}. ERR=%{GREEDYDATA:berror}
|
||||||
|
BACULA_LOG_NO_AUTH Fatal error: Unable to authenticate with File daemon at %{HOSTNAME}. Possible causes:
|
||||||
|
BACULA_LOG_NOSUIT No prior or suitable Full backup found in catalog. Doing FULL backup.
|
||||||
|
BACULA_LOG_NOPRIOR No prior Full backup Job record found.
|
||||||
|
|
||||||
|
BACULA_LOG_JOB (Error: )?Bacula %{BACULA_HOST} %{BACULA_VERSION} \(%{BACULA_VERSION}\):
|
||||||
|
|
||||||
|
BACULA_LOGLINE %{BACULA_TIMESTAMP:bts} %{BACULA_HOST:hostname} JobId %{INT:jobid}: (%{BACULA_LOG_MAX_CAPACITY}|%{BACULA_LOG_END_VOLUME}|%{BACULA_LOG_NEW_VOLUME}|%{BACULA_LOG_NEW_LABEL}|%{BACULA_LOG_WROTE_LABEL}|%{BACULA_LOG_NEW_MOUNT}|%{BACULA_LOG_NOOPEN}|%{BACULA_LOG_NOOPENDIR}|%{BACULA_LOG_NOSTAT}|%{BACULA_LOG_NOJOBS}|%{BACULA_LOG_ALL_RECORDS_PRUNED}|%{BACULA_LOG_BEGIN_PRUNE_JOBS}|%{BACULA_LOG_BEGIN_PRUNE_FILES}|%{BACULA_LOG_PRUNED_JOBS}|%{BACULA_LOG_PRUNED_FILES}|%{BACULA_LOG_ENDPRUNE}|%{BACULA_LOG_STARTJOB}|%{BACULA_LOG_STARTRESTORE}|%{BACULA_LOG_USEDEVICE}|%{BACULA_LOG_DIFF_FS}|%{BACULA_LOG_JOBEND}|%{BACULA_LOG_NOPRUNE_JOBS}|%{BACULA_LOG_NOPRUNE_FILES}|%{BACULA_LOG_VOLUME_PREVWRITTEN}|%{BACULA_LOG_READYAPPEND}|%{BACULA_LOG_CANCELLING}|%{BACULA_LOG_MARKCANCEL}|%{BACULA_LOG_CLIENT_RBJ}|%{BACULA_LOG_VSS}|%{BACULA_LOG_MAXSTART}|%{BACULA_LOG_DUPLICATE}|%{BACULA_LOG_NOJOBSTAT}|%{BACULA_LOG_FATAL_CONN}|%{BACULA_LOG_NO_CONNECT}|%{BACULA_LOG_NO_AUTH}|%{BACULA_LOG_NOSUIT}|%{BACULA_LOG_JOB}|%{BACULA_LOG_NOPRIOR})
|
13
config/patterns/bro
Normal file
13
config/patterns/bro
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# https://www.bro.org/sphinx/script-reference/log-files.html
|
||||||
|
|
||||||
|
# http.log
|
||||||
|
BRO_HTTP %{NUMBER:ts}\t%{NOTSPACE:uid}\t%{IP:orig_h}\t%{INT:orig_p}\t%{IP:resp_h}\t%{INT:resp_p}\t%{INT:trans_depth}\t%{GREEDYDATA:method}\t%{GREEDYDATA:domain}\t%{GREEDYDATA:uri}\t%{GREEDYDATA:referrer}\t%{GREEDYDATA:user_agent}\t%{NUMBER:request_body_len}\t%{NUMBER:response_body_len}\t%{GREEDYDATA:status_code}\t%{GREEDYDATA:status_msg}\t%{GREEDYDATA:info_code}\t%{GREEDYDATA:info_msg}\t%{GREEDYDATA:filename}\t%{GREEDYDATA:bro_tags}\t%{GREEDYDATA:username}\t%{GREEDYDATA:password}\t%{GREEDYDATA:proxied}\t%{GREEDYDATA:orig_fuids}\t%{GREEDYDATA:orig_mime_types}\t%{GREEDYDATA:resp_fuids}\t%{GREEDYDATA:resp_mime_types}
|
||||||
|
|
||||||
|
# dns.log
|
||||||
|
BRO_DNS %{NUMBER:ts}\t%{NOTSPACE:uid}\t%{IP:orig_h}\t%{INT:orig_p}\t%{IP:resp_h}\t%{INT:resp_p}\t%{WORD:proto}\t%{INT:trans_id}\t%{GREEDYDATA:query}\t%{GREEDYDATA:qclass}\t%{GREEDYDATA:qclass_name}\t%{GREEDYDATA:qtype}\t%{GREEDYDATA:qtype_name}\t%{GREEDYDATA:rcode}\t%{GREEDYDATA:rcode_name}\t%{GREEDYDATA:AA}\t%{GREEDYDATA:TC}\t%{GREEDYDATA:RD}\t%{GREEDYDATA:RA}\t%{GREEDYDATA:Z}\t%{GREEDYDATA:answers}\t%{GREEDYDATA:TTLs}\t%{GREEDYDATA:rejected}
|
||||||
|
|
||||||
|
# conn.log
|
||||||
|
BRO_CONN %{NUMBER:ts}\t%{NOTSPACE:uid}\t%{IP:orig_h}\t%{INT:orig_p}\t%{IP:resp_h}\t%{INT:resp_p}\t%{WORD:proto}\t%{GREEDYDATA:service}\t%{NUMBER:duration}\t%{NUMBER:orig_bytes}\t%{NUMBER:resp_bytes}\t%{GREEDYDATA:conn_state}\t%{GREEDYDATA:local_orig}\t%{GREEDYDATA:missed_bytes}\t%{GREEDYDATA:history}\t%{GREEDYDATA:orig_pkts}\t%{GREEDYDATA:orig_ip_bytes}\t%{GREEDYDATA:resp_pkts}\t%{GREEDYDATA:resp_ip_bytes}\t%{GREEDYDATA:tunnel_parents}
|
||||||
|
|
||||||
|
# files.log
|
||||||
|
BRO_FILES %{NUMBER:ts}\t%{NOTSPACE:fuid}\t%{IP:tx_hosts}\t%{IP:rx_hosts}\t%{NOTSPACE:conn_uids}\t%{GREEDYDATA:source}\t%{GREEDYDATA:depth}\t%{GREEDYDATA:analyzers}\t%{GREEDYDATA:mime_type}\t%{GREEDYDATA:filename}\t%{GREEDYDATA:duration}\t%{GREEDYDATA:local_orig}\t%{GREEDYDATA:is_orig}\t%{GREEDYDATA:seen_bytes}\t%{GREEDYDATA:total_bytes}\t%{GREEDYDATA:missing_bytes}\t%{GREEDYDATA:overflow_bytes}\t%{GREEDYDATA:timedout}\t%{GREEDYDATA:parent_fuid}\t%{GREEDYDATA:md5}\t%{GREEDYDATA:sha1}\t%{GREEDYDATA:sha256}\t%{GREEDYDATA:extracted}
|
1
config/patterns/cowrie_honeypot
Normal file
1
config/patterns/cowrie_honeypot
Normal file
|
@ -0,0 +1 @@
|
||||||
|
COWRIE_NEW_CO New connection: %{IPV4:source_ip}:[0-9]+ \(%{IPV4:dest_ip}:%{INT:dest_port}\) \[session: %{DATA:telnet_session}\]$
|
12
config/patterns/exim
Normal file
12
config/patterns/exim
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
EXIM_MSGID [0-9A-Za-z]{6}-[0-9A-Za-z]{6}-[0-9A-Za-z]{2}
|
||||||
|
EXIM_FLAGS (<=|[-=>*]>|[*]{2}|==)
|
||||||
|
EXIM_DATE %{YEAR:exim_year}-%{MONTHNUM:exim_month}-%{MONTHDAY:exim_day} %{TIME:exim_time}
|
||||||
|
EXIM_PID \[%{POSINT}\]
|
||||||
|
EXIM_QT ((\d+y)?(\d+w)?(\d+d)?(\d+h)?(\d+m)?(\d+s)?)
|
||||||
|
EXIM_EXCLUDE_TERMS (Message is frozen|(Start|End) queue run| Warning: | retry time not reached | no (IP address|host name) found for (IP address|host) | unexpected disconnection while reading SMTP command | no immediate delivery: |another process is handling this message)
|
||||||
|
EXIM_REMOTE_HOST (H=(%{NOTSPACE:remote_hostname} )?(\(%{NOTSPACE:remote_heloname}\) )?\[%{IP:remote_host}\])
|
||||||
|
EXIM_INTERFACE (I=\[%{IP:exim_interface}\](:%{NUMBER:exim_interface_port}))
|
||||||
|
EXIM_PROTOCOL (P=%{NOTSPACE:protocol})
|
||||||
|
EXIM_MSG_SIZE (S=%{NUMBER:exim_msg_size})
|
||||||
|
EXIM_HEADER_ID (id=%{NOTSPACE:exim_header_id})
|
||||||
|
EXIM_SUBJECT (T=%{QS:exim_subject})
|
86
config/patterns/firewalls
Normal file
86
config/patterns/firewalls
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# NetScreen firewall logs
|
||||||
|
NETSCREENSESSIONLOG %{SYSLOGTIMESTAMP:date} %{IPORHOST:device} %{IPORHOST}: NetScreen device_id=%{WORD:device_id}%{DATA}: start_time=%{QUOTEDSTRING:start_time} duration=%{INT:duration} policy_id=%{INT:policy_id} service=%{DATA:service} proto=%{INT:proto} src zone=%{WORD:src_zone} dst zone=%{WORD:dst_zone} action=%{WORD:action} sent=%{INT:sent} rcvd=%{INT:rcvd} src=%{IPORHOST:src_ip} dst=%{IPORHOST:dst_ip} src_port=%{INT:src_port} dst_port=%{INT:dst_port} src-xlated ip=%{IPORHOST:src_xlated_ip} port=%{INT:src_xlated_port} dst-xlated ip=%{IPORHOST:dst_xlated_ip} port=%{INT:dst_xlated_port} session_id=%{INT:session_id} reason=%{GREEDYDATA:reason}
|
||||||
|
|
||||||
|
#== Cisco ASA ==
|
||||||
|
CISCOTAG [A-Z0-9]+-%{INT}-(?:[A-Z0-9_]+)
|
||||||
|
CISCOTIMESTAMP %{MONTH} +%{MONTHDAY}(?: %{YEAR})? %{TIME}
|
||||||
|
CISCO_TAGGED_SYSLOG ^<%{POSINT:syslog_pri}>%{CISCOTIMESTAMP:timestamp}( %{SYSLOGHOST:sysloghost})? ?: %%{CISCOTAG:ciscotag}:
|
||||||
|
# Common Particles
|
||||||
|
CISCO_ACTION Built|Teardown|Deny|Denied|denied|requested|permitted|denied by ACL|discarded|est-allowed|Dropping|created|deleted
|
||||||
|
CISCO_REASON Duplicate TCP SYN|Failed to locate egress interface|Invalid transport field|No matching connection|DNS Response|DNS Query|(?:%{WORD}\s*)*
|
||||||
|
CISCO_DIRECTION Inbound|inbound|Outbound|outbound
|
||||||
|
CISCO_INTERVAL first hit|%{INT}-second interval
|
||||||
|
CISCO_XLATE_TYPE static|dynamic
|
||||||
|
# ASA-1-104001
|
||||||
|
CISCOFW104001 \((?:Primary|Secondary)\) Switching to ACTIVE - %{GREEDYDATA:switch_reason}
|
||||||
|
# ASA-1-104002
|
||||||
|
CISCOFW104002 \((?:Primary|Secondary)\) Switching to STANDBY - %{GREEDYDATA:switch_reason}
|
||||||
|
# ASA-1-104003
|
||||||
|
CISCOFW104003 \((?:Primary|Secondary)\) Switching to FAILED\.
|
||||||
|
# ASA-1-104004
|
||||||
|
CISCOFW104004 \((?:Primary|Secondary)\) Switching to OK\.
|
||||||
|
# ASA-1-105003
|
||||||
|
CISCOFW105003 \((?:Primary|Secondary)\) Monitoring on [Ii]nterface %{GREEDYDATA:interface_name} waiting
|
||||||
|
# ASA-1-105004
|
||||||
|
CISCOFW105004 \((?:Primary|Secondary)\) Monitoring on [Ii]nterface %{GREEDYDATA:interface_name} normal
|
||||||
|
# ASA-1-105005
|
||||||
|
CISCOFW105005 \((?:Primary|Secondary)\) Lost Failover communications with mate on [Ii]nterface %{GREEDYDATA:interface_name}
|
||||||
|
# ASA-1-105008
|
||||||
|
CISCOFW105008 \((?:Primary|Secondary)\) Testing [Ii]nterface %{GREEDYDATA:interface_name}
|
||||||
|
# ASA-1-105009
|
||||||
|
CISCOFW105009 \((?:Primary|Secondary)\) Testing on [Ii]nterface %{GREEDYDATA:interface_name} (?:Passed|Failed)
|
||||||
|
# ASA-2-106001
|
||||||
|
CISCOFW106001 %{CISCO_DIRECTION:direction} %{WORD:protocol} connection %{CISCO_ACTION:action} from %{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port} flags %{GREEDYDATA:tcp_flags} on interface %{GREEDYDATA:interface}
|
||||||
|
# ASA-2-106006, ASA-2-106007, ASA-2-106010
|
||||||
|
CISCOFW106006_106007_106010 %{CISCO_ACTION:action} %{CISCO_DIRECTION:direction} %{WORD:protocol} (?:from|src) %{IP:src_ip}/%{INT:src_port}(\(%{DATA:src_fwuser}\))? (?:to|dst) %{IP:dst_ip}/%{INT:dst_port}(\(%{DATA:dst_fwuser}\))? (?:on interface %{DATA:interface}|due to %{CISCO_REASON:reason})
|
||||||
|
# ASA-3-106014
|
||||||
|
CISCOFW106014 %{CISCO_ACTION:action} %{CISCO_DIRECTION:direction} %{WORD:protocol} src %{DATA:src_interface}:%{IP:src_ip}(\(%{DATA:src_fwuser}\))? dst %{DATA:dst_interface}:%{IP:dst_ip}(\(%{DATA:dst_fwuser}\))? \(type %{INT:icmp_type}, code %{INT:icmp_code}\)
|
||||||
|
# ASA-6-106015
|
||||||
|
CISCOFW106015 %{CISCO_ACTION:action} %{WORD:protocol} \(%{DATA:policy_id}\) from %{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port} flags %{DATA:tcp_flags} on interface %{GREEDYDATA:interface}
|
||||||
|
# ASA-1-106021
|
||||||
|
CISCOFW106021 %{CISCO_ACTION:action} %{WORD:protocol} reverse path check from %{IP:src_ip} to %{IP:dst_ip} on interface %{GREEDYDATA:interface}
|
||||||
|
# ASA-4-106023
|
||||||
|
CISCOFW106023 %{CISCO_ACTION:action}( protocol)? %{WORD:protocol} src %{DATA:src_interface}:%{DATA:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? dst %{DATA:dst_interface}:%{DATA:dst_ip}(/%{INT:dst_port})?(\(%{DATA:dst_fwuser}\))?( \(type %{INT:icmp_type}, code %{INT:icmp_code}\))? by access-group "?%{DATA:policy_id}"? \[%{DATA:hashcode1}, %{DATA:hashcode2}\]
|
||||||
|
# ASA-4-106100, ASA-4-106102, ASA-4-106103
|
||||||
|
CISCOFW106100_2_3 access-list %{NOTSPACE:policy_id} %{CISCO_ACTION:action} %{WORD:protocol} for user '%{DATA:src_fwuser}' %{DATA:src_interface}/%{IP:src_ip}\(%{INT:src_port}\) -> %{DATA:dst_interface}/%{IP:dst_ip}\(%{INT:dst_port}\) hit-cnt %{INT:hit_count} %{CISCO_INTERVAL:interval} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]
|
||||||
|
# ASA-5-106100
|
||||||
|
CISCOFW106100 access-list %{NOTSPACE:policy_id} %{CISCO_ACTION:action} %{WORD:protocol} %{DATA:src_interface}/%{IP:src_ip}\(%{INT:src_port}\)(\(%{DATA:src_fwuser}\))? -> %{DATA:dst_interface}/%{IP:dst_ip}\(%{INT:dst_port}\)(\(%{DATA:src_fwuser}\))? hit-cnt %{INT:hit_count} %{CISCO_INTERVAL:interval} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]
|
||||||
|
# ASA-6-110002
|
||||||
|
CISCOFW110002 %{CISCO_REASON:reason} for %{WORD:protocol} from %{DATA:src_interface}:%{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port}
|
||||||
|
# ASA-6-302010
|
||||||
|
CISCOFW302010 %{INT:connection_count} in use, %{INT:connection_count_max} most used
|
||||||
|
# ASA-6-302013, ASA-6-302014, ASA-6-302015, ASA-6-302016
|
||||||
|
CISCOFW302013_302014_302015_302016 %{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IP:src_ip}/%{INT:src_port}( \(%{IP:src_mapped_ip}/%{INT:src_mapped_port}\))?(\(%{DATA:src_fwuser}\))? to %{DATA:dst_interface}:%{IP:dst_ip}/%{INT:dst_port}( \(%{IP:dst_mapped_ip}/%{INT:dst_mapped_port}\))?(\(%{DATA:dst_fwuser}\))?( duration %{TIME:duration} bytes %{INT:bytes})?(?: %{CISCO_REASON:reason})?( \(%{DATA:user}\))?
|
||||||
|
# ASA-6-302020, ASA-6-302021
|
||||||
|
CISCOFW302020_302021 %{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection for faddr %{IP:dst_ip}/%{INT:icmp_seq_num}(?:\(%{DATA:fwuser}\))? gaddr %{IP:src_xlated_ip}/%{INT:icmp_code_xlated} laddr %{IP:src_ip}/%{INT:icmp_code}( \(%{DATA:user}\))?
|
||||||
|
# ASA-6-305011
|
||||||
|
CISCOFW305011 %{CISCO_ACTION:action} %{CISCO_XLATE_TYPE:xlate_type} %{WORD:protocol} translation from %{DATA:src_interface}:%{IP:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? to %{DATA:src_xlated_interface}:%{IP:src_xlated_ip}/%{DATA:src_xlated_port}
|
||||||
|
# ASA-3-313001, ASA-3-313004, ASA-3-313008
|
||||||
|
CISCOFW313001_313004_313008 %{CISCO_ACTION:action} %{WORD:protocol} type=%{INT:icmp_type}, code=%{INT:icmp_code} from %{IP:src_ip} on interface %{DATA:interface}( to %{IP:dst_ip})?
|
||||||
|
# ASA-4-313005
|
||||||
|
CISCOFW313005 %{CISCO_REASON:reason} for %{WORD:protocol} error message: %{WORD:err_protocol} src %{DATA:err_src_interface}:%{IP:err_src_ip}(\(%{DATA:err_src_fwuser}\))? dst %{DATA:err_dst_interface}:%{IP:err_dst_ip}(\(%{DATA:err_dst_fwuser}\))? \(type %{INT:err_icmp_type}, code %{INT:err_icmp_code}\) on %{DATA:interface} interface\. Original IP payload: %{WORD:protocol} src %{IP:orig_src_ip}/%{INT:orig_src_port}(\(%{DATA:orig_src_fwuser}\))? dst %{IP:orig_dst_ip}/%{INT:orig_dst_port}(\(%{DATA:orig_dst_fwuser}\))?
|
||||||
|
# ASA-5-321001
|
||||||
|
CISCOFW321001 Resource '%{WORD:resource_name}' limit of %{POSINT:resource_limit} reached for system
|
||||||
|
# ASA-4-402117
|
||||||
|
CISCOFW402117 %{WORD:protocol}: Received a non-IPSec packet \(protocol= %{WORD:orig_protocol}\) from %{IP:src_ip} to %{IP:dst_ip}
|
||||||
|
# ASA-4-402119
|
||||||
|
CISCOFW402119 %{WORD:protocol}: Received an %{WORD:orig_protocol} packet \(SPI= %{DATA:spi}, sequence number= %{DATA:seq_num}\) from %{IP:src_ip} \(user= %{DATA:user}\) to %{IP:dst_ip} that failed anti-replay checking
|
||||||
|
# ASA-4-419001
|
||||||
|
CISCOFW419001 %{CISCO_ACTION:action} %{WORD:protocol} packet from %{DATA:src_interface}:%{IP:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IP:dst_ip}/%{INT:dst_port}, reason: %{GREEDYDATA:reason}
|
||||||
|
# ASA-4-419002
|
||||||
|
CISCOFW419002 %{CISCO_REASON:reason} from %{DATA:src_interface}:%{IP:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IP:dst_ip}/%{INT:dst_port} with different initial sequence number
|
||||||
|
# ASA-4-500004
|
||||||
|
CISCOFW500004 %{CISCO_REASON:reason} for protocol=%{WORD:protocol}, from %{IP:src_ip}/%{INT:src_port} to %{IP:dst_ip}/%{INT:dst_port}
|
||||||
|
# ASA-6-602303, ASA-6-602304
|
||||||
|
CISCOFW602303_602304 %{WORD:protocol}: An %{CISCO_DIRECTION:direction} %{GREEDYDATA:tunnel_type} SA \(SPI= %{DATA:spi}\) between %{IP:src_ip} and %{IP:dst_ip} \(user= %{DATA:user}\) has been %{CISCO_ACTION:action}
|
||||||
|
# ASA-7-710001, ASA-7-710002, ASA-7-710003, ASA-7-710005, ASA-7-710006
|
||||||
|
CISCOFW710001_710002_710003_710005_710006 %{WORD:protocol} (?:request|access) %{CISCO_ACTION:action} from %{IP:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IP:dst_ip}/%{INT:dst_port}
|
||||||
|
# ASA-6-713172
|
||||||
|
CISCOFW713172 Group = %{GREEDYDATA:group}, IP = %{IP:src_ip}, Automatic NAT Detection Status:\s+Remote end\s*%{DATA:is_remote_natted}\s*behind a NAT device\s+This\s+end\s*%{DATA:is_local_natted}\s*behind a NAT device
|
||||||
|
# ASA-4-733100
|
||||||
|
CISCOFW733100 \[\s*%{DATA:drop_type}\s*\] drop %{DATA:drop_rate_id} exceeded. Current burst rate is %{INT:drop_rate_current_burst} per second, max configured rate is %{INT:drop_rate_max_burst}; Current average rate is %{INT:drop_rate_current_avg} per second, max configured rate is %{INT:drop_rate_max_avg}; Cumulative total count is %{INT:drop_total_count}
|
||||||
|
#== End Cisco ASA ==
|
||||||
|
|
||||||
|
# Shorewall firewall logs
|
||||||
|
SHOREWALL (%{SYSLOGTIMESTAMP:timestamp}) (%{WORD:nf_host}) kernel:.*Shorewall:(%{WORD:nf_action1})?:(%{WORD:nf_action2})?.*IN=(%{USERNAME:nf_in_interface})?.*(OUT= *MAC=(%{COMMONMAC:nf_dst_mac}):(%{COMMONMAC:nf_src_mac})?|OUT=%{USERNAME:nf_out_interface}).*SRC=(%{IPV4:nf_src_ip}).*DST=(%{IPV4:nf_dst_ip}).*LEN=(%{WORD:nf_len}).*?TOS=(%{WORD:nf_tos}).*?PREC=(%{WORD:nf_prec}).*?TTL=(%{INT:nf_ttl}).*?ID=(%{INT:nf_id}).*?PROTO=(%{WORD:nf_protocol}).*?SPT=(%{INT:nf_src_port}?.*DPT=%{INT:nf_dst_port}?.*)
|
||||||
|
#== End Shorewall
|
39
config/patterns/haproxy
Normal file
39
config/patterns/haproxy
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
## These patterns were tested w/ haproxy-1.4.15
|
||||||
|
|
||||||
|
## Documentation of the haproxy log formats can be found at the following links:
|
||||||
|
## http://code.google.com/p/haproxy-docs/wiki/HTTPLogFormat
|
||||||
|
## http://code.google.com/p/haproxy-docs/wiki/TCPLogFormat
|
||||||
|
|
||||||
|
HAPROXYTIME %{HOUR:haproxy_hour}:%{MINUTE:haproxy_minute}(?::%{SECOND:haproxy_second})
|
||||||
|
HAPROXYDATE %{MONTHDAY:haproxy_monthday}/%{MONTH:haproxy_month}/%{YEAR:haproxy_year}:%{HAPROXYTIME:haproxy_time}.%{INT:haproxy_milliseconds}
|
||||||
|
|
||||||
|
# Override these default patterns to parse out what is captured in your haproxy.cfg
|
||||||
|
HAPROXYCAPTUREDREQUESTHEADERS %{DATA:captured_request_headers}
|
||||||
|
HAPROXYCAPTUREDRESPONSEHEADERS %{DATA:captured_response_headers}
|
||||||
|
|
||||||
|
# Example:
|
||||||
|
# These haproxy config lines will add data to the logs that are captured
|
||||||
|
# by the patterns below. Place them in your custom patterns directory to
|
||||||
|
# override the defaults.
|
||||||
|
#
|
||||||
|
# capture request header Host len 40
|
||||||
|
# capture request header X-Forwarded-For len 50
|
||||||
|
# capture request header Accept-Language len 50
|
||||||
|
# capture request header Referer len 200
|
||||||
|
# capture request header User-Agent len 200
|
||||||
|
#
|
||||||
|
# capture response header Content-Type len 30
|
||||||
|
# capture response header Content-Encoding len 10
|
||||||
|
# capture response header Cache-Control len 200
|
||||||
|
# capture response header Last-Modified len 200
|
||||||
|
#
|
||||||
|
# HAPROXYCAPTUREDREQUESTHEADERS %{DATA:request_header_host}\|%{DATA:request_header_x_forwarded_for}\|%{DATA:request_header_accept_language}\|%{DATA:request_header_referer}\|%{DATA:request_header_user_agent}
|
||||||
|
# HAPROXYCAPTUREDRESPONSEHEADERS %{DATA:response_header_content_type}\|%{DATA:response_header_content_encoding}\|%{DATA:response_header_cache_control}\|%{DATA:response_header_last_modified}
|
||||||
|
|
||||||
|
# parse a haproxy 'httplog' line
|
||||||
|
HAPROXYHTTPBASE %{IP:client_ip}:%{INT:client_port} \[%{HAPROXYDATE:accept_date}\] %{NOTSPACE:frontend_name} %{NOTSPACE:backend_name}/%{NOTSPACE:server_name} %{INT:time_request}/%{INT:time_queue}/%{INT:time_backend_connect}/%{INT:time_backend_response}/%{NOTSPACE:time_duration} %{INT:http_status_code} %{NOTSPACE:bytes_read} %{DATA:captured_request_cookie} %{DATA:captured_response_cookie} %{NOTSPACE:termination_state} %{INT:actconn}/%{INT:feconn}/%{INT:beconn}/%{INT:srvconn}/%{NOTSPACE:retries} %{INT:srv_queue}/%{INT:backend_queue} (\{%{HAPROXYCAPTUREDREQUESTHEADERS}\})?( )?(\{%{HAPROXYCAPTUREDRESPONSEHEADERS}\})?( )?"(<BADREQ>|(%{WORD:http_verb} (%{URIPROTO:http_proto}://)?(?:%{USER:http_user}(?::[^@]*)?@)?(?:%{URIHOST:http_host})?(?:%{URIPATHPARAM:http_request})?( HTTP/%{NUMBER:http_version})?))?"
|
||||||
|
|
||||||
|
HAPROXYHTTP (?:%{SYSLOGTIMESTAMP:syslog_timestamp}|%{TIMESTAMP_ISO8601:timestamp8601}) %{IPORHOST:syslog_server} %{SYSLOGPROG}: %{HAPROXYHTTPBASE}
|
||||||
|
|
||||||
|
# parse a haproxy 'tcplog' line
|
||||||
|
HAPROXYTCP (?:%{SYSLOGTIMESTAMP:syslog_timestamp}|%{TIMESTAMP_ISO8601:timestamp8601}) %{IPORHOST:syslog_server} %{SYSLOGPROG}: %{IP:client_ip}:%{INT:client_port} \[%{HAPROXYDATE:accept_date}\] %{NOTSPACE:frontend_name} %{NOTSPACE:backend_name}/%{NOTSPACE:server_name} %{INT:time_queue}/%{INT:time_backend_connect}/%{NOTSPACE:time_duration} %{NOTSPACE:bytes_read} %{NOTSPACE:termination_state} %{INT:actconn}/%{INT:feconn}/%{INT:beconn}/%{INT:srvconn}/%{NOTSPACE:retries} %{INT:srv_queue}/%{INT:backend_queue}
|
20
config/patterns/java
Normal file
20
config/patterns/java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
JAVACLASS (?:[a-zA-Z$_][a-zA-Z$_0-9]*\.)*[a-zA-Z$_][a-zA-Z$_0-9]*
|
||||||
|
#Space is an allowed character to match special cases like 'Native Method' or 'Unknown Source'
|
||||||
|
JAVAFILE (?:[A-Za-z0-9_. -]+)
|
||||||
|
#Allow special <init> method
|
||||||
|
JAVAMETHOD (?:(<init>)|[a-zA-Z$_][a-zA-Z$_0-9]*)
|
||||||
|
#Line number is optional in special cases 'Native method' or 'Unknown source'
|
||||||
|
JAVASTACKTRACEPART %{SPACE}at %{JAVACLASS:class}\.%{JAVAMETHOD:method}\(%{JAVAFILE:file}(?::%{NUMBER:line})?\)
|
||||||
|
# Java Logs
|
||||||
|
JAVATHREAD (?:[A-Z]{2}-Processor[\d]+)
|
||||||
|
##JAVACLASS (?:[a-zA-Z0-9-]+\.)+[A-Za-z0-9$]+
|
||||||
|
##JAVAFILE (?:[A-Za-z0-9_.-]+)
|
||||||
|
##JAVASTACKTRACEPART at %{JAVACLASS:class}\.%{WORD:method}\(%{JAVAFILE:file}:%{NUMBER:line}\)
|
||||||
|
JAVALOGMESSAGE (.*)
|
||||||
|
# MMM dd, yyyy HH:mm:ss eg: Jan 9, 2014 7:13:13 AM
|
||||||
|
CATALINA_DATESTAMP %{MONTH} %{MONTHDAY}, 20%{YEAR} %{HOUR}:?%{MINUTE}(?::?%{SECOND}) (?:AM|PM)
|
||||||
|
# yyyy-MM-dd HH:mm:ss,SSS ZZZ eg: 2014-01-09 17:32:25,527 -0800
|
||||||
|
TOMCAT_DATESTAMP 20%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:?%{MINUTE}(?::?%{SECOND}) %{ISO8601_TIMEZONE}
|
||||||
|
CATALINALOG %{CATALINA_DATESTAMP:timestamp} %{JAVACLASS:class} %{JAVALOGMESSAGE:logmessage}
|
||||||
|
# 2014-01-09 20:03:28,269 -0800 | ERROR | com.example.service.ExampleService - something compeletely unexpected happened...
|
||||||
|
TOMCATLOG %{TOMCAT_DATESTAMP:timestamp} \| %{LOGLEVEL:level} \| %{JAVACLASS:class} - %{JAVALOGMESSAGE:logmessage}
|
8
config/patterns/junos
Normal file
8
config/patterns/junos
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# JUNOS 11.4 RT_FLOW patterns
|
||||||
|
RT_FLOW_EVENT (RT_FLOW_SESSION_CREATE|RT_FLOW_SESSION_CLOSE|RT_FLOW_SESSION_DENY)
|
||||||
|
|
||||||
|
RT_FLOW1 %{RT_FLOW_EVENT:event}: %{GREEDYDATA:close-reason}: %{IP:src-ip}/%{INT:src-port}->%{IP:dst-ip}/%{INT:dst-port} %{DATA:service} %{IP:nat-src-ip}/%{INT:nat-src-port}->%{IP:nat-dst-ip}/%{INT:nat-dst-port} %{DATA:src-nat-rule-name} %{DATA:dst-nat-rule-name} %{INT:protocol-id} %{DATA:policy-name} %{DATA:from-zone} %{DATA:to-zone} %{INT:session-id} \d+\(%{DATA:sent}\) \d+\(%{DATA:received}\) %{INT:elapsed-time} .*
|
||||||
|
|
||||||
|
RT_FLOW2 %{RT_FLOW_EVENT:event}: session created %{IP:src-ip}/%{INT:src-port}->%{IP:dst-ip}/%{INT:dst-port} %{DATA:service} %{IP:nat-src-ip}/%{INT:nat-src-port}->%{IP:nat-dst-ip}/%{INT:nat-dst-port} %{DATA:src-nat-rule-name} %{DATA:dst-nat-rule-name} %{INT:protocol-id} %{DATA:policy-name} %{DATA:from-zone} %{DATA:to-zone} %{INT:session-id} .*
|
||||||
|
|
||||||
|
RT_FLOW3 %{RT_FLOW_EVENT:event}: session denied %{IP:src-ip}/%{INT:src-port}->%{IP:dst-ip}/%{INT:dst-port} %{DATA:service} %{INT:protocol-id}\(\d\) %{DATA:policy-name} %{DATA:from-zone} %{DATA:to-zone} .*
|
16
config/patterns/linux-syslog
Normal file
16
config/patterns/linux-syslog
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
SYSLOG5424PRINTASCII [!-~]+
|
||||||
|
|
||||||
|
SYSLOGBASE2 (?:%{SYSLOGTIMESTAMP:timestamp}|%{TIMESTAMP_ISO8601:timestamp8601}) (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource}+(?: %{SYSLOGPROG}:|)
|
||||||
|
SYSLOGPAMSESSION %{SYSLOGBASE} %{GREEDYDATA:message}%{WORD:pam_module}\(%{DATA:pam_caller}\): session %{WORD:pam_session_state} for user %{USERNAME:username}(?: by %{GREEDYDATA:pam_by})?
|
||||||
|
|
||||||
|
CRON_ACTION [A-Z ]+
|
||||||
|
CRONLOG %{SYSLOGBASE} \(%{USER:user}\) %{CRON_ACTION:action} \(%{DATA:message}\)
|
||||||
|
|
||||||
|
SYSLOGLINE %{SYSLOGBASE2} %{GREEDYDATA:message}
|
||||||
|
|
||||||
|
# IETF 5424 syslog(8) format (see http://www.rfc-editor.org/info/rfc5424)
|
||||||
|
SYSLOG5424PRI <%{NONNEGINT:syslog5424_pri}>
|
||||||
|
SYSLOG5424SD \[%{DATA}\]+
|
||||||
|
SYSLOG5424BASE %{SYSLOG5424PRI}%{NONNEGINT:syslog5424_ver} +(?:%{TIMESTAMP_ISO8601:syslog5424_ts}|-) +(?:%{HOSTNAME:syslog5424_host}|-) +(-|%{SYSLOG5424PRINTASCII:syslog5424_app}) +(-|%{SYSLOG5424PRINTASCII:syslog5424_proc}) +(-|%{SYSLOG5424PRINTASCII:syslog5424_msgid}) +(?:%{SYSLOG5424SD:syslog5424_sd}|-|)
|
||||||
|
|
||||||
|
SYSLOG5424LINE %{SYSLOG5424BASE} +%{GREEDYDATA:syslog5424_msg}
|
4
config/patterns/mcollective
Normal file
4
config/patterns/mcollective
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Remember, these can be multi-line events.
|
||||||
|
MCOLLECTIVE ., \[%{TIMESTAMP_ISO8601:timestamp} #%{POSINT:pid}\]%{SPACE}%{LOGLEVEL:event_level}
|
||||||
|
|
||||||
|
MCOLLECTIVEAUDIT %{TIMESTAMP_ISO8601:timestamp}:
|
18
config/patterns/modsecurity
Normal file
18
config/patterns/modsecurity
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
APACHEERRORTIME %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR}
|
||||||
|
APACHEERRORPREFIX \[%{APACHEERRORTIME:timestamp}\] \[%{NOTSPACE:apacheseverity}\] (\[pid %{INT}:tid %{INT}\] )?\[client %{IPORHOST:sourcehost}(:%{INT:source_port})?\] (\[client %{IPORHOST}\])?
|
||||||
|
GENERICAPACHEERROR %{APACHEERRORPREFIX} %{GREEDYDATA:message}
|
||||||
|
MODSECPREFIX %{APACHEERRORPREFIX} ModSecurity: %{NOTSPACE:modsecseverity}\. %{GREEDYDATA:modsecmessage}
|
||||||
|
MODSECRULEFILE \[file %{QUOTEDSTRING:rulefile}\]
|
||||||
|
MODSECRULELINE \[line %{QUOTEDSTRING:ruleline}\]
|
||||||
|
MODSECMATCHOFFSET \[offset %{QUOTEDSTRING:matchoffset}\]
|
||||||
|
MODSECRULEID \[id %{QUOTEDSTRING:ruleid}\]
|
||||||
|
MODSECRULEREV \[rev %{QUOTEDSTRING:rulerev}\]
|
||||||
|
MODSECRULEMSG \[msg %{QUOTEDSTRING:rulemessage}\]
|
||||||
|
MODSECRULEDATA \[data %{QUOTEDSTRING:ruledata}\]
|
||||||
|
MODSECRULESEVERITY \[severity ["']%{WORD:ruleseverity}["']\]
|
||||||
|
MODSECRULEVERS \[ver "[^"]+"\]
|
||||||
|
MODSECRULETAGS (?:\[tag %{QUOTEDSTRING:ruletag0}\] )?(?:\[tag %{QUOTEDSTRING:ruletag1}\] )?(?:\[tag %{QUOTEDSTRING:ruletag2}\] )?(?:\[tag %{QUOTEDSTRING:ruletag3}\] )?(?:\[tag %{QUOTEDSTRING:ruletag4}\] )?(?:\[tag %{QUOTEDSTRING:ruletag5}\] )?(?:\[tag %{QUOTEDSTRING:ruletag6}\] )?(?:\[tag %{QUOTEDSTRING:ruletag7}\] )?(?:\[tag %{QUOTEDSTRING:ruletag8}\] )?(?:\[tag %{QUOTEDSTRING:ruletag9}\] )?(?:\[tag %{QUOTEDSTRING}\] )*
|
||||||
|
MODSECHOSTNAME \[hostname ['"]%{DATA:targethost}["']\]
|
||||||
|
MODSECURI \[uri ["']%{DATA:targeturi}["']\]
|
||||||
|
MODSECUID \[unique_id %{QUOTEDSTRING:uniqueid}\]
|
||||||
|
MODSECAPACHEERROR %{MODSECPREFIX} %{MODSECRULEFILE} %{MODSECRULELINE} (?:%{MODSECMATCHOFFSET} )?(?:%{MODSECRULEID} )?(?:%{MODSECRULEREV} )?(?:%{MODSECRULEMSG} )?(?:%{MODSECRULEDATA} )?(?:%{MODSECRULESEVERITY} )?(?:%{MODSECRULEVERS} )?%{MODSECRULETAGS}%{MODSECHOSTNAME} %{MODSECURI} %{MODSECUID}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue