Trim error messages on UserLogin events (#20017)

rim error messages on UserLogin events to prevent omitting audit events due to size
This commit is contained in:
Sam Freiberg 2023-01-11 17:13:13 -06:00 committed by GitHub
parent 62dbe3ecfd
commit edb3eade70
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 1 deletions

View file

@ -125,3 +125,30 @@ func (e *Exec) TrimToMaxSize(maxSize int) AuditEvent {
return out
}
// TrimToMaxSize trims the UserLogin event to the given maximum size.
// The initial implementation is to cover concerns that a malicious user could
// craft a request that creates error messages too large to be handled by the
// underlying storage and thus cause the events to be omitted entirely. See
// teleport-private#172.
func (e *UserLogin) TrimToMaxSize(maxSize int) AuditEvent {
size := e.Size()
if size <= maxSize {
return e
}
out := proto.Clone(e).(*UserLogin)
out.Status.Error = ""
out.Status.UserMessage = ""
// Use 10% max size ballast + message size without Error and UserMessage
sizeBallast := maxSize/10 + out.Size()
maxSize -= sizeBallast
maxFieldSize := maxSizePerField(maxSize, 2)
out.Status.Error = trimN(e.Status.Error, maxFieldSize)
out.Status.UserMessage = trimN(e.Status.UserMessage, maxFieldSize)
return out
}

View file

@ -21,6 +21,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
)
@ -34,7 +35,9 @@ func TestTrimToMaxSize(t *testing.T) {
maxSize int
in AuditEvent
want AuditEvent
cmpOpts []cmp.Option
}{
// DatabaseSessionQuery
{
name: "Query exceeds max limit size",
maxSize: 6000,
@ -99,6 +102,28 @@ func TestTrimToMaxSize(t *testing.T) {
DatabaseQuery: `{"a": "b","a":`,
},
},
// UserLogin
{
name: "UserLogin event with error",
maxSize: 3000,
in: &UserLogin{
Status: Status{
Error: strings.Repeat("A", 2000),
UserMessage: strings.Repeat("A", 2000),
},
},
want: &UserLogin{
Status: Status{
Error: strings.Repeat("A", 1336),
UserMessage: strings.Repeat("A", 1336),
},
},
cmpOpts: []cmp.Option{
// UserLogin.IdentityAttributes has an Equal method which gets used
// by cmp.Diff but fails whether nil or an empty struct is supplied.
cmpopts.IgnoreFields(UserLogin{}, "IdentityAttributes"),
},
},
}
for _, tc := range testCases {
@ -108,7 +133,7 @@ func TestTrimToMaxSize(t *testing.T) {
got := sr.TrimToMaxSize(tc.maxSize)
require.Empty(t, cmp.Diff(got, tc.want))
require.Empty(t, cmp.Diff(got, tc.want, tc.cmpOpts...))
require.Less(t, got.Size(), tc.maxSize)
})
}