Verify access to related catalog entities for all techdocs api routes

Signed-off-by: Joe Porpeglia <josephp@spotify.com>
Co-authored-by: Nataliya Issayeva <nissayeva@users.noreply.github.com>
This commit is contained in:
Joe Porpeglia
2022-01-05 14:57:07 -05:00
committed by Joe Porpeglia
parent 6680853e0c
commit b76fec242d
+37 -15
View File
@@ -18,7 +18,7 @@ import {
PluginCacheManager,
} from '@backstage/backend-common';
import { CatalogClient } from '@backstage/catalog-client';
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
import { stringifyEntityRef } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { NotFoundError, NotModifiedError } from '@backstage/errors';
import {
@@ -27,7 +27,6 @@ import {
PreparerBuilder,
PublisherBase,
} from '@backstage/techdocs-common';
import fetch from 'node-fetch';
import express, { Response } from 'express';
import Router from 'express-promise-router';
import { Knex } from 'knex';
@@ -107,6 +106,16 @@ export async function createRouter(
router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => {
const { kind, namespace, name } = req.params;
const entityName = { kind, namespace, name };
const token = getBearerToken(req.headers.authorization);
// Verify that the related entity exists and the current user has permission to view it.
const entity = await catalogClient.getEntityByName(entityName, { token });
if (!entity) {
throw new NotFoundError(
`Unable to get metadata for '${stringifyEntityRef(entityName)}'`,
);
}
try {
const techdocsMetadata = await publisher.fetchTechDocsMetadata(
@@ -128,23 +137,19 @@ export async function createRouter(
});
router.get('/metadata/entity/:namespace/:kind/:name', async (req, res) => {
const catalogUrl = await discovery.getBaseUrl('catalog');
const { kind, namespace, name } = req.params;
const entityName = { kind, namespace, name };
const token = getBearerToken(req.headers.authorization);
const entity = await catalogClient.getEntityByName(entityName, { token });
if (!entity) {
throw new NotFoundError(
`Unable to get metadata for '${stringifyEntityRef(entityName)}'`,
);
}
try {
const token = getBearerToken(req.headers.authorization);
// TODO: Consider using the catalog client here
const entity = (await (
await fetch(
`${catalogUrl}/entities/by-name/${kind}/${namespace}/${name}`,
{
headers: token ? { Authorization: `Bearer ${token}` } : {},
},
)
).json()) as Entity;
const locationMetadata = getLocationForEntity(entity, scmIntegrations);
res.json({ ...entity, locationMetadata });
} catch (err) {
@@ -226,6 +231,23 @@ export async function createRouter(
);
});
// Ensures that the related entity exists and the current user has permission to view it.
router.use('/static/docs/:namespace/:kind/:name', async (req, _res, next) => {
const { kind, namespace, name } = req.params;
const entityName = { kind, namespace, name };
const token = getBearerToken(req.headers.authorization);
const entity = await catalogClient.getEntityByName(entityName, { token });
if (!entity) {
throw new NotFoundError(
`Entity not found for ${stringifyEntityRef(entityName)}`,
);
}
next();
});
// If a cache manager was provided, attach the cache middleware.
if (cache) {
router.use(createCacheMiddleware({ logger, cache }));