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.
|
||||
// It's a comma-separated list, so we split it.
|
||||
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)
|
||||
if match == nil {
|
||||
return errors.New("Bad EntryPoints format: " + value)
|
||||
|
@ -120,6 +120,10 @@ func (ep *EntryPoints) Set(value string) error {
|
|||
Certificates: Certificates{},
|
||||
}
|
||||
}
|
||||
if len(result["CA"]) > 0 {
|
||||
files := strings.Split(result["CA"], ",")
|
||||
tls.ClientCAFiles = files
|
||||
}
|
||||
var redirect *Redirect
|
||||
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
|
||||
redirect = &Redirect{
|
||||
|
@ -168,7 +172,8 @@ type Redirect struct {
|
|||
|
||||
// TLS configures TLS for an entry point
|
||||
type TLS struct {
|
||||
Certificates Certificates
|
||||
Certificates Certificates
|
||||
ClientCAFiles []string
|
||||
}
|
||||
|
||||
// Certificates defines traefik certificates type
|
||||
|
|
|
@ -30,7 +30,7 @@ Entrypoints are the network entry points into Træfɪk.
|
|||
They can be defined using:
|
||||
|
||||
- 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`)
|
||||
|
||||
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 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
|
||||
|
||||
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]
|
||||
# regex = "^http://localhost/(.*)"
|
||||
# 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.http]
|
||||
|
|
18
server.go
18
server.go
|
@ -5,8 +5,10 @@ package main
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -298,6 +300,22 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou
|
|||
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 _, ok := server.serverEntryPoints[server.globalConfiguration.ACME.EntryPoint]; ok {
|
||||
if entryPointName == server.globalConfiguration.ACME.EntryPoint {
|
||||
|
|
Loading…
Reference in a new issue