mirror of
https://github.com/GlueOps/autoglue.git
synced 2026-02-13 04:40:05 +01:00
feat: sdk migration in progress
This commit is contained in:
138
internal/auth/jwt_signer.go
Normal file
138
internal/auth/jwt_signer.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/glueops/autoglue/internal/keys"
|
||||
"github.com/glueops/autoglue/internal/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type keyCache struct {
|
||||
mu sync.RWMutex
|
||||
pub map[string]interface{} // kid -> public key object
|
||||
meta map[string]models.SigningKey
|
||||
selKid string
|
||||
selAlg string
|
||||
selPriv any
|
||||
}
|
||||
|
||||
var kc keyCache
|
||||
|
||||
// Refresh loads active keys into memory. Call on startup and periodically (ticker/cron).
|
||||
func Refresh(db *gorm.DB, encKeyB64 string) error {
|
||||
var rows []models.SigningKey
|
||||
if err := db.Where("is_active = true AND (expires_at IS NULL OR expires_at > ?)", time.Now()).
|
||||
Order("created_at desc").Find(&rows).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub := make(map[string]interface{}, len(rows))
|
||||
meta := make(map[string]models.SigningKey, len(rows))
|
||||
var selKid string
|
||||
var selAlg string
|
||||
var selPriv any
|
||||
|
||||
for i, r := range rows {
|
||||
// parse public
|
||||
block, _ := pem.Decode([]byte(r.PublicPEM))
|
||||
if block == nil {
|
||||
continue
|
||||
}
|
||||
var pubKey any
|
||||
switch r.Alg {
|
||||
case "RS256", "RS384", "RS512":
|
||||
pubKey, _ = x509.ParsePKCS1PublicKey(block.Bytes)
|
||||
if pubKey == nil {
|
||||
// also allow PKIX format
|
||||
if k, err := x509.ParsePKIXPublicKey(block.Bytes); err == nil {
|
||||
pubKey = k
|
||||
}
|
||||
}
|
||||
case "EdDSA":
|
||||
k, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err == nil {
|
||||
if edk, ok := k.(ed25519.PublicKey); ok {
|
||||
pubKey = edk
|
||||
}
|
||||
}
|
||||
}
|
||||
if pubKey == nil {
|
||||
continue
|
||||
}
|
||||
pub[r.Kid] = pubKey
|
||||
meta[r.Kid] = r
|
||||
|
||||
// pick first row as current signer (most recent because of order desc)
|
||||
if i == 0 {
|
||||
privPEM := r.PrivatePEM
|
||||
// decrypt if necessary
|
||||
if len(privPEM) > 10 && privPEM[:10] == "enc:aesgcm" {
|
||||
pt, err := keysDecrypt(encKeyB64, privPEM)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
privPEM = string(pt)
|
||||
}
|
||||
blockPriv, _ := pem.Decode([]byte(privPEM))
|
||||
if blockPriv == nil {
|
||||
continue
|
||||
}
|
||||
switch r.Alg {
|
||||
case "RS256", "RS384", "RS512":
|
||||
if k, err := x509.ParsePKCS1PrivateKey(blockPriv.Bytes); err == nil {
|
||||
selPriv = k
|
||||
selAlg = r.Alg
|
||||
selKid = r.Kid
|
||||
} else if kAny, err := x509.ParsePKCS8PrivateKey(blockPriv.Bytes); err == nil {
|
||||
if k, ok := kAny.(*rsa.PrivateKey); ok {
|
||||
selPriv = k
|
||||
selAlg = r.Alg
|
||||
selKid = r.Kid
|
||||
}
|
||||
}
|
||||
case "EdDSA":
|
||||
if kAny, err := x509.ParsePKCS8PrivateKey(blockPriv.Bytes); err == nil {
|
||||
if k, ok := kAny.(ed25519.PrivateKey); ok {
|
||||
selPriv = k
|
||||
selAlg = r.Alg
|
||||
selKid = r.Kid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kc.mu.Lock()
|
||||
defer kc.mu.Unlock()
|
||||
kc.pub = pub
|
||||
kc.meta = meta
|
||||
kc.selKid = selKid
|
||||
kc.selAlg = selAlg
|
||||
kc.selPriv = selPriv
|
||||
return nil
|
||||
}
|
||||
|
||||
func keysDecrypt(encKey, enc string) ([]byte, error) {
|
||||
return keysDecryptImpl(encKey, enc)
|
||||
}
|
||||
|
||||
// indirection for same package
|
||||
var keysDecryptImpl = func(encKey, enc string) ([]byte, error) {
|
||||
return nil, errors.New("not wired")
|
||||
}
|
||||
|
||||
// Wire up from keys package
|
||||
func init() {
|
||||
keysDecryptImpl = keysDecryptShim
|
||||
}
|
||||
|
||||
func keysDecryptShim(encKey, enc string) ([]byte, error) {
|
||||
return keys.Decrypt(encKey, enc)
|
||||
}
|
||||
Reference in New Issue
Block a user