Documentation
¶
Index ¶
- Constants
- Variables
- type AdminKeyManager
- type KeyMetadata
- type KeyStore
- type SecretKeyStore
- func (s *SecretKeyStore) CountUserKeys(ctx context.Context, namespace, user string) (int, error)
- func (s *SecretKeyStore) Create(ctx context.Context, meta KeyMetadata) (rawToken, keyID string, err error)
- func (s *SecretKeyStore) CreateFromHash(ctx context.Context, meta KeyMetadata, tokenHash, hashPrefix string) error
- func (s *SecretKeyStore) Delete(ctx context.Context, keyID string) error
- func (s *SecretKeyStore) Get(ctx context.Context, keyID string) (*KeyMetadata, error)
- func (s *SecretKeyStore) List(ctx context.Context) ([]KeyMetadata, error)
- func (s *SecretKeyStore) ListByTeamAndUser(ctx context.Context, team, user string) ([]KeyMetadata, error)
- func (s *SecretKeyStore) Validate(ctx context.Context, rawToken string) (*KeyMetadata, error)
- type SecretKeyStoreConfig
Constants ¶
const ( // RoleAdmin is the admin role string. RoleAdmin = "admin" // RoleTenant is the tenant role string. RoleTenant = "tenant" )
const ( // LabelType marks Secrets managed by agentbox API key store. LabelType = "agentbox.io/type" // LabelTypeValue is the label value for API key secrets. LabelTypeValue = "api-key" // LabelNamespace stores the tenant namespace in the secret label. LabelNamespace = "agentbox.io/namespace" // LabelUser stores the user in the secret label. LabelUser = "agentbox.io/user" // LabelTeam stores the team in the secret label. LabelTeam = "agentbox.io/team" // LabelTokenHashPrefix is the first 16 hex chars of SHA-256(rawToken) for label selector. LabelTokenHashPrefix = "agentbox.io/token-hash" // LabelSyncSource marks the origin of the API key Secret. // "global" means the key was created/synced via ws-proxy (global key manager). // Resources without this label (locally-created or legacy) are treated as non-global. LabelSyncSource = "agentbox.io/sync-source" LabelSyncSourceGlobal = "global" // Token prefix for all API keys. TokenPrefix = "agbx_" )
Variables ¶
var ( // ErrTokenNotFound is returned when the provided token does not match any stored key. ErrTokenNotFound = errors.New("api key not found") // ErrTokenExpired is returned when the token is found but has passed its expiry time. ErrTokenExpired = errors.New("api key expired") )
Functions ¶
This section is empty.
Types ¶
type AdminKeyManager ¶
type AdminKeyManager struct {
// contains filtered or unexported fields
}
AdminKeyManager handles constant-time comparison of the admin API key.
func NewAdminKeyManager ¶
func NewAdminKeyManager(adminKey string) *AdminKeyManager
NewAdminKeyManager creates a new AdminKeyManager. adminKey is the raw admin key string. When empty, IsAdminKey always returns false.
func (*AdminKeyManager) IsAdminKey ¶
func (m *AdminKeyManager) IsAdminKey(key string) bool
IsAdminKey reports whether the provided key equals the admin key using constant-time comparison to prevent timing attacks.
type KeyMetadata ¶
type KeyMetadata struct {
// KeyID is the fully qualified secret identifier: "<namespace>/<name>".
KeyID string `json:"keyId"`
Namespace string `json:"namespace"`
Role string `json:"role"`
User string `json:"user"`
Team string `json:"team"`
QuotaURL string `json:"quotaURL"`
Description string `json:"description"`
IssuedAt time.Time `json:"issuedAt"`
ExpiresAt time.Time `json:"expiresAt"` // zero = never expires
// SyncSource is "global" when the key was created/synced via ws-proxy.
// Empty means locally-created or a legacy resource — both are treated as non-global.
SyncSource string `json:"syncSource,omitempty"`
// TokenHash is the full SHA-256 hex hash of the raw token, extracted from
// the Secret data. It is needed for sync (CreateFromHash) but MUST NOT be
// exposed via any external API — hence json:"-".
TokenHash string `json:"-"`
// RawToken is the full opaque token (agbx_...) stored in the Secret's "apikey"
// data field. Populated only for keys created after plaintext storage was
// introduced. Empty for legacy keys. MUST NOT be exposed in JSON — json:"-".
RawToken string `json:"-"`
}
KeyMetadata holds the full metadata stored in a Kubernetes Secret for one API key.
type KeyStore ¶
type KeyStore interface {
// Create generates a new random token, stores its metadata as a K8s Secret,
// and returns the raw token (shown only once) plus the secret name (KeyID short form).
Create(ctx context.Context, meta KeyMetadata) (rawToken, keyID string, err error)
// CreateFromHash writes a Secret using an already-computed tokenHash/hashPrefix
// (e.g. when importing a key from another cluster). It is idempotent:
// if the Secret already exists the call returns nil.
CreateFromHash(ctx context.Context, meta KeyMetadata, tokenHash, hashPrefix string) error
// Validate resolves rawToken to its KeyMetadata, using an in-memory cache.
// Returns ErrTokenNotFound if no matching secret exists.
// Returns ErrTokenExpired if the key has passed its ExpiresAt time.
Validate(ctx context.Context, rawToken string) (*KeyMetadata, error)
// List returns all API key metadata.
List(ctx context.Context) ([]KeyMetadata, error)
// ListByTeamAndUser returns API key metadata filtered by team and/or user
// labels. Pass empty strings to skip a filter dimension.
ListByTeamAndUser(ctx context.Context, team, user string) ([]KeyMetadata, error)
// Get returns the metadata for the secret identified by keyID (secret name,
// without namespace prefix).
Get(ctx context.Context, keyID string) (*KeyMetadata, error)
// Delete revokes the API key identified by keyID (secret name).
Delete(ctx context.Context, keyID string) error
}
KeyStore defines the operations for managing opaque API keys backed by Kubernetes Secrets.
type SecretKeyStore ¶
type SecretKeyStore struct {
// contains filtered or unexported fields
}
SecretKeyStore implements KeyStore backed by Kubernetes Secrets.
func NewSecretKeyStore ¶
func NewSecretKeyStore(cfg SecretKeyStoreConfig) *SecretKeyStore
NewSecretKeyStore creates a new SecretKeyStore.
func (*SecretKeyStore) CountUserKeys ¶
CountUserKeys returns the number of API key Secrets for the given namespace+user pair.
func (*SecretKeyStore) Create ¶
func (s *SecretKeyStore) Create(ctx context.Context, meta KeyMetadata) (rawToken, keyID string, err error)
Create generates a new opaque token "agbx_<base64url>", stores its SHA-256 hash and all metadata in a Kubernetes Secret, then returns the raw token. The raw token is shown only once; the caller must persist it.
func (*SecretKeyStore) CreateFromHash ¶
func (s *SecretKeyStore) CreateFromHash(ctx context.Context, meta KeyMetadata, tokenHash, hashPrefix string) error
CreateFromHash writes a Secret using an already-computed tokenHash/hashPrefix (e.g. when syncing a key created by the master cluster BFF). It is idempotent: if the Secret already exists the call returns nil.
func (*SecretKeyStore) Delete ¶
func (s *SecretKeyStore) Delete(ctx context.Context, keyID string) error
Delete revokes the API key by deleting its Kubernetes Secret. It reads the secret first to evict the cache entry precisely.
func (*SecretKeyStore) Get ¶
func (s *SecretKeyStore) Get(ctx context.Context, keyID string) (*KeyMetadata, error)
Get returns metadata for a single API key secret by its name (without namespace prefix).
func (*SecretKeyStore) List ¶
func (s *SecretKeyStore) List(ctx context.Context) ([]KeyMetadata, error)
List returns metadata for all API key secrets.
func (*SecretKeyStore) ListByTeamAndUser ¶
func (s *SecretKeyStore) ListByTeamAndUser(ctx context.Context, team, user string) ([]KeyMetadata, error)
ListByTeamAndUser returns API key metadata filtered by team and/or user labels at the Kubernetes level (label selector). Pass empty strings to skip a filter dimension.
func (*SecretKeyStore) Validate ¶
func (s *SecretKeyStore) Validate(ctx context.Context, rawToken string) (*KeyMetadata, error)
Validate resolves rawToken → KeyMetadata via in-memory cache, falling back to a Kubernetes Secret lookup.
type SecretKeyStoreConfig ¶
type SecretKeyStoreConfig struct {
// Client is the Kubernetes client used to read/write Secrets.
Client client.Client
// SecretsNamespace is the namespace where API key secrets are stored.
// Defaults to "agentbox-system" if empty.
SecretsNamespace string
// CacheTTL is how long a successful Validate result is cached in memory.
// Defaults to 1 minute if zero.
CacheTTL time.Duration
}
SecretKeyStoreConfig configures the SecretKeyStore.