Handle RootCAs Certificate
This commit is contained in:
parent
3776e58041
commit
81d011e57d
8 changed files with 245 additions and 32 deletions
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
|
@ -28,6 +29,7 @@ import (
|
||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
"github.com/docker/libkv/store"
|
"github.com/docker/libkv/store"
|
||||||
"github.com/satori/go.uuid"
|
"github.com/satori/go.uuid"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -104,6 +106,7 @@ Complete documentation is available at https://traefik.io`,
|
||||||
//add custom parsers
|
//add custom parsers
|
||||||
f.AddParser(reflect.TypeOf(server.EntryPoints{}), &server.EntryPoints{})
|
f.AddParser(reflect.TypeOf(server.EntryPoints{}), &server.EntryPoints{})
|
||||||
f.AddParser(reflect.TypeOf(server.DefaultEntryPoints{}), &server.DefaultEntryPoints{})
|
f.AddParser(reflect.TypeOf(server.DefaultEntryPoints{}), &server.DefaultEntryPoints{})
|
||||||
|
f.AddParser(reflect.TypeOf(server.RootCAs{}), &server.RootCAs{})
|
||||||
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
|
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
|
||||||
f.AddParser(reflect.TypeOf(kubernetes.Namespaces{}), &kubernetes.Namespaces{})
|
f.AddParser(reflect.TypeOf(kubernetes.Namespaces{}), &kubernetes.Namespaces{})
|
||||||
f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{})
|
f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{})
|
||||||
|
@ -180,6 +183,23 @@ func run(traefikConfiguration *server.TraefikConfiguration) {
|
||||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(globalConfiguration.RootCAs) > 0 {
|
||||||
|
roots := x509.NewCertPool()
|
||||||
|
for _, cert := range globalConfiguration.RootCAs {
|
||||||
|
certContent, err := cert.Read()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error while read RootCAs", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
roots.AppendCertsFromPEM(certContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
tr := http.DefaultTransport.(*http.Transport)
|
||||||
|
tr.TLSClientConfig = &tls.Config{RootCAs: roots}
|
||||||
|
|
||||||
|
http2.ConfigureTransport(tr)
|
||||||
|
}
|
||||||
|
|
||||||
if globalConfiguration.File != nil && len(globalConfiguration.File.Filename) == 0 {
|
if globalConfiguration.File != nil && len(globalConfiguration.File.Filename) == 0 {
|
||||||
// no filename, setting to global config file
|
// no filename, setting to global config file
|
||||||
if len(traefikConfiguration.ConfigFile) != 0 {
|
if len(traefikConfiguration.ConfigFile) != 0 {
|
||||||
|
|
|
@ -95,6 +95,13 @@
|
||||||
#
|
#
|
||||||
# InsecureSkipVerify = true
|
# InsecureSkipVerify = true
|
||||||
|
|
||||||
|
# Register Certificates in the RootCA. This certificates will be use for backends calls.
|
||||||
|
# Note: You can use file path or cert content directly
|
||||||
|
# Optional
|
||||||
|
# Default: []
|
||||||
|
#
|
||||||
|
# RootCAs = [ "/mycert.cert" ]
|
||||||
|
|
||||||
# Entrypoints to be used by frontends that do not specify any entrypoint.
|
# Entrypoints to be used by frontends that do not specify any entrypoint.
|
||||||
# Each frontend can specify its own entrypoints.
|
# Each frontend can specify its own entrypoints.
|
||||||
#
|
#
|
||||||
|
|
41
integration/fixtures/https/rootcas/https.toml
Normal file
41
integration/fixtures/https/rootcas/https.toml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
logLevel = "DEBUG"
|
||||||
|
|
||||||
|
defaultEntryPoints = ["http"]
|
||||||
|
|
||||||
|
# Use certificate in net/internal/testcert.go
|
||||||
|
RootCAs = [ """
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||||
|
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||||
|
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||||
|
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||||
|
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||||
|
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||||
|
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||||
|
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||||
|
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||||
|
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||||
|
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||||
|
fblo6RBxUQ==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
"""]
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":8081"
|
||||||
|
|
||||||
|
[web]
|
||||||
|
address = ":8080"
|
||||||
|
|
||||||
|
[file]
|
||||||
|
|
||||||
|
[backends]
|
||||||
|
[backends.backend1]
|
||||||
|
[backends.backend1.servers.server1]
|
||||||
|
url = "{{ .BackendHost }}"
|
||||||
|
|
||||||
|
[frontends]
|
||||||
|
[frontends.frontend1]
|
||||||
|
backend = "backend1"
|
||||||
|
[frontends.frontend1.routes.test_1]
|
||||||
|
rule = "Path: /ping"
|
25
integration/fixtures/https/rootcas/https_with_file.toml
Normal file
25
integration/fixtures/https/rootcas/https_with_file.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
logLevel = "DEBUG"
|
||||||
|
|
||||||
|
defaultEntryPoints = ["http"]
|
||||||
|
|
||||||
|
# Use certificate in net/internal/testcert.go
|
||||||
|
RootCAs = [ "fixtures/https/rootcas/local.crt"]
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":8081"
|
||||||
|
|
||||||
|
[web]
|
||||||
|
address = ":8080"
|
||||||
|
|
||||||
|
[file]
|
||||||
|
|
||||||
|
[backends]
|
||||||
|
[backends.backend1]
|
||||||
|
[backends.backend1.servers.server1]
|
||||||
|
url = "{{ .BackendHost }}"
|
||||||
|
[frontends]
|
||||||
|
[frontends.frontend1]
|
||||||
|
backend = "backend1"
|
||||||
|
[frontends.frontend1.routes.test_1]
|
||||||
|
rule = "Path: /ping"
|
14
integration/fixtures/https/rootcas/local.crt
Normal file
14
integration/fixtures/https/rootcas/local.crt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||||
|
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||||
|
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||||
|
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||||
|
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||||
|
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||||
|
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||||
|
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||||
|
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||||
|
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||||
|
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||||
|
fblo6RBxUQ==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containous/traefik/integration/try"
|
"github.com/containous/traefik/integration/try"
|
||||||
|
@ -271,6 +272,48 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipeCAsMultipleFi
|
||||||
c.Assert(err, checker.NotNil, check.Commentf("should not be allowed to connect to server"))
|
c.Assert(err, checker.NotNil, check.Commentf("should not be allowed to connect to server"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *HTTPSSuite) TestWithRootCAsContentForHTTPSOnBackend(c *check.C) {
|
||||||
|
backend := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
file := s.adaptFile(c, "fixtures/https/rootcas/https.toml", struct{ BackendHost string }{backend.URL})
|
||||||
|
defer os.Remove(file)
|
||||||
|
cmd, _ := s.cmdTraefikWithConfigFile(file)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
// wait for Traefik
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1000*time.Millisecond, try.BodyContains(backend.URL))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8081/ping", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HTTPSSuite) TestWithRootCAsFileForHTTPSOnBackend(c *check.C) {
|
||||||
|
backend := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
file := s.adaptFile(c, "fixtures/https/rootcas/https_with_file.toml", struct{ BackendHost string }{backend.URL})
|
||||||
|
defer os.Remove(file)
|
||||||
|
cmd, _ := s.cmdTraefikWithConfigFile(file)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
// wait for Traefik
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1000*time.Millisecond, try.BodyContains(backend.URL))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8081/ping", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
func startTestServer(port string, statusCode int) (ts *httptest.Server) {
|
func startTestServer(port string, statusCode int) (ts *httptest.Server) {
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(statusCode)
|
w.WriteHeader(statusCode)
|
||||||
|
|
|
@ -2,8 +2,8 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -56,6 +56,7 @@ type GlobalConfiguration struct {
|
||||||
MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"`
|
MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"`
|
||||||
IdleTimeout flaeg.Duration `description:"maximum amount of time an idle (keep-alive) connection will remain idle before closing itself."`
|
IdleTimeout flaeg.Duration `description:"maximum amount of time an idle (keep-alive) connection will remain idle before closing itself."`
|
||||||
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
|
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
|
||||||
|
RootCAs RootCAs `description:"Add cert file for self-signed certicate"`
|
||||||
Retry *Retry `description:"Enable retry sending request if network error"`
|
Retry *Retry `description:"Enable retry sending request if network error"`
|
||||||
HealthCheck *HealthCheckConfig `description:"Health check parameters"`
|
HealthCheck *HealthCheckConfig `description:"Health check parameters"`
|
||||||
Docker *docker.Provider `description:"Enable Docker backend"`
|
Docker *docker.Provider `description:"Enable Docker backend"`
|
||||||
|
@ -110,7 +111,69 @@ func (dep *DefaultEntryPoints) SetValue(val interface{}) {
|
||||||
|
|
||||||
// Type is type of the struct
|
// Type is type of the struct
|
||||||
func (dep *DefaultEntryPoints) Type() string {
|
func (dep *DefaultEntryPoints) Type() string {
|
||||||
return fmt.Sprint("defaultentrypoints")
|
return "defaultentrypoints"
|
||||||
|
}
|
||||||
|
|
||||||
|
// RootCAs hold the CA we want to have in root
|
||||||
|
type RootCAs []FileOrContent
|
||||||
|
|
||||||
|
// FileOrContent hold a file path or content
|
||||||
|
type FileOrContent string
|
||||||
|
|
||||||
|
func (f FileOrContent) String() string {
|
||||||
|
return string(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileOrContent) Read() ([]byte, error) {
|
||||||
|
var content []byte
|
||||||
|
if _, err := os.Stat(f.String()); err == nil {
|
||||||
|
content, err = ioutil.ReadFile(f.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content = []byte(f)
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is the method to format the flag's value, part of the flag.Value interface.
|
||||||
|
// The String method's output will be used in diagnostics.
|
||||||
|
func (r *RootCAs) String() string {
|
||||||
|
sliceOfString := make([]string, len([]FileOrContent(*r)))
|
||||||
|
for key, value := range *r {
|
||||||
|
sliceOfString[key] = value.String()
|
||||||
|
}
|
||||||
|
return strings.Join(sliceOfString, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is the method to set the flag value, part of the flag.Value interface.
|
||||||
|
// Set's argument is a string to be parsed to set the flag.
|
||||||
|
// It's a comma-separated list, so we split it.
|
||||||
|
func (r *RootCAs) Set(value string) error {
|
||||||
|
rootCAs := strings.Split(value, ",")
|
||||||
|
if len(rootCAs) == 0 {
|
||||||
|
return fmt.Errorf("bad RootCAs format: %s", value)
|
||||||
|
}
|
||||||
|
for _, rootCA := range rootCAs {
|
||||||
|
*r = append(*r, FileOrContent(rootCA))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get return the EntryPoints map
|
||||||
|
func (r *RootCAs) Get() interface{} {
|
||||||
|
return RootCAs(*r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValue sets the EntryPoints map with val
|
||||||
|
func (r *RootCAs) SetValue(val interface{}) {
|
||||||
|
*r = RootCAs(val.(RootCAs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type is type of the struct
|
||||||
|
func (r *RootCAs) Type() string {
|
||||||
|
return "rootcas"
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
|
// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
|
||||||
|
@ -192,7 +255,7 @@ func (ep *EntryPoints) SetValue(val interface{}) {
|
||||||
|
|
||||||
// Type is type of the struct
|
// Type is type of the struct
|
||||||
func (ep *EntryPoints) Type() string {
|
func (ep *EntryPoints) Type() string {
|
||||||
return fmt.Sprint("entrypoints")
|
return "entrypoints"
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
|
// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
|
||||||
|
@ -264,32 +327,25 @@ func (certs *Certificates) CreateTLSConfig() (*tls.Config, error) {
|
||||||
config.Certificates = []tls.Certificate{}
|
config.Certificates = []tls.Certificate{}
|
||||||
certsSlice := []Certificate(*certs)
|
certsSlice := []Certificate(*certs)
|
||||||
for _, v := range certsSlice {
|
for _, v := range certsSlice {
|
||||||
isAPath := false
|
cert := tls.Certificate{}
|
||||||
_, errCert := os.Stat(v.CertFile)
|
|
||||||
_, errKey := os.Stat(v.KeyFile)
|
var err error
|
||||||
if errCert == nil {
|
|
||||||
if errKey == nil {
|
certContent, err := v.CertFile.Read()
|
||||||
isAPath = true
|
if err != nil {
|
||||||
} else {
|
return nil, err
|
||||||
return nil, errors.New("bad TLS Certificate KeyFile format, expected a path")
|
|
||||||
}
|
|
||||||
} else if errKey == nil {
|
|
||||||
return nil, errors.New("bad TLS Certificate KeyFile format, expected a path")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := tls.Certificate{}
|
keyContent, err := v.KeyFile.Read()
|
||||||
var err error
|
if err != nil {
|
||||||
if isAPath {
|
return nil, err
|
||||||
cert, err = tls.LoadX509KeyPair(v.CertFile, v.KeyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cert, err = tls.X509KeyPair([]byte(v.CertFile), []byte(v.KeyFile))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cert, err = tls.X509KeyPair(certContent, keyContent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
config.Certificates = append(config.Certificates, cert)
|
config.Certificates = append(config.Certificates, cert)
|
||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
|
@ -303,7 +359,7 @@ func (certs *Certificates) String() string {
|
||||||
}
|
}
|
||||||
var result []string
|
var result []string
|
||||||
for _, certificate := range *certs {
|
for _, certificate := range *certs {
|
||||||
result = append(result, certificate.CertFile+","+certificate.KeyFile)
|
result = append(result, certificate.CertFile.String()+","+certificate.KeyFile.String())
|
||||||
}
|
}
|
||||||
return strings.Join(result, ";")
|
return strings.Join(result, ";")
|
||||||
}
|
}
|
||||||
|
@ -319,8 +375,8 @@ func (certs *Certificates) Set(value string) error {
|
||||||
return fmt.Errorf("bad certificates format: %s", value)
|
return fmt.Errorf("bad certificates format: %s", value)
|
||||||
}
|
}
|
||||||
*certs = append(*certs, Certificate{
|
*certs = append(*certs, Certificate{
|
||||||
CertFile: files[0],
|
CertFile: FileOrContent(files[0]),
|
||||||
KeyFile: files[1],
|
KeyFile: FileOrContent(files[1]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -328,14 +384,14 @@ func (certs *Certificates) Set(value string) error {
|
||||||
|
|
||||||
// Type is type of the struct
|
// Type is type of the struct
|
||||||
func (certs *Certificates) Type() string {
|
func (certs *Certificates) Type() string {
|
||||||
return fmt.Sprint("certificates")
|
return "certificates"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certificate holds a SSL cert/key pair
|
// Certificate holds a SSL cert/key pair
|
||||||
// Certs and Key could be either a file path, or the file content itself
|
// Certs and Key could be either a file path, or the file content itself
|
||||||
type Certificate struct {
|
type Certificate struct {
|
||||||
CertFile string
|
CertFile FileOrContent
|
||||||
KeyFile string
|
KeyFile FileOrContent
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry contains request retry config
|
// Retry contains request retry config
|
||||||
|
|
|
@ -76,6 +76,13 @@
|
||||||
#
|
#
|
||||||
# InsecureSkipVerify = true
|
# InsecureSkipVerify = true
|
||||||
|
|
||||||
|
# Register Certificates in the RootCA. This certificates will be use for backends calls.
|
||||||
|
# Note: You can use file path or cert content directly
|
||||||
|
# Optional
|
||||||
|
# Default: []
|
||||||
|
#
|
||||||
|
# RootCAs = [ "/mycert.cert" ]
|
||||||
|
|
||||||
# Entrypoints to be used by frontends that do not specify any entrypoint.
|
# Entrypoints to be used by frontends that do not specify any entrypoint.
|
||||||
# Each frontend can specify its own entrypoints.
|
# Each frontend can specify its own entrypoints.
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in a new issue