From 860de10fa67c2efa6ea3cf725e06792f68d7d381 Mon Sep 17 00:00:00 2001 From: Lucas Pires Date: Fri, 27 Jan 2023 17:58:28 -0300 Subject: [PATCH 1/4] feat: including authentication to server applications in scaffolder plugin Signed-off-by: Lucas Pires --- .changeset/backend-token-authentication.md | 5 ++++ packages/backend/src/plugins/scaffolder.ts | 1 + .../src/ScaffolderPlugin.ts | 3 +++ .../scaffolder-backend/src/service/router.ts | 26 ++++++++++++++----- 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 .changeset/backend-token-authentication.md diff --git a/.changeset/backend-token-authentication.md b/.changeset/backend-token-authentication.md new file mode 100644 index 0000000000..597921822f --- /dev/null +++ b/.changeset/backend-token-authentication.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Make identity valid if subject of token is a github-server token diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index d079b64c28..e734408d42 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -34,5 +34,6 @@ export default async function createPlugin( reader: env.reader, identity: env.identity, scheduler: env.scheduler, + tokenManager: env.tokenManager, }); } diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 43b8d30f99..639f9b0806 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -82,6 +82,7 @@ export const scaffolderPlugin = createBackendPlugin( database: coreServices.database, httpRouter: coreServices.httpRouter, catalogClient: catalogServiceRef, + tokenManager: coreServices.tokenManager, }, async init({ logger, @@ -90,6 +91,7 @@ export const scaffolderPlugin = createBackendPlugin( database, httpRouter, catalogClient, + tokenManager, }) { const { additionalTemplateFilters, @@ -127,6 +129,7 @@ export const scaffolderPlugin = createBackendPlugin( taskWorkers, additionalTemplateFilters, additionalTemplateGlobals, + tokenManager, }); httpRouter.use(router); }, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index c339de8d10..49cfa68306 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; +import { + PluginDatabaseManager, + TokenManager, + UrlReader, +} from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { CatalogApi } from '@backstage/catalog-client'; import { @@ -82,6 +86,7 @@ export interface RouterOptions { additionalTemplateFilters?: Record; additionalTemplateGlobals?: Record; identity?: IdentityApi; + tokenManager?: TokenManager; } function isSupportedTemplate(entity: TemplateEntityV1beta3) { @@ -96,13 +101,14 @@ function isSupportedTemplate(entity: TemplateEntityV1beta3) { * are using the IdentityApi, we can remove this function. */ function buildDefaultIdentityClient({ - logger, + options, }: { - logger: Logger; + options: RouterOptions; }): IdentityApi { return { getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => { const header = request.headers.authorization; + const { logger, tokenManager } = options; if (!header) { return undefined; @@ -132,8 +138,15 @@ function buildDefaultIdentityClient({ throw new TypeError('Expected string sub claim'); } - // Check that it's a valid ref, otherwise this will throw. - parseEntityRef(sub); + try { + // Check that it's a valid ref, otherwise this will throw. + parseEntityRef(sub); + } catch (e) { + if (sub !== 'backstage-server' || !options.tokenManager) { + throw e; + } + await tokenManager?.authenticate(token); + } return { identity: { @@ -179,8 +192,7 @@ export async function createRouter( const logger = parentLogger.child({ plugin: 'scaffolder' }); const identity: IdentityApi = - options.identity || buildDefaultIdentityClient({ logger }); - + options.identity || buildDefaultIdentityClient({ options }); const workingDirectory = await getWorkingDirectory(config, logger); const integrations = ScmIntegrations.fromConfig(config); From 9052ca8a2e37cf52268175b4d6096d460daa301d Mon Sep 17 00:00:00 2001 From: Lucas Pires Date: Fri, 27 Jan 2023 18:31:40 -0300 Subject: [PATCH 2/4] chore: including api changeset file Signed-off-by: Lucas Pires --- plugins/scaffolder-backend/api-report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 0d745862a1..81546dd00a 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -32,6 +32,7 @@ import { TaskSecrets as TaskSecrets_2 } from '@backstage/plugin-scaffolder-node' import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; +import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; @@ -642,6 +643,8 @@ export interface RouterOptions { taskBroker?: TaskBroker; // @deprecated (undocumented) taskWorkers?: number; + // (undocumented) + tokenManager?: TokenManager; } // @public (undocumented) From 770ecf61312cd89a042a10a3b83289cfe772c0db Mon Sep 17 00:00:00 2001 From: Lucas Pires Date: Wed, 15 Feb 2023 12:39:20 -0300 Subject: [PATCH 3/4] chore: removing token manager and adding backstage-server condition Signed-off-by: Lucas Pires --- .changeset/backend-token-authentication.md | 2 +- packages/backend/src/plugins/scaffolder.ts | 1 - plugins/scaffolder-backend/api-report.md | 3 --- .../src/ScaffolderPlugin.ts | 3 --- .../scaffolder-backend/src/service/router.ts | 24 +++++++------------ 5 files changed, 9 insertions(+), 24 deletions(-) diff --git a/.changeset/backend-token-authentication.md b/.changeset/backend-token-authentication.md index 597921822f..3b0f016800 100644 --- a/.changeset/backend-token-authentication.md +++ b/.changeset/backend-token-authentication.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend': patch --- -Make identity valid if subject of token is a github-server token +Make identity valid if subject of token is a backstage server-2-server auth token diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index e734408d42..d079b64c28 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -34,6 +34,5 @@ export default async function createPlugin( reader: env.reader, identity: env.identity, scheduler: env.scheduler, - tokenManager: env.tokenManager, }); } diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 81546dd00a..0d745862a1 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -32,7 +32,6 @@ import { TaskSecrets as TaskSecrets_2 } from '@backstage/plugin-scaffolder-node' import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; -import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; @@ -643,8 +642,6 @@ export interface RouterOptions { taskBroker?: TaskBroker; // @deprecated (undocumented) taskWorkers?: number; - // (undocumented) - tokenManager?: TokenManager; } // @public (undocumented) diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 639f9b0806..43b8d30f99 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -82,7 +82,6 @@ export const scaffolderPlugin = createBackendPlugin( database: coreServices.database, httpRouter: coreServices.httpRouter, catalogClient: catalogServiceRef, - tokenManager: coreServices.tokenManager, }, async init({ logger, @@ -91,7 +90,6 @@ export const scaffolderPlugin = createBackendPlugin( database, httpRouter, catalogClient, - tokenManager, }) { const { additionalTemplateFilters, @@ -129,7 +127,6 @@ export const scaffolderPlugin = createBackendPlugin( taskWorkers, additionalTemplateFilters, additionalTemplateGlobals, - tokenManager, }); httpRouter.use(router); }, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 49cfa68306..d082e3c268 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -86,7 +86,6 @@ export interface RouterOptions { additionalTemplateFilters?: Record; additionalTemplateGlobals?: Record; identity?: IdentityApi; - tokenManager?: TokenManager; } function isSupportedTemplate(entity: TemplateEntityV1beta3) { @@ -100,15 +99,11 @@ function isSupportedTemplate(entity: TemplateEntityV1beta3) { * until someone explicitly passes an IdentityApi. When we have reasonable confidence that most backstage deployments * are using the IdentityApi, we can remove this function. */ -function buildDefaultIdentityClient({ - options, -}: { - options: RouterOptions; -}): IdentityApi { +function buildDefaultIdentityClient(options: RouterOptions): IdentityApi { return { getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => { const header = request.headers.authorization; - const { logger, tokenManager } = options; + const { logger } = options; if (!header) { return undefined; @@ -138,16 +133,13 @@ function buildDefaultIdentityClient({ throw new TypeError('Expected string sub claim'); } - try { - // Check that it's a valid ref, otherwise this will throw. - parseEntityRef(sub); - } catch (e) { - if (sub !== 'backstage-server' || !options.tokenManager) { - throw e; - } - await tokenManager?.authenticate(token); + if (sub === 'backstage-server') { + return undefined; } + // Check that it's a valid ref, otherwise this will throw. + parseEntityRef(sub); + return { identity: { userEntityRef: sub, @@ -192,7 +184,7 @@ export async function createRouter( const logger = parentLogger.child({ plugin: 'scaffolder' }); const identity: IdentityApi = - options.identity || buildDefaultIdentityClient({ options }); + options.identity || buildDefaultIdentityClient(options); const workingDirectory = await getWorkingDirectory(config, logger); const integrations = ScmIntegrations.fromConfig(config); From 5e2a3987aaf426f27ee16189e22488aec54890e2 Mon Sep 17 00:00:00 2001 From: Lucas Pires Date: Wed, 15 Feb 2023 14:23:43 -0300 Subject: [PATCH 4/4] fix: removing unused var Signed-off-by: Lucas Pires --- plugins/scaffolder-backend/src/service/router.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index d082e3c268..7e8ffc1109 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - PluginDatabaseManager, - TokenManager, - UrlReader, -} from '@backstage/backend-common'; +import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { CatalogApi } from '@backstage/catalog-client'; import {