Skip to content

Commit 517d9cb

Browse files
committed
Implement TLS client authentication
1 parent 6bc87b8 commit 517d9cb

File tree

5 files changed

+38
-2
lines changed

5 files changed

+38
-2
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Kenny Keslar <[email protected]>
1010
Konrad Wojas <[email protected]>
1111
Matthew Holt <[email protected]>
1212
13+
Michael Zimmermann <[email protected]>
1314
Wayne Scott <[email protected]>
1415
Zlatko Čalušić <[email protected]>
1516
cgonzalez <[email protected]>

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Flags:
4747
--prometheus enable Prometheus metrics
4848
--prometheus-no-auth disable auth for Prometheus /metrics endpoint
4949
--tls turn on TLS support
50+
--tls-ca string TLS CA certificate path
5051
--tls-cert string TLS certificate path
5152
--tls-key string TLS key path
5253
-v, --version version for rest-server
@@ -68,7 +69,7 @@ If you want to disable authentication, you must add the `--no-auth` flag. If thi
6869

6970
NOTE: In older versions of rest-server (up to 0.9.7), this flag does not exist and the server disables authentication if `.htpasswd` is missing or cannot be opened.
7071

71-
By default the server uses HTTP protocol. This is not very secure since with Basic Authentication, user name and passwords will be sent in clear text in every request. In order to enable TLS support just add the `--tls` argument and add a private and public key at the root of your persistence directory. You may also specify private and public keys by `--tls-cert` and `--tls-key`.
72+
By default the server uses HTTP protocol. This is not very secure since with Basic Authentication, user name and passwords will be sent in clear text in every request. In order to enable TLS support just add the `--tls` argument and add a private and public key at the root of your persistence directory. You may also specify private and public keys by `--tls-cert` and `--tls-key`. Additionally, client authentication can be enabled by passing a CA certificate to `--tls-ca`.
7273

7374
Signed certificate is normally required by the restic backend, but if you just want to test the feature you can generate password-less unsigned keys with the following command:
7475

changelog/unreleased/issue-73

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Feature: TLS Client Authentication
2+
3+
It is now possible to require clients to provide a certificate that was signed
4+
by a certain CA.
5+
6+
https://github.com/restic/rest-server/issues/73
7+
https://github.com/restic/rest-server/pull/193

cmd/rest-server/main.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package main
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
46
"errors"
57
"fmt"
8+
"io/ioutil"
69
"log"
710
"net/http"
811
"os"
@@ -44,6 +47,7 @@ func init() {
4447
flags.Int64Var(&server.MaxRepoSize, "max-size", server.MaxRepoSize, "the maximum size of the repository in bytes")
4548
flags.StringVar(&server.Path, "path", server.Path, "data directory")
4649
flags.BoolVar(&server.TLS, "tls", server.TLS, "turn on TLS support")
50+
flags.StringVar(&server.TLSCACert, "tls-cacert", server.TLSCACert, "TLS CA certificate path")
4751
flags.StringVar(&server.TLSCert, "tls-cert", server.TLSCert, "TLS certificate path")
4852
flags.StringVar(&server.TLSKey, "tls-key", server.TLSKey, "TLS key path")
4953
flags.BoolVar(&server.NoAuth, "no-auth", server.NoAuth, "disable .htpasswd authentication")
@@ -140,7 +144,29 @@ func runRoot(cmd *cobra.Command, args []string) error {
140144
err = http.Serve(listener, handler)
141145
} else {
142146
log.Printf("TLS enabled, private key %s, pubkey %v", privateKey, publicKey)
143-
err = http.ServeTLS(listener, handler, publicKey, privateKey)
147+
148+
httpServer := &http.Server{
149+
Handler: handler,
150+
}
151+
152+
if server.TLSCACert != "" {
153+
log.Printf("TLS Client Authentication enabled, CA cert %s", server.TLSCACert)
154+
155+
caCert, err := ioutil.ReadFile(server.TLSCACert)
156+
if err != nil {
157+
return fmt.Errorf("unable to read CA certificate: %w", err)
158+
}
159+
caCertPool := x509.NewCertPool()
160+
caCertPool.AppendCertsFromPEM(caCert)
161+
162+
tlsConfig := &tls.Config{
163+
ClientAuth: tls.RequireAndVerifyClientCert,
164+
ClientCAs: caCertPool,
165+
}
166+
httpServer.TLSConfig = tlsConfig
167+
}
168+
169+
err = httpServer.ServeTLS(listener, publicKey, privateKey)
144170
}
145171

146172
return err

handlers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type Server struct {
1919
Listen string
2020
Log string
2121
CPUProfile string
22+
TLSCACert string
2223
TLSKey string
2324
TLSCert string
2425
TLS bool

0 commit comments

Comments
 (0)