Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions backend/src/lib/authenticated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ export function authenticated(req: Http2ServerRequest, res: Http2ServerResponse)
const token = getToken(req)
if (!token) return unauthorized(req, res)
isAuthenticated(token)
.then((response) => {
res.writeHead(response.status).end()
void response.blob()
.then((status) => {
res.writeHead(status).end()
})
.catch(catchInternalServerError(res))
}
24 changes: 13 additions & 11 deletions backend/src/lib/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ export function getToken(req: Http2ServerRequest): string | undefined {
return token
}

export async function isAuthenticated(token: string) {
return fetchRetry(process.env.CLUSTER_API_URL + '/apis', {
// GET /api returns the core API group (~200 bytes) — unlike /apis which grows
// with every installed CRD. The response body is drained so the socket returns
// to the keepAlive pool immediately and native memory does not accumulate.
export async function isAuthenticated(token: string): Promise<number> {
const response = await fetchRetry(process.env.CLUSTER_API_URL + '/api', {
headers: { [HTTP2_HEADER_AUTHORIZATION]: `Bearer ${token}` },
})
response.body?.on('error', () => undefined).resume()
return response.status
}

export const isHttp2ServerResponse = (
Expand All @@ -51,22 +56,19 @@ export async function getAuthenticatedToken(
const token = getToken(req)

if (token) {
const authResponse = await isAuthenticated(token)
const status = await isAuthenticated(token)
/* istanbul ignore if */
if (authResponse.status === constants.HTTP_STATUS_OK) {
if (status === constants.HTTP_STATUS_OK) {
if (process.env.NODE_ENV === 'development') {
const localStorage = new LocalStorage(LOCAL_STORAGE)
localStorage.setItem(ADMIN_TOKEN, token)
}
return token
}
if (isHttp2ServerResponse(resOrSocket)) {
resOrSocket.writeHead(status).end()
} else {
if (isHttp2ServerResponse(resOrSocket)) {
resOrSocket.writeHead(authResponse.status).end()
} else {
resOrSocket.destroy()
}

void authResponse.blob()
resOrSocket.destroy()
}
} else if (isHttp2ServerResponse(resOrSocket)) {
unauthorized(req, resOrSocket)
Expand Down
8 changes: 4 additions & 4 deletions backend/test/routes/aggregator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe(`aggregator Route`, function () {
})

it(`should page Unfiltered Applications`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)

// initialize events - cache sequentially to ensure deterministic order
for (const resource of resources) {
Expand Down Expand Up @@ -98,7 +98,7 @@ describe(`aggregator Route`, function () {
expect(await parseResponseJsonBody(res)).toEqual(responseNoFilter)
})
it(`should page Filtered Applications`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)

// initialize events - cache sequentially to ensure deterministic order
for (const resource of resources) {
Expand Down Expand Up @@ -129,7 +129,7 @@ describe(`aggregator Route`, function () {
expect(await parseResponseJsonBody(res)).toEqual(responseFiltered)
})
it(`should return application counts`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)

// initialize events - cache sequentially to ensure deterministic order
for (const resource of resources) {
Expand All @@ -153,7 +153,7 @@ describe(`aggregator Route`, function () {
expect(await parseResponseJsonBody(res)).toEqual(responseCount)
})
it(`should return appset data`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)

// initialize events - cache sequentially to ensure deterministic order
for (const resource of resources) {
Expand Down
19 changes: 10 additions & 9 deletions backend/test/routes/ansibletower.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function nockCredentialSecret(host: string) {

describe(`ansibletower Route`, function () {
it(`should list Ansible Automation controller Jobs`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
nock(TOWER_HOST).get(ansiblePaths[0]).reply(200, response)
const res = await request('POST', '/ansibletower', {
Expand All @@ -37,7 +37,7 @@ describe(`ansibletower Route`, function () {
})

it(`should reject body-supplied tower hostname`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
const res = await request('POST', '/ansibletower', {
towerHost: TOWER_HOST + ansiblePaths[0],
token: '12345',
Expand All @@ -46,7 +46,7 @@ describe(`ansibletower Route`, function () {
})

it(`should preserve the query string for paginated requests`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
nock(TOWER_HOST).get(ansiblePaths[0]).query({ page: '2', page_size: '20' }).reply(200, response)
const res = await request('POST', '/ansibletower', {
Expand All @@ -59,7 +59,7 @@ describe(`ansibletower Route`, function () {
})

it(`should reject an external absolute URL in ansiblePath`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
const res = await request('POST', '/ansibletower', {
secretNamespace: SECRET_NS,
Expand All @@ -70,7 +70,7 @@ describe(`ansibletower Route`, function () {
})

it(`should reject a network-path reference in ansiblePath`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
const res = await request('POST', '/ansibletower', {
secretNamespace: SECRET_NS,
Expand All @@ -81,7 +81,7 @@ describe(`ansibletower Route`, function () {
})

it(`should fail closed when caller cannot read the credential secret`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL)
.get(`/api/v1/namespaces/${SECRET_NS}/secrets/${SECRET_NAME}`)
.reply(403, { kind: 'Status', apiVersion: 'v1', status: 'Failure', reason: 'Forbidden', code: 403 })
Expand All @@ -94,7 +94,7 @@ describe(`ansibletower Route`, function () {
})

it(`when bad things happen to Ansible Automation controller Jobs 1`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
nock(TOWER_HOST).get(ansiblePaths[0]).reply(200, response)
const res = await request('POST', '/ansibletower', {
Expand All @@ -107,7 +107,7 @@ describe(`ansibletower Route`, function () {
})

it(`when bad things happen to Ansible Automation controller Jobs 2`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nockCredentialSecret(TOWER_HOST)
nock(TOWER_HOST).get(ansiblePaths[0]).reply(200, response)
const res = await request('POST', '/ansibletower', {
Expand All @@ -119,8 +119,9 @@ describe(`ansibletower Route`, function () {
})

it(`when bad things happen to Ansible Automation controller Jobs 3`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(400)
nock(process.env.CLUSTER_API_URL).get('/api').reply(401)
const res = await request('POST', '/ansibletower')
expect(res.statusCode).toEqual(401)
expect(JSON.stringify(await parsePipedJsonBody(res))).toEqual(JSON.stringify({}))
})
})
Expand Down
2 changes: 1 addition & 1 deletion backend/test/routes/apiPath.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe(`apiPath Route`, function () {

nock(process.env.CLUSTER_API_URL).get(paths[0]).reply(200, response)

nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
paths: response,
})
Expand Down
4 changes: 1 addition & 3 deletions backend/test/routes/hub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { request } from '../mock-request'

describe('global hub', function () {
it('should return the boolean', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL)
.get('/apis/apiextensions.k8s.io/v1/customresourcedefinitions') // .reply(200, { isGlobalHub: true })
.reply(200, {
Expand Down
2 changes: 1 addition & 1 deletion backend/test/routes/hypershift-status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { parseResponseJsonBody } from '../../src/lib/body-parser'
import nock from 'nock'

describe('hypershift-status Route', function () {
const mockAuth = () => nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, { status: 200 })
const mockAuth = () => nock(process.env.CLUSTER_API_URL).get('/api').reply(200, { status: 200 })

const mockMCE = (hypershiftEnabled = true, localHostingEnabled = true) =>
nock(process.env.CLUSTER_API_URL)
Expand Down
4 changes: 2 additions & 2 deletions backend/test/routes/metricsProxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { request } from '../mock-request'

describe('metrics proxy route', function () {
it('Successfully calls prometheus endpoint', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
const res = await request('GET', '/prometheus/query')
expect(res.statusCode).toEqual(200)
})
it(`Successfully calls observability endpoint`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
const res = await request('GET', '/observability/query')
Expand Down
6 changes: 3 additions & 3 deletions backend/test/routes/operatorCheck.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const subscriptionOperators = {

describe(`operatorCheck Route`, function () {
it(`returns valid response with version for installed operator`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand All @@ -38,7 +38,7 @@ describe(`operatorCheck Route`, function () {
})
})
it(`returns valid response for not-installed operator`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand All @@ -52,7 +52,7 @@ describe(`operatorCheck Route`, function () {
})
})
it(`returns bad request for arbitrary operator`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand Down
4 changes: 2 additions & 2 deletions backend/test/routes/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import nock from 'nock'

describe(`search Route`, function () {
it(`uses search-api in the namespace of the MultiClusterHub`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand All @@ -27,7 +27,7 @@ describe(`search Route`, function () {
//expect(res.statusCode).toEqual(200)
})
it(`uses search-api in namespace of pod if no MultiClusterHub`, async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL).get('/apis/operator.open-cluster-management.io/v1/multiclusterhubs').reply(200, {
Expand Down
2 changes: 1 addition & 1 deletion backend/test/routes/upgrade-risks-prediction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { request } from '../mock-request'

describe('Upgrade risks prediction Route', function () {
it('should return the upgrade risks', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL)
.get('/api/v1/namespaces/openshift-config/secrets')
.reply(200, {
Expand Down
5 changes: 3 additions & 2 deletions backend/test/routes/username.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import nock from 'nock'

describe('username Route', function () {
it('should return the username', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand All @@ -23,7 +23,7 @@ describe('username Route', function () {
expect(body).toEqual({ username: 'testuser' })
})
it('should return empty string if no username provided', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200, {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200, {
status: 200,
})
nock(process.env.CLUSTER_API_URL)
Expand All @@ -39,6 +39,7 @@ describe('username Route', function () {
expect(body).toEqual({ username: '' })
})
it('should handle errors', async function () {
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL).post('/apis/authentication.k8s.io/v1/tokenreviews').replyWithError('failed')
const res = await request('GET', '/username')
expect(res.statusCode).toEqual(500)
Expand Down
4 changes: 2 additions & 2 deletions backend/test/routes/userpreference.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { request } from '../mock-request'

describe('userpreference Route', function () {
it('should return the userpreference', async function () {
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL)
.post('/apis/authentication.k8s.io/v1/tokenreviews')
.reply(200, {
Expand Down Expand Up @@ -53,7 +53,7 @@ describe('userpreference Route', function () {
savedSearches: [{ description: '', id: '1678205878189', name: 'testing', searchText: 'kind:Pod' }],
},
}
nock(process.env.CLUSTER_API_URL).get('/apis').reply(200)
nock(process.env.CLUSTER_API_URL).get('/api').reply(200)
nock(process.env.CLUSTER_API_URL)
.post('/apis/authentication.k8s.io/v1/tokenreviews')
.reply(200, {
Expand Down
Loading