package api import ( "crypto/rand" "encoding/hex" "sync" "time" ) const spreadCredTokenTTL = 90 * time.Second type spreadCredTokenEntry struct { AgentID string ProfileID string Username string Password string Host string Subnet string Method string ExpiresAt time.Time } var ( spreadCredTokenMu sync.Mutex spreadCredTokens = map[string]spreadCredTokenEntry{} ) func issueSpreadCredToken(entry spreadCredTokenEntry) string { b := make([]byte, 24) _, _ = rand.Read(b) token := hex.EncodeToString(b) entry.ExpiresAt = time.Now().Add(spreadCredTokenTTL) spreadCredTokenMu.Lock() spreadCredTokens[token] = entry if len(spreadCredTokens) > 1024 { now := time.Now() for k, v := range spreadCredTokens { if now.After(v.ExpiresAt) { delete(spreadCredTokens, k) } } } spreadCredTokenMu.Unlock() return token } func consumeSpreadCredToken(token string) (spreadCredTokenEntry, bool) { spreadCredTokenMu.Lock() defer spreadCredTokenMu.Unlock() entry, ok := spreadCredTokens[token] if !ok || time.Now().After(entry.ExpiresAt) { if ok { delete(spreadCredTokens, token) } return spreadCredTokenEntry{}, false } delete(spreadCredTokens, token) return entry, true }