mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-12 12:55:53 +02:00
crowdsec: allow -t to work if using appsec and allowlists (#3484)
This commit is contained in:
parent
0bdb1f7f27
commit
c5f5896625
5 changed files with 60 additions and 31 deletions
|
@ -63,7 +63,6 @@ type AppsecSource struct {
|
||||||
lapiURL string
|
lapiURL string
|
||||||
AuthCache AuthCache
|
AuthCache AuthCache
|
||||||
AppsecRunners []AppsecRunner // one for each go-routine
|
AppsecRunners []AppsecRunner // one for each go-routine
|
||||||
apiClient *apiclient.ApiClient
|
|
||||||
appsecAllowlistClient *allowlists.AppsecAllowlist
|
appsecAllowlistClient *allowlists.AppsecAllowlist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,12 +225,7 @@ func (w *AppsecSource) Configure(yamlConfig []byte, logger *log.Entry, metricsLe
|
||||||
|
|
||||||
w.AppsecRunners = make([]AppsecRunner, w.config.Routines)
|
w.AppsecRunners = make([]AppsecRunner, w.config.Routines)
|
||||||
|
|
||||||
w.apiClient, err = apiclient.GetLAPIClient()
|
w.appsecAllowlistClient = allowlists.NewAppsecAllowlist(w.logger)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get authenticated LAPI client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.appsecAllowlistClient = allowlists.NewAppsecAllowlist(w.apiClient, w.logger)
|
|
||||||
|
|
||||||
for nbRoutine := range w.config.Routines {
|
for nbRoutine := range w.config.Routines {
|
||||||
appsecRunnerUUID := uuid.New().String()
|
appsecRunnerUUID := uuid.New().String()
|
||||||
|
@ -282,7 +276,16 @@ func (w *AppsecSource) OneShotAcquisition(_ context.Context, _ chan types.Event,
|
||||||
func (w *AppsecSource) StreamingAcquisition(ctx context.Context, out chan types.Event, t *tomb.Tomb) error {
|
func (w *AppsecSource) StreamingAcquisition(ctx context.Context, out chan types.Event, t *tomb.Tomb) error {
|
||||||
w.outChan = out
|
w.outChan = out
|
||||||
|
|
||||||
w.appsecAllowlistClient.StartRefresh(t)
|
apiClient, err := apiclient.GetLAPIClient()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get authenticated LAPI client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.appsecAllowlistClient.Start(ctx, apiClient)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch allowlists: %w", err)
|
||||||
|
}
|
||||||
|
w.appsecAllowlistClient.StartRefresh(ctx, t)
|
||||||
|
|
||||||
t.Go(func() error {
|
t.Go(func() error {
|
||||||
defer trace.CatchPanic("crowdsec/acquis/appsec/live")
|
defer trace.CatchPanic("crowdsec/acquis/appsec/live")
|
||||||
|
|
|
@ -146,10 +146,9 @@ func loadAppSecEngine(test appsecRuleTest, t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
allowlistClient := allowlists.NewAppsecAllowlist(client, logger)
|
allowlistClient := allowlists.NewAppsecAllowlist(logger)
|
||||||
// In real life, allowlists updater is started by the acquisition
|
|
||||||
// Do it manually here as we are simulating the appsec itself
|
err = allowlistClient.Start(t.Context(), client)
|
||||||
err = allowlistClient.FetchAllowlists()
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
runner := AppsecRunner{
|
runner := AppsecRunner{
|
||||||
inChan: InChan,
|
inChan: InChan,
|
||||||
|
|
|
@ -36,25 +36,26 @@ type AppsecAllowlist struct {
|
||||||
tomb *tomb.Tomb
|
tomb *tomb.Tomb
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAppsecAllowlist(client *apiclient.ApiClient, logger *log.Entry) *AppsecAllowlist {
|
func NewAppsecAllowlist(logger *log.Entry) *AppsecAllowlist {
|
||||||
a := &AppsecAllowlist{
|
a := &AppsecAllowlist{
|
||||||
LAPIClient: client,
|
|
||||||
logger: logger.WithField("component", "appsec-allowlist"),
|
logger: logger.WithField("component", "appsec-allowlist"),
|
||||||
ips: []ipAllowlist{},
|
ips: []ipAllowlist{},
|
||||||
ranges: []rangeAllowlist{},
|
ranges: []rangeAllowlist{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.FetchAllowlists(); err != nil {
|
|
||||||
a.logger.Errorf("failed to fetch allowlists: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppsecAllowlist) FetchAllowlists() error {
|
func (a *AppsecAllowlist) Start(ctx context.Context, client *apiclient.ApiClient) error {
|
||||||
|
a.LAPIClient = client
|
||||||
|
err := a.FetchAllowlists(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppsecAllowlist) FetchAllowlists(ctx context.Context) error {
|
||||||
a.logger.Debug("fetching allowlists")
|
a.logger.Debug("fetching allowlists")
|
||||||
|
|
||||||
allowlists, _, err := a.LAPIClient.Allowlists.List(context.TODO(), apiclient.AllowlistListOpts{WithContent: true})
|
allowlists, _, err := a.LAPIClient.Allowlists.List(ctx, apiclient.AllowlistListOpts{WithContent: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -92,6 +93,9 @@ func (a *AppsecAllowlist) FetchAllowlists() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(a.ips) != 0 || len(a.ranges) != 0 {
|
||||||
|
a.logger.Infof("fetched %d IPs and %d ranges", len(a.ips), len(a.ranges))
|
||||||
|
}
|
||||||
a.logger.Debugf("fetched %d IPs and %d ranges", len(a.ips), len(a.ranges))
|
a.logger.Debugf("fetched %d IPs and %d ranges", len(a.ips), len(a.ranges))
|
||||||
a.logger.Tracef("allowlisted ips: %+v", a.ips)
|
a.logger.Tracef("allowlisted ips: %+v", a.ips)
|
||||||
a.logger.Tracef("allowlisted ranges: %+v", a.ranges)
|
a.logger.Tracef("allowlisted ranges: %+v", a.ranges)
|
||||||
|
@ -99,25 +103,28 @@ func (a *AppsecAllowlist) FetchAllowlists() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppsecAllowlist) updateAllowlists() error {
|
func (a *AppsecAllowlist) updateAllowlists(ctx context.Context) {
|
||||||
ticker := time.NewTicker(allowlistRefreshInterval)
|
ticker := time.NewTicker(allowlistRefreshInterval)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if err := a.FetchAllowlists(); err != nil {
|
if err := a.FetchAllowlists(ctx); err != nil {
|
||||||
a.logger.Errorf("failed to fetch allowlists: %s", err)
|
a.logger.Errorf("failed to fetch allowlists: %s", err)
|
||||||
}
|
}
|
||||||
case <-a.tomb.Dying():
|
case <-a.tomb.Dying():
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppsecAllowlist) StartRefresh(t *tomb.Tomb) {
|
func (a *AppsecAllowlist) StartRefresh(ctx context.Context, t *tomb.Tomb) {
|
||||||
a.tomb = t
|
a.tomb = t
|
||||||
a.tomb.Go(a.updateAllowlists)
|
a.tomb.Go(func() error {
|
||||||
|
a.updateAllowlists(ctx)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppsecAllowlist) IsAllowlisted(sourceIP string) (bool, string) {
|
func (a *AppsecAllowlist) IsAllowlisted(sourceIP string) (bool, string) {
|
||||||
|
|
|
@ -64,9 +64,13 @@ func TestAppsecAllowlist(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
allowlistClient := NewAppsecAllowlist(client, log.NewEntry(log.StandardLogger()))
|
ctx := t.Context()
|
||||||
|
allowlistClient := NewAppsecAllowlist(log.NewEntry(log.StandardLogger()))
|
||||||
|
|
||||||
err = allowlistClient.FetchAllowlists()
|
err = allowlistClient.Start(ctx, client)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = allowlistClient.FetchAllowlists(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
res, reason := allowlistClient.IsAllowlisted("1.2.3.4")
|
res, reason := allowlistClient.IsAllowlisted("1.2.3.4")
|
||||||
|
@ -84,7 +88,7 @@ func TestAppsecAllowlist(t *testing.T) {
|
||||||
assert.Len(t, allowlistClient.ips, 1)
|
assert.Len(t, allowlistClient.ips, 1)
|
||||||
assert.Len(t, allowlistClient.ranges, 1)
|
assert.Len(t, allowlistClient.ranges, 1)
|
||||||
|
|
||||||
err = allowlistClient.FetchAllowlists()
|
err = allowlistClient.FetchAllowlists(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// No duplicates should be added
|
// No duplicates should be added
|
||||||
|
|
|
@ -76,3 +76,19 @@ teardown() {
|
||||||
assert_stderr --partial "datasource type missing in $ACQUIS_DIR/journal.yaml (position 0): detected 'source=journalctl'"
|
assert_stderr --partial "datasource type missing in $ACQUIS_DIR/journal.yaml (position 0): detected 'source=journalctl'"
|
||||||
assert_stderr --partial "datasource type mismatch in $ACQUIS_DIR/bad.yaml (position 0): found 'docker' but should probably be 'journalctl'"
|
assert_stderr --partial "datasource type mismatch in $ACQUIS_DIR/bad.yaml (position 0): found 'docker' but should probably be 'journalctl'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "test mode does not fail because of appsec and allowlists" {
|
||||||
|
rune -0 cscli collections install crowdsecurity/appsec-virtual-patching
|
||||||
|
cat >"$ACQUIS_DIR/appsec.yaml" <<-EOT
|
||||||
|
source: appsec
|
||||||
|
appsec_config: crowdsecurity/virtual-patching
|
||||||
|
labels:
|
||||||
|
type: appsec
|
||||||
|
EOT
|
||||||
|
|
||||||
|
config_set '.common.log_level="debug" | .common.log_media="stdout"'
|
||||||
|
|
||||||
|
rune -0 "$CROWDSEC" -t --trace
|
||||||
|
|
||||||
|
assert_stderr --partial "Configuration test done"
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue