1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package servetls
import (
"crypto/tls"
"errors"
"log/slog"
"path/filepath"
"strings"
"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/hostport"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/tlsreload"
)
func KeyFileFor(certFile string) string {
switch {
case certFile == "":
return ""
case strings.HasSuffix(certFile, ".crt"):
return strings.TrimSuffix(certFile, ".crt") + ".key"
case strings.HasSuffix(certFile, ".pem"):
return strings.TrimSuffix(certFile, ".pem") + ".key"
default:
return certFile + ".key"
}
}
func KeyFilesFor(certFile string) []string {
candidates := []string{KeyFileFor(certFile)}
if before, ok := strings.CutSuffix(certFile, ".pem"); ok {
candidates = append(candidates, before+"-key.pem")
}
return append(candidates, certFile)
}
func RefPath(ref string, storage *v1alpha1.ComponentStorage) string {
ref = strings.TrimSpace(ref)
if ref == "" {
return ""
}
if filepath.IsAbs(ref) || storage == nil || storage.CertsDir == "" {
return ref
}
return filepath.Join(storage.CertsDir, ref)
}
func CertificateFiles(certRef string, storage *v1alpha1.ComponentStorage, hostnames []string) (string, string) {
certFile := RefPath(certRef, storage)
if certFile == "" && storage != nil && storage.CertsDir != "" && len(hostnames) > 0 {
name := hostport.HostnameOnly(hostnames[0])
if name != "" && name != "*" {
certFile = filepath.Join(storage.CertsDir, name+".crt")
}
}
return certFile, KeyFileFor(certFile)
}
func Config(certFile string, fallback *tls.Config, log *slog.Logger) (*tls.Config, error) {
if certFile != "" {
reloader, err := tlsreload.New(certFile, KeyFilesFor(certFile), log)
if err != nil {
return nil, err
}
return reloader.TLSConfig(&tls.Config{MinVersion: tls.VersionTLS12, NextProtos: []string{"http/1.1"}}), nil
}
if fallback != nil {
tlsConfig := fallback.Clone()
if len(tlsConfig.NextProtos) == 0 {
tlsConfig.NextProtos = []string{"http/1.1"}
}
return tlsConfig, nil
}
return nil, errors.New("a TLS certificate is required")
}