open tls keys/certificate as root, pass fd's to the unprivileged child process

makes it easier to use tls keys/certs managed by other tools, with or without
acme. the root process has access to open such files. the child process reads
the key from the file descriptor, then closes the file.

for issue #30 by inigoserna, thanks!
This commit is contained in:
Mechiel Lukkien
2023-05-31 14:09:53 +02:00
parent dd0cede4f9
commit 70d07c5459
6 changed files with 119 additions and 36 deletions

View File

@ -10,6 +10,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
@ -1188,7 +1189,7 @@ func loadTLSKeyCerts(configFile, kind string, ctls *config.TLS) error {
for _, kp := range ctls.KeyCerts {
certPath := configDirPath(configFile, kp.CertFile)
keyPath := configDirPath(configFile, kp.KeyFile)
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
cert, err := loadX509KeyPairPrivileged(certPath, keyPath)
if err != nil {
return fmt.Errorf("tls config for %q: parsing x509 key pair: %v", kind, err)
}
@ -1199,3 +1200,27 @@ func loadTLSKeyCerts(configFile, kind string, ctls *config.TLS) error {
}
return nil
}
// load x509 key/cert files from file descriptor possibly passed in by privileged
// process.
func loadX509KeyPairPrivileged(certPath, keyPath string) (tls.Certificate, error) {
certBuf, err := readFilePrivileged(certPath)
if err != nil {
return tls.Certificate{}, fmt.Errorf("reading tls certificate: %v", err)
}
keyBuf, err := readFilePrivileged(keyPath)
if err != nil {
return tls.Certificate{}, fmt.Errorf("reading tls key: %v", err)
}
return tls.X509KeyPair(certBuf, keyBuf)
}
// like os.ReadFile, but open privileged file possibly passed in by root process.
func readFilePrivileged(path string) ([]byte, error) {
f, err := OpenPrivileged(path)
if err != nil {
return nil, err
}
defer f.Close()
return io.ReadAll(f)
}