Skip to content
This repository was archived by the owner on Nov 2, 2023. It is now read-only.

Commit f368d2b

Browse files
author
Julio Guerra
committed
v0.1.0-beta.9
New Features: - Request parameters such as query or post parameters are now added in the attack events and shown in the attack logs and in the event explorer pages of our dashboard. (#84) - PII scrubbing is now performed on every event sent to Sqreen, as documented on https://docs.sqreen.com/guides/how-sqreen-works/#pii-scrubbing. (#86) Fixes: - Add PII scrubbing to the WAF logs that may include data from the request. (#87) Internal Changes: - The In-App WAF has been intensively optimized so that large requests can no longer impact its execution time. (#83)
2 parents a3d20c7 + 447f329 commit f368d2b

36 files changed

+3347
-332
lines changed

README.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,39 +33,41 @@ For more details, visit [sqreen.com](https://www.sqreen.com/)
3333

3434
# Installation
3535

36-
1. Download the Go agent and the SDK using `go get`:
36+
Installing the agent is just installing a regular Go package. Simply import it
37+
and let the toolchain do the job.
3738

38-
```sh
39-
$ go get -v github.com/sqreen/go-agent@v0.1.0-beta.8
40-
```
4139

42-
1. Import the package `agent` in your `main` package of your app:
40+
1. Import the agent package into the `main` package of your app:
4341

4442
```go
4543
import _ "github.com/sqreen/go-agent/agent"
4644
```
4745

46+
1. Use the middleware function for the Go web framework you use:
47+
- [sqhttp](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqhttp) for the standard `net/http` package.
48+
- [Gin](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqgin) for `github.com/gin-gonic/gin`.
49+
- [Echo](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqecho) for `github.com/labstack/echo`.
50+
51+
If your framework is not in the list, it is usually possible to use the
52+
standard `net/http` middleware. If not, please, [create an issue](http://github.com/sqreen/go-agent/issues/new)
53+
to let us know.
54+
4855
1. [Signup to Sqreen](https://my.sqreen.io/signup) to get a token for your app,
4956
and store it in the agent's configuration file `sqreen.yaml`:
50-
57+
5158
```sh
5259
token: your token
5360
app_name: Your App Name
5461
```
55-
62+
5663
This file can be stored in your current working directory when starting the
5764
executable, the same directory as your app's executable file, or in any other
5865
path by defining the configuration file location into the environment
5966
variable `SQREEN_CONFIG_FILE`.
6067

61-
1. Set up Sqreen's middleware functions according to the web framework you use:
62-
- [sqhttp](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqhttp) for the standard `net/http` package.
63-
- [Gin](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqgin) for `github.com/gin-gonic/gin`.
64-
- [Echo](https://godoc.org/github.com/sqreen/go-agent/sdk/middleware/sqecho) for `github.com/labstack/echo`.
65-
66-
If your framework is not in the list, it is usually possible to use the
67-
standard `net/http` middleware. If not, please open an issue in this
68-
repository to start a discussion about it.
68+
1. You are done!
69+
Just recompile your Go program and the go toolchain will download the latests
70+
agent version.
6971

7072
1. Optionally, use the [SDK](https://godoc.org/github.com/sqreen/go-agent/sdk)
7173
to send security [events related to
@@ -74,6 +76,8 @@ For more details, visit [sqreen.com](https://www.sqreen.com/)
7476
events](https://godoc.org/github.com/sqreen/go-agent/sdk#HTTPRequestRecord.TrackEvent)
7577
you would like to track (eg. password changes).
7678

79+
Find out more about the agent installation at https://docs.sqreen.com/go/installation/
80+
7781
# Licensing
7882

7983
Sqreen for Go is free-to-use, proprietary software.

agent/internal/actor/action_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
func TestAction(t *testing.T) {
1919
t.Run("Blocking action", func(t *testing.T) {
20-
action := newBlockAction(testlib.RandString(1, 20))
20+
action := newBlockAction(testlib.RandPrintableUSASCIIString(1, 20))
2121

2222
t.Run("with duration", func(t *testing.T) {
2323
t.Run("not expired", func(t *testing.T) {
@@ -26,6 +26,7 @@ func TestAction(t *testing.T) {
2626
})
2727
t.Run("expired", func(t *testing.T) {
2828
action := withDuration(action, 0)
29+
time.Sleep(time.Millisecond)
2930
require.True(t, action.Expired())
3031
})
3132
})
@@ -44,7 +45,7 @@ func TestAction(t *testing.T) {
4445
})
4546

4647
t.Run("Block User", func(t *testing.T) {
47-
handler, err := NewUserActionHTTPHandler(action, map[string]string{"uid": testlib.RandString(1, 250)})
48+
handler, err := NewUserActionHTTPHandler(action, map[string]string{"uid": testlib.RandPrintableUSASCIIString(1, 250)})
4849
require.NoError(t, err)
4950
require.NotNil(t, handler)
5051
// Use the handler
@@ -59,13 +60,13 @@ func TestAction(t *testing.T) {
5960

6061
t.Run("Redirection action", func(t *testing.T) {
6162
t.Run("invalid location url", func(t *testing.T) {
62-
action, err := newRedirectAction(testlib.RandString(1, 20), "http//toto")
63+
action, err := newRedirectAction(testlib.RandPrintableUSASCIIString(1, 20), "http//toto")
6364
require.Nil(t, action)
6465
require.Error(t, err)
6566
})
6667

6768
t.Run("valid location url", func(t *testing.T) {
68-
action, err := newRedirectAction(testlib.RandString(1, 20), "http://sqreen.com")
69+
action, err := newRedirectAction(testlib.RandPrintableUSASCIIString(1, 20), "http://sqreen.com")
6970
require.NotNil(t, action)
7071
require.NoError(t, err)
7172

@@ -76,6 +77,7 @@ func TestAction(t *testing.T) {
7677
})
7778
t.Run("expired", func(t *testing.T) {
7879
action := withDuration(action, 0)
80+
time.Sleep(time.Millisecond)
7981
require.True(t, action.Expired())
8082
})
8183
})
@@ -95,7 +97,7 @@ func TestAction(t *testing.T) {
9597
})
9698

9799
t.Run("Redirect User", func(t *testing.T) {
98-
handler, err := NewUserActionHTTPHandler(action, map[string]string{"uid": testlib.RandString(1, 250)})
100+
handler, err := NewUserActionHTTPHandler(action, map[string]string{"uid": testlib.RandPrintableUSASCIIString(1, 250)})
99101
require.NoError(t, err)
100102
require.NotNil(t, handler)
101103
// Use the handler

agent/internal/actor/actor_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ func TestStore(t *testing.T) {
301301
{
302302
name: "Malformed",
303303
actions: map[*api.ActionsPackResponse_Action][]net.IP{
304-
NewBlockIPAction(testlib.RandString(2, 20)): nil,
304+
NewBlockIPAction(testlib.RandPrintableUSASCIIString(2, 20)): nil,
305305
},
306306
},
307307

@@ -610,8 +610,8 @@ func RandUser() map[string]string {
610610
count := int(1 + rand.Uint32()%10)
611611
user := make(map[string]string, count)
612612
for n := 0; n < count; n++ {
613-
k := testlib.RandString(1, 50)
614-
v := testlib.RandString(1, 50)
613+
k := testlib.RandPrintableUSASCIIString(1, 50)
614+
v := testlib.RandPrintableUSASCIIString(1, 50)
615615
user[k] = v
616616
}
617617
return user

agent/internal/agent.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/sqreen/go-agent/agent/internal/rule"
2727
"github.com/sqreen/go-agent/agent/sqlib/sqerrors"
2828
"github.com/sqreen/go-agent/agent/sqlib/sqsafe"
29+
"github.com/sqreen/go-agent/agent/sqlib/sqsanitize"
2930
"github.com/sqreen/go-agent/agent/sqlib/sqtime"
3031
"github.com/sqreen/go-agent/agent/types"
3132
"github.com/sqreen/go-agent/sdk"
@@ -139,6 +140,7 @@ type Agent struct {
139140
client *backend.Client
140141
actors *actor.Store
141142
rules *rule.Engine
143+
piiScrubber *sqsanitize.Scrubber
142144
}
143145

144146
func (a *Agent) FindActionByIP(ip net.IP) (action actor.Action, exists bool, err error) {
@@ -182,6 +184,12 @@ func New(cfg *config.Config) *Agent {
182184
sdkMetricsPeriod := time.Duration(cfg.SDKMetricsPeriod()) * time.Second
183185
logger.Debugf("using sdk metrics store period of %s", sdkMetricsPeriod)
184186

187+
piiScrubber, err := sqsanitize.NewScrubber(config.ScrubberKeyRegexp, config.ScrubberValueRegexp, config.ScrubberRedactedString)
188+
if err != nil {
189+
logger.Error(sqerrors.Wrap(err, "ecdsa public key"))
190+
return nil
191+
}
192+
185193
// Agent graceful stopping using context cancellation.
186194
ctx, cancel := context.WithCancel(context.Background())
187195
return &Agent{
@@ -195,19 +203,19 @@ func New(cfg *config.Config) *Agent {
195203
whitelistedIP: metrics.NewStore("whitelisted", sdkMetricsPeriod),
196204
errors: metrics.NewStore("errors", config.ErrorMetricsPeriod),
197205
},
198-
ctx: ctx,
199-
cancel: cancel,
200-
config: cfg,
201-
appInfo: app.NewInfo(logger),
202-
client: backend.NewClient(cfg.BackendHTTPAPIBaseURL(), cfg, logger),
203-
actors: actor.NewStore(logger),
204-
rules: rulesEngine,
206+
ctx: ctx,
207+
cancel: cancel,
208+
config: cfg,
209+
appInfo: app.NewInfo(logger),
210+
client: backend.NewClient(cfg.BackendHTTPAPIBaseURL(), cfg, logger),
211+
actors: actor.NewStore(logger),
212+
rules: rulesEngine,
213+
piiScrubber: piiScrubber,
205214
}
206215
}
207216

208217
func (a *Agent) NewRequestRecord(req *http.Request) (types.RequestRecord, *http.Request) {
209-
rr, req := record.NewRequestRecord(a, a.logger, req, a.config)
210-
return rr, req
218+
return record.NewRequestRecord(a, a.logger, req, a.config)
211219
}
212220

213221
func (a *Agent) Serve() error {
@@ -248,7 +256,7 @@ func (a *Agent) Serve() error {
248256

249257
batchSize := int(appLoginRes.Features.BatchSize)
250258
if batchSize == 0 {
251-
batchSize = config.MaxEventsPerHeatbeat
259+
batchSize = config.EventBatchMaxEventsPerHeartbeat
252260
}
253261
maxStaleness := time.Duration(appLoginRes.Features.MaxStaleness) * time.Second
254262
if maxStaleness == 0 {
@@ -486,10 +494,17 @@ func (m *eventManager) send(client *backend.Client, batch []Event) {
486494
var event api.BatchRequest_EventFace
487495
switch actual := e.(type) {
488496
case *HTTPRequestRecordEvent:
489-
event = (*api.RequestRecordEvent)(api.NewRequestRecordFromFace(actual))
497+
event = api.RequestRecordEvent{api.NewRequestRecordFromFace(actual)}
490498
case *ExceptionEvent:
491499
event = api.NewExceptionEventFromFace(actual)
492500
}
501+
502+
// Scrub the value, along with the set of scrubbed string values.
503+
if _, err := m.agent.piiScrubber.Scrub(event, nil); err != nil {
504+
// Only log this unexpected error and keep the event that may have been
505+
// partially scrubbed.
506+
m.agent.logger.Error(errors.Wrap(err, "could not send the event batch"))
507+
}
493508
req.Batch = append(req.Batch, *api.NewBatchRequest_EventFromFace(event))
494509
}
495510

0 commit comments

Comments
 (0)