authentik/internal/outpost/ak/crypto.go

86 lines
2.1 KiB
Go

package ak
import (
"context"
"crypto/tls"
log "github.com/sirupsen/logrus"
"goauthentik.io/api/v3"
)
type CryptoStore struct {
api *api.CryptoApiService
log *log.Entry
fingerprints map[string]string
certificates map[string]*tls.Certificate
}
func NewCryptoStore(cryptoApi *api.CryptoApiService) *CryptoStore {
return &CryptoStore{
api: cryptoApi,
log: log.WithField("logger", "authentik.outpost.cryptostore"),
fingerprints: make(map[string]string),
certificates: make(map[string]*tls.Certificate),
}
}
func (cs *CryptoStore) AddKeypair(uuid string) error {
// If they keypair was already added, don't
// do it again
if _, ok := cs.fingerprints[uuid]; ok {
return nil
}
// reset fingerprint to force update
cs.fingerprints[uuid] = ""
err := cs.Fetch(uuid)
if err != nil {
return err
}
cs.fingerprints[uuid] = cs.getFingerprint(uuid)
return nil
}
func (cs *CryptoStore) getFingerprint(uuid string) string {
kp, _, err := cs.api.CryptoCertificatekeypairsRetrieve(context.Background(), uuid).Execute()
if err != nil {
cs.log.WithField("uuid", uuid).WithError(err).Warning("Failed to fetch certificate's fingerprint")
return ""
}
return kp.FingerprintSha256
}
func (cs *CryptoStore) Fetch(uuid string) error {
cfp := cs.getFingerprint(uuid)
if cfp == cs.fingerprints[uuid] {
cs.log.WithField("uuid", uuid).Info("Fingerprint hasn't changed, not fetching cert")
return nil
}
cs.log.WithField("uuid", uuid).Info("Fetching certificate and private key")
cert, _, err := cs.api.CryptoCertificatekeypairsViewCertificateRetrieve(context.Background(), uuid).Execute()
if err != nil {
return err
}
key, _, err := cs.api.CryptoCertificatekeypairsViewPrivateKeyRetrieve(context.Background(), uuid).Execute()
if err != nil {
return err
}
x509cert, err := tls.X509KeyPair([]byte(cert.Data), []byte(key.Data))
if err != nil {
return err
}
cs.certificates[uuid] = &x509cert
return nil
}
func (cs *CryptoStore) Get(uuid string) *tls.Certificate {
err := cs.Fetch(uuid)
if err != nil {
cs.log.WithError(err).Warning("failed to fetch certificate")
}
return cs.certificates[uuid]
}