@acarmisc/backstage-plugin-litellm-backend 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +135 -60
- package/dist/index.cjs.js.map +4 -4
- package/dist/plugin.js +1 -0
- package/dist/routes/bridge.js +29 -0
- package/dist/routes/objectPermissions.js +16 -0
- package/dist/services/keyService.js +27 -1
- package/dist/services/mcpAccess.d.ts +20 -0
- package/dist/services/mcpAccess.js +28 -0
- package/package.json +2 -2
package/dist/index.cjs.js
CHANGED
|
@@ -7982,20 +7982,20 @@ __export(index_exports, {
|
|
|
7982
7982
|
getOrProvisionUser: () => getOrProvisionUser,
|
|
7983
7983
|
getOrProvisionUserFromClaims: () => getOrProvisionUserFromClaims,
|
|
7984
7984
|
isTeamManagementEnabled: () => isTeamManagementEnabled,
|
|
7985
|
-
litellmAuditReadPermission: () =>
|
|
7986
|
-
litellmKeyCreatePermission: () =>
|
|
7987
|
-
litellmKeyManagePermission: () =>
|
|
7988
|
-
litellmKeyResetSpendPermission: () =>
|
|
7989
|
-
litellmKeyRevokePermission: () =>
|
|
7990
|
-
litellmKeyUnblockPermission: () =>
|
|
7991
|
-
litellmPermissions: () =>
|
|
7985
|
+
litellmAuditReadPermission: () => import_backstage_plugin_litellm_common13.litellmAuditReadPermission,
|
|
7986
|
+
litellmKeyCreatePermission: () => import_backstage_plugin_litellm_common13.litellmKeyCreatePermission,
|
|
7987
|
+
litellmKeyManagePermission: () => import_backstage_plugin_litellm_common13.litellmKeyManagePermission,
|
|
7988
|
+
litellmKeyResetSpendPermission: () => import_backstage_plugin_litellm_common13.litellmKeyResetSpendPermission,
|
|
7989
|
+
litellmKeyRevokePermission: () => import_backstage_plugin_litellm_common13.litellmKeyRevokePermission,
|
|
7990
|
+
litellmKeyUnblockPermission: () => import_backstage_plugin_litellm_common13.litellmKeyUnblockPermission,
|
|
7991
|
+
litellmPermissions: () => import_backstage_plugin_litellm_common13.litellmPermissions,
|
|
7992
7992
|
litellmPlugin: () => litellmPlugin,
|
|
7993
|
-
litellmTeamCreatePermission: () =>
|
|
7994
|
-
litellmTeamDeletePermission: () =>
|
|
7995
|
-
litellmTeamKnowledgebaseManagePermission: () =>
|
|
7996
|
-
litellmTeamManagePermission: () =>
|
|
7997
|
-
litellmTeamMcpManagePermission: () =>
|
|
7998
|
-
litellmTeamMembersManagePermission: () =>
|
|
7993
|
+
litellmTeamCreatePermission: () => import_backstage_plugin_litellm_common13.litellmTeamCreatePermission,
|
|
7994
|
+
litellmTeamDeletePermission: () => import_backstage_plugin_litellm_common13.litellmTeamDeletePermission,
|
|
7995
|
+
litellmTeamKnowledgebaseManagePermission: () => import_backstage_plugin_litellm_common13.litellmTeamKnowledgebaseManagePermission,
|
|
7996
|
+
litellmTeamManagePermission: () => import_backstage_plugin_litellm_common13.litellmTeamManagePermission,
|
|
7997
|
+
litellmTeamMcpManagePermission: () => import_backstage_plugin_litellm_common13.litellmTeamMcpManagePermission,
|
|
7998
|
+
litellmTeamMembersManagePermission: () => import_backstage_plugin_litellm_common13.litellmTeamMembersManagePermission,
|
|
7999
7999
|
newDefaultVerifier: () => newDefaultVerifier,
|
|
8000
8000
|
provisionUser: () => provisionUser,
|
|
8001
8001
|
readBridgeConfig: () => readBridgeConfig,
|
|
@@ -9167,7 +9167,7 @@ async function resolveUserRole(userEntityRef, roleConfigs, catalogClient, auth,
|
|
|
9167
9167
|
}
|
|
9168
9168
|
|
|
9169
9169
|
// src/router.ts
|
|
9170
|
-
var
|
|
9170
|
+
var import_backstage_plugin_litellm_common11 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
9171
9171
|
|
|
9172
9172
|
// src/teamAdmin.ts
|
|
9173
9173
|
var import_plugin_permission_common = __toESM(require_index_cjs2());
|
|
@@ -10068,7 +10068,7 @@ function registerConfigRoutes(router, ctx) {
|
|
|
10068
10068
|
}
|
|
10069
10069
|
|
|
10070
10070
|
// src/routes/keys.ts
|
|
10071
|
-
var
|
|
10071
|
+
var import_backstage_plugin_litellm_common4 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
10072
10072
|
|
|
10073
10073
|
// src/services/modelAccess.ts
|
|
10074
10074
|
var import_backstage_plugin_litellm_common2 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
@@ -10090,6 +10090,18 @@ async function findDisallowedModels(client, requested, allowed) {
|
|
|
10090
10090
|
);
|
|
10091
10091
|
}
|
|
10092
10092
|
|
|
10093
|
+
// src/services/mcpAccess.ts
|
|
10094
|
+
var import_backstage_plugin_litellm_common3 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
10095
|
+
var NO_MCP_SERVERS = "no-mcp-servers";
|
|
10096
|
+
function teamMcpServers(team) {
|
|
10097
|
+
const listed = team?.object_permission?.mcp_servers ?? [];
|
|
10098
|
+
return [...new Set(listed)].filter((n) => import_backstage_plugin_litellm_common3.MCP_SERVER_NAME_RE.test(n));
|
|
10099
|
+
}
|
|
10100
|
+
function findDisallowedMcpServers(requested, allowed) {
|
|
10101
|
+
const ok = new Set(allowed);
|
|
10102
|
+
return [...new Set(requested)].filter((n) => !ok.has(n));
|
|
10103
|
+
}
|
|
10104
|
+
|
|
10093
10105
|
// src/services/keyService.ts
|
|
10094
10106
|
var KeyServiceError = class extends Error {
|
|
10095
10107
|
constructor(status, body, message2) {
|
|
@@ -10131,10 +10143,12 @@ async function createKeyForUser(user, input, ctx) {
|
|
|
10131
10143
|
);
|
|
10132
10144
|
}
|
|
10133
10145
|
}
|
|
10146
|
+
let teamPromise;
|
|
10147
|
+
const getTeam = (teamId) => teamPromise ??= client.getTeamInfo(teamId);
|
|
10134
10148
|
if (input.models && input.models.length > 0) {
|
|
10135
10149
|
let allowedModels = [];
|
|
10136
10150
|
if (input.team_id) {
|
|
10137
|
-
const teamInfo = await
|
|
10151
|
+
const teamInfo = await getTeam(input.team_id);
|
|
10138
10152
|
allowedModels = teamInfo?.models ?? [];
|
|
10139
10153
|
} else {
|
|
10140
10154
|
allowedModels = userInfo?.models ?? [];
|
|
@@ -10167,6 +10181,19 @@ async function createKeyForUser(user, input, ctx) {
|
|
|
10167
10181
|
...clientMetadata,
|
|
10168
10182
|
...serverMetadata
|
|
10169
10183
|
};
|
|
10184
|
+
const mcpServers = input.mcp_servers ? [...new Set(input.mcp_servers)] : void 0;
|
|
10185
|
+
if (mcpServers && mcpServers.length > 0) {
|
|
10186
|
+
if (!input.team_id) {
|
|
10187
|
+
throw new KeyServiceError(400, { error: "team_id is required when mcp_servers is set" });
|
|
10188
|
+
}
|
|
10189
|
+
const disallowed = findDisallowedMcpServers(mcpServers, teamMcpServers(await getTeam(input.team_id)));
|
|
10190
|
+
if (disallowed.length > 0) {
|
|
10191
|
+
throw new KeyServiceError(403, {
|
|
10192
|
+
error: "One or more requested MCP servers are not allowed",
|
|
10193
|
+
disallowed_mcp_servers: disallowed
|
|
10194
|
+
});
|
|
10195
|
+
}
|
|
10196
|
+
}
|
|
10170
10197
|
const upstreamRequest = {
|
|
10171
10198
|
alias: input.alias,
|
|
10172
10199
|
user_id: userInfo.user_id
|
|
@@ -10195,6 +10222,11 @@ async function createKeyForUser(user, input, ctx) {
|
|
|
10195
10222
|
if (input.key_type !== void 0) {
|
|
10196
10223
|
upstreamRequest.key_type = input.key_type;
|
|
10197
10224
|
}
|
|
10225
|
+
if (mcpServers) {
|
|
10226
|
+
upstreamRequest.object_permission = {
|
|
10227
|
+
mcp_servers: mcpServers.length > 0 ? mcpServers : [NO_MCP_SERVERS]
|
|
10228
|
+
};
|
|
10229
|
+
}
|
|
10198
10230
|
upstreamRequest.metadata = enrichedMetadata;
|
|
10199
10231
|
const result = await client.generateKey(upstreamRequest);
|
|
10200
10232
|
logger.info("key.generate", { userId: userInfo.user_id, keyAlias: input.alias });
|
|
@@ -10217,8 +10249,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10217
10249
|
assertPermission,
|
|
10218
10250
|
sendPermissionDenied
|
|
10219
10251
|
} = ctx;
|
|
10220
|
-
const generateKeyInputSchema = (0,
|
|
10221
|
-
const updateKeyInputSchema = (0,
|
|
10252
|
+
const generateKeyInputSchema = (0, import_backstage_plugin_litellm_common4.createGenerateKeyInputSchema)(keyValidationConfig);
|
|
10253
|
+
const updateKeyInputSchema = (0, import_backstage_plugin_litellm_common4.createUpdateKeyInputSchema)(keyValidationConfig);
|
|
10222
10254
|
router.get("/user/info", async (_req, res) => {
|
|
10223
10255
|
try {
|
|
10224
10256
|
const tokenEntityRef = res.locals.tokenEntityRef;
|
|
@@ -10255,8 +10287,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10255
10287
|
});
|
|
10256
10288
|
router.post("/keys/prune-expired", async (_req, res) => {
|
|
10257
10289
|
try {
|
|
10258
|
-
if (!await assertPermission(_req,
|
|
10259
|
-
sendPermissionDenied(res,
|
|
10290
|
+
if (!await assertPermission(_req, import_backstage_plugin_litellm_common4.litellmKeyRevokePermission)) {
|
|
10291
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyRevokePermission);
|
|
10260
10292
|
return;
|
|
10261
10293
|
}
|
|
10262
10294
|
await getProvisionedUser(ctx, res);
|
|
@@ -10320,8 +10352,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10320
10352
|
return;
|
|
10321
10353
|
}
|
|
10322
10354
|
const input = parseResult.data;
|
|
10323
|
-
if (!await assertPermission(req,
|
|
10324
|
-
sendPermissionDenied(res,
|
|
10355
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyCreatePermission)) {
|
|
10356
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyCreatePermission);
|
|
10325
10357
|
return;
|
|
10326
10358
|
}
|
|
10327
10359
|
const tokenEntityRef = res.locals.tokenEntityRef;
|
|
@@ -10370,8 +10402,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10370
10402
|
res.status(400).json({ error: "keyId is required" });
|
|
10371
10403
|
return;
|
|
10372
10404
|
}
|
|
10373
|
-
if (!await assertPermission(req,
|
|
10374
|
-
sendPermissionDenied(res,
|
|
10405
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyManagePermission)) {
|
|
10406
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyManagePermission);
|
|
10375
10407
|
return;
|
|
10376
10408
|
}
|
|
10377
10409
|
const { tokenEntityRef, userId, key } = await authorizeKeyAction(req, keyId);
|
|
@@ -10448,8 +10480,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10448
10480
|
res.status(400).json({ error: "keyId is required" });
|
|
10449
10481
|
return;
|
|
10450
10482
|
}
|
|
10451
|
-
if (!await assertPermission(req,
|
|
10452
|
-
sendPermissionDenied(res,
|
|
10483
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyRevokePermission)) {
|
|
10484
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyRevokePermission);
|
|
10453
10485
|
return;
|
|
10454
10486
|
}
|
|
10455
10487
|
const { tokenEntityRef } = await authorizeKeyAction(req, keyId);
|
|
@@ -10463,8 +10495,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10463
10495
|
router.post("/keys/:keyId/block", async (req, res) => {
|
|
10464
10496
|
try {
|
|
10465
10497
|
const { keyId } = req.params;
|
|
10466
|
-
if (!await assertPermission(req,
|
|
10467
|
-
sendPermissionDenied(res,
|
|
10498
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyManagePermission)) {
|
|
10499
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyManagePermission);
|
|
10468
10500
|
return;
|
|
10469
10501
|
}
|
|
10470
10502
|
const { tokenEntityRef, key } = await authorizeKeyAction(req, keyId);
|
|
@@ -10492,8 +10524,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10492
10524
|
try {
|
|
10493
10525
|
const { keyId } = req.params;
|
|
10494
10526
|
const { tokenEntityRef, key } = await authorizeKeyAction(req, keyId);
|
|
10495
|
-
if (!await assertPermission(req,
|
|
10496
|
-
sendPermissionDenied(res,
|
|
10527
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyUnblockPermission)) {
|
|
10528
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyUnblockPermission);
|
|
10497
10529
|
return;
|
|
10498
10530
|
}
|
|
10499
10531
|
await client.unblockKey(keyId);
|
|
@@ -10521,8 +10553,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10521
10553
|
});
|
|
10522
10554
|
return;
|
|
10523
10555
|
}
|
|
10524
|
-
if (!await assertPermission(req,
|
|
10525
|
-
sendPermissionDenied(res,
|
|
10556
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmKeyResetSpendPermission)) {
|
|
10557
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmKeyResetSpendPermission);
|
|
10526
10558
|
return;
|
|
10527
10559
|
}
|
|
10528
10560
|
const { tokenEntityRef } = await authorizeKeyAction(req, keyId);
|
|
@@ -10554,8 +10586,8 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10554
10586
|
res.status(403).json({ error: "Access denied: not a member of the audit group" });
|
|
10555
10587
|
return;
|
|
10556
10588
|
}
|
|
10557
|
-
if (!await assertPermission(req,
|
|
10558
|
-
sendPermissionDenied(res,
|
|
10589
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common4.litellmAuditReadPermission)) {
|
|
10590
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common4.litellmAuditReadPermission);
|
|
10559
10591
|
return;
|
|
10560
10592
|
}
|
|
10561
10593
|
try {
|
|
@@ -10607,7 +10639,7 @@ function registerKeysRoutes(router, ctx) {
|
|
|
10607
10639
|
}
|
|
10608
10640
|
|
|
10609
10641
|
// src/routes/opencode.ts
|
|
10610
|
-
var
|
|
10642
|
+
var import_backstage_plugin_litellm_common5 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
10611
10643
|
function isValidRedirectUri(uri) {
|
|
10612
10644
|
if (!uri) return false;
|
|
10613
10645
|
try {
|
|
@@ -10649,8 +10681,8 @@ function registerOpencodeRoutes(router, ctx) {
|
|
|
10649
10681
|
return null;
|
|
10650
10682
|
}
|
|
10651
10683
|
const redirectUri = redirectUriParam;
|
|
10652
|
-
if (!await assertPermission(req,
|
|
10653
|
-
sendPermissionDenied(res,
|
|
10684
|
+
if (!await assertPermission(req, import_backstage_plugin_litellm_common5.litellmKeyCreatePermission)) {
|
|
10685
|
+
sendPermissionDenied(res, import_backstage_plugin_litellm_common5.litellmKeyCreatePermission);
|
|
10654
10686
|
return null;
|
|
10655
10687
|
}
|
|
10656
10688
|
const computedUserId = toLiteLLMUserId(tokenEntityRef, userIdDomain);
|
|
@@ -10818,7 +10850,7 @@ function registerOpencodeRoutes(router, ctx) {
|
|
|
10818
10850
|
}
|
|
10819
10851
|
|
|
10820
10852
|
// src/routes/teams.ts
|
|
10821
|
-
var
|
|
10853
|
+
var import_backstage_plugin_litellm_common6 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
10822
10854
|
|
|
10823
10855
|
// src/http/respondTeam.ts
|
|
10824
10856
|
function respondTeam(res, team, ctx, caller) {
|
|
@@ -10913,7 +10945,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
10913
10945
|
permissions,
|
|
10914
10946
|
catalogClient,
|
|
10915
10947
|
teamAdminGroup: teamAdminCfg.group,
|
|
10916
|
-
permission:
|
|
10948
|
+
permission: import_backstage_plugin_litellm_common6.litellmTeamCreatePermission,
|
|
10917
10949
|
logger
|
|
10918
10950
|
});
|
|
10919
10951
|
if (!check.ok) {
|
|
@@ -10987,7 +11019,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
10987
11019
|
const authz = await authorizeTeamSubresource(
|
|
10988
11020
|
req,
|
|
10989
11021
|
res,
|
|
10990
|
-
|
|
11022
|
+
import_backstage_plugin_litellm_common6.litellmTeamManagePermission
|
|
10991
11023
|
);
|
|
10992
11024
|
if (!authz) return;
|
|
10993
11025
|
const { teamId, owningGroup, actor, team: existing } = authz;
|
|
@@ -11028,7 +11060,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
11028
11060
|
const authz = await authorizeTeamSubresource(
|
|
11029
11061
|
req,
|
|
11030
11062
|
res,
|
|
11031
|
-
|
|
11063
|
+
import_backstage_plugin_litellm_common6.litellmTeamDeletePermission
|
|
11032
11064
|
);
|
|
11033
11065
|
if (!authz) return;
|
|
11034
11066
|
const { teamId, owningGroup, actor } = authz;
|
|
@@ -11069,7 +11101,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
11069
11101
|
permissions,
|
|
11070
11102
|
catalogClient,
|
|
11071
11103
|
teamAdminGroup: teamAdminCfg.group,
|
|
11072
|
-
permission:
|
|
11104
|
+
permission: import_backstage_plugin_litellm_common6.litellmTeamManagePermission,
|
|
11073
11105
|
logger
|
|
11074
11106
|
});
|
|
11075
11107
|
if (!check.ok) {
|
|
@@ -11092,7 +11124,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
11092
11124
|
const authz = await authorizeTeamSubresource(
|
|
11093
11125
|
req,
|
|
11094
11126
|
res,
|
|
11095
|
-
|
|
11127
|
+
import_backstage_plugin_litellm_common6.litellmTeamMembersManagePermission,
|
|
11096
11128
|
{ allowTeamRole: true }
|
|
11097
11129
|
);
|
|
11098
11130
|
if (!authz) return;
|
|
@@ -11197,7 +11229,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
11197
11229
|
const authz = await authorizeTeamSubresource(
|
|
11198
11230
|
req,
|
|
11199
11231
|
res,
|
|
11200
|
-
|
|
11232
|
+
import_backstage_plugin_litellm_common6.litellmTeamMembersManagePermission,
|
|
11201
11233
|
{ allowTeamRole: true }
|
|
11202
11234
|
);
|
|
11203
11235
|
if (!authz) return;
|
|
@@ -11245,7 +11277,7 @@ function registerTeamsRoutes(router, ctx) {
|
|
|
11245
11277
|
}
|
|
11246
11278
|
|
|
11247
11279
|
// src/routes/objectPermissions.ts
|
|
11248
|
-
var
|
|
11280
|
+
var import_backstage_plugin_litellm_common7 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
11249
11281
|
function registerObjectPermissionsRoutes(router, ctx) {
|
|
11250
11282
|
const {
|
|
11251
11283
|
client,
|
|
@@ -11258,6 +11290,16 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11258
11290
|
sendTeamError,
|
|
11259
11291
|
authorizeTeamSubresource
|
|
11260
11292
|
} = ctx;
|
|
11293
|
+
router.get("/object-names", createRequireUser(ctx), async (_req, res) => {
|
|
11294
|
+
const [vectorStores, mcpServers] = await Promise.all([
|
|
11295
|
+
client.listVectorStores().catch(() => []),
|
|
11296
|
+
client.listMcpServers().catch(() => [])
|
|
11297
|
+
]);
|
|
11298
|
+
res.json({
|
|
11299
|
+
vector_stores: vectorStores.map(({ id, name }) => ({ id, name })),
|
|
11300
|
+
mcp_servers: mcpServers.map(({ id, name }) => ({ id, name }))
|
|
11301
|
+
});
|
|
11302
|
+
});
|
|
11261
11303
|
router.get("/vector-stores", async (req, res) => {
|
|
11262
11304
|
if (!requireObjectPerms(res)) return;
|
|
11263
11305
|
if (!teamAdminCfg.group) {
|
|
@@ -11270,7 +11312,7 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11270
11312
|
permissions,
|
|
11271
11313
|
catalogClient,
|
|
11272
11314
|
teamAdminGroup: teamAdminCfg.group,
|
|
11273
|
-
permission:
|
|
11315
|
+
permission: import_backstage_plugin_litellm_common7.litellmTeamKnowledgebaseManagePermission,
|
|
11274
11316
|
logger
|
|
11275
11317
|
});
|
|
11276
11318
|
if (!check.ok) {
|
|
@@ -11292,7 +11334,7 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11292
11334
|
const authz = await authorizeTeamSubresource(
|
|
11293
11335
|
req,
|
|
11294
11336
|
res,
|
|
11295
|
-
|
|
11337
|
+
import_backstage_plugin_litellm_common7.litellmTeamKnowledgebaseManagePermission
|
|
11296
11338
|
);
|
|
11297
11339
|
if (!authz) return;
|
|
11298
11340
|
const { teamId, owningGroup, actor, team } = authz;
|
|
@@ -11352,7 +11394,7 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11352
11394
|
permissions,
|
|
11353
11395
|
catalogClient,
|
|
11354
11396
|
teamAdminGroup: teamAdminCfg.group,
|
|
11355
|
-
permission:
|
|
11397
|
+
permission: import_backstage_plugin_litellm_common7.litellmTeamMcpManagePermission,
|
|
11356
11398
|
logger
|
|
11357
11399
|
});
|
|
11358
11400
|
if (!check.ok) {
|
|
@@ -11374,7 +11416,7 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11374
11416
|
const authz = await authorizeTeamSubresource(
|
|
11375
11417
|
req,
|
|
11376
11418
|
res,
|
|
11377
|
-
|
|
11419
|
+
import_backstage_plugin_litellm_common7.litellmTeamMcpManagePermission
|
|
11378
11420
|
);
|
|
11379
11421
|
if (!authz) return;
|
|
11380
11422
|
const { teamId, owningGroup, actor, team } = authz;
|
|
@@ -11427,7 +11469,7 @@ function registerObjectPermissionsRoutes(router, ctx) {
|
|
|
11427
11469
|
}
|
|
11428
11470
|
|
|
11429
11471
|
// src/routes/teamUsage.ts
|
|
11430
|
-
var
|
|
11472
|
+
var import_backstage_plugin_litellm_common8 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
11431
11473
|
function registerTeamUsageRoutes(router, ctx) {
|
|
11432
11474
|
const {
|
|
11433
11475
|
client,
|
|
@@ -11525,7 +11567,7 @@ function registerTeamUsageRoutes(router, ctx) {
|
|
|
11525
11567
|
}
|
|
11526
11568
|
const role = team.members_with_roles?.find((m) => m.user_id === callerId)?.role;
|
|
11527
11569
|
const viaRole = isMember && !!role && cfg.viewerRoles.includes(role);
|
|
11528
|
-
const allowed = isManager || viaRole || isMember && cfg.permissionEnabled && await ctx.assertPermission(req,
|
|
11570
|
+
const allowed = isManager || viaRole || isMember && cfg.permissionEnabled && await ctx.assertPermission(req, import_backstage_plugin_litellm_common8.litellmTeamUsageReadPermission);
|
|
11529
11571
|
if (!allowed) {
|
|
11530
11572
|
res.status(403).json({
|
|
11531
11573
|
error: "Access denied: viewing per-member usage needs a team role or permission"
|
|
@@ -13306,8 +13348,8 @@ async function bridgeListKeys(client, claims, provisioningEnabled, provisioningD
|
|
|
13306
13348
|
}
|
|
13307
13349
|
|
|
13308
13350
|
// src/routes/bridge.ts
|
|
13309
|
-
var import_backstage_plugin_litellm_common8 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
13310
13351
|
var import_backstage_plugin_litellm_common9 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
13352
|
+
var import_backstage_plugin_litellm_common10 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
13311
13353
|
function registerBridgeRoutes(router, ctx, bridgeOpts) {
|
|
13312
13354
|
const {
|
|
13313
13355
|
client,
|
|
@@ -13320,7 +13362,7 @@ function registerBridgeRoutes(router, ctx, bridgeOpts) {
|
|
|
13320
13362
|
keyValidationConfig
|
|
13321
13363
|
} = ctx;
|
|
13322
13364
|
const { config } = bridgeOpts;
|
|
13323
|
-
const generateKeyInputSchema = (0,
|
|
13365
|
+
const generateKeyInputSchema = (0, import_backstage_plugin_litellm_common10.createGenerateKeyInputSchema)(ctx.keyValidationConfig);
|
|
13324
13366
|
const bridgeCfg = readBridgeConfig(config);
|
|
13325
13367
|
const bridgeIdentity = {
|
|
13326
13368
|
userIdDomain,
|
|
@@ -13481,11 +13523,43 @@ function registerBridgeRoutes(router, ctx, bridgeOpts) {
|
|
|
13481
13523
|
}
|
|
13482
13524
|
const team = await client.getTeamInfo(teamId);
|
|
13483
13525
|
const allowed = team.models;
|
|
13484
|
-
if (!allowed || allowed.length === 0 || allowed.includes(
|
|
13526
|
+
if (!allowed || allowed.length === 0 || allowed.includes(import_backstage_plugin_litellm_common9.ALL_PROXY_MODELS)) {
|
|
13485
13527
|
res.json(models);
|
|
13486
13528
|
return;
|
|
13487
13529
|
}
|
|
13488
|
-
res.json(models.filter((m) => (0,
|
|
13530
|
+
res.json(models.filter((m) => (0, import_backstage_plugin_litellm_common9.isModelAllowed)(m, allowed)));
|
|
13531
|
+
} catch (error) {
|
|
13532
|
+
handleBridgeError(error, res);
|
|
13533
|
+
}
|
|
13534
|
+
});
|
|
13535
|
+
router.get("/bridge/mcp", async (req, res) => {
|
|
13536
|
+
try {
|
|
13537
|
+
const claims = await requireClaims(req);
|
|
13538
|
+
const teamId = typeof req.query.team_id === "string" ? req.query.team_id : "";
|
|
13539
|
+
if (!teamId) {
|
|
13540
|
+
res.status(400).json({ error: "team_id is required" });
|
|
13541
|
+
return;
|
|
13542
|
+
}
|
|
13543
|
+
const user = await getOrProvisionUserFromClaims(
|
|
13544
|
+
client,
|
|
13545
|
+
claims,
|
|
13546
|
+
provisioningEnabled,
|
|
13547
|
+
provisioningDefaults,
|
|
13548
|
+
logger,
|
|
13549
|
+
bridgeIdentity
|
|
13550
|
+
);
|
|
13551
|
+
if (!(user.teams ?? []).includes(teamId)) {
|
|
13552
|
+
res.status(403).json({ error: "Access denied: team is not one of your teams", team_id: teamId });
|
|
13553
|
+
return;
|
|
13554
|
+
}
|
|
13555
|
+
const names = teamMcpServers(await client.getTeamInfo(teamId));
|
|
13556
|
+
const catalogue = await client.listMcpServers().catch(() => []);
|
|
13557
|
+
res.json(
|
|
13558
|
+
names.map((server_name) => ({
|
|
13559
|
+
server_name,
|
|
13560
|
+
name: catalogue.find((s) => s.id === server_name || s.name === server_name)?.name ?? server_name
|
|
13561
|
+
}))
|
|
13562
|
+
);
|
|
13489
13563
|
} catch (error) {
|
|
13490
13564
|
handleBridgeError(error, res);
|
|
13491
13565
|
}
|
|
@@ -13517,13 +13591,13 @@ async function createRouter(options) {
|
|
|
13517
13591
|
const keyMaxBudget = config.getOptionalNumber("litellm.keys.maxBudget") ?? 100;
|
|
13518
13592
|
const keyMaxTpm = config.getOptionalNumber("litellm.keys.maxTpm") ?? 1e5;
|
|
13519
13593
|
const keyMaxRpm = config.getOptionalNumber("litellm.keys.maxRpm") ?? 1e3;
|
|
13520
|
-
const keyAllowedDurations = config.getOptionalStringArray("litellm.keys.allowedDurations") ??
|
|
13594
|
+
const keyAllowedDurations = config.getOptionalStringArray("litellm.keys.allowedDurations") ?? import_backstage_plugin_litellm_common11.DEFAULT_KEY_DURATIONS;
|
|
13521
13595
|
const keyValidationConfig = {
|
|
13522
13596
|
maxBudget: keyMaxBudget,
|
|
13523
13597
|
maxTpm: keyMaxTpm,
|
|
13524
13598
|
maxRpm: keyMaxRpm,
|
|
13525
13599
|
allowedDurations: keyAllowedDurations,
|
|
13526
|
-
allowedBudgetDurations: config.getOptionalStringArray("litellm.keys.allowedBudgetDurations") ??
|
|
13600
|
+
allowedBudgetDurations: config.getOptionalStringArray("litellm.keys.allowedBudgetDurations") ?? import_backstage_plugin_litellm_common11.DEFAULT_KEY_BUDGET_DURATIONS
|
|
13527
13601
|
};
|
|
13528
13602
|
const teamMgmtEnabled = isTeamManagementEnabled(config);
|
|
13529
13603
|
const objectPermsEnabled = isObjectPermissionsEnabled(config);
|
|
@@ -13736,10 +13810,11 @@ async function createRouter(options) {
|
|
|
13736
13810
|
}
|
|
13737
13811
|
|
|
13738
13812
|
// src/plugin.ts
|
|
13739
|
-
var
|
|
13813
|
+
var import_backstage_plugin_litellm_common12 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
13740
13814
|
var BRIDGE_UNAUTHENTICATED_PATHS = [
|
|
13741
13815
|
"/bridge/health",
|
|
13742
13816
|
"/bridge/keys",
|
|
13817
|
+
"/bridge/mcp",
|
|
13743
13818
|
"/bridge/models",
|
|
13744
13819
|
"/bridge/user/info"
|
|
13745
13820
|
];
|
|
@@ -13765,7 +13840,7 @@ var litellmPlugin = (0, import_backend_plugin_api.createBackendPlugin)({
|
|
|
13765
13840
|
permissions,
|
|
13766
13841
|
permissionsRegistry
|
|
13767
13842
|
}) {
|
|
13768
|
-
permissionsRegistry.addPermissions(
|
|
13843
|
+
permissionsRegistry.addPermissions(import_backstage_plugin_litellm_common12.litellmPermissions);
|
|
13769
13844
|
const router = await createRouter({
|
|
13770
13845
|
config,
|
|
13771
13846
|
logger,
|
|
@@ -13785,7 +13860,7 @@ var litellmPlugin = (0, import_backend_plugin_api.createBackendPlugin)({
|
|
|
13785
13860
|
});
|
|
13786
13861
|
|
|
13787
13862
|
// src/index.ts
|
|
13788
|
-
var
|
|
13863
|
+
var import_backstage_plugin_litellm_common13 = require("@acarmisc/backstage-plugin-litellm-common");
|
|
13789
13864
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13790
13865
|
0 && (module.exports = {
|
|
13791
13866
|
KeycloakJWTVerifier,
|