Skip to content

Commit 4f5cb26

Browse files
TLS authentication working
1 parent 65555c9 commit 4f5cb26

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

armor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package armor
22

33
import (
4+
"crypto/tls"
45
"sync"
56
"time"
67

@@ -75,6 +76,8 @@ type (
7576
Paths Paths `json:"paths"`
7677
Plugins []plugin.Plugin `json:"-"`
7778
Echo *echo.Echo `json:"-"`
79+
ClientCAs []string `json:"client_ca_der"`
80+
TLSConfig *tls.Config `json:"-"`
7881
}
7982

8083
Path struct {

http.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func (a *Armor) NewHTTP() (h *HTTP) {
4949
ReadTimeout: a.ReadTimeout * time.Second,
5050
WriteTimeout: a.WriteTimeout * time.Second,
5151
}
52+
e.TLSServer.TLSConfig.GetConfigForClient = a.GetConfigForClient
5253
e.AutoTLSManager.Email = a.TLS.Email
5354
e.AutoTLSManager.Client = new(acme.Client)
5455
if a.TLS.DirectoryURL != "" {

tls.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package armor
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"encoding/base64"
7+
)
8+
9+
// GetConfigForClient implements the
10+
func (a *Armor) GetConfigForClient(clientHelloInfo *tls.ClientHelloInfo) (*tls.Config, error) {
11+
// Get the host from the hello info
12+
host := a.Hosts[clientHelloInfo.ServerName]
13+
if len(host.ClientCAs) == 0 {
14+
return nil, nil
15+
}
16+
17+
// Use existing host config if exist
18+
if host.TLSConfig != nil {
19+
return host.TLSConfig, nil
20+
}
21+
22+
// Build and save the host config
23+
host.TLSConfig = a.buildTLSConfig(clientHelloInfo, host)
24+
25+
return host.TLSConfig, nil
26+
}
27+
28+
func (a *Armor) buildTLSConfig(clientHelloInfo *tls.ClientHelloInfo, host *Host) *tls.Config {
29+
// Copy the configurations from the regular server
30+
tlsConfig := new(tls.Config)
31+
*tlsConfig = *a.Echo.TLSServer.TLSConfig
32+
33+
// Set the client validation and the certification pool
34+
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
35+
tlsConfig.ClientCAs = a.buildClientCertPool(host)
36+
37+
return tlsConfig
38+
}
39+
40+
func (a *Armor) buildClientCertPool(host *Host) (certPool *x509.CertPool) {
41+
certPool = x509.NewCertPool()
42+
43+
// Loop every CA certs given as base64 DER encoding
44+
for _, clientCAString := range host.ClientCAs {
45+
// Decode base64
46+
derBytes, err := base64.StdEncoding.DecodeString(clientCAString)
47+
if err != nil {
48+
continue
49+
}
50+
if len(derBytes) == 0 {
51+
continue
52+
}
53+
54+
// Parse the DER encoded certificate
55+
var caCert *x509.Certificate
56+
caCert, err = x509.ParseCertificate(derBytes)
57+
if err != nil {
58+
continue
59+
}
60+
61+
// Add the certificate to CertPool
62+
certPool.AddCert(caCert)
63+
}
64+
65+
return certPool
66+
}

0 commit comments

Comments
 (0)