Modifications to rate limiting settings. (#4091)
Этот коммит содержится в:
коммит произвёл
Corey Hulen
родитель
dff985a924
Коммит
7fcc004beb
@@ -33,7 +33,7 @@ func SetupEnterprise() *TestHelper {
|
|||||||
utils.LoadConfig("config.json")
|
utils.LoadConfig("config.json")
|
||||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||||
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
||||||
utils.Cfg.RateLimitSettings.EnableRateLimiter = false
|
*utils.Cfg.RateLimitSettings.Enable = false
|
||||||
utils.DisableDebugLogForTest()
|
utils.DisableDebugLogForTest()
|
||||||
utils.License.Features.SetDefaults()
|
utils.License.Features.SetDefaults()
|
||||||
NewServer()
|
NewServer()
|
||||||
@@ -55,7 +55,7 @@ func Setup() *TestHelper {
|
|||||||
utils.LoadConfig("config.json")
|
utils.LoadConfig("config.json")
|
||||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||||
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
||||||
utils.Cfg.RateLimitSettings.EnableRateLimiter = false
|
*utils.Cfg.RateLimitSettings.Enable = false
|
||||||
utils.DisableDebugLogForTest()
|
utils.DisableDebugLogForTest()
|
||||||
NewServer()
|
NewServer()
|
||||||
StartServer()
|
StartServer()
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
l4g "github.com/alecthomas/log4go"
|
l4g "github.com/alecthomas/log4go"
|
||||||
"github.com/braintree/manners"
|
"github.com/braintree/manners"
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
@@ -12,9 +16,6 @@ import (
|
|||||||
"github.com/mattermost/platform/utils"
|
"github.com/mattermost/platform/utils"
|
||||||
"gopkg.in/throttled/throttled.v2"
|
"gopkg.in/throttled/throttled.v2"
|
||||||
"gopkg.in/throttled/throttled.v2/store/memstore"
|
"gopkg.in/throttled/throttled.v2/store/memstore"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
@@ -70,7 +71,7 @@ func StartServer() {
|
|||||||
|
|
||||||
var handler http.Handler = &CorsWrapper{Srv.Router}
|
var handler http.Handler = &CorsWrapper{Srv.Router}
|
||||||
|
|
||||||
if utils.Cfg.RateLimitSettings.EnableRateLimiter {
|
if *utils.Cfg.RateLimitSettings.Enable {
|
||||||
l4g.Info(utils.T("api.server.start_server.rate.info"))
|
l4g.Info(utils.T("api.server.start_server.rate.info"))
|
||||||
|
|
||||||
store, err := memstore.New(utils.Cfg.RateLimitSettings.MemoryStoreSize)
|
store, err := memstore.New(utils.Cfg.RateLimitSettings.MemoryStoreSize)
|
||||||
@@ -81,7 +82,7 @@ func StartServer() {
|
|||||||
|
|
||||||
quota := throttled.RateQuota{
|
quota := throttled.RateQuota{
|
||||||
MaxRate: throttled.PerSec(utils.Cfg.RateLimitSettings.PerSec),
|
MaxRate: throttled.PerSec(utils.Cfg.RateLimitSettings.PerSec),
|
||||||
MaxBurst: 100,
|
MaxBurst: *utils.Cfg.RateLimitSettings.MaxBurst,
|
||||||
}
|
}
|
||||||
|
|
||||||
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
|
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
|
||||||
|
|||||||
@@ -3043,6 +3043,10 @@
|
|||||||
"id": "model.config.is_valid.email_security.app_error",
|
"id": "model.config.is_valid.email_security.app_error",
|
||||||
"translation": "Invalid connection security for email settings. Must be '', 'TLS', or 'STARTTLS'"
|
"translation": "Invalid connection security for email settings. Must be '', 'TLS', or 'STARTTLS'"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "model.config.is_valid.max_burst.app_error",
|
||||||
|
"translation": "Max burst must be greater than zero."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "model.config.is_valid.encrypt_sql.app_error",
|
"id": "model.config.is_valid.encrypt_sql.app_error",
|
||||||
"translation": "Invalid at rest encrypt key for SQL settings. Must be 32 chars or more."
|
"translation": "Invalid at rest encrypt key for SQL settings. Must be 32 chars or more."
|
||||||
|
|||||||
@@ -177,11 +177,12 @@ type EmailSettings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RateLimitSettings struct {
|
type RateLimitSettings struct {
|
||||||
EnableRateLimiter bool
|
Enable *bool
|
||||||
PerSec int
|
PerSec int
|
||||||
MemoryStoreSize int
|
MaxBurst *int
|
||||||
VaryByRemoteAddr bool
|
MemoryStoreSize int
|
||||||
VaryByHeader string
|
VaryByRemoteAddr bool
|
||||||
|
VaryByHeader string
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrivacySettings struct {
|
type PrivacySettings struct {
|
||||||
@@ -894,6 +895,16 @@ func (o *Config) SetDefaults() {
|
|||||||
*o.NativeAppSettings.IosAppDownloadLink = "https://about.mattermost.com/mattermost-ios-app/"
|
*o.NativeAppSettings.IosAppDownloadLink = "https://about.mattermost.com/mattermost-ios-app/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.RateLimitSettings.Enable == nil {
|
||||||
|
o.RateLimitSettings.Enable = new(bool)
|
||||||
|
*o.RateLimitSettings.Enable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.RateLimitSettings.MaxBurst == nil {
|
||||||
|
o.RateLimitSettings.MaxBurst = new(int)
|
||||||
|
*o.RateLimitSettings.MaxBurst = 100
|
||||||
|
}
|
||||||
|
|
||||||
o.defaultWebrtcSettings()
|
o.defaultWebrtcSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1097,6 +1108,10 @@ func (o *Config) IsValid() *AppError {
|
|||||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "")
|
return NewLocAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *o.RateLimitSettings.MaxBurst <= 0 {
|
||||||
|
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "")
|
||||||
|
}
|
||||||
|
|
||||||
if err := o.isValidWebrtcSettings(); err != nil {
|
if err := o.isValidWebrtcSettings(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ func trackConfig() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
SendDiagnostic(TRACK_CONFIG_RATE, map[string]interface{}{
|
SendDiagnostic(TRACK_CONFIG_RATE, map[string]interface{}{
|
||||||
"enable_rate_limiter": Cfg.RateLimitSettings.EnableRateLimiter,
|
"enable_rate_limiter": *Cfg.RateLimitSettings.Enable,
|
||||||
"vary_by_remote_address": Cfg.RateLimitSettings.VaryByRemoteAddr,
|
"vary_by_remote_address": Cfg.RateLimitSettings.VaryByRemoteAddr,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ export default class RateSettings extends AdminSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getConfigFromState(config) {
|
getConfigFromState(config) {
|
||||||
config.RateLimitSettings.EnableRateLimiter = this.state.enableRateLimiter;
|
config.RateLimitSettings.Enable = this.state.enable;
|
||||||
config.RateLimitSettings.PerSec = this.parseIntNonZero(this.state.perSec);
|
config.RateLimitSettings.PerSec = this.parseIntNonZero(this.state.perSec);
|
||||||
|
config.RateLimitSettings.MaxBurst = this.parseIntNonZero(this.state.maxBurst);
|
||||||
config.RateLimitSettings.MemoryStoreSize = this.parseIntNonZero(this.state.memoryStoreSize);
|
config.RateLimitSettings.MemoryStoreSize = this.parseIntNonZero(this.state.memoryStoreSize);
|
||||||
config.RateLimitSettings.VaryByRemoteAddr = this.state.varyByRemoteAddr;
|
config.RateLimitSettings.VaryByRemoteAddr = this.state.varyByRemoteAddr;
|
||||||
config.RateLimitSettings.VaryByHeader = this.state.varyByHeader;
|
config.RateLimitSettings.VaryByHeader = this.state.varyByHeader;
|
||||||
@@ -32,8 +33,9 @@ export default class RateSettings extends AdminSettings {
|
|||||||
|
|
||||||
getStateFromConfig(config) {
|
getStateFromConfig(config) {
|
||||||
return {
|
return {
|
||||||
enableRateLimiter: config.RateLimitSettings.EnableRateLimiter,
|
enable: config.RateLimitSettings.Enable,
|
||||||
perSec: config.RateLimitSettings.PerSec,
|
perSec: config.RateLimitSettings.PerSec,
|
||||||
|
maxBurst: config.RateLimitSettings.MaxBurst,
|
||||||
memoryStoreSize: config.RateLimitSettings.MemoryStoreSize,
|
memoryStoreSize: config.RateLimitSettings.MemoryStoreSize,
|
||||||
varyByRemoteAddr: config.RateLimitSettings.VaryByRemoteAddr,
|
varyByRemoteAddr: config.RateLimitSettings.VaryByRemoteAddr,
|
||||||
varyByHeader: config.RateLimitSettings.VaryByHeader
|
varyByHeader: config.RateLimitSettings.VaryByHeader
|
||||||
@@ -63,7 +65,7 @@ export default class RateSettings extends AdminSettings {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
id='enableRateLimiter'
|
id='enable'
|
||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='admin.rate.enableLimiterTitle'
|
id='admin.rate.enableLimiterTitle'
|
||||||
@@ -76,7 +78,7 @@ export default class RateSettings extends AdminSettings {
|
|||||||
defaultMessage='When true, APIs are throttled at rates specified below.'
|
defaultMessage='When true, APIs are throttled at rates specified below.'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
value={this.state.enableRateLimiter}
|
value={this.state.enable}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
/>
|
/>
|
||||||
<TextSetting
|
<TextSetting
|
||||||
@@ -96,7 +98,26 @@ export default class RateSettings extends AdminSettings {
|
|||||||
}
|
}
|
||||||
value={this.state.perSec}
|
value={this.state.perSec}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
disabled={!this.state.enableRateLimiter}
|
disabled={!this.state.enable}
|
||||||
|
/>
|
||||||
|
<TextSetting
|
||||||
|
id='maxBurst'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.rate.maxBurst'
|
||||||
|
defaultMessage='Max Burst:'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder={Utils.localizeMessage('admin.rate.maxBurstExample', 'Ex "100"')}
|
||||||
|
helpText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.rate.maxBurstDescription'
|
||||||
|
defaultMessage='Maxumum number of requests allowed beyond the per second query limit.'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={this.state.maxBurst}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
disabled={!this.state.enable}
|
||||||
/>
|
/>
|
||||||
<TextSetting
|
<TextSetting
|
||||||
id='memoryStoreSize'
|
id='memoryStoreSize'
|
||||||
@@ -115,7 +136,7 @@ export default class RateSettings extends AdminSettings {
|
|||||||
}
|
}
|
||||||
value={this.state.memoryStoreSize}
|
value={this.state.memoryStoreSize}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
disabled={!this.state.enableRateLimiter}
|
disabled={!this.state.enable}
|
||||||
/>
|
/>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
id='varyByRemoteAddr'
|
id='varyByRemoteAddr'
|
||||||
@@ -133,7 +154,7 @@ export default class RateSettings extends AdminSettings {
|
|||||||
}
|
}
|
||||||
value={this.state.varyByRemoteAddr}
|
value={this.state.varyByRemoteAddr}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
disabled={!this.state.enableRateLimiter}
|
disabled={!this.state.enable}
|
||||||
/>
|
/>
|
||||||
<TextSetting
|
<TextSetting
|
||||||
id='varyByHeader'
|
id='varyByHeader'
|
||||||
@@ -152,7 +173,7 @@ export default class RateSettings extends AdminSettings {
|
|||||||
}
|
}
|
||||||
value={this.state.varyByHeader}
|
value={this.state.varyByHeader}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
disabled={!this.state.enableRateLimiter || this.state.varyByRemoteAddr}
|
disabled={!this.state.enable || this.state.varyByRemoteAddr}
|
||||||
/>
|
/>
|
||||||
</SettingsGroup>
|
</SettingsGroup>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -543,6 +543,9 @@
|
|||||||
"admin.rate.remoteDescription": "When true, rate limit API access by IP address.",
|
"admin.rate.remoteDescription": "When true, rate limit API access by IP address.",
|
||||||
"admin.rate.remoteTitle": "Vary rate limit by remote address: ",
|
"admin.rate.remoteTitle": "Vary rate limit by remote address: ",
|
||||||
"admin.rate.title": "Rate Limit Settings",
|
"admin.rate.title": "Rate Limit Settings",
|
||||||
|
"admin.rate.maxBurst": "Max Burst:",
|
||||||
|
"admin.rate.maxBurstExample": "Ex \"100\"",
|
||||||
|
"admin.rate.maxBurstDescription": "Maxumum number of requests allowed beyond the per second query limit.",
|
||||||
"admin.recycle.button": "Recycle Database Connections",
|
"admin.recycle.button": "Recycle Database Connections",
|
||||||
"admin.recycle.loading": " Recycling...",
|
"admin.recycle.loading": " Recycling...",
|
||||||
"admin.recycle.recycleDescription": "Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating \"config.json\" to the new desired configuration and using the <a href=\"../general/configuration\"><b>Configuration > Reload Configuration from Disk</b></a> feature to load the new settings while the server is running. The administrator should then use <b>Recycle Database Connections</b> feature to recycle the database connections based on the new settings.",
|
"admin.recycle.recycleDescription": "Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating \"config.json\" to the new desired configuration and using the <a href=\"../general/configuration\"><b>Configuration > Reload Configuration from Disk</b></a> feature to load the new settings while the server is running. The administrator should then use <b>Recycle Database Connections</b> feature to recycle the database connections based on the new settings.",
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user