|
| 1 | +package delegatingauthorizer |
| 2 | + |
| 3 | +import ( |
| 4 | + "crypto/sha256" |
| 5 | + "encoding/hex" |
| 6 | + "strings" |
| 7 | + "time" |
| 8 | + |
| 9 | + lru "github.com/hashicorp/golang-lru/v2" |
| 10 | + "k8s.io/apiserver/pkg/authorization/authorizer" |
| 11 | +) |
| 12 | + |
| 13 | +var ( |
| 14 | + cacheTime = 5 * time.Second |
| 15 | +) |
| 16 | + |
| 17 | +type Cache struct { |
| 18 | + cache *lru.Cache[string, cacheEntry] |
| 19 | +} |
| 20 | + |
| 21 | +func NewCache() *Cache { |
| 22 | + cache, _ := lru.New[string, cacheEntry](256) |
| 23 | + return &Cache{ |
| 24 | + cache: cache, |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +type cacheEntry struct { |
| 29 | + authorized authorizer.Decision |
| 30 | + reason string |
| 31 | + |
| 32 | + exp time.Time |
| 33 | +} |
| 34 | + |
| 35 | +func (c *Cache) Set(a authorizer.Attributes, authorized authorizer.Decision, reason string) { |
| 36 | + c.cache.Add(getCacheKey(a), cacheEntry{ |
| 37 | + authorized: authorized, |
| 38 | + reason: reason, |
| 39 | + exp: time.Now().Add(cacheTime), |
| 40 | + }) |
| 41 | +} |
| 42 | + |
| 43 | +func (c *Cache) Get(a authorizer.Attributes) (authorized authorizer.Decision, reason string, exists bool) { |
| 44 | + // check if in cache |
| 45 | + now := time.Now() |
| 46 | + entry, ok := c.cache.Get(getCacheKey(a)) |
| 47 | + if ok && entry.exp.After(now) { |
| 48 | + return entry.authorized, entry.reason, true |
| 49 | + } |
| 50 | + |
| 51 | + return authorizer.DecisionNoOpinion, "", false |
| 52 | +} |
| 53 | + |
| 54 | +func getCacheKey(a authorizer.Attributes) string { |
| 55 | + parts := []string{} |
| 56 | + if a.GetUser() != nil { |
| 57 | + parts = append(parts, a.GetUser().GetName(), a.GetUser().GetUID(), strings.Join(a.GetUser().GetGroups(), ",")) |
| 58 | + } |
| 59 | + if a.IsResourceRequest() { |
| 60 | + parts = append(parts, a.GetAPIGroup(), a.GetAPIVersion(), a.GetResource(), a.GetSubresource(), a.GetVerb(), a.GetNamespace(), a.GetName()) |
| 61 | + } else { |
| 62 | + parts = append(parts, a.GetPath(), a.GetVerb()) |
| 63 | + } |
| 64 | + |
| 65 | + // hash the string |
| 66 | + h := sha256.New() |
| 67 | + h.Write([]byte(strings.Join(parts, "#"))) |
| 68 | + return hex.EncodeToString(h.Sum(nil)) |
| 69 | +} |
0 commit comments