Support for client certificate authentication
This commit is contained in:
parent
8e333d0a03
commit
959c7dc783
4 changed files with 65 additions and 3 deletions
|
@ -94,7 +94,7 @@ func (ep *EntryPoints) String() string {
|
||||||
// Set's argument is a string to be parsed to set the flag.
|
// Set's argument is a string to be parsed to set the flag.
|
||||||
// It's a comma-separated list, so we split it.
|
// It's a comma-separated list, so we split it.
|
||||||
func (ep *EntryPoints) Set(value string) error {
|
func (ep *EntryPoints) Set(value string) error {
|
||||||
regex := regexp.MustCompile("(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*((?P<TLSACME>TLS))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?")
|
regex := regexp.MustCompile("(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*((?P<TLSACME>TLS))?\\s*(?:CA:(?P<CA>\\S*))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?")
|
||||||
match := regex.FindAllStringSubmatch(value, -1)
|
match := regex.FindAllStringSubmatch(value, -1)
|
||||||
if match == nil {
|
if match == nil {
|
||||||
return errors.New("Bad EntryPoints format: " + value)
|
return errors.New("Bad EntryPoints format: " + value)
|
||||||
|
@ -120,6 +120,10 @@ func (ep *EntryPoints) Set(value string) error {
|
||||||
Certificates: Certificates{},
|
Certificates: Certificates{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(result["CA"]) > 0 {
|
||||||
|
files := strings.Split(result["CA"], ",")
|
||||||
|
tls.ClientCAFiles = files
|
||||||
|
}
|
||||||
var redirect *Redirect
|
var redirect *Redirect
|
||||||
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
|
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
|
||||||
redirect = &Redirect{
|
redirect = &Redirect{
|
||||||
|
@ -168,7 +172,8 @@ type Redirect struct {
|
||||||
|
|
||||||
// TLS configures TLS for an entry point
|
// TLS configures TLS for an entry point
|
||||||
type TLS struct {
|
type TLS struct {
|
||||||
Certificates Certificates
|
Certificates Certificates
|
||||||
|
ClientCAFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certificates defines traefik certificates type
|
// Certificates defines traefik certificates type
|
||||||
|
|
|
@ -30,7 +30,7 @@ Entrypoints are the network entry points into Træfɪk.
|
||||||
They can be defined using:
|
They can be defined using:
|
||||||
|
|
||||||
- a port (80, 443...)
|
- a port (80, 443...)
|
||||||
- SSL (Certificates. Keys...)
|
- SSL (Certificates, Keys, authentication with a client certificate signed by a trusted CA...)
|
||||||
- redirection to another entrypoint (redirect `HTTP` to `HTTPS`)
|
- redirection to another entrypoint (redirect `HTTP` to `HTTPS`)
|
||||||
|
|
||||||
Here is an example of entrypoints definition:
|
Here is an example of entrypoints definition:
|
||||||
|
@ -54,6 +54,23 @@ Here is an example of entrypoints definition:
|
||||||
- We enable SSL on `https` by giving a certificate and a key.
|
- We enable SSL on `https` by giving a certificate and a key.
|
||||||
- We also redirect all the traffic from entrypoint `http` to `https`.
|
- We also redirect all the traffic from entrypoint `http` to `https`.
|
||||||
|
|
||||||
|
And here is another example with client certificate authentication:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.https]
|
||||||
|
address = ":443"
|
||||||
|
[entryPoints.https.tls]
|
||||||
|
clientCAFiles = ["tests/clientca1.crt", "tests/clientca2.crt"]
|
||||||
|
[[entryPoints.https.tls.certificates]]
|
||||||
|
certFile = "tests/traefik.crt"
|
||||||
|
keyFile = "tests/traefik.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We enable SSL on `https` by giving a certificate and a key.
|
||||||
|
- One or several files containing Certificate Authorities in PEM format are added.
|
||||||
|
- It is possible to have multiple CA:s in the same file or keep them in separate files.
|
||||||
|
|
||||||
## Frontends
|
## Frontends
|
||||||
|
|
||||||
A frontend is a set of rules that forwards the incoming traffic from an entrypoint to a backend.
|
A frontend is a set of rules that forwards the incoming traffic from an entrypoint to a backend.
|
||||||
|
|
22
docs/toml.md
22
docs/toml.md
|
@ -89,6 +89,28 @@
|
||||||
# [entryPoints.http.redirect]
|
# [entryPoints.http.redirect]
|
||||||
# regex = "^http://localhost/(.*)"
|
# regex = "^http://localhost/(.*)"
|
||||||
# replacement = "http://mydomain/$1"
|
# replacement = "http://mydomain/$1"
|
||||||
|
#
|
||||||
|
# Only accept clients that present a certificate signed by a specified
|
||||||
|
# Certificate Authority (CA)
|
||||||
|
# ClientCAFiles can be configured with multiple CA:s in the same file or
|
||||||
|
# use multiple files containing one or several CA:s. The CA:s has to be in PEM format.
|
||||||
|
# All clients will be required to present a valid cert.
|
||||||
|
# The requirement will apply to all server certs in the entrypoint
|
||||||
|
# In the example below both snitest.com and snitest.org will require client certs
|
||||||
|
#
|
||||||
|
# [entryPoints]
|
||||||
|
# [entryPoints.https]
|
||||||
|
# address = ":443"
|
||||||
|
# [entryPoints.https.tls]
|
||||||
|
# ClientCAFiles = ["tests/clientca1.crt", "tests/clientca2.crt"]
|
||||||
|
# [[entryPoints.https.tls.certificates]]
|
||||||
|
# CertFile = "integration/fixtures/https/snitest.com.cert"
|
||||||
|
# KeyFile = "integration/fixtures/https/snitest.com.key"
|
||||||
|
# [[entryPoints.https.tls.certificates]]
|
||||||
|
# CertFile = "integration/fixtures/https/snitest.org.cert"
|
||||||
|
# KeyFile = "integration/fixtures/https/snitest.org.key"
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.http]
|
[entryPoints.http]
|
||||||
|
|
18
server.go
18
server.go
|
@ -5,8 +5,10 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -298,6 +300,22 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou
|
||||||
config.Certificates = append(config.Certificates, cert)
|
config.Certificates = append(config.Certificates, cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(tlsOption.ClientCAFiles) > 0 {
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
for _, caFile := range tlsOption.ClientCAFiles {
|
||||||
|
data, err := ioutil.ReadFile(caFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ok := pool.AppendCertsFromPEM(data)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid certificate(s) in " + caFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.ClientCAs = pool
|
||||||
|
config.ClientAuth = tls.RequireAndVerifyClientCert
|
||||||
|
}
|
||||||
|
|
||||||
if server.globalConfiguration.ACME != nil {
|
if server.globalConfiguration.ACME != nil {
|
||||||
if _, ok := server.serverEntryPoints[server.globalConfiguration.ACME.EntryPoint]; ok {
|
if _, ok := server.serverEntryPoints[server.globalConfiguration.ACME.EntryPoint]; ok {
|
||||||
if entryPointName == server.globalConfiguration.ACME.EntryPoint {
|
if entryPointName == server.globalConfiguration.ACME.EntryPoint {
|
||||||
|
|
Loading…
Reference in a new issue