Add a new protocol
Co-authored-by: Gérald Croës <gerald@containo.us>
This commit is contained in:
parent
0ca2149408
commit
4a68d29ce2
231 changed files with 6895 additions and 4395 deletions
|
@ -13,11 +13,28 @@ import (
|
|||
|
||||
// Router holds the router configuration.
|
||||
type Router struct {
|
||||
EntryPoints []string `json:"entryPoints"`
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:",omitempty"`
|
||||
Service string `json:"service,omitempty" toml:",omitempty"`
|
||||
Rule string `json:"rule,omitempty" toml:",omitempty"`
|
||||
Priority int `json:"priority,omitempty" toml:"priority,omitzero"`
|
||||
EntryPoints []string `json:"entryPoints"`
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:",omitempty"`
|
||||
Service string `json:"service,omitempty" toml:",omitempty"`
|
||||
Rule string `json:"rule,omitempty" toml:",omitempty"`
|
||||
Priority int `json:"priority,omitempty" toml:"priority,omitzero"`
|
||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitzero" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// RouterTLSConfig holds the TLS configuration for a router
|
||||
type RouterTLSConfig struct{}
|
||||
|
||||
// TCPRouter holds the router configuration.
|
||||
type TCPRouter struct {
|
||||
EntryPoints []string `json:"entryPoints"`
|
||||
Service string `json:"service,omitempty" toml:",omitempty"`
|
||||
Rule string `json:"rule,omitempty" toml:",omitempty"`
|
||||
TLS *RouterTCPTLSConfig `json:"tls,omitempty" toml:"tls,omitzero" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// RouterTCPTLSConfig holds the TLS configuration for a router
|
||||
type RouterTCPTLSConfig struct {
|
||||
Passthrough bool `json:"passthrough,omitempty" toml:"passthrough,omitzero"`
|
||||
}
|
||||
|
||||
// LoadBalancerService holds the LoadBalancerService configuration.
|
||||
|
@ -30,6 +47,12 @@ type LoadBalancerService struct {
|
|||
ResponseForwarding *ResponseForwarding `json:"forwardingResponse,omitempty" toml:",omitempty"`
|
||||
}
|
||||
|
||||
// TCPLoadBalancerService holds the LoadBalancerService configuration.
|
||||
type TCPLoadBalancerService struct {
|
||||
Servers []TCPServer `json:"servers,omitempty" toml:",omitempty" label-slice-as-struct:"server"`
|
||||
Method string `json:"method,omitempty" toml:",omitempty"`
|
||||
}
|
||||
|
||||
// Mergeable tells if the given service is mergeable.
|
||||
func (l *LoadBalancerService) Mergeable(loadBalancer *LoadBalancerService) bool {
|
||||
savedServers := l.Servers
|
||||
|
@ -71,6 +94,12 @@ type Server struct {
|
|||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
// TCPServer holds a TCP Server configuration
|
||||
type TCPServer struct {
|
||||
Address string `json:"address" label:"-"`
|
||||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a Server.
|
||||
func (s *Server) SetDefaults() {
|
||||
s.Weight = 1
|
||||
|
@ -175,18 +204,37 @@ type Message struct {
|
|||
Configuration *Configuration
|
||||
}
|
||||
|
||||
// Configuration is the root of the dynamic configuration
|
||||
type Configuration struct {
|
||||
HTTP *HTTPConfiguration
|
||||
TCP *TCPConfiguration
|
||||
TLS []*traefiktls.Configuration `json:"-" label:"-"`
|
||||
TLSOptions map[string]traefiktls.TLS
|
||||
TLSStores map[string]traefiktls.Store
|
||||
}
|
||||
|
||||
// Configurations is for currentConfigurations Map.
|
||||
type Configurations map[string]*Configuration
|
||||
|
||||
// Configuration FIXME better name?
|
||||
type Configuration struct {
|
||||
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
|
||||
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
|
||||
Services map[string]*Service `json:"services,omitempty" toml:",omitempty"`
|
||||
TLS []*traefiktls.Configuration `json:"-" label:"-"`
|
||||
// HTTPConfiguration FIXME better name?
|
||||
type HTTPConfiguration struct {
|
||||
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
|
||||
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
|
||||
Services map[string]*Service `json:"services,omitempty" toml:",omitempty"`
|
||||
}
|
||||
|
||||
// TCPConfiguration FIXME better name?
|
||||
type TCPConfiguration struct {
|
||||
Routers map[string]*TCPRouter `json:"routers,omitempty" toml:",omitempty"`
|
||||
Services map[string]*TCPService `json:"services,omitempty" toml:",omitempty"`
|
||||
}
|
||||
|
||||
// Service holds a service configuration (can only be of one type at the same time).
|
||||
type Service struct {
|
||||
LoadBalancer *LoadBalancerService `json:"loadbalancer,omitempty" toml:",omitempty,omitzero"`
|
||||
}
|
||||
|
||||
// TCPService holds a tcp service configuration (can only be of one type at the same time).
|
||||
type TCPService struct {
|
||||
LoadBalancer *TCPLoadBalancerService `json:"loadbalancer,omitempty" toml:",omitempty,omitzero"`
|
||||
}
|
||||
|
|
|
@ -5,14 +5,12 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/tls"
|
||||
)
|
||||
|
||||
// EntryPoint holds the entry point configuration.
|
||||
type EntryPoint struct {
|
||||
Address string
|
||||
Transport *EntryPointsTransport
|
||||
TLS *tls.TLS
|
||||
ProxyProtocol *ProxyProtocol
|
||||
ForwardedHeaders *ForwardedHeaders
|
||||
}
|
||||
|
@ -65,14 +63,8 @@ func (ep *EntryPoints) Type() string {
|
|||
func (ep *EntryPoints) Set(value string) error {
|
||||
result := parseEntryPointsConfiguration(value)
|
||||
|
||||
configTLS, err := makeEntryPointTLS(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
(*ep)[result["name"]] = &EntryPoint{
|
||||
Address: result["address"],
|
||||
TLS: configTLS,
|
||||
ProxyProtocol: makeEntryPointProxyProtocol(result),
|
||||
ForwardedHeaders: makeEntryPointForwardedHeaders(result),
|
||||
}
|
||||
|
@ -100,55 +92,6 @@ func makeEntryPointProxyProtocol(result map[string]string) *ProxyProtocol {
|
|||
return proxyProtocol
|
||||
}
|
||||
|
||||
func makeEntryPointTLS(result map[string]string) (*tls.TLS, error) {
|
||||
var configTLS *tls.TLS
|
||||
|
||||
if len(result["tls"]) > 0 {
|
||||
certs := tls.Certificates{}
|
||||
if err := certs.Set(result["tls"]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configTLS = &tls.TLS{}
|
||||
} else if len(result["tls_acme"]) > 0 {
|
||||
configTLS = &tls.TLS{}
|
||||
}
|
||||
|
||||
if configTLS != nil {
|
||||
if len(result["ca"]) > 0 {
|
||||
files := tls.FilesOrContents{}
|
||||
if err := files.Set(result["ca"]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
optional := toBool(result, "ca_optional")
|
||||
configTLS.ClientCA = tls.ClientCA{
|
||||
Files: files,
|
||||
Optional: optional,
|
||||
}
|
||||
}
|
||||
|
||||
if len(result["tls_minversion"]) > 0 {
|
||||
configTLS.MinVersion = result["tls_minversion"]
|
||||
}
|
||||
|
||||
if len(result["tls_ciphersuites"]) > 0 {
|
||||
configTLS.CipherSuites = strings.Split(result["tls_ciphersuites"], ",")
|
||||
}
|
||||
|
||||
if len(result["tls_snistrict"]) > 0 {
|
||||
configTLS.SniStrict = toBool(result, "tls_snistrict")
|
||||
}
|
||||
|
||||
if len(result["tls_defaultcertificate_cert"]) > 0 && len(result["tls_defaultcertificate_key"]) > 0 {
|
||||
configTLS.DefaultCertificate = &tls.Certificate{
|
||||
CertFile: tls.FileOrContent(result["tls_defaultcertificate_cert"]),
|
||||
KeyFile: tls.FileOrContent(result["tls_defaultcertificate_key"]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return configTLS, nil
|
||||
}
|
||||
|
||||
func parseEntryPointsConfiguration(raw string) map[string]string {
|
||||
sections := strings.Fields(raw)
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package static
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/containous/traefik/tls"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -18,10 +17,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
|
|||
name: "all parameters",
|
||||
value: "Name:foo " +
|
||||
"Address::8000 " +
|
||||
"TLS:goo,gii " +
|
||||
"TLS " +
|
||||
"TLS.MinVersion:VersionTLS11 " +
|
||||
"TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
|
||||
"CA:car " +
|
||||
"CA.Optional:true " +
|
||||
"Redirect.EntryPoint:https " +
|
||||
|
@ -76,10 +71,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
|
|||
"redirect_permanent": "true",
|
||||
"redirect_regex": "http://localhost/(.*)",
|
||||
"redirect_replacement": "http://mydomain/$1",
|
||||
"tls": "goo,gii",
|
||||
"tls_acme": "TLS",
|
||||
"tls_ciphersuites": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"tls_minversion": "VersionTLS11",
|
||||
"whitelist_sourcerange": "10.42.0.0/16,152.89.1.33/32,afed:be44::/16",
|
||||
"whitelist_ipstrategy_depth": "3",
|
||||
"whitelist_ipstrategy_excludedips": "10.0.0.3/24,20.0.0.3/24",
|
||||
|
@ -95,15 +86,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
|
|||
"compress": "on",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "TLS",
|
||||
value: "Name:foo TLS:goo TLS",
|
||||
expectedResult: map[string]string{
|
||||
"name": "foo",
|
||||
"tls": "goo",
|
||||
"tls_acme": "TLS",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -185,23 +167,12 @@ func TestEntryPoints_Set(t *testing.T) {
|
|||
name: "all parameters camelcase",
|
||||
expression: "Name:foo " +
|
||||
"Address::8000 " +
|
||||
"TLS " +
|
||||
"TLS.MinVersion:VersionTLS11 " +
|
||||
"TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
|
||||
"CA:car " +
|
||||
"CA.Optional:true " +
|
||||
"ProxyProtocol.TrustedIPs:192.168.0.1 ",
|
||||
expectedEntryPointName: "foo",
|
||||
expectedEntryPoint: &EntryPoint{
|
||||
Address: ":8000",
|
||||
TLS: &tls.TLS{
|
||||
MinVersion: "VersionTLS11",
|
||||
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
|
||||
ClientCA: tls.ClientCA{
|
||||
Files: tls.FilesOrContents{"car"},
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
ProxyProtocol: &ProxyProtocol{
|
||||
Insecure: false,
|
||||
TrustedIPs: []string{"192.168.0.1"},
|
||||
|
@ -223,14 +194,6 @@ func TestEntryPoints_Set(t *testing.T) {
|
|||
expectedEntryPointName: "foo",
|
||||
expectedEntryPoint: &EntryPoint{
|
||||
Address: ":8000",
|
||||
TLS: &tls.TLS{
|
||||
MinVersion: "VersionTLS11",
|
||||
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
|
||||
ClientCA: tls.ClientCA{
|
||||
Files: tls.FilesOrContents{"car"},
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
ProxyProtocol: &ProxyProtocol{
|
||||
Insecure: false,
|
||||
TrustedIPs: []string{"192.168.0.1"},
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/containous/flaeg/parse"
|
||||
"github.com/containous/traefik/acme"
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/old/provider/boltdb"
|
||||
"github.com/containous/traefik/old/provider/consul"
|
||||
|
@ -70,7 +69,7 @@ type Configuration struct {
|
|||
|
||||
HostResolver *types.HostResolverConfig `description:"Enable CNAME Flattening" export:"true"`
|
||||
|
||||
ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true"`
|
||||
ACME *acmeprovider.Configuration `description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true"`
|
||||
}
|
||||
|
||||
// Global holds the global configuration.
|
||||
|
@ -338,10 +337,6 @@ func (c *Configuration) initACMEProvider() {
|
|||
log.Warn("Unable to use HTTP challenge and TLS challenge at the same time. Fallback to TLS challenge.")
|
||||
c.ACME.HTTPChallenge = nil
|
||||
}
|
||||
|
||||
if c.ACME.OnDemand {
|
||||
log.Warn("ACME.OnDemand is deprecated")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,18 +344,11 @@ func (c *Configuration) initACMEProvider() {
|
|||
func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) {
|
||||
if c.ACME != nil {
|
||||
if len(c.ACME.Storage) == 0 {
|
||||
// Delete the ACME configuration to avoid starting ACME in cluster mode
|
||||
c.ACME = nil
|
||||
return nil, errors.New("unable to initialize ACME provider with no storage location for the certificates")
|
||||
}
|
||||
provider := &acmeprovider.Provider{}
|
||||
provider.Configuration = convertACMEChallenge(c.ACME)
|
||||
|
||||
store := acmeprovider.NewLocalStore(provider.Storage)
|
||||
provider.Store = store
|
||||
acme.ConvertToNewFormat(provider.Storage)
|
||||
c.ACME = nil
|
||||
return provider, nil
|
||||
return &acmeprovider.Provider{
|
||||
Configuration: c.ACME,
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -368,12 +356,26 @@ func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) {
|
|||
// ValidateConfiguration validate that configuration is coherent
|
||||
func (c *Configuration) ValidateConfiguration() {
|
||||
if c.ACME != nil {
|
||||
if _, ok := c.EntryPoints[c.ACME.EntryPoint]; !ok {
|
||||
log.Fatalf("Unknown entrypoint %q for ACME configuration", c.ACME.EntryPoint)
|
||||
} else if c.EntryPoints[c.ACME.EntryPoint].TLS == nil {
|
||||
log.Fatalf("Entrypoint %q has no TLS configuration for ACME configuration", c.ACME.EntryPoint)
|
||||
for _, domain := range c.ACME.Domains {
|
||||
if domain.Main != dns01.UnFqdn(domain.Main) {
|
||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
|
||||
}
|
||||
for _, san := range domain.SANs {
|
||||
if san != dns01.UnFqdn(san) {
|
||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME Validate store config?
|
||||
// if c.ACME != nil {
|
||||
// if _, ok := c.EntryPoints[c.ACME.EntryPoint]; !ok {
|
||||
// log.Fatalf("Unknown entrypoint %q for ACME configuration", c.ACME.EntryPoint)
|
||||
// }
|
||||
// else if c.EntryPoints[c.ACME.EntryPoint].TLS == nil {
|
||||
// log.Fatalf("Entrypoint %q has no TLS configuration for ACME configuration", c.ACME.EntryPoint)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
func getSafeACMECAServer(caServerSrc string) string {
|
||||
|
@ -395,47 +397,3 @@ func getSafeACMECAServer(caServerSrc string) string {
|
|||
|
||||
return caServerSrc
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func convertACMEChallenge(oldACMEChallenge *acme.ACME) *acmeprovider.Configuration {
|
||||
conf := &acmeprovider.Configuration{
|
||||
KeyType: oldACMEChallenge.KeyType,
|
||||
OnHostRule: oldACMEChallenge.OnHostRule,
|
||||
OnDemand: oldACMEChallenge.OnDemand,
|
||||
Email: oldACMEChallenge.Email,
|
||||
Storage: oldACMEChallenge.Storage,
|
||||
ACMELogging: oldACMEChallenge.ACMELogging,
|
||||
CAServer: oldACMEChallenge.CAServer,
|
||||
EntryPoint: oldACMEChallenge.EntryPoint,
|
||||
}
|
||||
|
||||
for _, domain := range oldACMEChallenge.Domains {
|
||||
if domain.Main != dns01.UnFqdn(domain.Main) {
|
||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
|
||||
}
|
||||
for _, san := range domain.SANs {
|
||||
if san != dns01.UnFqdn(san) {
|
||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
|
||||
}
|
||||
}
|
||||
conf.Domains = append(conf.Domains, domain)
|
||||
}
|
||||
if oldACMEChallenge.HTTPChallenge != nil {
|
||||
conf.HTTPChallenge = &acmeprovider.HTTPChallenge{
|
||||
EntryPoint: oldACMEChallenge.HTTPChallenge.EntryPoint,
|
||||
}
|
||||
}
|
||||
|
||||
if oldACMEChallenge.DNSChallenge != nil {
|
||||
conf.DNSChallenge = &acmeprovider.DNSChallenge{
|
||||
Provider: oldACMEChallenge.DNSChallenge.Provider,
|
||||
DelayBeforeCheck: oldACMEChallenge.DNSChallenge.DelayBeforeCheck,
|
||||
}
|
||||
}
|
||||
|
||||
if oldACMEChallenge.TLSChallenge != nil {
|
||||
conf.TLSChallenge = &acmeprovider.TLSChallenge{}
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue