backend-common: provide legacyPlugin shims for identity and tokenManager
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -35,6 +35,7 @@ import { PermissionsService } from '@backstage/backend-plugin-api';
|
||||
import { PluginMetadataService } from '@backstage/backend-plugin-api';
|
||||
import { PushResult } from 'isomorphic-git';
|
||||
import { ReadCommitResult } from 'isomorphic-git';
|
||||
import { Request as Request_2 } from 'express';
|
||||
import { RequestHandler } from 'express';
|
||||
import { resolvePackagePath as resolvePackagePath_2 } from '@backstage/backend-plugin-api';
|
||||
import { resolveSafeChildPath as resolveSafeChildPath_2 } from '@backstage/backend-plugin-api';
|
||||
@@ -321,6 +322,23 @@ export type KubernetesContainerRunnerOptions = {
|
||||
// @public @deprecated (undocumented)
|
||||
export type LegacyCreateRouter<TEnv> = (deps: TEnv) => Promise<RequestHandler>;
|
||||
|
||||
// @public @deprecated
|
||||
export interface LegacyIdentityService {
|
||||
// (undocumented)
|
||||
getIdentity(options: { request: Request_2<unknown> }): Promise<
|
||||
| {
|
||||
expiresInSeconds?: number;
|
||||
token: string;
|
||||
identity: {
|
||||
type: 'user';
|
||||
userEntityRef: string;
|
||||
ownershipEntityRefs: string[];
|
||||
};
|
||||
}
|
||||
| undefined
|
||||
>;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export const legacyPlugin: (
|
||||
name: string,
|
||||
@@ -335,9 +353,7 @@ export const legacyPlugin: (
|
||||
logger: LoggerService;
|
||||
permissions: PermissionsService;
|
||||
scheduler: SchedulerService;
|
||||
tokenManager: TokenManagerService;
|
||||
reader: UrlReaderService;
|
||||
identity: IdentityService;
|
||||
},
|
||||
{
|
||||
logger: (log: LoggerService) => Logger;
|
||||
@@ -345,7 +361,10 @@ export const legacyPlugin: (
|
||||
getClient(options?: CacheServiceOptions | undefined): CacheService;
|
||||
};
|
||||
}
|
||||
>
|
||||
> & {
|
||||
tokenManager: ServerTokenManager;
|
||||
identity: LegacyIdentityService;
|
||||
}
|
||||
>;
|
||||
}>,
|
||||
) => BackendFeatureCompat;
|
||||
@@ -384,7 +403,12 @@ export function makeLegacyPlugin<
|
||||
): (
|
||||
name: string,
|
||||
createRouterImport: Promise<{
|
||||
default: LegacyCreateRouter<TransformedEnv<TEnv, TEnvTransforms>>;
|
||||
default: LegacyCreateRouter<
|
||||
TransformedEnv<TEnv, TEnvTransforms> & {
|
||||
tokenManager: ServerTokenManager;
|
||||
identity: LegacyIdentityService;
|
||||
}
|
||||
>;
|
||||
}>,
|
||||
) => BackendFeatureCompat;
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
*/
|
||||
|
||||
export { legacyPlugin, makeLegacyPlugin } from './legacy';
|
||||
export type { LegacyCreateRouter } from './legacy';
|
||||
export type { LegacyCreateRouter, LegacyIdentityService } from './legacy';
|
||||
|
||||
@@ -18,13 +18,17 @@ import {
|
||||
AuthService,
|
||||
coreServices,
|
||||
createBackendPlugin,
|
||||
HttpRouterService,
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
RootConfigService,
|
||||
ServiceRef,
|
||||
UserInfoService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { RequestHandler } from 'express';
|
||||
import { cacheToPluginCacheManager } from '../cache';
|
||||
import { loggerToWinstonLogger } from '../logging';
|
||||
import { TokenManager } from '../../deprecated';
|
||||
import { ServerTokenManager, TokenManager } from '../../deprecated';
|
||||
import { Request } from 'express';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -46,8 +50,13 @@ type TransformedEnv<
|
||||
// new plugin tokens, which we'll also be signaling by supporting the JWKS endpoint through
|
||||
// the http router.
|
||||
// This makes sure that we accept the new plugin tokens as valid tokens, but otherwise fall
|
||||
// back to whatever the token manager is doing.
|
||||
function wrapTokenManager(tokenManager: TokenManager, auth: AuthService) {
|
||||
// back to the legacy token manager.
|
||||
function createTokenManagerShim(
|
||||
auth: AuthService,
|
||||
config: RootConfigService,
|
||||
logger: LoggerService,
|
||||
): TokenManager {
|
||||
const tokenManager = ServerTokenManager.fromConfig(config, { logger });
|
||||
return {
|
||||
async getToken() {
|
||||
return tokenManager.getToken();
|
||||
@@ -64,7 +73,64 @@ function wrapTokenManager(tokenManager: TokenManager, auth: AuthService) {
|
||||
}
|
||||
await tokenManager.authenticate(token);
|
||||
},
|
||||
} satisfies TokenManager;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Originally IdentityApi from `@backstage/plugin-auth-node`, not re-declared here for backwards compatibility
|
||||
* @public
|
||||
* @deprecated Only relevant for legacy plugins, which are deprecated.
|
||||
*/
|
||||
export interface LegacyIdentityService {
|
||||
getIdentity(options: { request: Request<unknown> }): Promise<
|
||||
| {
|
||||
expiresInSeconds?: number;
|
||||
|
||||
token: string;
|
||||
identity: {
|
||||
type: 'user';
|
||||
userEntityRef: string;
|
||||
ownershipEntityRefs: string[];
|
||||
};
|
||||
}
|
||||
| undefined
|
||||
>;
|
||||
}
|
||||
|
||||
function createIdentityServiceShim(
|
||||
httpAuth: HttpAuthService,
|
||||
userInfo: UserInfoService,
|
||||
): LegacyIdentityService {
|
||||
return {
|
||||
async getIdentity(options) {
|
||||
const credentials = await httpAuth
|
||||
.credentials(options.request, {
|
||||
allow: ['user'],
|
||||
})
|
||||
.catch(() => undefined);
|
||||
|
||||
if (!credentials) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const info = await userInfo.getUserInfo(credentials);
|
||||
|
||||
return {
|
||||
get token(): string {
|
||||
throw new Error(
|
||||
'The identity service shim provided by legacyPlugin does not support accessing the user token. ' +
|
||||
'The calling plugin needs to be migrated to use the new auth services. ' +
|
||||
'See https://backstage.io/docs/tutorials/auth-service-migration',
|
||||
);
|
||||
},
|
||||
identity: {
|
||||
type: 'user',
|
||||
userEntityRef: info.userEntityRef,
|
||||
ownershipEntityRefs: info.ownershipEntityRefs,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +153,12 @@ export function makeLegacyPlugin<
|
||||
return (
|
||||
name: string,
|
||||
createRouterImport: Promise<{
|
||||
default: LegacyCreateRouter<TransformedEnv<TEnv, TEnvTransforms>>;
|
||||
default: LegacyCreateRouter<
|
||||
TransformedEnv<TEnv, TEnvTransforms> & {
|
||||
tokenManager: ServerTokenManager;
|
||||
identity: LegacyIdentityService;
|
||||
}
|
||||
>;
|
||||
}>,
|
||||
) => {
|
||||
const compatPlugin = createBackendPlugin({
|
||||
@@ -96,10 +167,22 @@ export function makeLegacyPlugin<
|
||||
env.registerInit({
|
||||
deps: {
|
||||
...envMapping,
|
||||
_router: coreServices.httpRouter,
|
||||
_auth: coreServices.auth,
|
||||
$$router: coreServices.httpRouter,
|
||||
$$auth: coreServices.auth,
|
||||
$$httpAuth: coreServices.httpAuth,
|
||||
$$userInfo: coreServices.userInfo,
|
||||
$$config: coreServices.rootConfig,
|
||||
$$logger: coreServices.logger,
|
||||
},
|
||||
async init({ _router, _auth, ...envDeps }) {
|
||||
async init({
|
||||
$$auth,
|
||||
$$config,
|
||||
$$httpAuth,
|
||||
$$logger,
|
||||
$$router,
|
||||
$$userInfo,
|
||||
...envDeps
|
||||
}) {
|
||||
const { default: createRouter } = await createRouterImport;
|
||||
const pluginEnv = Object.fromEntries(
|
||||
Object.entries(envDeps).map(([key, dep]) => {
|
||||
@@ -107,19 +190,32 @@ export function makeLegacyPlugin<
|
||||
if (transform) {
|
||||
return [key, transform(dep)];
|
||||
}
|
||||
if (key === 'tokenManager') {
|
||||
return [
|
||||
key,
|
||||
wrapTokenManager(dep as TokenManager, _auth as AuthService),
|
||||
];
|
||||
}
|
||||
return [key, dep];
|
||||
}),
|
||||
);
|
||||
const router = await createRouter(
|
||||
pluginEnv as TransformedEnv<TEnv, TEnvTransforms>,
|
||||
|
||||
const auth = $$auth as typeof coreServices.auth.T;
|
||||
const config = $$config as typeof coreServices.rootConfig.T;
|
||||
const httpAuth = $$httpAuth as typeof coreServices.httpAuth.T;
|
||||
const logger = $$logger as typeof coreServices.logger.T;
|
||||
const router = $$router as typeof coreServices.httpRouter.T;
|
||||
const userInfo = $$userInfo as typeof coreServices.userInfo.T;
|
||||
|
||||
// Token manager and identity services are no longer supported in the new backend system, so we provide shims for them.
|
||||
pluginEnv.tokenManager = createTokenManagerShim(
|
||||
auth,
|
||||
config,
|
||||
logger,
|
||||
);
|
||||
(_router as HttpRouterService).use(router);
|
||||
pluginEnv.identity = createIdentityServiceShim(httpAuth, userInfo);
|
||||
|
||||
const pluginRouter = await createRouter(
|
||||
pluginEnv as TransformedEnv<TEnv, TEnvTransforms> & {
|
||||
tokenManager: ServerTokenManager;
|
||||
identity: LegacyIdentityService;
|
||||
},
|
||||
);
|
||||
router.use(pluginRouter);
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -155,9 +251,7 @@ export const legacyPlugin = makeLegacyPlugin(
|
||||
logger: coreServices.logger,
|
||||
permissions: coreServices.permissions,
|
||||
scheduler: coreServices.scheduler,
|
||||
tokenManager: coreServices.tokenManager,
|
||||
reader: coreServices.urlReader,
|
||||
identity: coreServices.identity,
|
||||
},
|
||||
{
|
||||
logger: log => loggerToWinstonLogger(log),
|
||||
|
||||
Reference in New Issue
Block a user