MM-55320 - Limit length of browser user agent version; ratelimit the /sessions endpoint (#25900)

* add ratelimit to /sessions; cap userAgent version length; tests

* add MaxSessionsLimit; remove oldest session first; tests

* can't use slices in 1.20; improve test

* nits

* add GetLRUSessions; move limiting to CreateSession; remove rate limiting

* use queryBuilder

* mysql needs a limit when using offset

* update i18n

* refactor into limitNumberOfSessions; protect createSessionForUserAccessToken

* add comment to GetLRUSessions

* add limit to oauth path; PR comments
Этот коммит содержится в:
Christopher Poile
2024-03-21 08:48:24 -04:00
коммит произвёл GitHub
родитель 9a2d96073e
Коммит 17d11db395
16 изменённых файлов: 321 добавлений и 4 удалений

Просмотреть файл

@@ -5,8 +5,11 @@ package app
import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -395,3 +398,57 @@ func TestGetRemoteClusterSession(t *testing.T) {
require.Nil(t, session)
})
}
func TestSessionsLimit(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
user := th.BasicUser
var sessions []*model.Session
r := &http.Request{}
w := httptest.NewRecorder()
for i := 0; i < maxSessionsLimit; i++ {
session, err := th.App.DoLogin(th.Context, w, r, th.BasicUser, "", false, false, false)
require.Nil(t, err)
sessions = append(sessions, session)
time.Sleep(1 * time.Millisecond)
}
gotSessions, _ := th.App.GetSessions(th.Context, user.Id)
require.Equal(t, maxSessionsLimit, len(gotSessions), "should have maxSessionsLimit number of sessions")
// Ensure we are retrieving the same sessions.
reverse(gotSessions)
for i, sess := range gotSessions {
require.Equal(t, sessions[i].Id, sess.Id)
}
// Now add 10 more.
for i := 0; i < 10; i++ {
session, err := th.App.DoLogin(th.Context, w, r, th.BasicUser, "", false, false, false)
require.Nil(t, err, "should not have an error creating user sessions")
// Remove oldest, append newest.
sessions = sessions[1:]
sessions = append(sessions, session)
time.Sleep(1 * time.Millisecond)
}
// Ensure that we still only have the max allowed.
gotSessions, _ = th.App.GetSessions(th.Context, user.Id)
require.Equal(t, maxSessionsLimit, len(gotSessions), "should have maxSessionsLimit number of sessions")
// Ensure the the oldest sessions were removed first.
reverse(gotSessions)
for i, sess := range gotSessions {
require.Equal(t, sessions[i].Id, sess.Id)
}
}
// reverse can be replaced by the slices version when we move to 1.21+
func reverse[S ~[]E, E any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}