controller: support rate-limiting incoming requests

helps constraining resource usage and against flood attacks.

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
This commit is contained in:
Ramkumar Chinchani
2022-01-21 20:30:09 +00:00
committed by Ramkumar Chinchani
parent f251e7af10
commit 1e5ea7e09c
8 changed files with 238 additions and 4 deletions
+121
View File
@@ -388,6 +388,127 @@ func TestHtpasswdFiveCreds(t *testing.T) {
})
}
func TestRatelimit(t *testing.T) {
Convey("Make a new controller", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
rate := 1
conf.HTTP.Ratelimit = &config.RatelimitConfig{
Rate: &rate,
}
ctlr := api.NewController(conf)
dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
ctlr.Config.Storage.RootDirectory = dir
go startServer(ctlr)
defer stopServer(ctlr)
WaitTillServerReady(baseURL)
Convey("Ratelimit", func() {
client := resty.New()
// first request should succeed
resp, err := client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
// second request back-to-back should fail
resp, err = client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusTooManyRequests)
})
})
Convey("Make a new controller", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.HTTP.Ratelimit = &config.RatelimitConfig{
Methods: []config.MethodRatelimitConfig{
{
Method: http.MethodGet,
Rate: 1,
},
},
}
ctlr := api.NewController(conf)
dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
ctlr.Config.Storage.RootDirectory = dir
go startServer(ctlr)
defer stopServer(ctlr)
WaitTillServerReady(baseURL)
Convey("Method Ratelimit", func() {
client := resty.New()
// first request should succeed
resp, err := client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
// second request back-to-back should fail
resp, err = client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusTooManyRequests)
})
})
Convey("Make a new controller", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
rate := 1
conf.HTTP.Ratelimit = &config.RatelimitConfig{
Rate: &rate, // this dominates
Methods: []config.MethodRatelimitConfig{
{
Method: http.MethodGet,
Rate: 100,
},
},
}
ctlr := api.NewController(conf)
dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
ctlr.Config.Storage.RootDirectory = dir
go startServer(ctlr)
defer stopServer(ctlr)
WaitTillServerReady(baseURL)
Convey("Global and Method Ratelimit", func() {
client := resty.New()
// first request should succeed
resp, err := client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
// second request back-to-back should fail
resp, err = client.R().Get(baseURL + "/v2/")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusTooManyRequests)
})
})
}
func TestBasicAuth(t *testing.T) {
Convey("Make a new controller", t, func() {
port := GetFreePort()