Copys the incoming TLS client certificate to the outgoing request. The backend can then use this certificate for client authentication ie. k8s client cert authentication
312 lines
8.2 KiB
Go
312 lines
8.2 KiB
Go
package types
|
|
|
|
import (
|
|
"encoding"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/libkv/store"
|
|
"github.com/ryanuber/go-glob"
|
|
)
|
|
|
|
// Backend holds backend configuration.
|
|
type Backend struct {
|
|
Servers map[string]Server `json:"servers,omitempty"`
|
|
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"`
|
|
LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty"`
|
|
MaxConn *MaxConn `json:"maxConn,omitempty"`
|
|
HealthCheck *HealthCheck `json:"healthCheck,omitempty"`
|
|
}
|
|
|
|
// MaxConn holds maximum connection configuration
|
|
type MaxConn struct {
|
|
Amount int64 `json:"amount,omitempty"`
|
|
ExtractorFunc string `json:"extractorFunc,omitempty"`
|
|
}
|
|
|
|
// LoadBalancer holds load balancing configuration.
|
|
type LoadBalancer struct {
|
|
Method string `json:"method,omitempty"`
|
|
Sticky bool `json:"sticky,omitempty"`
|
|
}
|
|
|
|
// CircuitBreaker holds circuit breaker configuration.
|
|
type CircuitBreaker struct {
|
|
Expression string `json:"expression,omitempty"`
|
|
}
|
|
|
|
// HealthCheck holds HealthCheck configuration
|
|
type HealthCheck struct {
|
|
Path string `json:"path,omitempty"`
|
|
Interval string `json:"interval,omitempty"`
|
|
}
|
|
|
|
// Server holds server configuration.
|
|
type Server struct {
|
|
URL string `json:"url,omitempty"`
|
|
Weight int `json:"weight"`
|
|
}
|
|
|
|
// Route holds route configuration.
|
|
type Route struct {
|
|
Rule string `json:"rule,omitempty"`
|
|
}
|
|
|
|
// Frontend holds frontend configuration.
|
|
type Frontend struct {
|
|
EntryPoints []string `json:"entryPoints,omitempty"`
|
|
Backend string `json:"backend,omitempty"`
|
|
Routes map[string]Route `json:"routes,omitempty"`
|
|
PassHostHeader bool `json:"passHostHeader,omitempty"`
|
|
PassTLSCert bool `json:"passTLSCert,omitempty"`
|
|
Priority int `json:"priority"`
|
|
BasicAuth []string `json:"basicAuth"`
|
|
WhitelistSourceRange []string `json:"whitelistSourceRange,omitempty"`
|
|
}
|
|
|
|
// LoadBalancerMethod holds the method of load balancing to use.
|
|
type LoadBalancerMethod uint8
|
|
|
|
const (
|
|
// Wrr (default) = Weighted Round Robin
|
|
Wrr LoadBalancerMethod = iota
|
|
// Drr = Dynamic Round Robin
|
|
Drr
|
|
)
|
|
|
|
var loadBalancerMethodNames = []string{
|
|
"Wrr",
|
|
"Drr",
|
|
}
|
|
|
|
// NewLoadBalancerMethod create a new LoadBalancerMethod from a given LoadBalancer.
|
|
func NewLoadBalancerMethod(loadBalancer *LoadBalancer) (LoadBalancerMethod, error) {
|
|
var method string
|
|
if loadBalancer != nil {
|
|
method = loadBalancer.Method
|
|
for i, name := range loadBalancerMethodNames {
|
|
if strings.EqualFold(name, method) {
|
|
return LoadBalancerMethod(i), nil
|
|
}
|
|
}
|
|
}
|
|
return Wrr, fmt.Errorf("invalid load-balancing method '%s'", method)
|
|
}
|
|
|
|
// Configuration of a provider.
|
|
type Configuration struct {
|
|
Backends map[string]*Backend `json:"backends,omitempty"`
|
|
Frontends map[string]*Frontend `json:"frontends,omitempty"`
|
|
}
|
|
|
|
// ConfigMessage hold configuration information exchanged between parts of traefik.
|
|
type ConfigMessage struct {
|
|
ProviderName string
|
|
Configuration *Configuration
|
|
}
|
|
|
|
// Constraint hold a parsed constraint expresssion
|
|
type Constraint struct {
|
|
Key string
|
|
// MustMatch is true if operator is "==" or false if operator is "!="
|
|
MustMatch bool
|
|
// TODO: support regex
|
|
Regex string
|
|
}
|
|
|
|
// NewConstraint receive a string and return a *Constraint, after checking syntax and parsing the constraint expression
|
|
func NewConstraint(exp string) (*Constraint, error) {
|
|
sep := ""
|
|
constraint := &Constraint{}
|
|
|
|
if strings.Contains(exp, "==") {
|
|
sep = "=="
|
|
constraint.MustMatch = true
|
|
} else if strings.Contains(exp, "!=") {
|
|
sep = "!="
|
|
constraint.MustMatch = false
|
|
} else {
|
|
return nil, errors.New("Constraint expression missing valid operator: '==' or '!='")
|
|
}
|
|
|
|
kv := strings.SplitN(exp, sep, 2)
|
|
if len(kv) == 2 {
|
|
// At the moment, it only supports tags
|
|
if kv[0] != "tag" {
|
|
return nil, errors.New("Constraint must be tag-based. Syntax: tag==us-*")
|
|
}
|
|
|
|
constraint.Key = kv[0]
|
|
constraint.Regex = kv[1]
|
|
return constraint, nil
|
|
}
|
|
|
|
return nil, errors.New("Incorrect constraint expression: " + exp)
|
|
}
|
|
|
|
func (c *Constraint) String() string {
|
|
if c.MustMatch {
|
|
return c.Key + "==" + c.Regex
|
|
}
|
|
return c.Key + "!=" + c.Regex
|
|
}
|
|
|
|
var _ encoding.TextUnmarshaler = (*Constraint)(nil)
|
|
|
|
// UnmarshalText define how unmarshal in TOML parsing
|
|
func (c *Constraint) UnmarshalText(text []byte) error {
|
|
constraint, err := NewConstraint(string(text))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.Key = constraint.Key
|
|
c.MustMatch = constraint.MustMatch
|
|
c.Regex = constraint.Regex
|
|
return nil
|
|
}
|
|
|
|
var _ encoding.TextMarshaler = (*Constraint)(nil)
|
|
|
|
// MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
|
|
func (c *Constraint) MarshalText() (text []byte, err error) {
|
|
return []byte(c.String()), nil
|
|
}
|
|
|
|
// MatchConstraintWithAtLeastOneTag tests a constraint for one single service
|
|
func (c *Constraint) MatchConstraintWithAtLeastOneTag(tags []string) bool {
|
|
for _, tag := range tags {
|
|
if glob.Glob(c.Regex, tag) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
//Set []*Constraint
|
|
func (cs *Constraints) Set(str string) error {
|
|
exps := strings.Split(str, ",")
|
|
if len(exps) == 0 {
|
|
return errors.New("Bad Constraint format: " + str)
|
|
}
|
|
for _, exp := range exps {
|
|
constraint, err := NewConstraint(exp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*cs = append(*cs, constraint)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Constraints holds a Constraint parser
|
|
type Constraints []*Constraint
|
|
|
|
//Get []*Constraint
|
|
func (cs *Constraints) Get() interface{} { return []*Constraint(*cs) }
|
|
|
|
//String returns []*Constraint in string
|
|
func (cs *Constraints) String() string { return fmt.Sprintf("%+v", *cs) }
|
|
|
|
//SetValue sets []*Constraint into the parser
|
|
func (cs *Constraints) SetValue(val interface{}) {
|
|
*cs = Constraints(val.(Constraints))
|
|
}
|
|
|
|
// Type exports the Constraints type as a string
|
|
func (cs *Constraints) Type() string {
|
|
return fmt.Sprint("constraint")
|
|
}
|
|
|
|
// Store holds KV store cluster config
|
|
type Store struct {
|
|
store.Store
|
|
Prefix string // like this "prefix" (without the /)
|
|
}
|
|
|
|
// Cluster holds cluster config
|
|
type Cluster struct {
|
|
Node string `description:"Node name"`
|
|
Store *Store
|
|
}
|
|
|
|
// Auth holds authentication configuration (BASIC, DIGEST, users)
|
|
type Auth struct {
|
|
Basic *Basic
|
|
Digest *Digest
|
|
HeaderField string
|
|
}
|
|
|
|
// Users authentication users
|
|
type Users []string
|
|
|
|
// Basic HTTP basic authentication
|
|
type Basic struct {
|
|
Users `mapstructure:","`
|
|
UsersFile string
|
|
}
|
|
|
|
// Digest HTTP authentication
|
|
type Digest struct {
|
|
Users `mapstructure:","`
|
|
UsersFile string
|
|
}
|
|
|
|
// CanonicalDomain returns a lower case domain with trim space
|
|
func CanonicalDomain(domain string) string {
|
|
return strings.ToLower(strings.TrimSpace(domain))
|
|
}
|
|
|
|
// Statistics provides options for monitoring request and response stats
|
|
type Statistics struct {
|
|
RecentErrors int `description:"Number of recent errors logged"`
|
|
}
|
|
|
|
// Metrics provides options to expose and send Traefik metrics to different third party monitoring systems
|
|
type Metrics struct {
|
|
Prometheus *Prometheus `description:"Prometheus metrics exporter type"`
|
|
}
|
|
|
|
// Prometheus can contain specific configuration used by the Prometheus Metrics exporter
|
|
type Prometheus struct {
|
|
Buckets Buckets `description:"Buckets for latency metrics"`
|
|
}
|
|
|
|
// Buckets holds Prometheus Buckets
|
|
type Buckets []float64
|
|
|
|
//Set adds strings elem into the the parser
|
|
//it splits str on "," and ";" and apply ParseFloat to string
|
|
func (b *Buckets) Set(str string) error {
|
|
fargs := func(c rune) bool {
|
|
return c == ',' || c == ';'
|
|
}
|
|
// get function
|
|
slice := strings.FieldsFunc(str, fargs)
|
|
for _, bucket := range slice {
|
|
bu, err := strconv.ParseFloat(bucket, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*b = append(*b, bu)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
//Get []float64
|
|
func (b *Buckets) Get() interface{} { return Buckets(*b) }
|
|
|
|
//String return slice in a string
|
|
func (b *Buckets) String() string { return fmt.Sprintf("%v", *b) }
|
|
|
|
//SetValue sets []float64 into the parser
|
|
func (b *Buckets) SetValue(val interface{}) {
|
|
*b = Buckets(val.(Buckets))
|
|
}
|
|
|
|
// AccessLog holds the configuration settings for the access logger (middlewares/accesslog).
|
|
type AccessLog struct {
|
|
FilePath string `json:"file,omitempty" description:"Access log file path"`
|
|
Format string `json:"format,omitempty" description:"Access log format: json | common"`
|
|
}
|