@kuadrant/kuadrant-backstage-plugin-backend 0.0.1-test.1-57ace816 → 0.0.1-test.1-48246e3
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/alpha.d.ts +27 -0
- package/dist/index.cjs.js +3 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +50 -0
- package/dist/permissions.cjs.js +18 -0
- package/dist/permissions.cjs.js.map +1 -1
- package/dist/rbac.d.ts +11 -0
- package/dist/router.cjs.js +152 -222
- package/dist/router.cjs.js.map +1 -1
- package/package.json +41 -5
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import { RootConfigService } from '@backstage/backend-plugin-api';
|
|
3
|
+
import { EntityProvider, EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
|
4
|
+
|
|
5
|
+
declare class APIProductEntityProvider implements EntityProvider {
|
|
6
|
+
private readonly k8sClient;
|
|
7
|
+
private connection?;
|
|
8
|
+
private readonly providerId;
|
|
9
|
+
constructor(config: RootConfigService);
|
|
10
|
+
getProviderName(): string;
|
|
11
|
+
connect(connection: EntityProviderConnection): Promise<void>;
|
|
12
|
+
refresh(): Promise<void>;
|
|
13
|
+
private transformToEntity;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* get the apiproduct entity provider instance
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
declare function getAPIProductEntityProvider(): APIProductEntityProvider | null;
|
|
21
|
+
/**
|
|
22
|
+
* backend module for apiproduct entity provider
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
declare const catalogModuleApiProductEntityProvider: _backstage_backend_plugin_api.BackendFeature;
|
|
26
|
+
|
|
27
|
+
export { catalogModuleApiProductEntityProvider, catalogModuleApiProductEntityProvider as default, getAPIProductEntityProvider };
|
package/dist/index.cjs.js
CHANGED
|
@@ -15,9 +15,12 @@ exports.kuadrantApiKeyDeleteOwnPermission = permissions.kuadrantApiKeyDeleteOwnP
|
|
|
15
15
|
exports.kuadrantApiKeyReadAllPermission = permissions.kuadrantApiKeyReadAllPermission;
|
|
16
16
|
exports.kuadrantApiKeyReadOwnPermission = permissions.kuadrantApiKeyReadOwnPermission;
|
|
17
17
|
exports.kuadrantApiKeyRequestCreatePermission = permissions.kuadrantApiKeyRequestCreatePermission;
|
|
18
|
+
exports.kuadrantApiKeyRequestDeleteAllPermission = permissions.kuadrantApiKeyRequestDeleteAllPermission;
|
|
19
|
+
exports.kuadrantApiKeyRequestDeleteOwnPermission = permissions.kuadrantApiKeyRequestDeleteOwnPermission;
|
|
18
20
|
exports.kuadrantApiKeyRequestListPermission = permissions.kuadrantApiKeyRequestListPermission;
|
|
19
21
|
exports.kuadrantApiKeyRequestReadAllPermission = permissions.kuadrantApiKeyRequestReadAllPermission;
|
|
20
22
|
exports.kuadrantApiKeyRequestReadOwnPermission = permissions.kuadrantApiKeyRequestReadOwnPermission;
|
|
23
|
+
exports.kuadrantApiKeyRequestUpdateOwnPermission = permissions.kuadrantApiKeyRequestUpdateOwnPermission;
|
|
21
24
|
exports.kuadrantApiKeyRequestUpdatePermission = permissions.kuadrantApiKeyRequestUpdatePermission;
|
|
22
25
|
exports.kuadrantApiProductCreatePermission = permissions.kuadrantApiProductCreatePermission;
|
|
23
26
|
exports.kuadrantApiProductDeletePermission = permissions.kuadrantApiProductDeletePermission;
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import * as _backstage_plugin_permission_common from '@backstage/plugin-permission-common';
|
|
3
|
+
export { default as catalogModuleApiProductEntityProvider } from './alpha.js';
|
|
4
|
+
export { default as kuadrantRbacModule } from './rbac.js';
|
|
5
|
+
import '@backstage/plugin-catalog-node';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* kuadrantPlugin backend plugin
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
declare const kuadrantPlugin: _backstage_backend_plugin_api.BackendFeature;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Permission definitions for the Kuadrant plugin
|
|
16
|
+
*
|
|
17
|
+
* These permissions control access to PlanPolicy, APIProduct, APIKeyRequest,
|
|
18
|
+
* and API key management within the Kuadrant Backstage plugin.
|
|
19
|
+
*
|
|
20
|
+
* Permissions are composable - use them to build custom roles beyond the
|
|
21
|
+
* three reference personas (Platform Engineer, API Owner, API Consumer).
|
|
22
|
+
*/
|
|
23
|
+
declare const kuadrantPlanPolicyCreatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
24
|
+
declare const kuadrantPlanPolicyReadPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
25
|
+
declare const kuadrantPlanPolicyUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
26
|
+
declare const kuadrantPlanPolicyDeletePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
27
|
+
declare const kuadrantPlanPolicyListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
28
|
+
declare const kuadrantApiProductCreatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
29
|
+
declare const kuadrantApiProductReadPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
30
|
+
declare const kuadrantApiProductUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
31
|
+
declare const kuadrantApiProductDeletePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
32
|
+
declare const kuadrantApiProductListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
33
|
+
declare const kuadrantApiKeyRequestCreatePermission: _backstage_plugin_permission_common.ResourcePermission<"apiproduct">;
|
|
34
|
+
declare const kuadrantApiKeyRequestReadOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
35
|
+
declare const kuadrantApiKeyRequestReadAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
36
|
+
declare const kuadrantApiKeyRequestUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
37
|
+
declare const kuadrantApiKeyRequestListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
38
|
+
declare const kuadrantApiKeyRequestUpdateOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
39
|
+
declare const kuadrantApiKeyRequestDeleteOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
40
|
+
declare const kuadrantApiKeyRequestDeleteAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
41
|
+
declare const kuadrantApiKeyReadOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
42
|
+
declare const kuadrantApiKeyReadAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
43
|
+
declare const kuadrantApiKeyDeleteOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
44
|
+
declare const kuadrantApiKeyDeleteAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
45
|
+
/**
|
|
46
|
+
* All Kuadrant permissions as an array for easy iteration
|
|
47
|
+
*/
|
|
48
|
+
declare const kuadrantPermissions: (_backstage_plugin_permission_common.BasicPermission | _backstage_plugin_permission_common.ResourcePermission<"apiproduct">)[];
|
|
49
|
+
|
|
50
|
+
export { kuadrantPlugin as default, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyRequestCreatePermission, kuadrantApiKeyRequestDeleteAllPermission, kuadrantApiKeyRequestDeleteOwnPermission, kuadrantApiKeyRequestListPermission, kuadrantApiKeyRequestReadAllPermission, kuadrantApiKeyRequestReadOwnPermission, kuadrantApiKeyRequestUpdateOwnPermission, kuadrantApiKeyRequestUpdatePermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeletePermission, kuadrantApiProductListPermission, kuadrantApiProductReadPermission, kuadrantApiProductUpdatePermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission };
|
package/dist/permissions.cjs.js
CHANGED
|
@@ -63,6 +63,18 @@ const kuadrantApiKeyRequestListPermission = pluginPermissionCommon.createPermiss
|
|
|
63
63
|
name: "kuadrant.apikeyrequest.list",
|
|
64
64
|
attributes: { action: "read" }
|
|
65
65
|
});
|
|
66
|
+
const kuadrantApiKeyRequestUpdateOwnPermission = pluginPermissionCommon.createPermission({
|
|
67
|
+
name: "kuadrant.apikeyrequest.update.own",
|
|
68
|
+
attributes: { action: "update" }
|
|
69
|
+
});
|
|
70
|
+
const kuadrantApiKeyRequestDeleteOwnPermission = pluginPermissionCommon.createPermission({
|
|
71
|
+
name: "kuadrant.apikeyrequest.delete.own",
|
|
72
|
+
attributes: { action: "delete" }
|
|
73
|
+
});
|
|
74
|
+
const kuadrantApiKeyRequestDeleteAllPermission = pluginPermissionCommon.createPermission({
|
|
75
|
+
name: "kuadrant.apikeyrequest.delete.all",
|
|
76
|
+
attributes: { action: "delete" }
|
|
77
|
+
});
|
|
66
78
|
const kuadrantApiKeyReadOwnPermission = pluginPermissionCommon.createPermission({
|
|
67
79
|
name: "kuadrant.apikey.read.own",
|
|
68
80
|
attributes: { action: "read" }
|
|
@@ -94,7 +106,10 @@ const kuadrantPermissions = [
|
|
|
94
106
|
kuadrantApiKeyRequestReadOwnPermission,
|
|
95
107
|
kuadrantApiKeyRequestReadAllPermission,
|
|
96
108
|
kuadrantApiKeyRequestUpdatePermission,
|
|
109
|
+
kuadrantApiKeyRequestUpdateOwnPermission,
|
|
97
110
|
kuadrantApiKeyRequestListPermission,
|
|
111
|
+
kuadrantApiKeyRequestDeleteOwnPermission,
|
|
112
|
+
kuadrantApiKeyRequestDeleteAllPermission,
|
|
98
113
|
kuadrantApiKeyReadOwnPermission,
|
|
99
114
|
kuadrantApiKeyReadAllPermission,
|
|
100
115
|
kuadrantApiKeyDeleteOwnPermission,
|
|
@@ -106,9 +121,12 @@ exports.kuadrantApiKeyDeleteOwnPermission = kuadrantApiKeyDeleteOwnPermission;
|
|
|
106
121
|
exports.kuadrantApiKeyReadAllPermission = kuadrantApiKeyReadAllPermission;
|
|
107
122
|
exports.kuadrantApiKeyReadOwnPermission = kuadrantApiKeyReadOwnPermission;
|
|
108
123
|
exports.kuadrantApiKeyRequestCreatePermission = kuadrantApiKeyRequestCreatePermission;
|
|
124
|
+
exports.kuadrantApiKeyRequestDeleteAllPermission = kuadrantApiKeyRequestDeleteAllPermission;
|
|
125
|
+
exports.kuadrantApiKeyRequestDeleteOwnPermission = kuadrantApiKeyRequestDeleteOwnPermission;
|
|
109
126
|
exports.kuadrantApiKeyRequestListPermission = kuadrantApiKeyRequestListPermission;
|
|
110
127
|
exports.kuadrantApiKeyRequestReadAllPermission = kuadrantApiKeyRequestReadAllPermission;
|
|
111
128
|
exports.kuadrantApiKeyRequestReadOwnPermission = kuadrantApiKeyRequestReadOwnPermission;
|
|
129
|
+
exports.kuadrantApiKeyRequestUpdateOwnPermission = kuadrantApiKeyRequestUpdateOwnPermission;
|
|
112
130
|
exports.kuadrantApiKeyRequestUpdatePermission = kuadrantApiKeyRequestUpdatePermission;
|
|
113
131
|
exports.kuadrantApiProductCreatePermission = kuadrantApiProductCreatePermission;
|
|
114
132
|
exports.kuadrantApiProductDeletePermission = kuadrantApiProductDeletePermission;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.cjs.js","sources":["../src/permissions.ts"],"sourcesContent":["import { createPermission } from '@backstage/plugin-permission-common';\n\n/**\n * Permission definitions for the Kuadrant plugin\n *\n * These permissions control access to PlanPolicy, APIProduct, APIKeyRequest,\n * and API key management within the Kuadrant Backstage plugin.\n *\n * Permissions are composable - use them to build custom roles beyond the\n * three reference personas (Platform Engineer, API Owner, API Consumer).\n */\n\n// planpolicy permissions (rate limit tiers)\nexport const kuadrantPlanPolicyCreatePermission = createPermission({\n name: 'kuadrant.planpolicy.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantPlanPolicyReadPermission = createPermission({\n name: 'kuadrant.planpolicy.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantPlanPolicyUpdatePermission = createPermission({\n name: 'kuadrant.planpolicy.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantPlanPolicyDeletePermission = createPermission({\n name: 'kuadrant.planpolicy.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantPlanPolicyListPermission = createPermission({\n name: 'kuadrant.planpolicy.list',\n attributes: { action: 'read' },\n});\n\n// apiproduct permissions (catalog entries)\nexport const kuadrantApiProductCreatePermission = createPermission({\n name: 'kuadrant.apiproduct.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantApiProductReadPermission = createPermission({\n name: 'kuadrant.apiproduct.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiProductUpdatePermission = createPermission({\n name: 'kuadrant.apiproduct.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiProductDeletePermission = createPermission({\n name: 'kuadrant.apiproduct.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiProductListPermission = createPermission({\n name: 'kuadrant.apiproduct.list',\n attributes: { action: 'read' },\n});\n\n// apikeyrequest permissions (access requests)\nexport const kuadrantApiKeyRequestCreatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.create',\n attributes: { action: 'create' },\n resourceType: 'apiproduct',\n});\n\nexport const kuadrantApiKeyRequestReadOwnPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.own',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyRequestReadAllPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.all',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyRequestUpdatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiKeyRequestListPermission = createPermission({\n name: 'kuadrant.apikeyrequest.list',\n attributes: { action: 'read' },\n});\n\n// api key permissions (managed secrets)\nexport const kuadrantApiKeyReadOwnPermission = createPermission({\n name: 'kuadrant.apikey.read.own',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyReadAllPermission = createPermission({\n name: 'kuadrant.apikey.read.all',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyDeleteOwnPermission = createPermission({\n name: 'kuadrant.apikey.delete.own',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiKeyDeleteAllPermission = createPermission({\n name: 'kuadrant.apikey.delete.all',\n attributes: { action: 'delete' },\n});\n\n/**\n * All Kuadrant permissions as an array for easy iteration\n */\nexport const kuadrantPermissions = [\n kuadrantPlanPolicyCreatePermission,\n kuadrantPlanPolicyReadPermission,\n kuadrantPlanPolicyUpdatePermission,\n kuadrantPlanPolicyDeletePermission,\n kuadrantPlanPolicyListPermission,\n kuadrantApiProductCreatePermission,\n kuadrantApiProductReadPermission,\n kuadrantApiProductUpdatePermission,\n kuadrantApiProductDeletePermission,\n kuadrantApiProductListPermission,\n kuadrantApiKeyRequestCreatePermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantApiKeyRequestReadAllPermission,\n kuadrantApiKeyRequestUpdatePermission,\n kuadrantApiKeyRequestListPermission,\n kuadrantApiKeyReadOwnPermission,\n kuadrantApiKeyReadAllPermission,\n kuadrantApiKeyDeleteOwnPermission,\n kuadrantApiKeyDeleteAllPermission,\n];\n"],"names":["createPermission"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"permissions.cjs.js","sources":["../src/permissions.ts"],"sourcesContent":["import { createPermission } from '@backstage/plugin-permission-common';\n\n/**\n * Permission definitions for the Kuadrant plugin\n *\n * These permissions control access to PlanPolicy, APIProduct, APIKeyRequest,\n * and API key management within the Kuadrant Backstage plugin.\n *\n * Permissions are composable - use them to build custom roles beyond the\n * three reference personas (Platform Engineer, API Owner, API Consumer).\n */\n\n// planpolicy permissions (rate limit tiers)\nexport const kuadrantPlanPolicyCreatePermission = createPermission({\n name: 'kuadrant.planpolicy.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantPlanPolicyReadPermission = createPermission({\n name: 'kuadrant.planpolicy.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantPlanPolicyUpdatePermission = createPermission({\n name: 'kuadrant.planpolicy.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantPlanPolicyDeletePermission = createPermission({\n name: 'kuadrant.planpolicy.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantPlanPolicyListPermission = createPermission({\n name: 'kuadrant.planpolicy.list',\n attributes: { action: 'read' },\n});\n\n// apiproduct permissions (catalog entries)\nexport const kuadrantApiProductCreatePermission = createPermission({\n name: 'kuadrant.apiproduct.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantApiProductReadPermission = createPermission({\n name: 'kuadrant.apiproduct.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiProductUpdatePermission = createPermission({\n name: 'kuadrant.apiproduct.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiProductDeletePermission = createPermission({\n name: 'kuadrant.apiproduct.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiProductListPermission = createPermission({\n name: 'kuadrant.apiproduct.list',\n attributes: { action: 'read' },\n});\n\n// apikeyrequest permissions (access requests)\nexport const kuadrantApiKeyRequestCreatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.create',\n attributes: { action: 'create' },\n resourceType: 'apiproduct',\n});\n\nexport const kuadrantApiKeyRequestReadOwnPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.own',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyRequestReadAllPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.all',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyRequestUpdatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiKeyRequestListPermission = createPermission({\n name: 'kuadrant.apikeyrequest.list',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyRequestUpdateOwnPermission = createPermission({\n name: 'kuadrant.apikeyrequest.update.own',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiKeyRequestDeleteOwnPermission = createPermission({\n name: 'kuadrant.apikeyrequest.delete.own',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiKeyRequestDeleteAllPermission = createPermission({\n name: 'kuadrant.apikeyrequest.delete.all',\n attributes: { action: 'delete' },\n});\n\n// api key permissions (managed secrets)\nexport const kuadrantApiKeyReadOwnPermission = createPermission({\n name: 'kuadrant.apikey.read.own',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyReadAllPermission = createPermission({\n name: 'kuadrant.apikey.read.all',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiKeyDeleteOwnPermission = createPermission({\n name: 'kuadrant.apikey.delete.own',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiKeyDeleteAllPermission = createPermission({\n name: 'kuadrant.apikey.delete.all',\n attributes: { action: 'delete' },\n});\n\n/**\n * All Kuadrant permissions as an array for easy iteration\n */\nexport const kuadrantPermissions = [\n kuadrantPlanPolicyCreatePermission,\n kuadrantPlanPolicyReadPermission,\n kuadrantPlanPolicyUpdatePermission,\n kuadrantPlanPolicyDeletePermission,\n kuadrantPlanPolicyListPermission,\n kuadrantApiProductCreatePermission,\n kuadrantApiProductReadPermission,\n kuadrantApiProductUpdatePermission,\n kuadrantApiProductDeletePermission,\n kuadrantApiProductListPermission,\n kuadrantApiKeyRequestCreatePermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantApiKeyRequestReadAllPermission,\n kuadrantApiKeyRequestUpdatePermission,\n kuadrantApiKeyRequestUpdateOwnPermission,\n kuadrantApiKeyRequestListPermission,\n kuadrantApiKeyRequestDeleteOwnPermission,\n kuadrantApiKeyRequestDeleteAllPermission,\n kuadrantApiKeyReadOwnPermission,\n kuadrantApiKeyReadAllPermission,\n kuadrantApiKeyDeleteOwnPermission,\n kuadrantApiKeyDeleteAllPermission,\n];\n"],"names":["createPermission"],"mappings":"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"}
|
package/dist/rbac.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* backend module that registers kuadrant plugin id with rbac
|
|
5
|
+
* this makes kuadrant permissions discoverable in the rbac ui
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
declare const kuadrantRbacModule: _backstage_backend_plugin_api.BackendFeature;
|
|
10
|
+
|
|
11
|
+
export { kuadrantRbacModule as default, kuadrantRbacModule };
|
package/dist/router.cjs.js
CHANGED
|
@@ -22,45 +22,19 @@ function generateApiKey() {
|
|
|
22
22
|
return crypto.randomBytes(32).toString("hex");
|
|
23
23
|
}
|
|
24
24
|
async function getUserIdentity(req, httpAuth, userInfo) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
console.log("no user credentials, treating as guest api owner");
|
|
29
|
-
return {
|
|
30
|
-
userId: "guest",
|
|
31
|
-
isPlatformEngineer: false,
|
|
32
|
-
isApiOwner: true,
|
|
33
|
-
// allow guest as api owner in development
|
|
34
|
-
isApiConsumer: true,
|
|
35
|
-
groups: []
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const info = await userInfo.getUserInfo(credentials);
|
|
39
|
-
const userId = info.userEntityRef.split("/")[1] || "guest";
|
|
40
|
-
const groups = info.ownershipEntityRefs || [];
|
|
41
|
-
const isPlatformEngineer = userId === "guest" || groups.some(
|
|
42
|
-
(ref) => ref === "group:default/platform-engineers" || ref === "group:default/platform-admins"
|
|
43
|
-
);
|
|
44
|
-
const isApiOwner = userId === "guest" || groups.some(
|
|
45
|
-
(ref) => ref === "group:default/api-owners" || ref === "group:default/app-developers"
|
|
46
|
-
);
|
|
47
|
-
const isApiConsumer = groups.some(
|
|
48
|
-
(ref) => ref === "group:default/api-consumers"
|
|
49
|
-
);
|
|
50
|
-
console.log(`user identity resolved: userId=${userId}, isPlatformEngineer=${isPlatformEngineer}, isApiOwner=${isApiOwner}, isApiConsumer=${isApiConsumer}, groups=${groups.join(",")}`);
|
|
51
|
-
return { userId, isPlatformEngineer, isApiOwner, isApiConsumer, groups };
|
|
52
|
-
} catch (error) {
|
|
53
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
54
|
-
console.warn(`failed to get user identity, defaulting to guest api owner: ${errorMsg}`);
|
|
55
|
-
return {
|
|
56
|
-
userId: "guest",
|
|
57
|
-
isPlatformEngineer: false,
|
|
58
|
-
isApiOwner: true,
|
|
59
|
-
// allow guest as api owner in development
|
|
60
|
-
isApiConsumer: true,
|
|
61
|
-
groups: []
|
|
62
|
-
};
|
|
25
|
+
const credentials = await httpAuth.credentials(req);
|
|
26
|
+
if (!credentials || !credentials.principal) {
|
|
27
|
+
throw new errors.NotAllowedError("authentication required");
|
|
63
28
|
}
|
|
29
|
+
const info = await userInfo.getUserInfo(credentials);
|
|
30
|
+
const userId = info.userEntityRef.split("/")[1];
|
|
31
|
+
const groups = info.ownershipEntityRefs || [];
|
|
32
|
+
console.log(`user identity resolved: userId=${userId}, userEntityRef=${info.userEntityRef}, groups=${groups.join(",")}`);
|
|
33
|
+
return {
|
|
34
|
+
userId,
|
|
35
|
+
userEntityRef: info.userEntityRef,
|
|
36
|
+
groups
|
|
37
|
+
};
|
|
64
38
|
}
|
|
65
39
|
async function createRouter({
|
|
66
40
|
httpAuth,
|
|
@@ -130,19 +104,17 @@ async function createRouter({
|
|
|
130
104
|
}
|
|
131
105
|
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
132
106
|
const apiProduct = req.body;
|
|
133
|
-
const namespace = apiProduct.metadata?.namespace;
|
|
134
107
|
const targetRef = apiProduct.spec?.targetRef;
|
|
135
|
-
if (!namespace) {
|
|
136
|
-
throw new errors.InputError("namespace is required
|
|
137
|
-
}
|
|
138
|
-
if (!targetRef?.name || !targetRef?.kind) {
|
|
139
|
-
throw new errors.InputError("targetRef with name and kind is required");
|
|
108
|
+
if (!targetRef?.name || !targetRef?.kind || !targetRef?.namespace) {
|
|
109
|
+
throw new errors.InputError("targetRef with name, kind, and namespace is required");
|
|
140
110
|
}
|
|
111
|
+
const namespace = targetRef.namespace;
|
|
112
|
+
apiProduct.metadata.namespace = namespace;
|
|
141
113
|
if (!apiProduct.spec.contact) {
|
|
142
114
|
apiProduct.spec.contact = {};
|
|
143
115
|
}
|
|
144
116
|
apiProduct.spec.contact.team = `user:default/${userId}`;
|
|
145
|
-
const httpRouteNamespace =
|
|
117
|
+
const httpRouteNamespace = namespace;
|
|
146
118
|
const httpRouteName = targetRef.name;
|
|
147
119
|
try {
|
|
148
120
|
const planPoliciesResponse = await k8sClient$1.listCustomResources(
|
|
@@ -246,8 +218,34 @@ async function createRouter({
|
|
|
246
218
|
}
|
|
247
219
|
});
|
|
248
220
|
router.patch("/apiproducts/:namespace/:name", async (req, res) => {
|
|
221
|
+
const patchSchema = zod.z.object({
|
|
222
|
+
spec: zod.z.object({
|
|
223
|
+
displayName: zod.z.string().optional(),
|
|
224
|
+
description: zod.z.string().optional(),
|
|
225
|
+
version: zod.z.string().optional(),
|
|
226
|
+
publishStatus: zod.z.enum(["Draft", "Published"]).optional(),
|
|
227
|
+
approvalMode: zod.z.enum(["automatic", "manual"]).optional(),
|
|
228
|
+
tags: zod.z.array(zod.z.string()).optional(),
|
|
229
|
+
contact: zod.z.object({
|
|
230
|
+
email: zod.z.string().optional(),
|
|
231
|
+
team: zod.z.string().optional(),
|
|
232
|
+
slack: zod.z.string().optional()
|
|
233
|
+
}).partial().optional(),
|
|
234
|
+
documentation: zod.z.object({
|
|
235
|
+
docsURL: zod.z.string().optional(),
|
|
236
|
+
openAPISpec: zod.z.string().optional()
|
|
237
|
+
}).partial().optional()
|
|
238
|
+
}).partial()
|
|
239
|
+
});
|
|
240
|
+
const parsed = patchSchema.safeParse(req.body);
|
|
241
|
+
if (!parsed.success) {
|
|
242
|
+
return res.status(400).json({ error: "invalid patch: " + parsed.error.toString() });
|
|
243
|
+
}
|
|
249
244
|
try {
|
|
250
|
-
const credentials = await httpAuth.credentials(req
|
|
245
|
+
const credentials = await httpAuth.credentials(req);
|
|
246
|
+
if (!credentials || !credentials.principal) {
|
|
247
|
+
throw new errors.NotAllowedError("authentication required");
|
|
248
|
+
}
|
|
251
249
|
const decision = await permissions$1.authorize(
|
|
252
250
|
[{ permission: permissions.kuadrantApiProductUpdatePermission }],
|
|
253
251
|
{ credentials }
|
|
@@ -256,25 +254,24 @@ async function createRouter({
|
|
|
256
254
|
throw new errors.NotAllowedError("unauthorised");
|
|
257
255
|
}
|
|
258
256
|
const { namespace, name } = req.params;
|
|
259
|
-
const patch = req.body;
|
|
260
257
|
const updated = await k8sClient$1.patchCustomResource(
|
|
261
258
|
"extensions.kuadrant.io",
|
|
262
259
|
"v1alpha1",
|
|
263
260
|
namespace,
|
|
264
261
|
"apiproducts",
|
|
265
262
|
name,
|
|
266
|
-
|
|
263
|
+
parsed.data
|
|
267
264
|
);
|
|
268
|
-
res.json(updated);
|
|
265
|
+
return res.json(updated);
|
|
269
266
|
} catch (error) {
|
|
270
267
|
console.error("error updating apiproduct:", error);
|
|
271
268
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
272
269
|
if (error instanceof errors.NotAllowedError) {
|
|
273
|
-
res.status(403).json({ error: error.message });
|
|
270
|
+
return res.status(403).json({ error: error.message });
|
|
274
271
|
} else if (error instanceof errors.InputError) {
|
|
275
|
-
res.status(400).json({ error: error.message });
|
|
272
|
+
return res.status(400).json({ error: error.message });
|
|
276
273
|
} else {
|
|
277
|
-
res.status(500).json({ error: errorMessage });
|
|
274
|
+
return res.status(500).json({ error: errorMessage });
|
|
278
275
|
}
|
|
279
276
|
}
|
|
280
277
|
});
|
|
@@ -294,7 +291,19 @@ async function createRouter({
|
|
|
294
291
|
metadata: {
|
|
295
292
|
name: policy.metadata.name,
|
|
296
293
|
namespace: policy.metadata.namespace
|
|
297
|
-
}
|
|
294
|
+
},
|
|
295
|
+
// only expose targetRef to allow UI to match PlanPolicy -> HTTPRoute
|
|
296
|
+
targetRef: policy.spec?.targetRef ? {
|
|
297
|
+
kind: policy.spec.targetRef.kind,
|
|
298
|
+
name: policy.spec.targetRef.name,
|
|
299
|
+
namespace: policy.spec.targetRef.namespace
|
|
300
|
+
} : void 0,
|
|
301
|
+
// only expose plan tier info, no other spec details
|
|
302
|
+
plans: (policy.spec?.plans || []).map((plan) => ({
|
|
303
|
+
tier: plan.tier,
|
|
304
|
+
description: plan.description,
|
|
305
|
+
limits: plan.limits
|
|
306
|
+
}))
|
|
298
307
|
}))
|
|
299
308
|
};
|
|
300
309
|
res.json(filtered);
|
|
@@ -329,85 +338,12 @@ async function createRouter({
|
|
|
329
338
|
}
|
|
330
339
|
}
|
|
331
340
|
});
|
|
332
|
-
router.get("/apikeys", async (req, res) => {
|
|
333
|
-
try {
|
|
334
|
-
const credentials = await httpAuth.credentials(req);
|
|
335
|
-
const userId = req.query.userId;
|
|
336
|
-
const namespace = req.query.namespace;
|
|
337
|
-
if (!namespace) {
|
|
338
|
-
throw new errors.InputError("namespace query parameter is required");
|
|
339
|
-
}
|
|
340
|
-
const permission = userId ? permissions.kuadrantApiKeyReadOwnPermission : permissions.kuadrantApiKeyReadAllPermission;
|
|
341
|
-
const decision = await permissions$1.authorize(
|
|
342
|
-
[{ permission }],
|
|
343
|
-
{ credentials }
|
|
344
|
-
);
|
|
345
|
-
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
346
|
-
throw new errors.NotAllowedError("unauthorised");
|
|
347
|
-
}
|
|
348
|
-
const data = await k8sClient$1.listSecrets(namespace);
|
|
349
|
-
let filteredItems = data.items || [];
|
|
350
|
-
if (userId) {
|
|
351
|
-
filteredItems = filteredItems.filter(
|
|
352
|
-
(secret) => secret.metadata?.annotations?.["secret.kuadrant.io/user-id"] === userId
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
filteredItems = filteredItems.filter(
|
|
356
|
-
(secret) => secret.metadata?.annotations?.["secret.kuadrant.io/user-id"]
|
|
357
|
-
);
|
|
358
|
-
res.json({ items: filteredItems });
|
|
359
|
-
} catch (error) {
|
|
360
|
-
console.error("error fetching api keys:", error);
|
|
361
|
-
if (error instanceof errors.NotAllowedError) {
|
|
362
|
-
res.status(403).json({ error: error.message });
|
|
363
|
-
} else {
|
|
364
|
-
res.status(500).json({ error: "failed to fetch api keys" });
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
router.delete("/apikeys/:namespace/:name", async (req, res) => {
|
|
369
|
-
try {
|
|
370
|
-
const credentials = await httpAuth.credentials(req);
|
|
371
|
-
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
372
|
-
const { namespace, name } = req.params;
|
|
373
|
-
const secret = await k8sClient$1.getSecret(namespace, name);
|
|
374
|
-
const secretUserId = secret.metadata?.annotations?.["secret.kuadrant.io/user-id"];
|
|
375
|
-
const deleteAllDecision = await permissions$1.authorize(
|
|
376
|
-
[{ permission: permissions.kuadrantApiKeyDeleteAllPermission }],
|
|
377
|
-
{ credentials }
|
|
378
|
-
);
|
|
379
|
-
const canDeleteAll = deleteAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
380
|
-
if (!canDeleteAll) {
|
|
381
|
-
const deleteOwnDecision = await permissions$1.authorize(
|
|
382
|
-
[{ permission: permissions.kuadrantApiKeyDeleteOwnPermission }],
|
|
383
|
-
{ credentials }
|
|
384
|
-
);
|
|
385
|
-
if (deleteOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
386
|
-
throw new errors.NotAllowedError("unauthorised");
|
|
387
|
-
}
|
|
388
|
-
if (secretUserId !== userId) {
|
|
389
|
-
throw new errors.NotAllowedError("you can only delete your own api keys");
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
await k8sClient$1.deleteSecret(namespace, name);
|
|
393
|
-
res.status(204).send();
|
|
394
|
-
} catch (error) {
|
|
395
|
-
console.error("error deleting api key:", error);
|
|
396
|
-
if (error instanceof errors.NotAllowedError) {
|
|
397
|
-
res.status(403).json({ error: error.message });
|
|
398
|
-
} else {
|
|
399
|
-
res.status(500).json({ error: "failed to delete api key" });
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
341
|
const requestSchema = zod.z.object({
|
|
404
342
|
apiName: zod.z.string(),
|
|
405
343
|
apiNamespace: zod.z.string(),
|
|
406
344
|
planTier: zod.z.string(),
|
|
407
345
|
useCase: zod.z.string().optional(),
|
|
408
|
-
|
|
409
|
-
userEmail: zod.z.string().optional(),
|
|
410
|
-
namespace: zod.z.string()
|
|
346
|
+
userEmail: zod.z.string().optional()
|
|
411
347
|
});
|
|
412
348
|
router.post("/requests", async (req, res) => {
|
|
413
349
|
const parsed = requestSchema.safeParse(req.body);
|
|
@@ -416,7 +352,8 @@ async function createRouter({
|
|
|
416
352
|
}
|
|
417
353
|
try {
|
|
418
354
|
const credentials = await httpAuth.credentials(req);
|
|
419
|
-
const { apiName, apiNamespace, planTier, useCase,
|
|
355
|
+
const { apiName, apiNamespace, planTier, useCase, userEmail } = parsed.data;
|
|
356
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
420
357
|
const resourceRef = `apiproduct:${apiNamespace}/${apiName}`;
|
|
421
358
|
const decision = await permissions$1.authorize(
|
|
422
359
|
[{
|
|
@@ -428,11 +365,6 @@ async function createRouter({
|
|
|
428
365
|
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
429
366
|
throw new errors.NotAllowedError(`not authorised to request access to ${apiName}`);
|
|
430
367
|
}
|
|
431
|
-
const { userId: authenticatedUserId, isPlatformEngineer, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);
|
|
432
|
-
const canCreateForOthers = isPlatformEngineer || isApiOwner;
|
|
433
|
-
if (!canCreateForOthers && userId !== authenticatedUserId) {
|
|
434
|
-
throw new errors.NotAllowedError("you can only create api key requests for yourself");
|
|
435
|
-
}
|
|
436
368
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
437
369
|
const randomSuffix = crypto.randomBytes(4).toString("hex");
|
|
438
370
|
const requestName = `${userId}-${apiName}-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
@@ -445,7 +377,7 @@ async function createRouter({
|
|
|
445
377
|
kind: "APIKeyRequest",
|
|
446
378
|
metadata: {
|
|
447
379
|
name: requestName,
|
|
448
|
-
namespace
|
|
380
|
+
namespace: apiNamespace
|
|
449
381
|
},
|
|
450
382
|
spec: {
|
|
451
383
|
apiName,
|
|
@@ -459,7 +391,7 @@ async function createRouter({
|
|
|
459
391
|
const created = await k8sClient$1.createCustomResource(
|
|
460
392
|
"extensions.kuadrant.io",
|
|
461
393
|
"v1alpha1",
|
|
462
|
-
|
|
394
|
+
apiNamespace,
|
|
463
395
|
"apikeyrequests",
|
|
464
396
|
request
|
|
465
397
|
);
|
|
@@ -529,7 +461,7 @@ async function createRouter({
|
|
|
529
461
|
await k8sClient$1.patchCustomResourceStatus(
|
|
530
462
|
"extensions.kuadrant.io",
|
|
531
463
|
"v1alpha1",
|
|
532
|
-
|
|
464
|
+
apiNamespace,
|
|
533
465
|
"apikeyrequests",
|
|
534
466
|
requestName,
|
|
535
467
|
status
|
|
@@ -593,11 +525,8 @@ async function createRouter({
|
|
|
593
525
|
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
594
526
|
throw new errors.NotAllowedError("unauthorised");
|
|
595
527
|
}
|
|
596
|
-
const userId = req
|
|
528
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
597
529
|
const namespace = req.query.namespace;
|
|
598
|
-
if (!userId) {
|
|
599
|
-
throw new errors.InputError("userId query parameter is required");
|
|
600
|
-
}
|
|
601
530
|
let data;
|
|
602
531
|
if (namespace) {
|
|
603
532
|
data = await k8sClient$1.listCustomResources("extensions.kuadrant.io", "v1alpha1", "apikeyrequests", namespace);
|
|
@@ -626,24 +555,14 @@ async function createRouter({
|
|
|
626
555
|
throw new errors.InputError(parsed.error.toString());
|
|
627
556
|
}
|
|
628
557
|
try {
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
{ credentials }
|
|
638
|
-
);
|
|
639
|
-
canApprove = decision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
640
|
-
}
|
|
641
|
-
} catch (error) {
|
|
642
|
-
console.warn("permission check failed, using group-based authorization:", error);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
if (!canApprove) {
|
|
646
|
-
throw new errors.NotAllowedError("you do not have permission to approve api key requests");
|
|
558
|
+
const credentials = await httpAuth.credentials(req);
|
|
559
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
560
|
+
const decision = await permissions$1.authorize(
|
|
561
|
+
[{ permission: permissions.kuadrantApiKeyRequestUpdatePermission }],
|
|
562
|
+
{ credentials }
|
|
563
|
+
);
|
|
564
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
565
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
647
566
|
}
|
|
648
567
|
const { namespace, name } = req.params;
|
|
649
568
|
const { comment } = parsed.data;
|
|
@@ -761,24 +680,14 @@ async function createRouter({
|
|
|
761
680
|
throw new errors.InputError(parsed.error.toString());
|
|
762
681
|
}
|
|
763
682
|
try {
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
{ credentials }
|
|
773
|
-
);
|
|
774
|
-
canReject = decision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
775
|
-
}
|
|
776
|
-
} catch (error) {
|
|
777
|
-
console.warn("permission check failed, using group-based authorization:", error);
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
if (!canReject) {
|
|
781
|
-
throw new errors.NotAllowedError("you do not have permission to reject api key requests");
|
|
683
|
+
const credentials = await httpAuth.credentials(req);
|
|
684
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
685
|
+
const decision = await permissions$1.authorize(
|
|
686
|
+
[{ permission: permissions.kuadrantApiKeyRequestUpdatePermission }],
|
|
687
|
+
{ credentials }
|
|
688
|
+
);
|
|
689
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
690
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
782
691
|
}
|
|
783
692
|
const { namespace, name } = req.params;
|
|
784
693
|
const { comment } = parsed.data;
|
|
@@ -820,24 +729,14 @@ async function createRouter({
|
|
|
820
729
|
throw new errors.InputError(parsed.error.toString());
|
|
821
730
|
}
|
|
822
731
|
try {
|
|
823
|
-
const
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
{ credentials }
|
|
832
|
-
);
|
|
833
|
-
canApprove = decision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
834
|
-
}
|
|
835
|
-
} catch (error) {
|
|
836
|
-
console.warn("permission check failed, using group-based authorization:", error);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
if (!canApprove) {
|
|
840
|
-
throw new errors.NotAllowedError("you do not have permission to approve api key requests");
|
|
732
|
+
const credentials = await httpAuth.credentials(req);
|
|
733
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
734
|
+
const decision = await permissions$1.authorize(
|
|
735
|
+
[{ permission: permissions.kuadrantApiKeyRequestUpdatePermission }],
|
|
736
|
+
{ credentials }
|
|
737
|
+
);
|
|
738
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
739
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
841
740
|
}
|
|
842
741
|
const { requests, comment } = parsed.data;
|
|
843
742
|
const reviewedBy = `user:default/${userId}`;
|
|
@@ -968,24 +867,14 @@ async function createRouter({
|
|
|
968
867
|
throw new errors.InputError(parsed.error.toString());
|
|
969
868
|
}
|
|
970
869
|
try {
|
|
971
|
-
const
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
{ credentials }
|
|
980
|
-
);
|
|
981
|
-
canReject = decision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
982
|
-
}
|
|
983
|
-
} catch (error) {
|
|
984
|
-
console.warn("permission check failed, using group-based authorization:", error);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
if (!canReject) {
|
|
988
|
-
throw new errors.NotAllowedError("you do not have permission to reject api key requests");
|
|
870
|
+
const credentials = await httpAuth.credentials(req);
|
|
871
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
872
|
+
const decision = await permissions$1.authorize(
|
|
873
|
+
[{ permission: permissions.kuadrantApiKeyRequestUpdatePermission }],
|
|
874
|
+
{ credentials }
|
|
875
|
+
);
|
|
876
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
877
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
989
878
|
}
|
|
990
879
|
const { requests, comment } = parsed.data;
|
|
991
880
|
const reviewedBy = `user:default/${userId}`;
|
|
@@ -1029,7 +918,8 @@ async function createRouter({
|
|
|
1029
918
|
});
|
|
1030
919
|
router.delete("/requests/:namespace/:name", async (req, res) => {
|
|
1031
920
|
try {
|
|
1032
|
-
const
|
|
921
|
+
const credentials = await httpAuth.credentials(req);
|
|
922
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
1033
923
|
const { namespace, name } = req.params;
|
|
1034
924
|
const request = await k8sClient$1.getCustomResource(
|
|
1035
925
|
"extensions.kuadrant.io",
|
|
@@ -1039,9 +929,22 @@ async function createRouter({
|
|
|
1039
929
|
name
|
|
1040
930
|
);
|
|
1041
931
|
const requestUserId = request.spec?.requestedBy?.userId;
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
932
|
+
const deleteAllDecision = await permissions$1.authorize(
|
|
933
|
+
[{ permission: permissions.kuadrantApiKeyRequestDeleteAllPermission }],
|
|
934
|
+
{ credentials }
|
|
935
|
+
);
|
|
936
|
+
const canDeleteAll = deleteAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
|
|
937
|
+
if (!canDeleteAll) {
|
|
938
|
+
const deleteOwnDecision = await permissions$1.authorize(
|
|
939
|
+
[{ permission: permissions.kuadrantApiKeyRequestDeleteOwnPermission }],
|
|
940
|
+
{ credentials }
|
|
941
|
+
);
|
|
942
|
+
if (deleteOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
943
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
944
|
+
}
|
|
945
|
+
if (requestUserId !== userId) {
|
|
946
|
+
throw new errors.NotAllowedError("you can only delete your own api key requests");
|
|
947
|
+
}
|
|
1045
948
|
}
|
|
1046
949
|
if (request.status?.phase === "Approved") {
|
|
1047
950
|
try {
|
|
@@ -1078,30 +981,57 @@ async function createRouter({
|
|
|
1078
981
|
}
|
|
1079
982
|
});
|
|
1080
983
|
router.patch("/requests/:namespace/:name", async (req, res) => {
|
|
984
|
+
const patchSchema = zod.z.object({
|
|
985
|
+
spec: zod.z.object({
|
|
986
|
+
useCase: zod.z.string().optional()
|
|
987
|
+
}).partial()
|
|
988
|
+
});
|
|
989
|
+
const parsed = patchSchema.safeParse(req.body);
|
|
990
|
+
if (!parsed.success) {
|
|
991
|
+
throw new errors.InputError("invalid patch: " + parsed.error.toString());
|
|
992
|
+
}
|
|
1081
993
|
try {
|
|
1082
994
|
const credentials = await httpAuth.credentials(req);
|
|
1083
|
-
const
|
|
995
|
+
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
996
|
+
const { namespace, name } = req.params;
|
|
997
|
+
const existing = await k8sClient$1.getCustomResource(
|
|
998
|
+
"extensions.kuadrant.io",
|
|
999
|
+
"v1alpha1",
|
|
1000
|
+
namespace,
|
|
1001
|
+
"apikeyrequests",
|
|
1002
|
+
name
|
|
1003
|
+
);
|
|
1004
|
+
const updateAllDecision = await permissions$1.authorize(
|
|
1084
1005
|
[{ permission: permissions.kuadrantApiKeyRequestUpdatePermission }],
|
|
1085
1006
|
{ credentials }
|
|
1086
1007
|
);
|
|
1087
|
-
if (
|
|
1088
|
-
|
|
1008
|
+
if (updateAllDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
1009
|
+
const updateOwnDecision = await permissions$1.authorize(
|
|
1010
|
+
[{ permission: permissions.kuadrantApiKeyRequestUpdateOwnPermission }],
|
|
1011
|
+
{ credentials }
|
|
1012
|
+
);
|
|
1013
|
+
if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
1014
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
1015
|
+
}
|
|
1016
|
+
if (existing.spec?.requestedBy?.userId !== userId) {
|
|
1017
|
+
throw new errors.NotAllowedError("you can only update your own api key requests");
|
|
1018
|
+
}
|
|
1089
1019
|
}
|
|
1090
|
-
const { namespace, name } = req.params;
|
|
1091
|
-
const patch = req.body;
|
|
1092
1020
|
const updated = await k8sClient$1.patchCustomResource(
|
|
1093
1021
|
"extensions.kuadrant.io",
|
|
1094
1022
|
"v1alpha1",
|
|
1095
1023
|
namespace,
|
|
1096
1024
|
"apikeyrequests",
|
|
1097
1025
|
name,
|
|
1098
|
-
|
|
1026
|
+
parsed.data
|
|
1099
1027
|
);
|
|
1100
1028
|
res.json(updated);
|
|
1101
1029
|
} catch (error) {
|
|
1102
1030
|
console.error("error updating api key request:", error);
|
|
1103
1031
|
if (error instanceof errors.NotAllowedError) {
|
|
1104
1032
|
res.status(403).json({ error: error.message });
|
|
1033
|
+
} else if (error instanceof errors.InputError) {
|
|
1034
|
+
res.status(400).json({ error: error.message });
|
|
1105
1035
|
} else {
|
|
1106
1036
|
res.status(500).json({ error: "failed to update api key request" });
|
|
1107
1037
|
}
|
package/dist/router.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../src/router.ts"],"sourcesContent":["import { HttpAuthService, RootConfigService, UserInfoService, PermissionsService } from '@backstage/backend-plugin-api';\nimport { InputError, NotAllowedError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\nimport { z } from 'zod';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport cors from 'cors';\nimport { randomBytes } from 'crypto';\nimport { KuadrantK8sClient } from './k8s-client';\nimport { getAPIProductEntityProvider } from './module';\nimport {\n kuadrantPermissions,\n kuadrantApiKeyDeleteAllPermission,\n kuadrantPlanPolicyListPermission,\n kuadrantPlanPolicyReadPermission,\n kuadrantApiProductListPermission,\n kuadrantApiProductReadPermission,\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeletePermission,\n kuadrantApiKeyRequestCreatePermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantApiKeyRequestUpdatePermission,\n kuadrantApiKeyRequestListPermission,\n kuadrantApiKeyReadOwnPermission,\n kuadrantApiKeyReadAllPermission,\n kuadrantApiKeyDeleteOwnPermission, kuadrantApiProductUpdatePermission,\n} from './permissions';\n\nfunction generateApiKey(): string {\n return randomBytes(32).toString('hex');\n}\n\nasync function getUserIdentity(req: express.Request, httpAuth: HttpAuthService, userInfo: UserInfoService): Promise<{\n userId: string;\n isPlatformEngineer: boolean;\n isApiOwner: boolean;\n isApiConsumer: boolean;\n groups: string[];\n}> {\n try {\n // allow both user credentials and unauthenticated (guest) access\n const credentials = await httpAuth.credentials(req, { allow: ['user', 'none'] });\n\n if (!credentials || !credentials.principal || credentials.principal.type === 'none') {\n // no credentials or guest user - treat as api owner in development\n console.log('no user credentials, treating as guest api owner');\n return {\n userId: 'guest',\n isPlatformEngineer: false,\n isApiOwner: true, // allow guest as api owner in development\n isApiConsumer: true,\n groups: []\n };\n }\n\n // get user info from credentials\n const info = await userInfo.getUserInfo(credentials);\n\n // extract userId from entity ref (format: \"user:default/alice\" -> \"alice\")\n const userId = info.userEntityRef.split('/')[1] || 'guest';\n const groups = info.ownershipEntityRefs || [];\n\n // check user roles based on group membership\n const isPlatformEngineer = userId === 'guest' || groups.some((ref: string) =>\n ref === 'group:default/platform-engineers' ||\n ref === 'group:default/platform-admins'\n );\n\n const isApiOwner = userId === 'guest' || groups.some((ref: string) =>\n ref === 'group:default/api-owners' ||\n ref === 'group:default/app-developers'\n );\n\n const isApiConsumer = groups.some((ref: string) =>\n ref === 'group:default/api-consumers'\n );\n\n console.log(`user identity resolved: userId=${userId}, isPlatformEngineer=${isPlatformEngineer}, isApiOwner=${isApiOwner}, isApiConsumer=${isApiConsumer}, groups=${groups.join(',')}`);\n return { userId, isPlatformEngineer, isApiOwner, isApiConsumer, groups };\n } catch (error) {\n // if credentials fail to verify (e.g. JWT issues with guest auth), treat as guest api owner\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.warn(`failed to get user identity, defaulting to guest api owner: ${errorMsg}`);\n return {\n userId: 'guest',\n isPlatformEngineer: false,\n isApiOwner: true, // allow guest as api owner in development\n isApiConsumer: true,\n groups: []\n };\n }\n}\n\nexport async function createRouter({\n httpAuth,\n userInfo,\n config,\n permissions,\n}: {\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n config: RootConfigService;\n permissions: PermissionsService;\n}): Promise<express.Router> {\n const router = Router();\n\n // enable cors for dev mode (allows frontend on :3000 to call backend on :7007)\n router.use(cors({\n origin: 'http://localhost:3000',\n credentials: true,\n }));\n\n router.use(express.json());\n\n const k8sClient = new KuadrantK8sClient(config);\n\n // apiproduct endpoints\n router.get('/apiproducts', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n res.json(data);\n } catch (error) {\n console.error('error fetching apiproducts:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch apiproducts' });\n }\n }\n });\n\n router.get('/apiproducts/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductReadPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const data = await k8sClient.getCustomResource('extensions.kuadrant.io', 'v1alpha1', namespace, 'apiproducts', name);\n res.json(data);\n } catch (error) {\n console.error('error fetching apiproduct:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch apiproduct' });\n }\n }\n });\n\n router.post('/apiproducts', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductCreatePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const apiProduct = req.body;\n const namespace = apiProduct.metadata?.namespace;\n const targetRef = apiProduct.spec?.targetRef;\n\n if (!namespace) {\n throw new InputError('namespace is required in metadata');\n }\n\n if (!targetRef?.name || !targetRef?.kind) {\n throw new InputError('targetRef with name and kind is required');\n }\n\n // set the owner to the authenticated user\n if (!apiProduct.spec.contact) {\n apiProduct.spec.contact = {};\n }\n apiProduct.spec.contact.team = `user:default/${userId}`;\n\n // temporary: populate plans from planpolicy until controller implements this\n // look up httproute and find planpolicy targeting it\n const httpRouteNamespace = targetRef.namespace || namespace;\n const httpRouteName = targetRef.name;\n\n try {\n // list all planpolicies in the httproute's namespace\n const planPoliciesResponse = await k8sClient.listCustomResources(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n 'planpolicies',\n httpRouteNamespace\n );\n\n // find planpolicy targeting this httproute\n const planPolicy = (planPoliciesResponse.items || []).find((pp: any) => {\n const ref = pp.spec?.targetRef;\n return ref?.kind === 'HTTPRoute' &&\n ref?.name === httpRouteName &&\n (!ref?.namespace || ref?.namespace === httpRouteNamespace);\n });\n\n if (planPolicy && planPolicy.spec?.plans) {\n // copy plans from planpolicy to apiproduct spec\n apiProduct.spec.plans = planPolicy.spec.plans.map((plan: any) => ({\n tier: plan.tier,\n description: plan.description,\n limits: plan.limits\n }));\n console.log(`copied ${apiProduct.spec.plans.length} plans from planpolicy ${planPolicy.metadata.name}`);\n } else {\n console.log(`no planpolicy found for httproute ${httpRouteNamespace}/${httpRouteName}`);\n }\n } catch (error) {\n console.warn('failed to populate plans from planpolicy:', error);\n // continue without plans rather than failing the creation\n }\n\n const created = await k8sClient.createCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n apiProduct,\n );\n\n // trigger immediate catalog sync\n const provider = getAPIProductEntityProvider();\n if (provider) {\n await provider.refresh();\n }\n\n res.status(201).json(created);\n } catch (error) {\n console.error('error creating apiproduct:', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else if (error instanceof InputError) {\n res.status(400).json({ error: error.message });\n } else {\n // pass the detailed error message to the frontend\n res.status(500).json({ error: errorMessage });\n }\n }\n });\n\n router.delete('/apiproducts/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductDeletePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n\n await k8sClient.deleteCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n name\n );\n\n // trigger immediate catalog sync\n const provider = getAPIProductEntityProvider();\n if (provider) {\n await provider.refresh();\n }\n\n res.status(204).send();\n } catch (error) {\n console.error('error deleting apiproduct:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to delete apiproduct' });\n }\n }\n });\n\n // httproute endpoints\n router.get('/httproutes', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('gateway.networking.k8s.io', 'v1', 'httproutes');\n\n res.json(data);\n } catch (error) {\n console.error('error fetching httproutes:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch httproutes' });\n }\n }\n });\n\n router.patch('/apiproducts/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req, { allow: ['user', 'none'] });\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductUpdatePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const patch = req.body;\n\n const updated = await k8sClient.patchCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n name,\n patch,\n );\n\n res.json(updated);\n } catch (error) {\n console.error('error updating apiproduct:', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else if (error instanceof InputError) {\n res.status(400).json({ error: error.message });\n } else {\n res.status(500).json({ error: errorMessage });\n }\n }\n });\n\n // planpolicy endpoints\n router.get('/planpolicies', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantPlanPolicyListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'planpolicies');\n\n // filter to only return name and namespace to avoid leaking plan details\n const filtered = {\n items: (data.items || []).map((policy: any) => ({\n metadata: {\n name: policy.metadata.name,\n namespace: policy.metadata.namespace,\n },\n })),\n };\n\n res.json(filtered);\n } catch (error) {\n console.error('error fetching planpolicies:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch planpolicies' });\n }\n }\n });\n\n router.get('/planpolicies/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantPlanPolicyReadPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const data = await k8sClient.getCustomResource('extensions.kuadrant.io', 'v1alpha1', namespace, 'planpolicies', name);\n res.json(data);\n } catch (error) {\n console.error('error fetching planpolicy:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch planpolicy' });\n }\n }\n });\n\n // api key secret management (for viewing existing keys)\n router.get('/apikeys', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n const userId = req.query.userId as string;\n const namespace = req.query.namespace as string;\n\n if (!namespace) {\n throw new InputError('namespace query parameter is required');\n }\n\n // if userId is provided, check for .own permission, otherwise .all permission\n const permission = userId ? kuadrantApiKeyReadOwnPermission : kuadrantApiKeyReadAllPermission;\n const decision = await permissions.authorize(\n [{ permission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listSecrets(namespace);\n\n let filteredItems = data.items || [];\n if (userId) {\n filteredItems = filteredItems.filter((secret: any) =>\n secret.metadata?.annotations?.['secret.kuadrant.io/user-id'] === userId\n );\n }\n\n filteredItems = filteredItems.filter((secret: any) =>\n secret.metadata?.annotations?.['secret.kuadrant.io/user-id']\n );\n\n res.json({ items: filteredItems });\n } catch (error) {\n console.error('error fetching api keys:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch api keys' });\n }\n }\n });\n\n router.delete('/apikeys/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const { namespace, name } = req.params;\n\n const secret = await k8sClient.getSecret(namespace, name);\n const secretUserId = secret.metadata?.annotations?.['secret.kuadrant.io/user-id'];\n\n // check if user can delete all keys or just their own\n const deleteAllDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyDeleteAllPermission }],\n { credentials }\n );\n\n const canDeleteAll = deleteAllDecision[0].result === AuthorizeResult.ALLOW;\n\n if (!canDeleteAll) {\n // check if user can delete their own keys\n const deleteOwnDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyDeleteOwnPermission }],\n { credentials }\n );\n\n if (deleteOwnDecision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n // verify ownership\n if (secretUserId !== userId) {\n throw new NotAllowedError('you can only delete your own api keys');\n }\n }\n\n await k8sClient.deleteSecret(namespace, name);\n res.status(204).send();\n } catch (error) {\n console.error('error deleting api key:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to delete api key' });\n }\n }\n });\n\n // apikeyrequest crud endpoints\n const requestSchema = z.object({\n apiName: z.string(),\n apiNamespace: z.string(),\n planTier: z.string(),\n useCase: z.string().optional(),\n userId: z.string(),\n userEmail: z.string().optional(),\n namespace: z.string(),\n });\n\n router.post('/requests', async (req, res) => {\n const parsed = requestSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { apiName, apiNamespace, planTier, useCase, userId, userEmail, namespace } = parsed.data;\n\n // check permission with resource reference (per-apiproduct access control)\n const resourceRef = `apiproduct:${apiNamespace}/${apiName}`;\n const decision = await permissions.authorize(\n [{\n permission: kuadrantApiKeyRequestCreatePermission,\n resourceRef,\n }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError(`not authorised to request access to ${apiName}`);\n }\n\n const { userId: authenticatedUserId, isPlatformEngineer, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n\n // validate userId matches authenticated user (platform engineers and api owners can create on behalf of others)\n const canCreateForOthers = isPlatformEngineer || isApiOwner;\n if (!canCreateForOthers && userId !== authenticatedUserId) {\n throw new NotAllowedError('you can only create api key requests for yourself');\n }\n const timestamp = new Date().toISOString();\n const randomSuffix = randomBytes(4).toString('hex');\n const requestName = `${userId}-${apiName}-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\n const requestedBy: any = { userId };\n if (userEmail) {\n requestedBy.email = userEmail;\n }\n\n const request = {\n apiVersion: 'extensions.kuadrant.io/v1alpha1',\n kind: 'APIKeyRequest',\n metadata: {\n name: requestName,\n namespace,\n },\n spec: {\n apiName,\n apiNamespace,\n planTier,\n useCase: useCase || '',\n requestedBy,\n requestedAt: timestamp,\n },\n };\n\n const created = await k8sClient.createCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n request,\n );\n\n // check if apiproduct has automatic approval mode\n try {\n const apiProduct = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n apiNamespace,\n 'apiproducts',\n apiName,\n );\n\n if (apiProduct.spec?.approvalMode === 'automatic') {\n // automatically approve and create secret\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${userId}-${apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: apiNamespace,\n labels: {\n app: apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': planTier,\n 'secret.kuadrant.io/user-id': userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(apiNamespace, secret);\n\n // get plan limits\n let planLimits: any = null;\n const plan = apiProduct.spec?.plans?.find((p: any) => p.tier === planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n apiNamespace,\n 'httproutes',\n apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n // update request status to approved\n const status = {\n phase: 'Approved',\n reviewedBy: 'system',\n reviewedAt: new Date().toISOString(),\n reason: 'automatic approval',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n requestName,\n status,\n );\n }\n } catch (error) {\n console.warn('could not check approval mode or auto-approve:', error);\n // continue anyway - request was created successfully\n }\n\n res.status(201).json(created);\n } catch (error) {\n console.error('error creating api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to create api key request' });\n }\n }\n });\n\n router.get('/requests', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const status = req.query.status as string;\n const namespace = req.query.namespace as string;\n\n let data;\n if (namespace) {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests', namespace);\n } else {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests');\n }\n\n let filteredItems = data.items || [];\n if (status) {\n filteredItems = filteredItems.filter((req: any) => {\n const phase = req.status?.phase || 'Pending';\n return phase === status;\n });\n }\n\n res.json({ items: filteredItems });\n } catch (error) {\n console.error('error fetching api key requests:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch api key requests' });\n }\n }\n });\n\n router.get('/requests/my', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestReadOwnPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const userId = req.query.userId as string;\n const namespace = req.query.namespace as string;\n\n if (!userId) {\n throw new InputError('userId query parameter is required');\n }\n\n let data;\n if (namespace) {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests', namespace);\n } else {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests');\n }\n\n const filteredItems = (data.items || []).filter(\n (req: any) => req.spec?.requestedBy?.userId === userId\n );\n\n res.json({ items: filteredItems });\n } catch (error) {\n console.error('error fetching user api key requests:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch user api key requests' });\n }\n }\n });\n\n const approveRejectSchema = z.object({\n comment: z.string().optional(),\n });\n\n router.post('/requests/:namespace/:name/approve', async (req, res) => {\n const parsed = approveRejectSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const { userId, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n let canApprove = isApiOwner; // api owners can approve requests\n\n // if permissions are enabled, also check via permission framework\n if (!canApprove) {\n try {\n const credentials = await httpAuth.credentials(req, { allow: ['none'] });\n if (credentials) {\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n canApprove = decision[0].result === AuthorizeResult.ALLOW;\n }\n } catch (error) {\n // permission check failed, rely on group-based check\n console.warn('permission check failed, using group-based authorization:', error);\n }\n }\n\n if (!canApprove) {\n throw new NotAllowedError('you do not have permission to approve api key requests');\n }\n\n const { namespace, name } = req.params;\n const { comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n\n const spec = request.spec as any;\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${spec.requestedBy.userId}-${spec.apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: spec.apiNamespace,\n labels: {\n app: spec.apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': spec.planTier,\n 'secret.kuadrant.io/user-id': spec.requestedBy.userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(spec.apiNamespace, secret);\n\n // try to get plan limits from apiproduct or planpolicy\n let planLimits: any = null;\n try {\n const products = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n const product = (products.items || []).find((p: any) =>\n p.metadata.name.includes(spec.apiName) || p.spec?.displayName?.toLowerCase().includes(spec.apiName.toLowerCase())\n );\n if (product) {\n const plan = product.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n }\n } catch (e) {\n console.warn('could not fetch apiproduct for plan limits:', e);\n }\n\n if (!planLimits) {\n try {\n const policy = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n spec.apiNamespace,\n 'planpolicies',\n `${spec.apiName}-plan`,\n );\n const plan = policy.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n } catch (e) {\n console.warn('could not fetch planpolicy for plan limits:', e);\n }\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${spec.apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n spec.apiNamespace,\n 'httproutes',\n spec.apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n const status = {\n phase: 'Approved',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'approved',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${spec.apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n status,\n );\n\n res.json({ secretName });\n } catch (error) {\n console.error('error approving api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to approve api key request' });\n }\n }\n });\n\n router.post('/requests/:namespace/:name/reject', async (req, res) => {\n const parsed = approveRejectSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const { userId, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n let canReject = isApiOwner; // api owners can reject requests\n\n // if permissions are enabled, also check via permission framework\n if (!canReject) {\n try {\n const credentials = await httpAuth.credentials(req, { allow: ['none'] });\n if (credentials) {\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n canReject = decision[0].result === AuthorizeResult.ALLOW;\n }\n } catch (error) {\n // permission check failed, rely on group-based check\n console.warn('permission check failed, using group-based authorization:', error);\n }\n }\n\n if (!canReject) {\n throw new NotAllowedError('you do not have permission to reject api key requests');\n }\n\n const { namespace, name } = req.params;\n const { comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n\n const status = {\n phase: 'Rejected',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'rejected',\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n status,\n );\n\n res.status(204).send();\n } catch (error) {\n console.error('error rejecting api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to reject api key request' });\n }\n }\n });\n\n const bulkApproveSchema = z.object({\n requests: z.array(z.object({\n namespace: z.string(),\n name: z.string(),\n })),\n comment: z.string().optional(),\n });\n\n router.post('/requests/bulk-approve', async (req, res) => {\n const parsed = bulkApproveSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const { userId, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n let canApprove = isApiOwner;\n\n // if permissions are enabled, also check via permission framework\n if (!canApprove) {\n try {\n const credentials = await httpAuth.credentials(req, { allow: ['none'] });\n if (credentials) {\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n canApprove = decision[0].result === AuthorizeResult.ALLOW;\n }\n } catch (error) {\n console.warn('permission check failed, using group-based authorization:', error);\n }\n }\n\n if (!canApprove) {\n throw new NotAllowedError('you do not have permission to approve api key requests');\n }\n\n const { requests, comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n const results = [];\n\n for (const reqRef of requests) {\n try {\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n );\n\n const spec = request.spec as any;\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${spec.requestedBy.userId}-${spec.apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: spec.apiNamespace,\n labels: {\n app: spec.apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': spec.planTier,\n 'secret.kuadrant.io/user-id': spec.requestedBy.userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(spec.apiNamespace, secret);\n\n // try to get plan limits from apiproduct or planpolicy\n let planLimits: any = null;\n try {\n const products = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n const product = (products.items || []).find((p: any) =>\n p.metadata.name.includes(spec.apiName) || p.spec?.displayName?.toLowerCase().includes(spec.apiName.toLowerCase())\n );\n if (product) {\n const plan = product.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n }\n } catch (e) {\n console.warn('could not fetch apiproduct for plan limits:', e);\n }\n\n if (!planLimits) {\n try {\n const policy = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n spec.apiNamespace,\n 'planpolicies',\n `${spec.apiName}-plan`,\n );\n const plan = policy.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n } catch (e) {\n console.warn('could not fetch planpolicy for plan limits:', e);\n }\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${spec.apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n spec.apiNamespace,\n 'httproutes',\n spec.apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n const status = {\n phase: 'Approved',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'approved',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${spec.apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n status,\n );\n\n results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true, secretName });\n } catch (error) {\n console.error(`error approving request ${reqRef.namespace}/${reqRef.name}:`, error);\n results.push({\n namespace: reqRef.namespace,\n name: reqRef.name,\n success: false,\n error: error instanceof Error ? error.message : 'unknown error'\n });\n }\n }\n\n res.json({ results });\n } catch (error) {\n console.error('error in bulk approve:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to bulk approve api key requests' });\n }\n }\n });\n\n router.post('/requests/bulk-reject', async (req, res) => {\n const parsed = bulkApproveSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const { userId, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n let canReject = isApiOwner;\n\n // if permissions are enabled, also check via permission framework\n if (!canReject) {\n try {\n const credentials = await httpAuth.credentials(req, { allow: ['none'] });\n if (credentials) {\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n canReject = decision[0].result === AuthorizeResult.ALLOW;\n }\n } catch (error) {\n console.warn('permission check failed, using group-based authorization:', error);\n }\n }\n\n if (!canReject) {\n throw new NotAllowedError('you do not have permission to reject api key requests');\n }\n\n const { requests, comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n const results = [];\n\n for (const reqRef of requests) {\n try {\n const status = {\n phase: 'Rejected',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'rejected',\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n status,\n );\n\n results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true });\n } catch (error) {\n console.error(`error rejecting request ${reqRef.namespace}/${reqRef.name}:`, error);\n results.push({\n namespace: reqRef.namespace,\n name: reqRef.name,\n success: false,\n error: error instanceof Error ? error.message : 'unknown error'\n });\n }\n }\n\n res.json({ results });\n } catch (error) {\n console.error('error in bulk reject:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to bulk reject api key requests' });\n }\n }\n });\n\n router.delete('/requests/:namespace/:name', async (req, res) => {\n try {\n const { userId, isPlatformEngineer, isApiOwner } = await getUserIdentity(req, httpAuth, userInfo);\n const { namespace, name } = req.params;\n\n // get request to verify ownership\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n\n const requestUserId = request.spec?.requestedBy?.userId;\n\n // platform engineers and api owners can delete any request, consumers can only delete their own\n const canDeleteAll = isPlatformEngineer || isApiOwner;\n if (!canDeleteAll && requestUserId !== userId) {\n throw new NotAllowedError('you can only delete your own api key requests');\n }\n\n // if request is approved, find and delete associated secret\n if (request.status?.phase === 'Approved') {\n try {\n const apiNamespace = request.spec?.apiNamespace;\n const apiName = request.spec?.apiName;\n const planTier = request.spec?.planTier;\n\n // list secrets in the api namespace and find the one with matching annotations\n const secrets = await k8sClient.listSecrets(apiNamespace);\n const matchingSecret = secrets.items?.find((s: any) => {\n const annotations = s.metadata?.annotations || {};\n return (\n annotations['secret.kuadrant.io/user-id'] === requestUserId &&\n annotations['secret.kuadrant.io/plan-id'] === planTier &&\n s.metadata?.labels?.app === apiName\n );\n });\n\n if (matchingSecret) {\n await k8sClient.deleteSecret(apiNamespace, matchingSecret.metadata.name);\n }\n } catch (error) {\n console.warn('failed to delete associated secret:', error);\n // continue with request deletion even if secret deletion fails\n }\n }\n\n await k8sClient.deleteCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n res.status(204).send();\n } catch (error) {\n console.error('error deleting api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to delete api key request' });\n }\n }\n });\n\n router.patch('/requests/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const patch = req.body;\n\n const updated = await k8sClient.patchCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n patch,\n );\n\n res.json(updated);\n } catch (error) {\n console.error('error updating api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to update api key request' });\n }\n }\n });\n\n // expose permissions for backstage permission framework\n router.use(createPermissionIntegrationRouter({\n permissions: kuadrantPermissions,\n }));\n\n return router;\n}\n"],"names":["randomBytes","permissions","Router","cors","express","k8sClient","KuadrantK8sClient","kuadrantApiProductListPermission","AuthorizeResult","NotAllowedError","kuadrantApiProductReadPermission","kuadrantApiProductCreatePermission","InputError","getAPIProductEntityProvider","kuadrantApiProductDeletePermission","kuadrantApiProductUpdatePermission","kuadrantPlanPolicyListPermission","kuadrantPlanPolicyReadPermission","kuadrantApiKeyReadOwnPermission","kuadrantApiKeyReadAllPermission","kuadrantApiKeyDeleteAllPermission","kuadrantApiKeyDeleteOwnPermission","z","kuadrantApiKeyRequestCreatePermission","timestamp","kuadrantApiKeyRequestListPermission","req","kuadrantApiKeyRequestReadOwnPermission","kuadrantApiKeyRequestUpdatePermission","createPermissionIntegrationRouter","kuadrantPermissions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../src/router.ts"],"sourcesContent":["import { HttpAuthService, RootConfigService, UserInfoService, PermissionsService } from '@backstage/backend-plugin-api';\nimport { InputError, NotAllowedError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\nimport { z } from 'zod';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport cors from 'cors';\nimport { randomBytes } from 'crypto';\nimport { KuadrantK8sClient } from './k8s-client';\nimport { getAPIProductEntityProvider } from './module';\nimport {\n kuadrantPermissions,\n kuadrantPlanPolicyListPermission,\n kuadrantPlanPolicyReadPermission,\n kuadrantApiProductListPermission,\n kuadrantApiProductReadPermission,\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeletePermission,\n kuadrantApiKeyRequestCreatePermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantApiKeyRequestUpdatePermission,\n kuadrantApiKeyRequestUpdateOwnPermission,\n kuadrantApiKeyRequestListPermission,\n kuadrantApiKeyRequestDeleteOwnPermission,\n kuadrantApiKeyRequestDeleteAllPermission,\n kuadrantApiProductUpdatePermission,\n} from './permissions';\n\nfunction generateApiKey(): string {\n return randomBytes(32).toString('hex');\n}\n\nasync function getUserIdentity(req: express.Request, httpAuth: HttpAuthService, userInfo: UserInfoService): Promise<{\n userId: string;\n userEntityRef: string;\n groups: string[];\n}> {\n const credentials = await httpAuth.credentials(req);\n\n if (!credentials || !credentials.principal) {\n throw new NotAllowedError('authentication required');\n }\n\n // get user info from credentials\n const info = await userInfo.getUserInfo(credentials);\n\n // extract userId from entity ref (format: \"user:default/alice\" -> \"alice\")\n const userId = info.userEntityRef.split('/')[1];\n const groups = info.ownershipEntityRefs || [];\n\n console.log(`user identity resolved: userId=${userId}, userEntityRef=${info.userEntityRef}, groups=${groups.join(',')}`);\n return {\n userId,\n userEntityRef: info.userEntityRef,\n groups\n };\n}\n\nexport async function createRouter({\n httpAuth,\n userInfo,\n config,\n permissions,\n}: {\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n config: RootConfigService;\n permissions: PermissionsService;\n}): Promise<express.Router> {\n const router = Router();\n\n // enable cors for dev mode (allows frontend on :3000 to call backend on :7007)\n router.use(cors({\n origin: 'http://localhost:3000',\n credentials: true,\n }));\n\n router.use(express.json());\n\n const k8sClient = new KuadrantK8sClient(config);\n\n // apiproduct endpoints\n router.get('/apiproducts', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n res.json(data);\n } catch (error) {\n console.error('error fetching apiproducts:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch apiproducts' });\n }\n }\n });\n\n router.get('/apiproducts/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductReadPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const data = await k8sClient.getCustomResource('extensions.kuadrant.io', 'v1alpha1', namespace, 'apiproducts', name);\n res.json(data);\n } catch (error) {\n console.error('error fetching apiproduct:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch apiproduct' });\n }\n }\n });\n\n router.post('/apiproducts', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductCreatePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const apiProduct = req.body;\n const targetRef = apiProduct.spec?.targetRef;\n\n if (!targetRef?.name || !targetRef?.kind || !targetRef?.namespace) {\n throw new InputError('targetRef with name, kind, and namespace is required');\n }\n\n // derive namespace from httproute - apiproduct lives in same namespace as httproute\n const namespace = targetRef.namespace;\n apiProduct.metadata.namespace = namespace;\n\n // set the owner to the authenticated user\n if (!apiProduct.spec.contact) {\n apiProduct.spec.contact = {};\n }\n apiProduct.spec.contact.team = `user:default/${userId}`;\n\n // temporary: populate plans from planpolicy until controller implements this\n // look up httproute and find planpolicy targeting it\n const httpRouteNamespace = namespace;\n const httpRouteName = targetRef.name;\n\n try {\n // list all planpolicies in the httproute's namespace\n const planPoliciesResponse = await k8sClient.listCustomResources(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n 'planpolicies',\n httpRouteNamespace\n );\n\n // find planpolicy targeting this httproute\n const planPolicy = (planPoliciesResponse.items || []).find((pp: any) => {\n const ref = pp.spec?.targetRef;\n return ref?.kind === 'HTTPRoute' &&\n ref?.name === httpRouteName &&\n (!ref?.namespace || ref?.namespace === httpRouteNamespace);\n });\n\n if (planPolicy && planPolicy.spec?.plans) {\n // copy plans from planpolicy to apiproduct spec\n apiProduct.spec.plans = planPolicy.spec.plans.map((plan: any) => ({\n tier: plan.tier,\n description: plan.description,\n limits: plan.limits\n }));\n console.log(`copied ${apiProduct.spec.plans.length} plans from planpolicy ${planPolicy.metadata.name}`);\n } else {\n console.log(`no planpolicy found for httproute ${httpRouteNamespace}/${httpRouteName}`);\n }\n } catch (error) {\n console.warn('failed to populate plans from planpolicy:', error);\n // continue without plans rather than failing the creation\n }\n\n const created = await k8sClient.createCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n apiProduct,\n );\n\n // trigger immediate catalog sync\n const provider = getAPIProductEntityProvider();\n if (provider) {\n await provider.refresh();\n }\n\n res.status(201).json(created);\n } catch (error) {\n console.error('error creating apiproduct:', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else if (error instanceof InputError) {\n res.status(400).json({ error: error.message });\n } else {\n // pass the detailed error message to the frontend\n res.status(500).json({ error: errorMessage });\n }\n }\n });\n\n router.delete('/apiproducts/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductDeletePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n\n await k8sClient.deleteCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n name\n );\n\n // trigger immediate catalog sync\n const provider = getAPIProductEntityProvider();\n if (provider) {\n await provider.refresh();\n }\n\n res.status(204).send();\n } catch (error) {\n console.error('error deleting apiproduct:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to delete apiproduct' });\n }\n }\n });\n\n // httproute endpoints\n router.get('/httproutes', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('gateway.networking.k8s.io', 'v1', 'httproutes');\n\n res.json(data);\n } catch (error) {\n console.error('error fetching httproutes:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch httproutes' });\n }\n }\n });\n\n router.patch('/apiproducts/:namespace/:name', async (req, res) => {\n // whitelist allowed fields for patching\n const patchSchema = z.object({\n spec: z.object({\n displayName: z.string().optional(),\n description: z.string().optional(),\n version: z.string().optional(),\n publishStatus: z.enum(['Draft', 'Published']).optional(),\n approvalMode: z.enum(['automatic', 'manual']).optional(),\n tags: z.array(z.string()).optional(),\n contact: z.object({\n email: z.string().optional(),\n team: z.string().optional(),\n slack: z.string().optional(),\n }).partial().optional(),\n documentation: z.object({\n docsURL: z.string().optional(),\n openAPISpec: z.string().optional(),\n }).partial().optional(),\n }).partial(),\n });\n\n const parsed = patchSchema.safeParse(req.body);\n if (!parsed.success) {\n return res.status(400).json({ error: 'invalid patch: ' + parsed.error.toString() });\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n\n if (!credentials || !credentials.principal) {\n throw new NotAllowedError('authentication required');\n }\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiProductUpdatePermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n\n const updated = await k8sClient.patchCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n name,\n parsed.data,\n );\n\n return res.json(updated);\n } catch (error) {\n console.error('error updating apiproduct:', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof NotAllowedError) {\n return res.status(403).json({ error: error.message });\n } else if (error instanceof InputError) {\n return res.status(400).json({ error: error.message });\n } else {\n return res.status(500).json({ error: errorMessage });\n }\n }\n });\n\n // planpolicy endpoints\n router.get('/planpolicies', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantPlanPolicyListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'planpolicies');\n\n // only expose minimal info needed for UI association\n const filtered = {\n items: (data.items || []).map((policy: any) => ({\n metadata: {\n name: policy.metadata.name,\n namespace: policy.metadata.namespace,\n },\n // only expose targetRef to allow UI to match PlanPolicy -> HTTPRoute\n targetRef: policy.spec?.targetRef ? {\n kind: policy.spec.targetRef.kind,\n name: policy.spec.targetRef.name,\n namespace: policy.spec.targetRef.namespace,\n } : undefined,\n // only expose plan tier info, no other spec details\n plans: (policy.spec?.plans || []).map((plan: any) => ({\n tier: plan.tier,\n description: plan.description,\n limits: plan.limits,\n })),\n })),\n };\n\n res.json(filtered);\n } catch (error) {\n console.error('error fetching planpolicies:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch planpolicies' });\n }\n }\n });\n\n router.get('/planpolicies/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantPlanPolicyReadPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const data = await k8sClient.getCustomResource('extensions.kuadrant.io', 'v1alpha1', namespace, 'planpolicies', name);\n res.json(data);\n } catch (error) {\n console.error('error fetching planpolicy:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch planpolicy' });\n }\n }\n });\n\n // apikeyrequest crud endpoints\n const requestSchema = z.object({\n apiName: z.string(),\n apiNamespace: z.string(),\n planTier: z.string(),\n useCase: z.string().optional(),\n userEmail: z.string().optional(),\n });\n\n router.post('/requests', async (req, res) => {\n const parsed = requestSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { apiName, apiNamespace, planTier, useCase, userEmail } = parsed.data;\n\n // extract userId from authenticated credentials, not from request body\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n\n // check permission with resource reference (per-apiproduct access control)\n const resourceRef = `apiproduct:${apiNamespace}/${apiName}`;\n const decision = await permissions.authorize(\n [{\n permission: kuadrantApiKeyRequestCreatePermission,\n resourceRef,\n }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError(`not authorised to request access to ${apiName}`);\n }\n const timestamp = new Date().toISOString();\n const randomSuffix = randomBytes(4).toString('hex');\n const requestName = `${userId}-${apiName}-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\n const requestedBy: any = { userId };\n if (userEmail) {\n requestedBy.email = userEmail;\n }\n\n const request = {\n apiVersion: 'extensions.kuadrant.io/v1alpha1',\n kind: 'APIKeyRequest',\n metadata: {\n name: requestName,\n namespace: apiNamespace,\n },\n spec: {\n apiName,\n apiNamespace,\n planTier,\n useCase: useCase || '',\n requestedBy,\n requestedAt: timestamp,\n },\n };\n\n const created = await k8sClient.createCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n apiNamespace,\n 'apikeyrequests',\n request,\n );\n\n // check if apiproduct has automatic approval mode\n try {\n const apiProduct = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n apiNamespace,\n 'apiproducts',\n apiName,\n );\n\n if (apiProduct.spec?.approvalMode === 'automatic') {\n // automatically approve and create secret\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${userId}-${apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: apiNamespace,\n labels: {\n app: apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': planTier,\n 'secret.kuadrant.io/user-id': userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(apiNamespace, secret);\n\n // get plan limits\n let planLimits: any = null;\n const plan = apiProduct.spec?.plans?.find((p: any) => p.tier === planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n apiNamespace,\n 'httproutes',\n apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n // update request status to approved\n const status = {\n phase: 'Approved',\n reviewedBy: 'system',\n reviewedAt: new Date().toISOString(),\n reason: 'automatic approval',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n apiNamespace,\n 'apikeyrequests',\n requestName,\n status,\n );\n }\n } catch (error) {\n console.warn('could not check approval mode or auto-approve:', error);\n // continue anyway - request was created successfully\n }\n\n res.status(201).json(created);\n } catch (error) {\n console.error('error creating api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to create api key request' });\n }\n }\n });\n\n router.get('/requests', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestListPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const status = req.query.status as string;\n const namespace = req.query.namespace as string;\n\n let data;\n if (namespace) {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests', namespace);\n } else {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests');\n }\n\n let filteredItems = data.items || [];\n if (status) {\n filteredItems = filteredItems.filter((req: any) => {\n const phase = req.status?.phase || 'Pending';\n return phase === status;\n });\n }\n\n res.json({ items: filteredItems });\n } catch (error) {\n console.error('error fetching api key requests:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch api key requests' });\n }\n }\n });\n\n router.get('/requests/my', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestReadOwnPermission }],\n { credentials }\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n // extract userId from authenticated credentials, not from query params\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const namespace = req.query.namespace as string;\n\n let data;\n if (namespace) {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests', namespace);\n } else {\n data = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apikeyrequests');\n }\n\n const filteredItems = (data.items || []).filter(\n (req: any) => req.spec?.requestedBy?.userId === userId\n );\n\n res.json({ items: filteredItems });\n } catch (error) {\n console.error('error fetching user api key requests:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to fetch user api key requests' });\n }\n }\n });\n\n const approveRejectSchema = z.object({\n comment: z.string().optional(),\n });\n\n router.post('/requests/:namespace/:name/approve', async (req, res) => {\n const parsed = approveRejectSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const { comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n\n const spec = request.spec as any;\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${spec.requestedBy.userId}-${spec.apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: spec.apiNamespace,\n labels: {\n app: spec.apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': spec.planTier,\n 'secret.kuadrant.io/user-id': spec.requestedBy.userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(spec.apiNamespace, secret);\n\n // try to get plan limits from apiproduct or planpolicy\n let planLimits: any = null;\n try {\n const products = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n const product = (products.items || []).find((p: any) =>\n p.metadata.name.includes(spec.apiName) || p.spec?.displayName?.toLowerCase().includes(spec.apiName.toLowerCase())\n );\n if (product) {\n const plan = product.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n }\n } catch (e) {\n console.warn('could not fetch apiproduct for plan limits:', e);\n }\n\n if (!planLimits) {\n try {\n const policy = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n spec.apiNamespace,\n 'planpolicies',\n `${spec.apiName}-plan`,\n );\n const plan = policy.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n } catch (e) {\n console.warn('could not fetch planpolicy for plan limits:', e);\n }\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${spec.apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n spec.apiNamespace,\n 'httproutes',\n spec.apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n const status = {\n phase: 'Approved',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'approved',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${spec.apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n status,\n );\n\n res.json({ secretName });\n } catch (error) {\n console.error('error approving api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to approve api key request' });\n }\n }\n });\n\n router.post('/requests/:namespace/:name/reject', async (req, res) => {\n const parsed = approveRejectSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { namespace, name } = req.params;\n const { comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n\n const status = {\n phase: 'Rejected',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'rejected',\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n status,\n );\n\n res.status(204).send();\n } catch (error) {\n console.error('error rejecting api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to reject api key request' });\n }\n }\n });\n\n const bulkApproveSchema = z.object({\n requests: z.array(z.object({\n namespace: z.string(),\n name: z.string(),\n })),\n comment: z.string().optional(),\n });\n\n router.post('/requests/bulk-approve', async (req, res) => {\n const parsed = bulkApproveSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { requests, comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n const results = [];\n\n for (const reqRef of requests) {\n try {\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n );\n\n const spec = request.spec as any;\n const apiKey = generateApiKey();\n const timestamp = Date.now();\n const secretName = `${spec.requestedBy.userId}-${spec.apiName}-${timestamp}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n\n const secret = {\n apiVersion: 'v1',\n kind: 'Secret',\n metadata: {\n name: secretName,\n namespace: spec.apiNamespace,\n labels: {\n app: spec.apiName,\n },\n annotations: {\n 'secret.kuadrant.io/plan-id': spec.planTier,\n 'secret.kuadrant.io/user-id': spec.requestedBy.userId,\n },\n },\n stringData: {\n api_key: apiKey,\n },\n type: 'Opaque',\n };\n\n await k8sClient.createSecret(spec.apiNamespace, secret);\n\n // try to get plan limits from apiproduct or planpolicy\n let planLimits: any = null;\n try {\n const products = await k8sClient.listCustomResources('extensions.kuadrant.io', 'v1alpha1', 'apiproducts');\n const product = (products.items || []).find((p: any) =>\n p.metadata.name.includes(spec.apiName) || p.spec?.displayName?.toLowerCase().includes(spec.apiName.toLowerCase())\n );\n if (product) {\n const plan = product.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n }\n } catch (e) {\n console.warn('could not fetch apiproduct for plan limits:', e);\n }\n\n if (!planLimits) {\n try {\n const policy = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n spec.apiNamespace,\n 'planpolicies',\n `${spec.apiName}-plan`,\n );\n const plan = policy.spec?.plans?.find((p: any) => p.tier === spec.planTier);\n if (plan) {\n planLimits = plan.limits;\n }\n } catch (e) {\n console.warn('could not fetch planpolicy for plan limits:', e);\n }\n }\n\n // fetch httproute to get hostname\n let apiHostname = `${spec.apiName}.apps.example.com`;\n try {\n const httproute = await k8sClient.getCustomResource(\n 'gateway.networking.k8s.io',\n 'v1',\n spec.apiNamespace,\n 'httproutes',\n spec.apiName,\n );\n if (httproute.spec?.hostnames && httproute.spec.hostnames.length > 0) {\n apiHostname = httproute.spec.hostnames[0];\n }\n } catch (error) {\n console.warn('could not fetch httproute for hostname, using default:', error);\n }\n\n const status = {\n phase: 'Approved',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'approved',\n apiKey,\n apiHostname,\n apiBasePath: '/api/v1',\n apiDescription: `${spec.apiName} api`,\n planLimits,\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n status,\n );\n\n results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true, secretName });\n } catch (error) {\n console.error(`error approving request ${reqRef.namespace}/${reqRef.name}:`, error);\n results.push({\n namespace: reqRef.namespace,\n name: reqRef.name,\n success: false,\n error: error instanceof Error ? error.message : 'unknown error'\n });\n }\n }\n\n res.json({ results });\n } catch (error) {\n console.error('error in bulk approve:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to bulk approve api key requests' });\n }\n }\n });\n\n router.post('/requests/bulk-reject', async (req, res) => {\n const parsed = bulkApproveSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError(parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n\n const decision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials },\n );\n\n if (decision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n const { requests, comment } = parsed.data;\n const reviewedBy = `user:default/${userId}`;\n const results = [];\n\n for (const reqRef of requests) {\n try {\n const status = {\n phase: 'Rejected',\n reviewedBy,\n reviewedAt: new Date().toISOString(),\n reason: comment || 'rejected',\n };\n\n await k8sClient.patchCustomResourceStatus(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n reqRef.namespace,\n 'apikeyrequests',\n reqRef.name,\n status,\n );\n\n results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true });\n } catch (error) {\n console.error(`error rejecting request ${reqRef.namespace}/${reqRef.name}:`, error);\n results.push({\n namespace: reqRef.namespace,\n name: reqRef.name,\n success: false,\n error: error instanceof Error ? error.message : 'unknown error'\n });\n }\n }\n\n res.json({ results });\n } catch (error) {\n console.error('error in bulk reject:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to bulk reject api key requests' });\n }\n }\n });\n\n router.delete('/requests/:namespace/:name', async (req, res) => {\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const { namespace, name } = req.params;\n\n // get request to verify ownership\n const request = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n\n const requestUserId = request.spec?.requestedBy?.userId;\n\n // check if user can delete all requests or just their own\n const deleteAllDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestDeleteAllPermission }],\n { credentials }\n );\n\n const canDeleteAll = deleteAllDecision[0].result === AuthorizeResult.ALLOW;\n\n if (!canDeleteAll) {\n // check if user can delete their own requests\n const deleteOwnDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestDeleteOwnPermission }],\n { credentials }\n );\n\n if (deleteOwnDecision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n // verify ownership\n if (requestUserId !== userId) {\n throw new NotAllowedError('you can only delete your own api key requests');\n }\n }\n\n // if request is approved, find and delete associated secret\n if (request.status?.phase === 'Approved') {\n try {\n const apiNamespace = request.spec?.apiNamespace;\n const apiName = request.spec?.apiName;\n const planTier = request.spec?.planTier;\n\n // list secrets in the api namespace and find the one with matching annotations\n const secrets = await k8sClient.listSecrets(apiNamespace);\n const matchingSecret = secrets.items?.find((s: any) => {\n const annotations = s.metadata?.annotations || {};\n return (\n annotations['secret.kuadrant.io/user-id'] === requestUserId &&\n annotations['secret.kuadrant.io/plan-id'] === planTier &&\n s.metadata?.labels?.app === apiName\n );\n });\n\n if (matchingSecret) {\n await k8sClient.deleteSecret(apiNamespace, matchingSecret.metadata.name);\n }\n } catch (error) {\n console.warn('failed to delete associated secret:', error);\n // continue with request deletion even if secret deletion fails\n }\n }\n\n await k8sClient.deleteCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n res.status(204).send();\n } catch (error) {\n console.error('error deleting api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to delete api key request' });\n }\n }\n });\n\n router.patch('/requests/:namespace/:name', async (req, res) => {\n // whitelist allowed fields for patching\n const patchSchema = z.object({\n spec: z.object({\n useCase: z.string().optional(),\n }).partial(),\n });\n\n const parsed = patchSchema.safeParse(req.body);\n if (!parsed.success) {\n throw new InputError('invalid patch: ' + parsed.error.toString());\n }\n\n try {\n const credentials = await httpAuth.credentials(req);\n const { userId } = await getUserIdentity(req, httpAuth, userInfo);\n const { namespace, name } = req.params;\n\n // get existing request to check ownership\n const existing = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n );\n\n // check if user can update all requests or just their own\n const updateAllDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdatePermission }],\n { credentials }\n );\n\n if (updateAllDecision[0].result !== AuthorizeResult.ALLOW) {\n // check if user can update their own requests\n const updateOwnDecision = await permissions.authorize(\n [{ permission: kuadrantApiKeyRequestUpdateOwnPermission }],\n { credentials }\n );\n\n if (updateOwnDecision[0].result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('unauthorised');\n }\n\n // verify ownership\n if (existing.spec?.requestedBy?.userId !== userId) {\n throw new NotAllowedError('you can only update your own api key requests');\n }\n }\n\n // apply validated patch\n const updated = await k8sClient.patchCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apikeyrequests',\n name,\n parsed.data,\n );\n\n res.json(updated);\n } catch (error) {\n console.error('error updating api key request:', error);\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else if (error instanceof InputError) {\n res.status(400).json({ error: error.message });\n } else {\n res.status(500).json({ error: 'failed to update api key request' });\n }\n }\n });\n\n // expose permissions for backstage permission framework\n router.use(createPermissionIntegrationRouter({\n permissions: kuadrantPermissions,\n }));\n\n return router;\n}\n"],"names":["randomBytes","NotAllowedError","permissions","Router","cors","express","k8sClient","KuadrantK8sClient","kuadrantApiProductListPermission","AuthorizeResult","kuadrantApiProductReadPermission","kuadrantApiProductCreatePermission","InputError","getAPIProductEntityProvider","kuadrantApiProductDeletePermission","z","kuadrantApiProductUpdatePermission","kuadrantPlanPolicyListPermission","kuadrantPlanPolicyReadPermission","kuadrantApiKeyRequestCreatePermission","timestamp","kuadrantApiKeyRequestListPermission","req","kuadrantApiKeyRequestReadOwnPermission","kuadrantApiKeyRequestUpdatePermission","kuadrantApiKeyRequestDeleteAllPermission","kuadrantApiKeyRequestDeleteOwnPermission","kuadrantApiKeyRequestUpdateOwnPermission","createPermissionIntegrationRouter","kuadrantPermissions"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuadrant/kuadrant-backstage-plugin-backend",
|
|
3
|
-
"version": "0.0.1-test.1-
|
|
3
|
+
"version": "0.0.1-test.1-48246e3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,19 +19,38 @@
|
|
|
19
19
|
"pluginId": "kuadrant",
|
|
20
20
|
"pluginPackages": [
|
|
21
21
|
"@kuadrant/kuadrant-backstage-plugin-backend"
|
|
22
|
-
]
|
|
22
|
+
],
|
|
23
|
+
"features": {
|
|
24
|
+
".": "@backstage/BackendFeature",
|
|
25
|
+
"./alpha": "@backstage/BackendFeature",
|
|
26
|
+
"./rbac": "@backstage/BackendFeature"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"scalprum": {
|
|
30
|
+
"name": "internal.plugin-kuadrant-backend",
|
|
31
|
+
"exposedModules": {
|
|
32
|
+
"PluginRoot": "./src/index.ts",
|
|
33
|
+
"KuadrantAlpha": "./src/module.ts",
|
|
34
|
+
"KuadrantRBAC": "./src/rbac-module.ts"
|
|
35
|
+
}
|
|
23
36
|
},
|
|
24
37
|
"exports": {
|
|
25
38
|
".": {
|
|
39
|
+
"backstage": "@backstage/BackendFeature",
|
|
26
40
|
"require": "./dist/index.cjs.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
27
42
|
"default": "./dist/index.cjs.js"
|
|
28
43
|
},
|
|
29
44
|
"./alpha": {
|
|
45
|
+
"backstage": "@backstage/BackendFeature",
|
|
30
46
|
"require": "./dist/alpha.cjs.js",
|
|
47
|
+
"types": "./dist/alpha.d.ts",
|
|
31
48
|
"default": "./dist/alpha.cjs.js"
|
|
32
49
|
},
|
|
33
50
|
"./rbac": {
|
|
51
|
+
"backstage": "@backstage/BackendFeature",
|
|
34
52
|
"require": "./dist/rbac.cjs.js",
|
|
53
|
+
"types": "./dist/rbac.d.ts",
|
|
35
54
|
"default": "./dist/rbac.cjs.js"
|
|
36
55
|
},
|
|
37
56
|
"./package.json": "./package.json"
|
|
@@ -44,7 +63,9 @@
|
|
|
44
63
|
"clean": "backstage-cli package clean",
|
|
45
64
|
"prepack": "backstage-cli package prepack",
|
|
46
65
|
"postpack": "backstage-cli package postpack",
|
|
47
|
-
"tsc": "tsc"
|
|
66
|
+
"tsc": "tsc",
|
|
67
|
+
"export-dynamic": "janus-cli package export-dynamic-plugin --in-place",
|
|
68
|
+
"export-dynamic:clean": "run export-dynamic --clean"
|
|
48
69
|
},
|
|
49
70
|
"dependencies": {
|
|
50
71
|
"@backstage/backend-defaults": "^0.12.1",
|
|
@@ -65,6 +86,7 @@
|
|
|
65
86
|
"devDependencies": {
|
|
66
87
|
"@backstage/backend-test-utils": "^1.9.0",
|
|
67
88
|
"@backstage/cli": "^0.34.2",
|
|
89
|
+
"@janus-idp/cli": "^1.13.0",
|
|
68
90
|
"@types/express": "^4.17.6",
|
|
69
91
|
"@types/supertest": "^2.0.12",
|
|
70
92
|
"supertest": "^6.2.4",
|
|
@@ -73,6 +95,20 @@
|
|
|
73
95
|
"files": [
|
|
74
96
|
"dist",
|
|
75
97
|
"alpha",
|
|
76
|
-
"rbac"
|
|
77
|
-
|
|
98
|
+
"rbac",
|
|
99
|
+
"dist-dynamic"
|
|
100
|
+
],
|
|
101
|
+
"typesVersions": {
|
|
102
|
+
"*": {
|
|
103
|
+
"alpha": [
|
|
104
|
+
"dist/alpha.d.ts"
|
|
105
|
+
],
|
|
106
|
+
"rbac": [
|
|
107
|
+
"dist/rbac.d.ts"
|
|
108
|
+
],
|
|
109
|
+
"package.json": [
|
|
110
|
+
"package.json"
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
78
114
|
}
|