mission-control/tests/agent-api-keys.spec.ts

83 lines
2.8 KiB
TypeScript

import { expect, test } from '@playwright/test'
import { API_KEY_HEADER, createTestAgent, deleteTestAgent } from './helpers'
test.describe('Agent API keys', () => {
const cleanup: number[] = []
test.afterEach(async ({ request }) => {
for (const id of cleanup.splice(0)) {
await deleteTestAgent(request, id).catch(() => {})
}
})
test('supports scoped agent auth without x-agent-name and allows revoke', async ({ request }) => {
const primary = await createTestAgent(request)
const other = await createTestAgent(request)
cleanup.push(primary.id, other.id)
const createKeyRes = await request.post(`/api/agents/${primary.id}/keys`, {
headers: API_KEY_HEADER,
data: {
name: 'diag-key',
scopes: ['viewer', 'agent:self', 'agent:diagnostics'],
expires_in_days: 1,
},
})
expect(createKeyRes.status()).toBe(201)
const createKeyBody = await createKeyRes.json()
expect(createKeyBody.api_key).toMatch(/^mca_/)
const agentKeyHeader = { 'x-api-key': createKeyBody.api_key as string }
const selfRes = await request.get(`/api/agents/${primary.id}/diagnostics?section=summary`, {
headers: agentKeyHeader,
})
expect(selfRes.status()).toBe(200)
const crossRes = await request.get(`/api/agents/${other.id}/diagnostics?section=summary`, {
headers: agentKeyHeader,
})
expect(crossRes.status()).toBe(403)
const listRes = await request.get(`/api/agents/${primary.id}/keys`, { headers: API_KEY_HEADER })
expect(listRes.status()).toBe(200)
const listBody = await listRes.json()
const storedKey = listBody.keys.find((entry: any) => entry.id === createKeyBody.key.id)
expect(storedKey).toBeDefined()
expect(storedKey.key_prefix).toBe(createKeyBody.key.key_prefix)
const revokeRes = await request.delete(`/api/agents/${primary.id}/keys`, {
headers: API_KEY_HEADER,
data: { key_id: createKeyBody.key.id },
})
expect(revokeRes.status()).toBe(200)
const afterRevoke = await request.get(`/api/agents/${primary.id}/diagnostics?section=summary`, {
headers: agentKeyHeader,
})
expect(afterRevoke.status()).toBe(401)
})
test('rejects expired agent keys', async ({ request }) => {
const primary = await createTestAgent(request)
cleanup.push(primary.id)
const createKeyRes = await request.post(`/api/agents/${primary.id}/keys`, {
headers: API_KEY_HEADER,
data: {
name: 'expired-key',
scopes: ['viewer', 'agent:self'],
expires_at: Math.floor(Date.now() / 1000) - 5,
},
})
expect(createKeyRes.status()).toBe(201)
const { api_key } = await createKeyRes.json()
const expiredRes = await request.get(`/api/agents/${primary.id}/attribution?section=identity`, {
headers: { 'x-api-key': api_key },
})
expect(expiredRes.status()).toBe(401)
})
})