234 行
8.5 KiB
YAML
234 行
8.5 KiB
YAML
apiVersion: helm.cattle.io/v1
|
|
kind: HelmChart
|
|
metadata:
|
|
name: crowdsec
|
|
namespace: infra-net
|
|
spec:
|
|
repo: https://crowdsecurity.github.io/helm-charts
|
|
chart: crowdsec
|
|
targetNamespace: infra-net
|
|
version: 0.19.5
|
|
valuesContent: |-
|
|
container_runtime: containerd
|
|
image:
|
|
tag: v1.6.11
|
|
agent:
|
|
affinity:
|
|
podAffinity:
|
|
preferredDuringSchedulingIgnoredDuringExecution:
|
|
- weight: 100
|
|
podAffinityTerm:
|
|
labelSelector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: loki
|
|
topologyKey: kubernetes.io/hostname
|
|
namespaceSelector: {}
|
|
isDeployment: true
|
|
additionalAcquisition:
|
|
- source: loki
|
|
log_level: info
|
|
url: http://loki.infra-monitor:3100/
|
|
limit: 1000
|
|
query: |
|
|
{job="infra-net/ingress-nginx"}
|
|
labels:
|
|
type: nginx
|
|
env:
|
|
- name: COLLECTIONS
|
|
value: "crowdsecurity/base-http-scenarios crowdsecurity/http-dos"
|
|
- name: SCENARIOS
|
|
value: "crowdsecurity/nginx-req-limit-exceeded"
|
|
persistentVolume:
|
|
config:
|
|
enabled: false
|
|
appsec:
|
|
affinity:
|
|
nodeAffinity:
|
|
preferredDuringSchedulingIgnoredDuringExecution:
|
|
- weight: 1
|
|
preference:
|
|
matchExpressions:
|
|
- key: topology.kubernetes.io/region
|
|
operator: In
|
|
values:
|
|
- cn-hk
|
|
enabled: false
|
|
acquisitions:
|
|
- source: appsec
|
|
listen_addr: "0.0.0.0:7422"
|
|
path: /
|
|
appsec_config: crowdsecurity/crs-vpatch
|
|
labels:
|
|
type: appsec
|
|
configs:
|
|
mycustom-appsec-config.yaml: |
|
|
name: crowdsecurity/crs-vpatch
|
|
default_remediation: ban
|
|
#log_level: debug
|
|
outofband_rules:
|
|
- crowdsecurity/crs
|
|
inband_rules:
|
|
- crowdsecurity/base-config
|
|
- crowdsecurity/vpatch-*
|
|
env:
|
|
- name: COLLECTIONS
|
|
value: "crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-crs"
|
|
lapi:
|
|
affinity:
|
|
nodeAffinity:
|
|
preferredDuringSchedulingIgnoredDuringExecution:
|
|
- weight: 1
|
|
preference:
|
|
matchExpressions:
|
|
- key: topology.kubernetes.io/region
|
|
operator: In
|
|
values:
|
|
- cn-hk
|
|
resources:
|
|
requests:
|
|
cpu: 150m
|
|
memory: 100Mi
|
|
persistentVolume:
|
|
config:
|
|
enabled: false
|
|
data:
|
|
enabled: false
|
|
config:
|
|
# api config.yaml配置
|
|
config.yaml.local: |
|
|
db_config:
|
|
type: postgresql
|
|
host: cnpg17-cluster-hk-rw.infra-data
|
|
port: 5432
|
|
db_name: crowdsec
|
|
user: app
|
|
password: FybaFtf6NV5jnxhj5bOPpHbO6KypZeHiyiskgAWkM5nioW2j82HtCf6GnW9xVKjE
|
|
sslmode: require
|
|
api:
|
|
server:
|
|
auto_registration:
|
|
enabled: true
|
|
token: "${REGISTRATION_TOKEN}"
|
|
allowed_ranges:
|
|
- "127.0.0.1/32"
|
|
- "192.168.0.0/16"
|
|
- "172.16.0.0/12"
|
|
- "10.0.0.0/8"
|
|
# api profiles.yaml配置
|
|
profiles.yaml: |
|
|
name: captcha_remediation
|
|
filters:
|
|
# 规则过滤条件 1.范围为Ip 2.触发场景为http或nginx 3.24小时内决策次数小于等于3
|
|
- Alert.Remediation == true && Alert.GetScope() == "Ip" &&
|
|
(Alert.GetScenario() contains "http" || Alert.GetScenario() contains "nginx") &&
|
|
GetDecisionsSinceCount(Alert.GetValue(), "24h") <= 3
|
|
decisions:
|
|
- type: captcha
|
|
duration: 4h
|
|
on_success: break
|
|
---
|
|
name: default_ip_remediation
|
|
filters:
|
|
- Alert.Remediation == true && Alert.GetScope() == "Ip"
|
|
decisions:
|
|
- type: ban
|
|
duration: 4h
|
|
on_success: break
|
|
---
|
|
name: default_range_remediation
|
|
filters:
|
|
- Alert.Remediation == true && Alert.GetScope() == "Range"
|
|
decisions:
|
|
- type: ban
|
|
duration: 4h
|
|
on_success: break
|
|
# agent parsers 配置
|
|
parsers:
|
|
s01-parse:
|
|
# 新增nginx json日志解析
|
|
nginx-logs.yaml: |
|
|
filter: "evt.Parsed.program startsWith 'nginx'"
|
|
onsuccess: next_stage
|
|
name: crowdsecurity/nginx-logs
|
|
description: "Parse nginx access and error logs"
|
|
pattern_syntax:
|
|
NGCUSTOMURIPATH: "(?:/[A-Za-z0-9$.+!*'\\(\\)\\{\\},~:;=@\\#%&_\\-]*)+"
|
|
NGCUSTOMURIPATHPARAM: '%{NGCUSTOMURIPATH}(?:%{URIPARAM})?'
|
|
nodes:
|
|
# nginx access logs
|
|
- filter: TrimSpace(evt.Parsed.message) startsWith "{" && UnmarshalJSON(evt.Parsed.message, evt.Unmarshaled, "nginx") in ["", nil]
|
|
statics:
|
|
- meta: service
|
|
value: http
|
|
- meta: log_type
|
|
value: http_access-log
|
|
- target: evt.StrTime
|
|
expression: evt.Unmarshaled.nginx.time_local
|
|
- meta: source_ip
|
|
expression: evt.Unmarshaled.nginx.remote_addr
|
|
- meta: http_status
|
|
expression: evt.Unmarshaled.nginx.status
|
|
- meta: http_path
|
|
expression: evt.Unmarshaled.nginx.request_uri
|
|
- meta: http_verb
|
|
expression: evt.Unmarshaled.nginx.request_method
|
|
- meta: http_user_agent
|
|
expression: evt.Unmarshaled.nginx.http_user_agent
|
|
- meta: target_fqdn
|
|
expression: evt.Unmarshaled.nginx.server_name
|
|
# nginx error logs
|
|
- grok:
|
|
pattern: '(%{IPORHOST:target_fqdn} )?%{NGINXERRTIME:time} \[%{LOGLEVEL:loglevel}\] %{NONNEGINT:pid}#%{NONNEGINT:tid}: (\*%{NONNEGINT:cid} )?%{GREEDYDATA:message}, client: %{IPORHOST:remote_addr}, server: %{DATA:target_fqdn}, request: "%{WORD:verb} ([^/]+)?%{NGCUSTOMURIPATHPARAM:request}( HTTP/%{NUMBER:http_version})?", host: "%{IPORHOST}(:%{NONNEGINT})?"'
|
|
apply_on: message
|
|
statics:
|
|
- meta: service
|
|
value: http
|
|
- meta: log_type
|
|
value: http_error-log
|
|
- target: evt.StrTime
|
|
expression: evt.Parsed.time
|
|
- meta: source_ip
|
|
expression: evt.Parsed.remote_addr
|
|
- meta: http_status
|
|
expression: evt.Parsed.status
|
|
- meta: http_path
|
|
expression: evt.Parsed.request
|
|
- meta: http_verb
|
|
expression: evt.Parsed.verb
|
|
- meta: http_user_agent
|
|
expression: evt.Parsed.http_user_agent
|
|
- meta: target_fqdn
|
|
expression: evt.Parsed.target_fqdn
|
|
pattern_syntax:
|
|
NO_DOUBLE_QUOTE: '[^"]+'
|
|
onsuccess: next_stage
|
|
nodes:
|
|
- filter: "evt.Parsed.message contains 'was not found in'"
|
|
pattern_syntax:
|
|
USER_NOT_FOUND: 'user "%{NO_DOUBLE_QUOTE:username}" was not found in "%{NO_DOUBLE_QUOTE}"'
|
|
grok:
|
|
pattern: '%{USER_NOT_FOUND}'
|
|
apply_on: message
|
|
statics:
|
|
- meta: sub_type
|
|
value: "auth_fail"
|
|
- meta: username
|
|
expression: evt.Parsed.username
|
|
- filter: "evt.Parsed.message contains 'password mismatch'"
|
|
pattern_syntax:
|
|
PASSWORD_MISMATCH: 'user "%{NO_DOUBLE_QUOTE:username}": password mismatch'
|
|
grok:
|
|
pattern: '%{PASSWORD_MISMATCH}'
|
|
apply_on: message
|
|
statics:
|
|
- meta: sub_type
|
|
value: "auth_fail"
|
|
- meta: username
|
|
expression: evt.Parsed.username
|
|
- filter: "evt.Parsed.message contains 'limiting requests, excess'"
|
|
statics:
|
|
- meta: sub_type
|
|
value: "req_limit_exceeded"
|
|
|
|
|