Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorVladimir Shushlin <vshushlin@gitlab.com>2022-02-22 13:17:56 +0300
committerVladimir Shushlin <vshushlin@gitlab.com>2022-02-22 13:17:56 +0300
commite7ad17b8d0818dd4c94f3a06e81781f4068c1b97 (patch)
tree026e2619a53da1abf202322c0d4e656ed2e93ba3 /test
parentdbd3785baf9f6af3c0c6a76ef44b12f3fd49b68a (diff)
parentdec4b09ac1f6fdf98487d4db61055c1e64358c15 (diff)
Merge branch 'reject-tls-2' into 'master'
feat: add rate limits on the TLS connection level See merge request gitlab-org/gitlab-pages!700
Diffstat (limited to 'test')
-rw-r--r--test/acceptance/helpers_test.go12
-rw-r--r--test/acceptance/ratelimiter_test.go128
2 files changed, 139 insertions, 1 deletions
diff --git a/test/acceptance/helpers_test.go b/test/acceptance/helpers_test.go
index c44058ba..1b514a85 100644
--- a/test/acceptance/helpers_test.go
+++ b/test/acceptance/helpers_test.go
@@ -602,3 +602,15 @@ func copyFile(dest, src string) error {
_, err = io.Copy(destFile, srcFile)
return err
}
+
+// RequireMetricEqual requests prometheus metrics and makes sure metric is there
+func RequireMetricEqual(t *testing.T, metricsAddress, metricWithValue string) {
+ resp, err := http.Get(fmt.Sprintf("http://%s/metrics", metricsAddress))
+ require.NoError(t, err)
+
+ defer resp.Body.Close()
+ body, err := io.ReadAll(resp.Body)
+ require.NoError(t, err)
+
+ require.Contains(t, string(body), metricWithValue)
+}
diff --git a/test/acceptance/ratelimiter_test.go b/test/acceptance/ratelimiter_test.go
index 02ba54f5..a97fdfb1 100644
--- a/test/acceptance/ratelimiter_test.go
+++ b/test/acceptance/ratelimiter_test.go
@@ -3,6 +3,7 @@ package acceptance_test
import (
"fmt"
"net/http"
+ "strconv"
"testing"
"time"
@@ -77,7 +78,7 @@ func TestIPRateLimits(t *testing.T) {
}
}
-func TestDomainateLimits(t *testing.T) {
+func TestDomainRateLimits(t *testing.T) {
testhelpers.StubFeatureFlagValue(t, feature.EnforceDomainRateLimits.EnvVariable, true)
for name, tc := range ratelimitedListeners {
@@ -112,6 +113,131 @@ func TestDomainateLimits(t *testing.T) {
}
}
+func TestTLSRateLimits(t *testing.T) {
+ tests := map[string]struct {
+ spec ListenSpec
+ domainLimit bool
+ sourceIP string
+ enforceEnabled bool
+ }{
+ "https_with_domain_limit": {
+ spec: httpsListener,
+ domainLimit: true,
+ sourceIP: "127.0.0.1",
+ enforceEnabled: true,
+ },
+ "https_with_domain_limit_not_enforced": {
+ spec: httpsListener,
+ domainLimit: true,
+ sourceIP: "127.0.0.1",
+ enforceEnabled: false,
+ },
+ "https_with_ip_limit": {
+ spec: httpsListener,
+ sourceIP: "127.0.0.1",
+ enforceEnabled: true,
+ },
+ "https_with_ip_limit_not_enforced": {
+ spec: httpsListener,
+ sourceIP: "127.0.0.1",
+ enforceEnabled: false,
+ },
+ "proxyv2_with_domain_limit": {
+ spec: httpsProxyv2Listener,
+ domainLimit: true,
+ sourceIP: "10.1.1.1",
+ enforceEnabled: true,
+ },
+ "proxyv2_with_domain_limit_not_enforced": {
+ spec: httpsProxyv2Listener,
+ domainLimit: true,
+ sourceIP: "10.1.1.1",
+ enforceEnabled: false,
+ },
+ "proxyv2_with_ip_limit": {
+ spec: httpsProxyv2Listener,
+ sourceIP: "10.1.1.1",
+ enforceEnabled: true,
+ },
+ "proxyv2_with_ip_limit_not_enforced": {
+ spec: httpsProxyv2Listener,
+ sourceIP: "10.1.1.1",
+ enforceEnabled: false,
+ },
+ }
+
+ for name, tt := range tests {
+ t.Run(name, func(t *testing.T) {
+ rateLimit := 5
+
+ options := []processOption{
+ withListeners([]ListenSpec{tt.spec}),
+ withExtraArgument("metrics-address", ":42345"),
+ }
+
+ featureName := feature.EnforceIPTLSRateLimits.EnvVariable
+ limitName := "tls_connections_by_source_ip"
+
+ if tt.domainLimit {
+ options = append(options,
+ withExtraArgument("rate-limit-tls-domain", fmt.Sprint(rateLimit)),
+ withExtraArgument("rate-limit-tls-domain-burst", fmt.Sprint(rateLimit)))
+
+ featureName = feature.EnforceDomainTLSRateLimits.EnvVariable
+ limitName = "tls_connections_by_domain"
+ } else {
+ options = append(options,
+ withExtraArgument("rate-limit-tls-source-ip", fmt.Sprint(rateLimit)),
+ withExtraArgument("rate-limit-tls-source-ip-burst", fmt.Sprint(rateLimit)))
+ }
+
+ testhelpers.StubFeatureFlagValue(t, featureName, tt.enforceEnabled)
+ logBuf := RunPagesProcess(t, options...)
+
+ // when we start the process we make 1 requests to verify that process is up
+ // it gets counted in the rate limit for IP, but host is different
+ if !tt.domainLimit {
+ rateLimit--
+ }
+
+ for i := 0; i < 10; i++ {
+ rsp, err := makeTLSRequest(t, tt.spec)
+
+ if i >= rateLimit {
+ assertLogFound(t, logBuf, []string{
+ "TLS connection rate-limited",
+ "\"req_host\":\"group.gitlab-example.com\"",
+ fmt.Sprintf("\"source_ip\":\"%s\"", tt.sourceIP),
+ "\"enforced\":" + strconv.FormatBool(tt.enforceEnabled)})
+
+ if tt.enforceEnabled {
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "remote error: tls: internal error")
+ }
+
+ continue
+ }
+
+ require.NoError(t, err, "request: %d failed", i)
+ require.NoError(t, rsp.Body.Close())
+ require.Equal(t, http.StatusOK, rsp.StatusCode, "request: %d failed", i)
+ }
+ expectedMetric := fmt.Sprintf(
+ "gitlab_pages_rate_limit_blocked_count{enforced=\"%t\",limit_name=\"%s\"} %v",
+ tt.enforceEnabled, limitName, 10-rateLimit)
+
+ RequireMetricEqual(t, "127.0.0.1:42345", expectedMetric)
+ })
+ }
+}
+
+func makeTLSRequest(t *testing.T, spec ListenSpec) (*http.Response, error) {
+ req, err := http.NewRequest("GET", "https://group.gitlab-example.com/project", nil)
+ require.NoError(t, err)
+
+ return spec.Client().Do(req)
+}
+
func assertLogFound(t *testing.T, logBuf *LogCaptureBuffer, expectedLogs []string) {
t.Helper()