2021-12-22 10:43:45 +00:00
|
|
|
package tenant_tls
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"goauthentik.io/api"
|
|
|
|
"goauthentik.io/internal/crypto"
|
|
|
|
"goauthentik.io/internal/outpost/ak"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Watcher struct {
|
|
|
|
client *api.APIClient
|
|
|
|
log *log.Entry
|
|
|
|
cs *ak.CryptoStore
|
|
|
|
fallback *tls.Certificate
|
|
|
|
tenants []api.Tenant
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewWatcher(client *api.APIClient) *Watcher {
|
|
|
|
cs := ak.NewCryptoStore(client.CryptoApi)
|
|
|
|
l := log.WithField("logger", "authentik.router.tenant_tls")
|
|
|
|
cert, err := crypto.GenerateSelfSignedCert()
|
|
|
|
if err != nil {
|
|
|
|
l.WithError(err).Error("failed to generate default cert")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Watcher{
|
|
|
|
client: client,
|
|
|
|
log: l,
|
|
|
|
cs: cs,
|
|
|
|
fallback: &cert,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *Watcher) Start() {
|
|
|
|
ticker := time.NewTicker(time.Minute * 3)
|
|
|
|
w.log.Info("Starting Tenant TLS Checker")
|
|
|
|
for ; true; <-ticker.C {
|
|
|
|
w.Check()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *Watcher) Check() {
|
2021-12-22 23:38:49 +00:00
|
|
|
w.log.Info("updating tenant certificates")
|
2021-12-22 10:43:45 +00:00
|
|
|
tenants, _, err := w.client.CoreApi.CoreTenantsListExecute(api.ApiCoreTenantsListRequest{})
|
|
|
|
if err != nil {
|
|
|
|
w.log.WithError(err).Warning("failed to get tenants")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, t := range tenants.Results {
|
|
|
|
if t.WebCertificate.IsSet() {
|
|
|
|
err := w.cs.AddKeypair(*t.WebCertificate.Get())
|
|
|
|
if err != nil {
|
|
|
|
w.log.WithError(err).Warning("failed to add certificate")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.tenants = tenants.Results
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *Watcher) GetCertificate(ch *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
|
|
var bestSelection *api.Tenant
|
|
|
|
for _, t := range w.tenants {
|
|
|
|
if !t.WebCertificate.IsSet() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if *t.Default {
|
|
|
|
bestSelection = &t
|
|
|
|
}
|
|
|
|
if strings.HasSuffix(ch.ServerName, t.Domain) {
|
|
|
|
bestSelection = &t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if bestSelection == nil {
|
|
|
|
return w.fallback, nil
|
|
|
|
}
|
|
|
|
cert := w.cs.Get(*bestSelection.WebCertificate.Get())
|
|
|
|
return cert, nil
|
|
|
|
}
|