gRPC migration update
Change-Id: Icdd1a824948fa994cd36bd121c962f5ecf74e3cf
diff --git a/vendor/github.com/jcmturner/gokrb5/v8/client/cache.go b/vendor/github.com/jcmturner/gokrb5/v8/client/cache.go
new file mode 100644
index 0000000..552e73e
--- /dev/null
+++ b/vendor/github.com/jcmturner/gokrb5/v8/client/cache.go
@@ -0,0 +1,134 @@
+package client
+
+import (
+ "encoding/json"
+ "errors"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/jcmturner/gokrb5/v8/messages"
+ "github.com/jcmturner/gokrb5/v8/types"
+)
+
+// Cache for service tickets held by the client.
+type Cache struct {
+ Entries map[string]CacheEntry
+ mux sync.RWMutex
+}
+
+// CacheEntry holds details for a cache entry.
+type CacheEntry struct {
+ SPN string
+ Ticket messages.Ticket `json:"-"`
+ AuthTime time.Time
+ StartTime time.Time
+ EndTime time.Time
+ RenewTill time.Time
+ SessionKey types.EncryptionKey `json:"-"`
+}
+
+// NewCache creates a new client ticket cache instance.
+func NewCache() *Cache {
+ return &Cache{
+ Entries: map[string]CacheEntry{},
+ }
+}
+
+// getEntry returns a cache entry that matches the SPN.
+func (c *Cache) getEntry(spn string) (CacheEntry, bool) {
+ c.mux.RLock()
+ defer c.mux.RUnlock()
+ e, ok := (*c).Entries[spn]
+ return e, ok
+}
+
+// JSON returns information about the cached service tickets in a JSON format.
+func (c *Cache) JSON() (string, error) {
+ c.mux.RLock()
+ defer c.mux.RUnlock()
+ var es []CacheEntry
+ keys := make([]string, 0, len(c.Entries))
+ for k := range c.Entries {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ es = append(es, c.Entries[k])
+ }
+ b, err := json.MarshalIndent(&es, "", " ")
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+}
+
+// addEntry adds a ticket to the cache.
+func (c *Cache) addEntry(tkt messages.Ticket, authTime, startTime, endTime, renewTill time.Time, sessionKey types.EncryptionKey) CacheEntry {
+ spn := tkt.SName.PrincipalNameString()
+ c.mux.Lock()
+ defer c.mux.Unlock()
+ (*c).Entries[spn] = CacheEntry{
+ SPN: spn,
+ Ticket: tkt,
+ AuthTime: authTime,
+ StartTime: startTime,
+ EndTime: endTime,
+ RenewTill: renewTill,
+ SessionKey: sessionKey,
+ }
+ return c.Entries[spn]
+}
+
+// clear deletes all the cache entries
+func (c *Cache) clear() {
+ c.mux.Lock()
+ defer c.mux.Unlock()
+ for k := range c.Entries {
+ delete(c.Entries, k)
+ }
+}
+
+// RemoveEntry removes the cache entry for the defined SPN.
+func (c *Cache) RemoveEntry(spn string) {
+ c.mux.Lock()
+ defer c.mux.Unlock()
+ delete(c.Entries, spn)
+}
+
+// GetCachedTicket returns a ticket from the cache for the SPN.
+// Only a ticket that is currently valid will be returned.
+func (cl *Client) GetCachedTicket(spn string) (messages.Ticket, types.EncryptionKey, bool) {
+ if e, ok := cl.cache.getEntry(spn); ok {
+ //If within time window of ticket return it
+ if time.Now().UTC().After(e.StartTime) && time.Now().UTC().Before(e.EndTime) {
+ cl.Log("ticket received from cache for %s", spn)
+ return e.Ticket, e.SessionKey, true
+ } else if time.Now().UTC().Before(e.RenewTill) {
+ e, err := cl.renewTicket(e)
+ if err != nil {
+ return e.Ticket, e.SessionKey, false
+ }
+ return e.Ticket, e.SessionKey, true
+ }
+ }
+ var tkt messages.Ticket
+ var key types.EncryptionKey
+ return tkt, key, false
+}
+
+// renewTicket renews a cache entry ticket.
+// To renew from outside the client package use GetCachedTicket
+func (cl *Client) renewTicket(e CacheEntry) (CacheEntry, error) {
+ spn := e.Ticket.SName
+ _, _, err := cl.TGSREQGenerateAndExchange(spn, e.Ticket.Realm, e.Ticket, e.SessionKey, true)
+ if err != nil {
+ return e, err
+ }
+ e, ok := cl.cache.getEntry(e.Ticket.SName.PrincipalNameString())
+ if !ok {
+ return e, errors.New("ticket was not added to cache")
+ }
+ cl.Log("ticket renewed for %s (EndTime: %v)", spn.PrincipalNameString(), e.EndTime)
+ return e, nil
+}