feat(coderd/database): add AI Gateway key auth lookup and last-used queries - #26505
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
aaa5bce to
00065d0
Compare
| } | ||
|
|
||
| // Authenticates a standalone AI Gateway replica by its hashed key secret, returning the key ID used to record liveness. | ||
| func (q *querier) GetAIGatewayKeyIDByHashedSecret(ctx context.Context, hashedSecret []byte) (uuid.UUID, error) { |
There was a problem hiding this comment.
I have 1 question about this function. Should it return just ID or more info (eg. prefix)?
This is used later in logger, eg WIP:
coder/enterprise/coderd/aibridgeserve.go
Line 78 in c768ef1
Maybe logging prefix would be ok? At the same time prefix could be extracted from header but maybe returning it here would be cleaner.
There was a problem hiding this comment.
It could return the whole row, that'd be consistent with GetProvisionerKeyByHashedSecret, no? We can also add an RBACObject() to AIGatewayKey (returning ResourceAIGatewayKey.WithID(k.ID)) and switch this to fetch(). That'd also align with the existing CRUD on this table, which already authorizes against ResourceAIGatewayKey.
There was a problem hiding this comment.
CRUD is a bit separate. CRUD is for managing keys by user while GetByHash + UpdateLastSeen is for system to auth and keep track of key usage.
I'm not sure why fetch() would be better here. If I understand correctly it queries object from DB then checks if caller has access to it. In Gateway keys case there is no per object check (and probably won't ever be) that could be made, either subject can access all or none.
Changed getter to GetAIGatewayKeyByHashedSecret that returns full key, kept current check format.
00065d0 to
3a82a8f
Compare
| } | ||
|
|
||
| // Authenticates a standalone AI Gateway replica by its hashed key secret, returning the key ID used to record liveness. | ||
| func (q *querier) GetAIGatewayKeyIDByHashedSecret(ctx context.Context, hashedSecret []byte) (uuid.UUID, error) { |
There was a problem hiding this comment.
It could return the whole row, that'd be consistent with GetProvisionerKeyByHashedSecret, no? We can also add an RBACObject() to AIGatewayKey (returning ResourceAIGatewayKey.WithID(k.ID)) and switch this to fetch(). That'd also align with the existing CRUD on this table, which already authorizes against ResourceAIGatewayKey.
| // Records liveness for an active DRPC sessions between coderd and standalone AI Gateway. | ||
| func (q *querier) UpdateAIGatewayKeyLastUsedAt(ctx context.Context, id uuid.UUID) error { | ||
| // Standalone AI Gateway has no Coder identity. DRPC connection liveness update is a system operation. | ||
| if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { |
There was a problem hiding this comment.
Can't we use ResourceAIGatewayKey?
There was a problem hiding this comment.
My idea was that Gateway keys are immutable. This kind of can be done by not adding ActionUpdate to ResourceAIGatewayKey. Then even if some subject gets full access to that resource it can't update it.
At the same time there are no API methods to update it so maybe it is a bit too much.
Changed to rbac.ResourceAIGatewayKey and updated subject permissions.
70b1fea to
65dff84
Compare
Docs preview📖 View docs preview for |
154ccfc to
156894e
Compare
156894e to
a3269ec
Compare
dannykopping
left a comment
There was a problem hiding this comment.
LGTM except for the use of the system subject.
a3269ec to
4fd9fb0
Compare
…ueries Part of AIGOV-308. Generated with Coder Agents.
…sed methods, updated subject permissions
4fd9fb0 to
36e5b2a
Compare

Adds DB methods
GetAIGatewayKeyIDByHashedSecretandUpdateAIGatewayKeyLastUsedAt.GetAIGatewayKeyIDByHashedSecret- returns AI Gateway key ID by hashed secret value.UpdateAIGatewayKeyLastUsedAt- updates last used timestamp for given AI Gateway key.Used by standalone AI Gateway for authentication and keeping track of currently used keys.