feat(cache): implement hashed API key storage and retrieval
Adds a new hashed key storage mechanism for API keys in the cache. Replaces direct mapping to API keys with composite keys based on organizationId and name. Implements searching of API keys using hash comparisons for improved security. Updates related tests to ensure correct functionality and validate the hashing. Also, adds support for a new dependency `golang.org/x/crypto`.
This commit is contained in:
Vendored
+26
-16
@@ -14,7 +14,7 @@ import (
|
||||
type Cache struct {
|
||||
organizations map[string]domain.Organization
|
||||
users map[string][]string
|
||||
apiKeys map[string]domain.APIKey
|
||||
apiKeys map[string]domain.APIKey // keyed by organizationId-name
|
||||
services map[string]map[string]map[string]struct{}
|
||||
subGraphs map[string]string
|
||||
lastUpdate map[string]string
|
||||
@@ -22,15 +22,17 @@ type Cache struct {
|
||||
}
|
||||
|
||||
func (c *Cache) OrganizationByAPIKey(apiKey string) *domain.Organization {
|
||||
key, exists := c.apiKeys[apiKey]
|
||||
if !exists {
|
||||
return nil
|
||||
// Find the API key by comparing hashes
|
||||
for _, key := range c.apiKeys {
|
||||
if hash.CompareAPIKey(key.Key, apiKey) {
|
||||
org, exists := c.organizations[key.OrganizationId]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
return &org
|
||||
}
|
||||
}
|
||||
org, exists := c.organizations[key.OrganizationId]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
return &org
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) OrganizationsByUser(sub string) []domain.Organization {
|
||||
@@ -43,11 +45,13 @@ func (c *Cache) OrganizationsByUser(sub string) []domain.Organization {
|
||||
}
|
||||
|
||||
func (c *Cache) ApiKeyByKey(key string) *domain.APIKey {
|
||||
k, exists := c.apiKeys[hash.String(key)]
|
||||
if !exists {
|
||||
return nil
|
||||
// Find the API key by comparing hashes
|
||||
for _, apiKey := range c.apiKeys {
|
||||
if hash.CompareAPIKey(apiKey.Key, key) {
|
||||
return &apiKey
|
||||
}
|
||||
}
|
||||
return &k
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) Services(orgId, ref, lastUpdate string) ([]string, string) {
|
||||
@@ -76,14 +80,15 @@ func (c *Cache) Update(msg any, _ goamqp.Headers) (any, error) {
|
||||
key := domain.APIKey{
|
||||
Name: m.Name,
|
||||
OrganizationId: m.OrganizationId,
|
||||
Key: m.Key,
|
||||
Key: m.Key, // This is now the hashed key
|
||||
Refs: m.Refs,
|
||||
Read: m.Read,
|
||||
Publish: m.Publish,
|
||||
CreatedBy: m.Initiator,
|
||||
CreatedAt: m.When(),
|
||||
}
|
||||
c.apiKeys[m.Key] = key
|
||||
// Use composite key: organizationId-name
|
||||
c.apiKeys[apiKeyId(m.OrganizationId, m.Name)] = key
|
||||
org := c.organizations[m.OrganizationId]
|
||||
org.APIKeys = append(org.APIKeys, key)
|
||||
c.organizations[m.OrganizationId] = org
|
||||
@@ -93,7 +98,8 @@ func (c *Cache) Update(msg any, _ goamqp.Headers) (any, error) {
|
||||
c.organizations[m.ID.String()] = *m
|
||||
c.addUser(m.CreatedBy, *m)
|
||||
for _, k := range m.APIKeys {
|
||||
c.apiKeys[k.Key] = k
|
||||
// Use composite key: organizationId-name
|
||||
c.apiKeys[apiKeyId(k.OrganizationId, k.Name)] = k
|
||||
}
|
||||
case *domain.SubGraph:
|
||||
c.updateSubGraph(m.OrganizationId, m.Ref, m.ID.String(), m.Service, m.ChangedAt)
|
||||
@@ -143,3 +149,7 @@ func refKey(orgId string, ref string) string {
|
||||
func subGraphKey(orgId string, ref string, service string) string {
|
||||
return fmt.Sprintf("%s<->%s<->%s", orgId, ref, service)
|
||||
}
|
||||
|
||||
func apiKeyId(orgId string, name string) string {
|
||||
return fmt.Sprintf("%s<->%s", orgId, name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user