@kuadrant/kuadrant-backstage-plugin-backend 0.0.1-test.1-d62c1cdb → 0.0.1-test.1-57ace816
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.cjs.js +6 -0
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/k8s-client.cjs.js +9 -1
- package/dist/k8s-client.cjs.js.map +1 -1
- package/dist/providers/APIProductEntityProvider.cjs.js.map +1 -1
- package/dist/router.cjs.js +92 -15
- package/dist/router.cjs.js.map +1 -1
- package/package.json +1 -1
package/dist/alpha.cjs.js
CHANGED
|
@@ -6,6 +6,10 @@ var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
|
6
6
|
var alpha = require('@backstage/plugin-catalog-node/alpha');
|
|
7
7
|
var APIProductEntityProvider = require('./providers/APIProductEntityProvider.cjs.js');
|
|
8
8
|
|
|
9
|
+
let apiProductProviderInstance = null;
|
|
10
|
+
function getAPIProductEntityProvider() {
|
|
11
|
+
return apiProductProviderInstance;
|
|
12
|
+
}
|
|
9
13
|
const catalogModuleApiProductEntityProvider = backendPluginApi.createBackendModule({
|
|
10
14
|
pluginId: "catalog",
|
|
11
15
|
moduleId: "kuadrant-apiproduct-provider",
|
|
@@ -19,6 +23,7 @@ const catalogModuleApiProductEntityProvider = backendPluginApi.createBackendModu
|
|
|
19
23
|
async init({ catalog, config, logger }) {
|
|
20
24
|
logger.info("registering kuadrant apiproduct entity provider");
|
|
21
25
|
const provider = new APIProductEntityProvider.APIProductEntityProvider(config);
|
|
26
|
+
apiProductProviderInstance = provider;
|
|
22
27
|
catalog.addEntityProvider(provider);
|
|
23
28
|
logger.info("apiproduct entity provider registered successfully");
|
|
24
29
|
}
|
|
@@ -28,4 +33,5 @@ const catalogModuleApiProductEntityProvider = backendPluginApi.createBackendModu
|
|
|
28
33
|
|
|
29
34
|
exports.catalogModuleApiProductEntityProvider = catalogModuleApiProductEntityProvider;
|
|
30
35
|
exports.default = catalogModuleApiProductEntityProvider;
|
|
36
|
+
exports.getAPIProductEntityProvider = getAPIProductEntityProvider;
|
|
31
37
|
//# sourceMappingURL=alpha.cjs.js.map
|
package/dist/alpha.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.cjs.js","sources":["../src/module.ts"],"sourcesContent":["import {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\nimport { APIProductEntityProvider } from './providers/APIProductEntityProvider';\n\n/**\n * backend module for apiproduct entity provider\n * @public\n */\nexport const catalogModuleApiProductEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'kuadrant-apiproduct-provider',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n },\n async init({ catalog, config, logger }) {\n logger.info('registering kuadrant apiproduct entity provider');\n const provider = new APIProductEntityProvider(config);\n catalog.addEntityProvider(provider);\n logger.info('apiproduct entity provider registered successfully');\n },\n });\n },\n});\n\nexport default catalogModuleApiProductEntityProvider;\n\n"],"names":["createBackendModule","catalogProcessingExtensionPoint","coreServices","APIProductEntityProvider"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/module.ts"],"sourcesContent":["import {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\nimport { APIProductEntityProvider } from './providers/APIProductEntityProvider';\n\n// singleton instance for sharing provider between module and router\nlet apiProductProviderInstance: APIProductEntityProvider | null = null;\n\n/**\n * get the apiproduct entity provider instance\n * @public\n */\nexport function getAPIProductEntityProvider(): APIProductEntityProvider | null {\n return apiProductProviderInstance;\n}\n\n/**\n * backend module for apiproduct entity provider\n * @public\n */\nexport const catalogModuleApiProductEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'kuadrant-apiproduct-provider',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n },\n async init({ catalog, config, logger }) {\n logger.info('registering kuadrant apiproduct entity provider');\n const provider = new APIProductEntityProvider(config);\n apiProductProviderInstance = provider;\n catalog.addEntityProvider(provider);\n logger.info('apiproduct entity provider registered successfully');\n },\n });\n },\n});\n\nexport default catalogModuleApiProductEntityProvider;\n\n"],"names":["createBackendModule","catalogProcessingExtensionPoint","coreServices","APIProductEntityProvider"],"mappings":";;;;;;;;AAQA,IAAI,0BAA8D,GAAA,IAAA;AAM3D,SAAS,2BAA+D,GAAA;AAC7E,EAAO,OAAA,0BAAA;AACT;AAMO,MAAM,wCAAwCA,oCAAoB,CAAA;AAAA,EACvE,QAAU,EAAA,SAAA;AAAA,EACV,QAAU,EAAA,8BAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,OAAS,EAAAC,qCAAA;AAAA,QACT,QAAQC,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA;AAAA,OACvB;AAAA,MACA,MAAM,IAAK,CAAA,EAAE,OAAS,EAAA,MAAA,EAAQ,QAAU,EAAA;AACtC,QAAA,MAAA,CAAO,KAAK,iDAAiD,CAAA;AAC7D,QAAM,MAAA,QAAA,GAAW,IAAIC,iDAAA,CAAyB,MAAM,CAAA;AACpD,QAA6B,0BAAA,GAAA,QAAA;AAC7B,QAAA,OAAA,CAAQ,kBAAkB,QAAQ,CAAA;AAClC,QAAA,MAAA,CAAO,KAAK,oDAAoD,CAAA;AAAA;AAClE,KACD,CAAA;AAAA;AAEL,CAAC;;;;;;"}
|
package/dist/k8s-client.cjs.js
CHANGED
|
@@ -236,7 +236,15 @@ class KuadrantK8sClient {
|
|
|
236
236
|
namespace,
|
|
237
237
|
plural,
|
|
238
238
|
name,
|
|
239
|
-
patch
|
|
239
|
+
patch,
|
|
240
|
+
void 0,
|
|
241
|
+
void 0,
|
|
242
|
+
void 0,
|
|
243
|
+
{
|
|
244
|
+
headers: {
|
|
245
|
+
"Content-Type": "application/merge-patch+json"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
240
248
|
);
|
|
241
249
|
return response.body;
|
|
242
250
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k8s-client.cjs.js","sources":["../src/k8s-client.ts"],"sourcesContent":["import * as k8s from '@kubernetes/client-node';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\n\nexport interface K8sResource {\n apiVersion: string;\n kind: string;\n metadata: {\n name: string;\n namespace?: string;\n creationTimestamp?: string;\n labels?: Record<string, string>;\n annotations?: Record<string, string>;\n [key: string]: any;\n };\n spec?: any;\n status?: any;\n data?: any;\n stringData?: any;\n [key: string]: any;\n}\n\nexport interface K8sList {\n items: K8sResource[];\n}\n\nexport class KuadrantK8sClient {\n private kc: k8s.KubeConfig;\n private customApi: k8s.CustomObjectsApi;\n private coreApi: k8s.CoreV1Api;\n\n constructor(config: RootConfigService) {\n this.kc = new k8s.KubeConfig();\n\n const hasK8sConfig = config.has('kubernetes');\n\n if (hasK8sConfig) {\n const clusterLocatorMethods = config.getOptionalConfigArray('kubernetes.clusterLocatorMethods') || [];\n\n // look for type: config with explicit cluster configuration\n const configLocator = clusterLocatorMethods.find(c => c.getString('type') === 'config');\n\n if (configLocator) {\n const clusters = configLocator.getOptionalConfigArray('clusters') || [];\n\n if (clusters.length > 0) {\n // use the first cluster config\n const clusterConfig = clusters[0];\n const clusterName = clusterConfig.getString('name');\n const clusterUrl = clusterConfig.getString('url');\n const authProvider = clusterConfig.getOptionalString('authProvider');\n const skipTLSVerify = clusterConfig.getOptionalBoolean('skipTLSVerify') || false;\n\n if (authProvider === 'serviceAccount') {\n const serviceAccountToken = clusterConfig.getString('serviceAccountToken');\n\n // configure kubeconfig manually with service account\n const cluster = {\n name: clusterName,\n server: clusterUrl,\n skipTLSVerify: skipTLSVerify,\n };\n\n const user = {\n name: `${clusterName}-service-account`,\n token: serviceAccountToken,\n };\n\n const context = {\n name: `${clusterName}-context`,\n cluster: clusterName,\n user: user.name,\n };\n\n this.kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n\n console.log(`k8s client initialised with explicit cluster config`);\n console.log(` cluster: ${clusterName}`);\n console.log(` url: ${clusterUrl}`);\n console.log(` auth: serviceAccount`);\n console.log(` skipTLSVerify: ${skipTLSVerify}`);\n } else {\n // unsupported auth provider, fall back to default\n console.log(`unsupported authProvider: ${authProvider}, falling back to default`);\n this.kc.loadFromDefault();\n }\n } else {\n // no clusters defined, fall back to default\n this.kc.loadFromDefault();\n this.logDefaultConfig('no clusters defined');\n }\n } else {\n // no type: config locator, fall back to default\n this.kc.loadFromDefault();\n this.logDefaultConfig('no config locator found');\n }\n } else {\n // no kubernetes config, use default (in-cluster or local kubeconfig)\n this.kc.loadFromDefault();\n this.logDefaultConfig('no kubernetes config in app-config.yaml');\n }\n\n this.customApi = this.kc.makeApiClient(k8s.CustomObjectsApi);\n this.coreApi = this.kc.makeApiClient(k8s.CoreV1Api);\n }\n\n private logDefaultConfig(reason: string): void {\n console.log(`k8s client initialised using default config (${reason})`);\n\n // determine if running in-cluster or using local kubeconfig\n const inClusterToken = process.env.KUBERNETES_SERVICE_HOST;\n\n if (inClusterToken) {\n console.log(' auth: in-cluster service account');\n console.log(' location: /var/run/secrets/kubernetes.io/serviceaccount/');\n } else {\n const kubeconfig = process.env.KUBECONFIG || '~/.kube/config';\n console.log(' auth: local kubeconfig');\n console.log(` location: ${kubeconfig}`);\n }\n }\n\n async listCustomResources(\n group: string,\n version: string,\n plural: string,\n namespace?: string,\n ): Promise<K8sList> {\n try {\n const response = namespace\n ? await this.customApi.listNamespacedCustomObject(group, version, namespace, plural)\n : await this.customApi.listClusterCustomObject(group, version, plural);\n\n return response.body as K8sList;\n } catch (error: any) {\n throw new Error(`failed to list ${plural}: ${error.message}`);\n }\n }\n\n async getCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.getNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get ${plural}/${name}: ${error.message}`);\n }\n }\n\n async createSecret(namespace: string, secret: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.createNamespacedSecret(namespace, secret as k8s.V1Secret);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to create secret: ${error.message}`);\n }\n }\n\n async listSecrets(namespace: string): Promise<K8sList> {\n try {\n const response = await this.coreApi.listNamespacedSecret(namespace);\n return { items: (response.body.items || []) as unknown as K8sResource[] };\n } catch (error: any) {\n throw new Error(`failed to list secrets: ${error.message}`);\n }\n }\n\n async getSecret(namespace: string, name: string): Promise<K8sResource> {\n try {\n const response = await this.coreApi.readNamespacedSecret(name, namespace);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get secret: ${error.message}`);\n }\n }\n\n async deleteSecret(namespace: string, name: string): Promise<void> {\n try {\n await this.coreApi.deleteNamespacedSecret(name, namespace);\n } catch (error: any) {\n throw new Error(`failed to delete secret: ${error.message}`);\n }\n }\n\n async createConfigMap(namespace: string, configMap: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.createNamespacedConfigMap(namespace, configMap as k8s.V1ConfigMap);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to create configmap: ${error.message}`);\n }\n }\n\n async listConfigMaps(namespace: string, labelSelector?: string): Promise<K8sList> {\n try {\n const response = await this.coreApi.listNamespacedConfigMap(namespace, undefined, undefined, undefined, undefined, labelSelector);\n return { items: (response.body.items || []) as unknown as K8sResource[] };\n } catch (error: any) {\n throw new Error(`failed to list configmaps: ${error.message}`);\n }\n }\n\n async getConfigMap(namespace: string, name: string): Promise<K8sResource> {\n try {\n const response = await this.coreApi.readNamespacedConfigMap(name, namespace);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get configmap: ${error.message}`);\n }\n }\n\n async updateConfigMap(namespace: string, name: string, configMap: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.replaceNamespacedConfigMap(name, namespace, configMap as k8s.V1ConfigMap);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to update configmap: ${error.message}`);\n }\n }\n\n async deleteConfigMap(namespace: string, name: string): Promise<void> {\n try {\n await this.coreApi.deleteNamespacedConfigMap(name, namespace);\n } catch (error: any) {\n throw new Error(`failed to delete configmap: ${error.message}`);\n }\n }\n\n async createCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n resource: K8sResource,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.createNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n resource as any,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n // extract detailed error from kubernetes api response\n const statusCode = error.response?.statusCode || error.statusCode;\n const body = error.response?.body || error.body;\n const message = body?.message || error.message;\n const reason = body?.reason;\n const details = body?.details;\n\n console.error(`failed to create ${plural}:`, {\n statusCode,\n message,\n reason,\n details: JSON.stringify(details),\n });\n\n throw new Error(`failed to create ${plural}: ${message}${reason ? ` (${reason})` : ''}`);\n }\n }\n\n async deleteCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n ): Promise<void> {\n try {\n await this.customApi.deleteNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n );\n } catch (error: any) {\n throw new Error(`failed to delete ${plural}/${name}: ${error.message}`);\n }\n }\n\n async patchCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n patch: any,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.patchNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n patch,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to patch ${plural}/${name}: ${error.message}`);\n }\n }\n\n async patchCustomResourceStatus(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n status: any,\n ): Promise<K8sResource> {\n try {\n // get the existing resource first\n const existing = await this.getCustomResource(group, version, namespace, plural, name);\n\n // replace the entire resource with updated status\n const updated = {\n ...existing,\n status,\n };\n\n const response = await this.customApi.replaceNamespacedCustomObjectStatus(\n group,\n version,\n namespace,\n plural,\n name,\n updated,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to patch ${plural}/${name} status: ${error.message}`);\n }\n }\n}\n\n"],"names":["k8s"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"k8s-client.cjs.js","sources":["../src/k8s-client.ts"],"sourcesContent":["import * as k8s from '@kubernetes/client-node';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\n\nexport interface K8sResource {\n apiVersion: string;\n kind: string;\n metadata: {\n name: string;\n namespace?: string;\n creationTimestamp?: string;\n labels?: Record<string, string>;\n annotations?: Record<string, string>;\n [key: string]: any;\n };\n spec?: any;\n status?: any;\n data?: any;\n stringData?: any;\n [key: string]: any;\n}\n\nexport interface K8sList {\n items: K8sResource[];\n}\n\nexport class KuadrantK8sClient {\n private kc: k8s.KubeConfig;\n private customApi: k8s.CustomObjectsApi;\n private coreApi: k8s.CoreV1Api;\n\n constructor(config: RootConfigService) {\n this.kc = new k8s.KubeConfig();\n\n const hasK8sConfig = config.has('kubernetes');\n\n if (hasK8sConfig) {\n const clusterLocatorMethods = config.getOptionalConfigArray('kubernetes.clusterLocatorMethods') || [];\n\n // look for type: config with explicit cluster configuration\n const configLocator = clusterLocatorMethods.find(c => c.getString('type') === 'config');\n\n if (configLocator) {\n const clusters = configLocator.getOptionalConfigArray('clusters') || [];\n\n if (clusters.length > 0) {\n // use the first cluster config\n const clusterConfig = clusters[0];\n const clusterName = clusterConfig.getString('name');\n const clusterUrl = clusterConfig.getString('url');\n const authProvider = clusterConfig.getOptionalString('authProvider');\n const skipTLSVerify = clusterConfig.getOptionalBoolean('skipTLSVerify') || false;\n\n if (authProvider === 'serviceAccount') {\n const serviceAccountToken = clusterConfig.getString('serviceAccountToken');\n\n // configure kubeconfig manually with service account\n const cluster = {\n name: clusterName,\n server: clusterUrl,\n skipTLSVerify: skipTLSVerify,\n };\n\n const user = {\n name: `${clusterName}-service-account`,\n token: serviceAccountToken,\n };\n\n const context = {\n name: `${clusterName}-context`,\n cluster: clusterName,\n user: user.name,\n };\n\n this.kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n\n console.log(`k8s client initialised with explicit cluster config`);\n console.log(` cluster: ${clusterName}`);\n console.log(` url: ${clusterUrl}`);\n console.log(` auth: serviceAccount`);\n console.log(` skipTLSVerify: ${skipTLSVerify}`);\n } else {\n // unsupported auth provider, fall back to default\n console.log(`unsupported authProvider: ${authProvider}, falling back to default`);\n this.kc.loadFromDefault();\n }\n } else {\n // no clusters defined, fall back to default\n this.kc.loadFromDefault();\n this.logDefaultConfig('no clusters defined');\n }\n } else {\n // no type: config locator, fall back to default\n this.kc.loadFromDefault();\n this.logDefaultConfig('no config locator found');\n }\n } else {\n // no kubernetes config, use default (in-cluster or local kubeconfig)\n this.kc.loadFromDefault();\n this.logDefaultConfig('no kubernetes config in app-config.yaml');\n }\n\n this.customApi = this.kc.makeApiClient(k8s.CustomObjectsApi);\n this.coreApi = this.kc.makeApiClient(k8s.CoreV1Api);\n }\n\n private logDefaultConfig(reason: string): void {\n console.log(`k8s client initialised using default config (${reason})`);\n\n // determine if running in-cluster or using local kubeconfig\n const inClusterToken = process.env.KUBERNETES_SERVICE_HOST;\n\n if (inClusterToken) {\n console.log(' auth: in-cluster service account');\n console.log(' location: /var/run/secrets/kubernetes.io/serviceaccount/');\n } else {\n const kubeconfig = process.env.KUBECONFIG || '~/.kube/config';\n console.log(' auth: local kubeconfig');\n console.log(` location: ${kubeconfig}`);\n }\n }\n\n async listCustomResources(\n group: string,\n version: string,\n plural: string,\n namespace?: string,\n ): Promise<K8sList> {\n try {\n const response = namespace\n ? await this.customApi.listNamespacedCustomObject(group, version, namespace, plural)\n : await this.customApi.listClusterCustomObject(group, version, plural);\n\n return response.body as K8sList;\n } catch (error: any) {\n throw new Error(`failed to list ${plural}: ${error.message}`);\n }\n }\n\n async getCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.getNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get ${plural}/${name}: ${error.message}`);\n }\n }\n\n async createSecret(namespace: string, secret: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.createNamespacedSecret(namespace, secret as k8s.V1Secret);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to create secret: ${error.message}`);\n }\n }\n\n async listSecrets(namespace: string): Promise<K8sList> {\n try {\n const response = await this.coreApi.listNamespacedSecret(namespace);\n return { items: (response.body.items || []) as unknown as K8sResource[] };\n } catch (error: any) {\n throw new Error(`failed to list secrets: ${error.message}`);\n }\n }\n\n async getSecret(namespace: string, name: string): Promise<K8sResource> {\n try {\n const response = await this.coreApi.readNamespacedSecret(name, namespace);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get secret: ${error.message}`);\n }\n }\n\n async deleteSecret(namespace: string, name: string): Promise<void> {\n try {\n await this.coreApi.deleteNamespacedSecret(name, namespace);\n } catch (error: any) {\n throw new Error(`failed to delete secret: ${error.message}`);\n }\n }\n\n async createConfigMap(namespace: string, configMap: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.createNamespacedConfigMap(namespace, configMap as k8s.V1ConfigMap);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to create configmap: ${error.message}`);\n }\n }\n\n async listConfigMaps(namespace: string, labelSelector?: string): Promise<K8sList> {\n try {\n const response = await this.coreApi.listNamespacedConfigMap(namespace, undefined, undefined, undefined, undefined, labelSelector);\n return { items: (response.body.items || []) as unknown as K8sResource[] };\n } catch (error: any) {\n throw new Error(`failed to list configmaps: ${error.message}`);\n }\n }\n\n async getConfigMap(namespace: string, name: string): Promise<K8sResource> {\n try {\n const response = await this.coreApi.readNamespacedConfigMap(name, namespace);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to get configmap: ${error.message}`);\n }\n }\n\n async updateConfigMap(namespace: string, name: string, configMap: K8sResource): Promise<K8sResource> {\n try {\n const response = await this.coreApi.replaceNamespacedConfigMap(name, namespace, configMap as k8s.V1ConfigMap);\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to update configmap: ${error.message}`);\n }\n }\n\n async deleteConfigMap(namespace: string, name: string): Promise<void> {\n try {\n await this.coreApi.deleteNamespacedConfigMap(name, namespace);\n } catch (error: any) {\n throw new Error(`failed to delete configmap: ${error.message}`);\n }\n }\n\n async createCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n resource: K8sResource,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.createNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n resource as any,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n // extract detailed error from kubernetes api response\n const statusCode = error.response?.statusCode || error.statusCode;\n const body = error.response?.body || error.body;\n const message = body?.message || error.message;\n const reason = body?.reason;\n const details = body?.details;\n\n console.error(`failed to create ${plural}:`, {\n statusCode,\n message,\n reason,\n details: JSON.stringify(details),\n });\n\n throw new Error(`failed to create ${plural}: ${message}${reason ? ` (${reason})` : ''}`);\n }\n }\n\n async deleteCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n ): Promise<void> {\n try {\n await this.customApi.deleteNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n );\n } catch (error: any) {\n throw new Error(`failed to delete ${plural}/${name}: ${error.message}`);\n }\n }\n\n async patchCustomResource(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n patch: any,\n ): Promise<K8sResource> {\n try {\n const response = await this.customApi.patchNamespacedCustomObject(\n group,\n version,\n namespace,\n plural,\n name,\n patch,\n undefined,\n undefined,\n undefined,\n {\n headers: {\n 'Content-Type': 'application/merge-patch+json',\n },\n }\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to patch ${plural}/${name}: ${error.message}`);\n }\n }\n\n async patchCustomResourceStatus(\n group: string,\n version: string,\n namespace: string,\n plural: string,\n name: string,\n status: any,\n ): Promise<K8sResource> {\n try {\n // get the existing resource first\n const existing = await this.getCustomResource(group, version, namespace, plural, name);\n\n // replace the entire resource with updated status\n const updated = {\n ...existing,\n status,\n };\n\n const response = await this.customApi.replaceNamespacedCustomObjectStatus(\n group,\n version,\n namespace,\n plural,\n name,\n updated,\n );\n return response.body as K8sResource;\n } catch (error: any) {\n throw new Error(`failed to patch ${plural}/${name} status: ${error.message}`);\n }\n }\n}\n\n"],"names":["k8s"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"APIProductEntityProvider.cjs.js","sources":["../../src/providers/APIProductEntityProvider.ts"],"sourcesContent":["import { ApiEntity } from '@backstage/catalog-model';\nimport { EntityProvider, EntityProviderConnection } from '@backstage/plugin-catalog-node';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\nimport { KuadrantK8sClient } from '../k8s-client';\n\ninterface APIProduct {\n apiVersion: string;\n kind: string;\n metadata: {\n name: string;\n namespace: string;\n uid: string;\n resourceVersion: string;\n creationTimestamp: string;\n annotations?: Record<string, string>;\n labels?: Record<string, string>;\n };\n spec: {\n displayName?: string;\n description?: string;\n version?: string;\n tags?: string[];\n publishStatus?: 'Draft' | 'Published';\n plans?: Array<{\n tier: string;\n description?: string;\n limits?: any;\n }>;\n planPolicyRef?: {\n name: string;\n namespace: string;\n };\n documentation?: {\n openAPISpec?: string;\n docsURL?: string;\n gitRepository?: string;\n techdocsRef?: string;\n };\n contact?: {\n team?: string;\n email?: string;\n slack?: string;\n };\n };\n}\n\nexport class APIProductEntityProvider implements EntityProvider {\n private readonly k8sClient: KuadrantK8sClient;\n private connection?: EntityProviderConnection;\n private readonly providerId = 'kuadrant-apiproduct-provider';\n\n constructor(config: RootConfigService) {\n console.log('apiproduct provider: constructor called');\n this.k8sClient = new KuadrantK8sClient(config);\n }\n\n getProviderName(): string {\n return this.providerId;\n }\n\n async connect(connection: EntityProviderConnection): Promise<void> {\n console.log('apiproduct provider: connect called');\n this.connection = connection;\n\n console.log('apiproduct provider: starting initial sync');\n // initial full sync\n await this.refresh();\n\n // schedule periodic refresh (every 30 seconds for development)\n // note: in production, consider 5-10 minutes to reduce api load\n console.log('apiproduct provider: scheduling periodic refresh every 30 seconds');\n setInterval(async () => {\n await this.refresh();\n }, 30 * 1000);\n }\n\n private async refresh(): Promise<void> {\n console.log('apiproduct provider: refresh called');\n if (!this.connection) {\n console.log('apiproduct provider: no connection, skipping refresh');\n return;\n }\n\n try {\n console.log('apiproduct provider: fetching apiproducts from kubernetes');\n // fetch all apiproducts from kubernetes\n const response = await this.k8sClient.listCustomResources(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n 'apiproducts'\n );\n\n const apiProducts = (response.items || []) as APIProduct[];\n console.log(`apiproduct provider: found ${apiProducts.length} apiproducts`);\n\n // filter out Draft API products - only include Published ones\n const publishedProducts = apiProducts.filter(product => {\n const publishStatus = product.spec.publishStatus || 'Draft'; // default to Draft if not specified\n return publishStatus === 'Published';\n });\n console.log(`apiproduct provider: filtered to ${publishedProducts.length} published apiproducts (${apiProducts.length - publishedProducts.length} drafts excluded)`);\n\n // transform apiproducts to backstage api entities\n const entities = publishedProducts.map(product => this.transformToEntity(product));\n console.log(`apiproduct provider: transformed ${entities.length} entities`);\n\n // submit entities to catalog\n console.log('apiproduct provider: submitting entities to catalog');\n await this.connection.applyMutation({\n type: 'full',\n entities: entities.map(entity => ({\n entity,\n locationKey: `kuadrant-apiproduct:${entity.metadata.namespace}/${entity.metadata.name}`,\n })),\n });\n\n console.log(`apiproduct provider: synced ${entities.length} api products`);\n } catch (error) {\n console.error('error refreshing apiproduct entities:', error);\n }\n }\n\n private transformToEntity(product: APIProduct): ApiEntity {\n const namespace = product.metadata.namespace || 'default';\n const name = product.metadata.name;\n const displayName = product.spec.displayName || name;\n const description = product.spec.description || `api product: ${displayName}`;\n\n // determine lifecycle from labels or default to production\n const lifecycle = product.metadata.labels?.lifecycle || 'production';\n\n // determine owner from contact info or default to guests\n const owner = product.spec.contact?.team || 'guests';\n\n // build tags from product tags\n const tags = product.spec.tags || [];\n\n // create entity with proper backstage structure\n const entity: ApiEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'API',\n metadata: {\n name: `${name}`,\n namespace: 'default',\n title: displayName,\n description,\n annotations: {\n 'backstage.io/managed-by-location': `kuadrant:${namespace}/${name}`,\n 'backstage.io/managed-by-origin-location': `kuadrant:${namespace}/${name}`,\n 'backstage.io/orphan-strategy': 'keep',\n 'kuadrant.io/namespace': namespace,\n 'kuadrant.io/apiproduct': name,\n // add httproute annotation if we can infer it (usually same as apiproduct name without -api suffix)\n 'kuadrant.io/httproute': name.endsWith('-api') ? name.slice(0, -4) : name,\n ...(product.spec.documentation?.openAPISpec && {\n 'kuadrant.io/openapi-spec-url': product.spec.documentation.openAPISpec,\n }),\n ...(product.spec.documentation?.docsURL && {\n 'kuadrant.io/docs-url': product.spec.documentation.docsURL,\n }),\n ...(product.spec.documentation?.gitRepository && {\n 'backstage.io/source-location': `url:${product.spec.documentation.gitRepository}`,\n }),\n ...(product.spec.documentation?.techdocsRef && {\n 'backstage.io/techdocs-ref': product.spec.documentation.techdocsRef,\n }),\n ...(product.spec.contact?.email && {\n 'kuadrant.io/contact-email': product.spec.contact.email,\n }),\n ...(product.spec.contact?.slack && {\n 'kuadrant.io/contact-slack': product.spec.contact.slack,\n }),\n },\n tags: [...tags, 'kuadrant', 'apiproduct'],\n labels: {\n 'kuadrant.io/synced': 'true',\n ...(product.metadata.labels || {}),\n },\n },\n spec: {\n type: 'openapi',\n lifecycle,\n owner,\n definition: product.spec.documentation?.openAPISpec\n ? `# openapi spec available at: ${product.spec.documentation.openAPISpec}\\n\\nopenapi: 3.0.0\\ninfo:\\n title: ${displayName}\\n version: ${product.spec.version || '1.0.0'}\\n description: ${description}\\n`\n : `# no openapi spec configured\\n\\nopenapi: 3.0.0\\ninfo:\\n title: ${displayName}\\n version: ${product.spec.version || '1.0.0'}\\n description: ${description}\\n`,\n },\n };\n\n return entity;\n }\n}\n"],"names":["KuadrantK8sClient"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"APIProductEntityProvider.cjs.js","sources":["../../src/providers/APIProductEntityProvider.ts"],"sourcesContent":["import { ApiEntity } from '@backstage/catalog-model';\nimport { EntityProvider, EntityProviderConnection } from '@backstage/plugin-catalog-node';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\nimport { KuadrantK8sClient } from '../k8s-client';\n\ninterface APIProduct {\n apiVersion: string;\n kind: string;\n metadata: {\n name: string;\n namespace: string;\n uid: string;\n resourceVersion: string;\n creationTimestamp: string;\n annotations?: Record<string, string>;\n labels?: Record<string, string>;\n };\n spec: {\n displayName?: string;\n description?: string;\n version?: string;\n tags?: string[];\n publishStatus?: 'Draft' | 'Published';\n plans?: Array<{\n tier: string;\n description?: string;\n limits?: any;\n }>;\n planPolicyRef?: {\n name: string;\n namespace: string;\n };\n documentation?: {\n openAPISpec?: string;\n docsURL?: string;\n gitRepository?: string;\n techdocsRef?: string;\n };\n contact?: {\n team?: string;\n email?: string;\n slack?: string;\n };\n };\n}\n\nexport class APIProductEntityProvider implements EntityProvider {\n private readonly k8sClient: KuadrantK8sClient;\n private connection?: EntityProviderConnection;\n private readonly providerId = 'kuadrant-apiproduct-provider';\n\n constructor(config: RootConfigService) {\n console.log('apiproduct provider: constructor called');\n this.k8sClient = new KuadrantK8sClient(config);\n }\n\n getProviderName(): string {\n return this.providerId;\n }\n\n async connect(connection: EntityProviderConnection): Promise<void> {\n console.log('apiproduct provider: connect called');\n this.connection = connection;\n\n console.log('apiproduct provider: starting initial sync');\n // initial full sync\n await this.refresh();\n\n // schedule periodic refresh (every 30 seconds for development)\n // note: in production, consider 5-10 minutes to reduce api load\n console.log('apiproduct provider: scheduling periodic refresh every 30 seconds');\n setInterval(async () => {\n await this.refresh();\n }, 30 * 1000);\n }\n\n public async refresh(): Promise<void> {\n console.log('apiproduct provider: refresh called');\n if (!this.connection) {\n console.log('apiproduct provider: no connection, skipping refresh');\n return;\n }\n\n try {\n console.log('apiproduct provider: fetching apiproducts from kubernetes');\n // fetch all apiproducts from kubernetes\n const response = await this.k8sClient.listCustomResources(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n 'apiproducts'\n );\n\n const apiProducts = (response.items || []) as APIProduct[];\n console.log(`apiproduct provider: found ${apiProducts.length} apiproducts`);\n\n // filter out Draft API products - only include Published ones\n const publishedProducts = apiProducts.filter(product => {\n const publishStatus = product.spec.publishStatus || 'Draft'; // default to Draft if not specified\n return publishStatus === 'Published';\n });\n console.log(`apiproduct provider: filtered to ${publishedProducts.length} published apiproducts (${apiProducts.length - publishedProducts.length} drafts excluded)`);\n\n // transform apiproducts to backstage api entities\n const entities = publishedProducts.map(product => this.transformToEntity(product));\n console.log(`apiproduct provider: transformed ${entities.length} entities`);\n\n // submit entities to catalog\n console.log('apiproduct provider: submitting entities to catalog');\n await this.connection.applyMutation({\n type: 'full',\n entities: entities.map(entity => ({\n entity,\n locationKey: `kuadrant-apiproduct:${entity.metadata.namespace}/${entity.metadata.name}`,\n })),\n });\n\n console.log(`apiproduct provider: synced ${entities.length} api products`);\n } catch (error) {\n console.error('error refreshing apiproduct entities:', error);\n }\n }\n\n private transformToEntity(product: APIProduct): ApiEntity {\n const namespace = product.metadata.namespace || 'default';\n const name = product.metadata.name;\n const displayName = product.spec.displayName || name;\n const description = product.spec.description || `api product: ${displayName}`;\n\n // determine lifecycle from labels or default to production\n const lifecycle = product.metadata.labels?.lifecycle || 'production';\n\n // determine owner from contact info or default to guests\n const owner = product.spec.contact?.team || 'guests';\n\n // build tags from product tags\n const tags = product.spec.tags || [];\n\n // create entity with proper backstage structure\n const entity: ApiEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'API',\n metadata: {\n name: `${name}`,\n namespace: 'default',\n title: displayName,\n description,\n annotations: {\n 'backstage.io/managed-by-location': `kuadrant:${namespace}/${name}`,\n 'backstage.io/managed-by-origin-location': `kuadrant:${namespace}/${name}`,\n 'backstage.io/orphan-strategy': 'keep',\n 'kuadrant.io/namespace': namespace,\n 'kuadrant.io/apiproduct': name,\n // add httproute annotation if we can infer it (usually same as apiproduct name without -api suffix)\n 'kuadrant.io/httproute': name.endsWith('-api') ? name.slice(0, -4) : name,\n ...(product.spec.documentation?.openAPISpec && {\n 'kuadrant.io/openapi-spec-url': product.spec.documentation.openAPISpec,\n }),\n ...(product.spec.documentation?.docsURL && {\n 'kuadrant.io/docs-url': product.spec.documentation.docsURL,\n }),\n ...(product.spec.documentation?.gitRepository && {\n 'backstage.io/source-location': `url:${product.spec.documentation.gitRepository}`,\n }),\n ...(product.spec.documentation?.techdocsRef && {\n 'backstage.io/techdocs-ref': product.spec.documentation.techdocsRef,\n }),\n ...(product.spec.contact?.email && {\n 'kuadrant.io/contact-email': product.spec.contact.email,\n }),\n ...(product.spec.contact?.slack && {\n 'kuadrant.io/contact-slack': product.spec.contact.slack,\n }),\n },\n tags: [...tags, 'kuadrant', 'apiproduct'],\n labels: {\n 'kuadrant.io/synced': 'true',\n ...(product.metadata.labels || {}),\n },\n },\n spec: {\n type: 'openapi',\n lifecycle,\n owner,\n definition: product.spec.documentation?.openAPISpec\n ? `# openapi spec available at: ${product.spec.documentation.openAPISpec}\\n\\nopenapi: 3.0.0\\ninfo:\\n title: ${displayName}\\n version: ${product.spec.version || '1.0.0'}\\n description: ${description}\\n`\n : `# no openapi spec configured\\n\\nopenapi: 3.0.0\\ninfo:\\n title: ${displayName}\\n version: ${product.spec.version || '1.0.0'}\\n description: ${description}\\n`,\n },\n };\n\n return entity;\n }\n}\n"],"names":["KuadrantK8sClient"],"mappings":"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"}
|
package/dist/router.cjs.js
CHANGED
|
@@ -9,6 +9,7 @@ var Router = require('express-promise-router');
|
|
|
9
9
|
var cors = require('cors');
|
|
10
10
|
var crypto = require('crypto');
|
|
11
11
|
var k8sClient = require('./k8s-client.cjs.js');
|
|
12
|
+
var alpha = require('./alpha.cjs.js');
|
|
12
13
|
var permissions = require('./permissions.cjs.js');
|
|
13
14
|
|
|
14
15
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
@@ -130,29 +131,43 @@ async function createRouter({
|
|
|
130
131
|
const { userId } = await getUserIdentity(req, httpAuth, userInfo);
|
|
131
132
|
const apiProduct = req.body;
|
|
132
133
|
const namespace = apiProduct.metadata?.namespace;
|
|
133
|
-
const
|
|
134
|
+
const targetRef = apiProduct.spec?.targetRef;
|
|
134
135
|
if (!namespace) {
|
|
135
136
|
throw new errors.InputError("namespace is required in metadata");
|
|
136
137
|
}
|
|
137
|
-
if (!
|
|
138
|
-
throw new errors.InputError("
|
|
138
|
+
if (!targetRef?.name || !targetRef?.kind) {
|
|
139
|
+
throw new errors.InputError("targetRef with name and kind is required");
|
|
139
140
|
}
|
|
140
|
-
const planPolicy = await k8sClient$1.getCustomResource(
|
|
141
|
-
"extensions.kuadrant.io",
|
|
142
|
-
"v1alpha1",
|
|
143
|
-
planPolicyRef.namespace,
|
|
144
|
-
"planpolicies",
|
|
145
|
-
planPolicyRef.name
|
|
146
|
-
);
|
|
147
|
-
const plans = planPolicy.spec?.plans || [];
|
|
148
|
-
if (plans.length === 0) {
|
|
149
|
-
throw new errors.InputError("selected planpolicy has no plans defined");
|
|
150
|
-
}
|
|
151
|
-
apiProduct.spec.plans = plans;
|
|
152
141
|
if (!apiProduct.spec.contact) {
|
|
153
142
|
apiProduct.spec.contact = {};
|
|
154
143
|
}
|
|
155
144
|
apiProduct.spec.contact.team = `user:default/${userId}`;
|
|
145
|
+
const httpRouteNamespace = targetRef.namespace || namespace;
|
|
146
|
+
const httpRouteName = targetRef.name;
|
|
147
|
+
try {
|
|
148
|
+
const planPoliciesResponse = await k8sClient$1.listCustomResources(
|
|
149
|
+
"extensions.kuadrant.io",
|
|
150
|
+
"v1alpha1",
|
|
151
|
+
"planpolicies",
|
|
152
|
+
httpRouteNamespace
|
|
153
|
+
);
|
|
154
|
+
const planPolicy = (planPoliciesResponse.items || []).find((pp) => {
|
|
155
|
+
const ref = pp.spec?.targetRef;
|
|
156
|
+
return ref?.kind === "HTTPRoute" && ref?.name === httpRouteName && (!ref?.namespace || ref?.namespace === httpRouteNamespace);
|
|
157
|
+
});
|
|
158
|
+
if (planPolicy && planPolicy.spec?.plans) {
|
|
159
|
+
apiProduct.spec.plans = planPolicy.spec.plans.map((plan) => ({
|
|
160
|
+
tier: plan.tier,
|
|
161
|
+
description: plan.description,
|
|
162
|
+
limits: plan.limits
|
|
163
|
+
}));
|
|
164
|
+
console.log(`copied ${apiProduct.spec.plans.length} plans from planpolicy ${planPolicy.metadata.name}`);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(`no planpolicy found for httproute ${httpRouteNamespace}/${httpRouteName}`);
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.warn("failed to populate plans from planpolicy:", error);
|
|
170
|
+
}
|
|
156
171
|
const created = await k8sClient$1.createCustomResource(
|
|
157
172
|
"extensions.kuadrant.io",
|
|
158
173
|
"v1alpha1",
|
|
@@ -160,6 +175,10 @@ async function createRouter({
|
|
|
160
175
|
"apiproducts",
|
|
161
176
|
apiProduct
|
|
162
177
|
);
|
|
178
|
+
const provider = alpha.getAPIProductEntityProvider();
|
|
179
|
+
if (provider) {
|
|
180
|
+
await provider.refresh();
|
|
181
|
+
}
|
|
163
182
|
res.status(201).json(created);
|
|
164
183
|
} catch (error) {
|
|
165
184
|
console.error("error creating apiproduct:", error);
|
|
@@ -191,6 +210,10 @@ async function createRouter({
|
|
|
191
210
|
"apiproducts",
|
|
192
211
|
name
|
|
193
212
|
);
|
|
213
|
+
const provider = alpha.getAPIProductEntityProvider();
|
|
214
|
+
if (provider) {
|
|
215
|
+
await provider.refresh();
|
|
216
|
+
}
|
|
194
217
|
res.status(204).send();
|
|
195
218
|
} catch (error) {
|
|
196
219
|
console.error("error deleting apiproduct:", error);
|
|
@@ -201,6 +224,60 @@ async function createRouter({
|
|
|
201
224
|
}
|
|
202
225
|
}
|
|
203
226
|
});
|
|
227
|
+
router.get("/httproutes", async (req, res) => {
|
|
228
|
+
try {
|
|
229
|
+
const credentials = await httpAuth.credentials(req);
|
|
230
|
+
const decision = await permissions$1.authorize(
|
|
231
|
+
[{ permission: permissions.kuadrantApiProductListPermission }],
|
|
232
|
+
{ credentials }
|
|
233
|
+
);
|
|
234
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
235
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
236
|
+
}
|
|
237
|
+
const data = await k8sClient$1.listCustomResources("gateway.networking.k8s.io", "v1", "httproutes");
|
|
238
|
+
res.json(data);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error("error fetching httproutes:", error);
|
|
241
|
+
if (error instanceof errors.NotAllowedError) {
|
|
242
|
+
res.status(403).json({ error: error.message });
|
|
243
|
+
} else {
|
|
244
|
+
res.status(500).json({ error: "failed to fetch httproutes" });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
router.patch("/apiproducts/:namespace/:name", async (req, res) => {
|
|
249
|
+
try {
|
|
250
|
+
const credentials = await httpAuth.credentials(req, { allow: ["user", "none"] });
|
|
251
|
+
const decision = await permissions$1.authorize(
|
|
252
|
+
[{ permission: permissions.kuadrantApiProductUpdatePermission }],
|
|
253
|
+
{ credentials }
|
|
254
|
+
);
|
|
255
|
+
if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
256
|
+
throw new errors.NotAllowedError("unauthorised");
|
|
257
|
+
}
|
|
258
|
+
const { namespace, name } = req.params;
|
|
259
|
+
const patch = req.body;
|
|
260
|
+
const updated = await k8sClient$1.patchCustomResource(
|
|
261
|
+
"extensions.kuadrant.io",
|
|
262
|
+
"v1alpha1",
|
|
263
|
+
namespace,
|
|
264
|
+
"apiproducts",
|
|
265
|
+
name,
|
|
266
|
+
patch
|
|
267
|
+
);
|
|
268
|
+
res.json(updated);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.error("error updating apiproduct:", error);
|
|
271
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
272
|
+
if (error instanceof errors.NotAllowedError) {
|
|
273
|
+
res.status(403).json({ error: error.message });
|
|
274
|
+
} else if (error instanceof errors.InputError) {
|
|
275
|
+
res.status(400).json({ error: error.message });
|
|
276
|
+
} else {
|
|
277
|
+
res.status(500).json({ error: errorMessage });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
});
|
|
204
281
|
router.get("/planpolicies", async (req, res) => {
|
|
205
282
|
try {
|
|
206
283
|
const credentials = await httpAuth.credentials(req);
|
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 {\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,\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 planPolicyRef = apiProduct.spec?.planPolicyRef;\n\n if (!namespace) {\n throw new InputError('namespace is required in metadata');\n }\n\n if (!planPolicyRef?.name || !planPolicyRef?.namespace) {\n throw new InputError('planPolicyRef with name and namespace is required');\n }\n\n // fetch the planpolicy to get plan details\n const planPolicy = await k8sClient.getCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n planPolicyRef.namespace,\n 'planpolicies',\n planPolicyRef.name,\n );\n\n // extract plans from planpolicy\n const plans = planPolicy.spec?.plans || [];\n\n if (plans.length === 0) {\n throw new InputError('selected planpolicy has no plans defined');\n }\n\n // inject plans into apiproduct spec\n apiProduct.spec.plans = plans;\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 const created = await k8sClient.createCustomResource(\n 'extensions.kuadrant.io',\n 'v1alpha1',\n namespace,\n 'apiproducts',\n apiProduct,\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 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 // 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","kuadrantApiProductDeletePermission","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 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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"}
|