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

tls.go « tls « internal - gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c222fccea9639e5d1e507cf8b7838e3f3181d91f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package tls

import (
	"crypto/tls"

	"gitlab.com/gitlab-org/gitlab-pages/internal/config"
	"gitlab.com/gitlab-org/gitlab-pages/internal/feature"
	"gitlab.com/gitlab-org/gitlab-pages/internal/ratelimiter"
	"gitlab.com/gitlab-org/gitlab-pages/metrics"
)

var preferredCipherSuites = []uint16{
	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
	tls.TLS_AES_128_GCM_SHA256,
	tls.TLS_AES_256_GCM_SHA384,
	tls.TLS_CHACHA20_POLY1305_SHA256,
}

// GetCertificateFunc returns the certificate to be used for given domain
type GetCertificateFunc func(*tls.ClientHelloInfo) (*tls.Certificate, error)

// GetTLSConfig initializes tls.Config based on config flags
// getCertificateByServerName obtains certificate based on domain
func GetTLSConfig(cfg *config.Config, getCertificateByServerName GetCertificateFunc) (*tls.Config, error) {
	certificate, err := tls.X509KeyPair(cfg.General.RootCertificate, cfg.General.RootKey)
	if err != nil {
		return nil, err
	}

	getCertificate := func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
		// Golang calls tls.Config.GetCertificate only if it's set and
		// 1. ServerName != ""
		// 2. Or tls.Config.Certificates is empty array
		// tls.Config.Certificates contain wildcard certificate
		// We want to implement rate limits via GetCertificate, so we need to call it every time
		// So we don't set tls.Config.Certificates, but simulate the behavior of golang:
		// 1. try to get certificate by name
		// 2. if we can't, fallback to default(wildcard) certificate
		cert, err := getCertificateByServerName(info)

		if cert != nil || err != nil {
			return cert, err
		}

		return &certificate, nil
	}

	TLSDomainRateLimiter := ratelimiter.New(
		"tls_connections_by_domain",
		ratelimiter.WithTLSKeyFunc(ratelimiter.TLSHostnameKey),
		ratelimiter.WithCacheMaxSize(ratelimiter.DefaultDomainCacheSize),
		ratelimiter.WithCachedEntriesMetric(metrics.RateLimitCachedEntries),
		ratelimiter.WithCachedRequestsMetric(metrics.RateLimitCacheRequests),
		ratelimiter.WithBlockedCountMetric(metrics.RateLimitBlockedCount),
		ratelimiter.WithLimitPerSecond(cfg.RateLimit.TLSDomainLimitPerSecond),
		ratelimiter.WithBurstSize(cfg.RateLimit.TLSDomainBurst),
		ratelimiter.WithEnforce(feature.EnforceDomainTLSRateLimits.Enabled()),
	)

	TLSSourceIPRateLimiter := ratelimiter.New(
		"tls_connections_by_source_ip",
		ratelimiter.WithTLSKeyFunc(ratelimiter.TLSClientIPKey),
		ratelimiter.WithCacheMaxSize(ratelimiter.DefaultSourceIPCacheSize),
		ratelimiter.WithCachedEntriesMetric(metrics.RateLimitCachedEntries),
		ratelimiter.WithCachedRequestsMetric(metrics.RateLimitCacheRequests),
		ratelimiter.WithBlockedCountMetric(metrics.RateLimitBlockedCount),
		ratelimiter.WithLimitPerSecond(cfg.RateLimit.TLSSourceIPLimitPerSecond),
		ratelimiter.WithBurstSize(cfg.RateLimit.TLSSourceIPBurst),
		ratelimiter.WithEnforce(feature.EnforceIPTLSRateLimits.Enabled()),
	)

	getCertificate = TLSDomainRateLimiter.GetCertificateMiddleware(getCertificate)
	getCertificate = TLSSourceIPRateLimiter.GetCertificateMiddleware(getCertificate)

	// set MinVersion to fix gosec: G402
	tlsConfig := &tls.Config{GetCertificate: getCertificate, MinVersion: tls.VersionTLS12}

	if !cfg.General.InsecureCiphers {
		configureTLSCiphers(tlsConfig)
	}

	tlsConfig.MinVersion = cfg.TLS.MinVersion
	tlsConfig.MaxVersion = cfg.TLS.MaxVersion

	return tlsConfig, nil
}

func configureTLSCiphers(tlsConfig *tls.Config) {
	tlsConfig.PreferServerCipherSuites = true
	tlsConfig.CipherSuites = preferredCipherSuites
}