@backstage/plugin-kubernetes-backend 0.21.11-next.2 → 0.21.12-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/actions/createGetKubernetesClustersAction.cjs.js +88 -0
  3. package/dist/actions/createGetKubernetesClustersAction.cjs.js.map +1 -0
  4. package/dist/actions/createGetKubernetesResourcesForEntityAction.cjs.js +137 -0
  5. package/dist/actions/createGetKubernetesResourcesForEntityAction.cjs.js.map +1 -0
  6. package/dist/actions/index.cjs.js +12 -0
  7. package/dist/actions/index.cjs.js.map +1 -0
  8. package/dist/auth/AksStrategy.cjs.js.map +1 -1
  9. package/dist/auth/AnonymousStrategy.cjs.js.map +1 -1
  10. package/dist/auth/AwsIamStrategy.cjs.js.map +1 -1
  11. package/dist/auth/AzureIdentityStrategy.cjs.js.map +1 -1
  12. package/dist/auth/DispatchStrategy.cjs.js.map +1 -1
  13. package/dist/auth/GoogleServiceAccountStrategy.cjs.js.map +1 -1
  14. package/dist/auth/GoogleStrategy.cjs.js.map +1 -1
  15. package/dist/auth/OidcStrategy.cjs.js.map +1 -1
  16. package/dist/auth/ServiceAccountStrategy.cjs.js.map +1 -1
  17. package/dist/auth/buildDefaultAuthStrategyMap.cjs.js.map +1 -1
  18. package/dist/auth/requirePermission.cjs.js.map +1 -1
  19. package/dist/cluster-locator/CatalogClusterLocator.cjs.js.map +1 -1
  20. package/dist/cluster-locator/CatalogClusterLocatorOptions.cjs.js.map +1 -1
  21. package/dist/cluster-locator/ConfigClusterLocator.cjs.js.map +1 -1
  22. package/dist/cluster-locator/GkeClusterLocator.cjs.js.map +1 -1
  23. package/dist/cluster-locator/LocalKubectlProxyLocator.cjs.js.map +1 -1
  24. package/dist/cluster-locator/catalogClusterAuthMetadata.cjs.js.map +1 -1
  25. package/dist/cluster-locator/index.cjs.js.map +1 -1
  26. package/dist/cluster-locator/validateClusterApiServerUrl.cjs.js.map +1 -1
  27. package/dist/package.json.cjs.js +1 -1
  28. package/dist/package.json.cjs.js.map +1 -1
  29. package/dist/plugin.cjs.js +16 -2
  30. package/dist/plugin.cjs.js.map +1 -1
  31. package/dist/routes/resourcesRoutes.cjs.js.map +1 -1
  32. package/dist/service/KubernetesConnection.cjs.js.map +1 -1
  33. package/dist/service/KubernetesFanOutHandler.cjs.js.map +1 -1
  34. package/dist/service/KubernetesFetcher.cjs.js.map +1 -1
  35. package/dist/service/KubernetesInitializer.cjs.js.map +1 -1
  36. package/dist/service/KubernetesProxy.cjs.js +1 -1
  37. package/dist/service/KubernetesProxy.cjs.js.map +1 -1
  38. package/dist/service/KubernetesRouter.cjs.js +0 -6
  39. package/dist/service/KubernetesRouter.cjs.js.map +1 -1
  40. package/dist/service/ProxyAuditSession.cjs.js +3 -0
  41. package/dist/service/ProxyAuditSession.cjs.js.map +1 -1
  42. package/dist/service/ProxyMiddlewareCache.cjs.js.map +1 -1
  43. package/dist/service/runPeriodically.cjs.js.map +1 -1
  44. package/dist/service-locator/CatalogRelationServiceLocator.cjs.js.map +1 -1
  45. package/dist/service-locator/MultiTenantServiceLocator.cjs.js.map +1 -1
  46. package/dist/service-locator/SingleTenantServiceLocator.cjs.js.map +1 -1
  47. package/dist/service-locator/buildDefaultServiceLocator.cjs.js.map +1 -1
  48. package/package.json +17 -17
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @backstage/plugin-kubernetes-backend
2
2
 
3
+ ## 0.21.12-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/config@1.3.10-next.0
9
+ - @backstage/errors@1.3.2-next.0
10
+ - @backstage/backend-plugin-api@1.10.2-next.0
11
+ - @backstage/integration-aws-node@0.2.3-next.0
12
+ - @backstage/plugin-permission-common@0.9.12-next.0
13
+ - @backstage/plugin-permission-node@0.11.5-next.0
14
+ - @backstage/catalog-client@1.16.3-next.0
15
+ - @backstage/catalog-model@1.10.2-next.0
16
+ - @backstage/plugin-catalog-node@2.2.6-next.0
17
+ - @backstage/plugin-kubernetes-common@0.9.14-next.0
18
+ - @backstage/plugin-kubernetes-node@0.4.9-next.0
19
+
20
+ ## 0.21.11
21
+
22
+ ### Patch Changes
23
+
24
+ - 736d84e: Use locale-insensitive Unicode casing for consistent string handling across environments.
25
+ - 1d7b704: Reject unsupported service account authentication in catalog-provided cluster definitions.
26
+ - b11c9b4: Improved entity resolution on the deprecated services endpoint.
27
+ - 5268d63: Migrated tests from MSW v1 to MSW v2.
28
+ - ad8f2a8: Added actions to get kubernetes clusters and entity resources
29
+ - 28bdf75: Improved handling of Kubernetes resource response data.
30
+ - 97a7e8e: The catalog cluster locator now validates Kubernetes API server URLs to block SSRF targets (non-public addresses, cloud metadata endpoints, and non-HTTPS URLs by default). Operators may list trusted hostnames in `dangerouslyAllowClusterUrls` on the catalog locator method to permit HTTP or non-public addresses for those hosts only (for example local minikube). Catalog entities cannot use the `serviceAccount` auth provider, cannot enable TLS verification skipping unless `dangerouslyAllowSkipTLSVerify` is set on the locator method, and only permitted annotations are passed through as auth metadata. Kubernetes API fetches no longer follow HTTP redirects automatically.
31
+ - d9a57de: Add `KubernetesWatcher` interface for streaming Kubernetes resource changes via an async iterator. The watcher is separated from `KubernetesFetcher` because watching is a long-lived streaming connection that only works with server-side auth providers. Watch supports all event types (ADDED, MODIFIED, DELETED, BOOKMARK, ERROR) with errors yielded as data rather than thrown.
32
+ - Updated dependencies
33
+ - @backstage/catalog-client@1.16.2
34
+ - @backstage/catalog-model@1.10.1
35
+ - @backstage/config@1.3.9
36
+ - @backstage/plugin-kubernetes-node@0.4.8
37
+ - @backstage/plugin-kubernetes-common@0.9.13
38
+ - @backstage/plugin-permission-node@0.11.4
39
+ - @backstage/backend-plugin-api@1.10.1
40
+ - @backstage/integration-aws-node@0.2.2
41
+ - @backstage/plugin-catalog-node@2.2.5
42
+ - @backstage/plugin-permission-common@0.9.11
43
+
3
44
  ## 0.21.11-next.2
4
45
 
5
46
  ### Patch Changes
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ var pluginKubernetesCommon = require('@backstage/plugin-kubernetes-common');
4
+
5
+ const createGetKubernetesClustersAction = ({
6
+ clusterSupplier,
7
+ actionsRegistry
8
+ }) => {
9
+ actionsRegistry.register({
10
+ name: "get-kubernetes-clusters",
11
+ title: "Get Kubernetes Clusters",
12
+ description: `
13
+ Lists all Kubernetes clusters registered with this Backstage instance.
14
+
15
+ Each cluster entry includes its internal \`name\` (unique identifier used in other actions and config),
16
+ an optional human-readable \`title\`, an optional \`dashboardUrl\` to its Kubernetes dashboard,
17
+ and an optional \`dashboardApp\` indicating the dashboard type (e.g. "standard", "gke", "eks", "aks",
18
+ "rancher", "openshift").
19
+
20
+ ## When to use
21
+
22
+ Use this action to discover which clusters are available before looking up resources on a specific
23
+ cluster. The \`name\` returned here is the identifier to use when describing which cluster a resource
24
+ belongs to.
25
+ `,
26
+ attributes: {
27
+ destructive: false,
28
+ readOnly: true,
29
+ idempotent: true
30
+ },
31
+ visibilityPermission: pluginKubernetesCommon.kubernetesClustersReadPermission,
32
+ schema: {
33
+ input: (z) => z.object({}),
34
+ output: (z) => z.object({
35
+ clusters: z.array(
36
+ z.object({
37
+ name: z.string().describe(
38
+ "Unique internal name of the cluster, used as an identifier in other actions."
39
+ ),
40
+ title: z.string().optional().describe(
41
+ "Human-readable display name for the cluster, if configured."
42
+ ),
43
+ dashboardUrl: z.string().optional().describe(
44
+ "URL to the Kubernetes dashboard for this cluster."
45
+ ),
46
+ dashboardApp: z.string().optional().describe(
47
+ 'Dashboard type, e.g. "standard", "gke", "eks", "aks", "rancher", "openshift".'
48
+ )
49
+ })
50
+ ).describe("List of all registered Kubernetes clusters.")
51
+ })
52
+ },
53
+ examples: [
54
+ {
55
+ title: "List all clusters",
56
+ input: {},
57
+ output: {
58
+ clusters: [
59
+ { name: "production", title: "Production Cluster" },
60
+ {
61
+ name: "staging",
62
+ title: "Staging Cluster",
63
+ dashboardApp: "standard",
64
+ dashboardUrl: "https://dashboard.staging.example.com"
65
+ }
66
+ ]
67
+ }
68
+ }
69
+ ],
70
+ action: async ({ credentials, logger }) => {
71
+ logger.info("Fetching Kubernetes clusters");
72
+ const clusterDetails = await clusterSupplier.getClusters({ credentials });
73
+ return {
74
+ output: {
75
+ clusters: clusterDetails.map((cd) => ({
76
+ name: cd.name,
77
+ ...cd.title && { title: cd.title },
78
+ ...cd.dashboardUrl && { dashboardUrl: cd.dashboardUrl },
79
+ ...cd.dashboardApp && { dashboardApp: cd.dashboardApp }
80
+ }))
81
+ }
82
+ };
83
+ }
84
+ });
85
+ };
86
+
87
+ exports.createGetKubernetesClustersAction = createGetKubernetesClustersAction;
88
+ //# sourceMappingURL=createGetKubernetesClustersAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGetKubernetesClustersAction.cjs.js","sources":["../../src/actions/createGetKubernetesClustersAction.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { kubernetesClustersReadPermission } from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node';\n\nexport const createGetKubernetesClustersAction = ({\n clusterSupplier,\n actionsRegistry,\n}: {\n clusterSupplier: KubernetesClustersSupplier;\n actionsRegistry: ActionsRegistryService;\n}) => {\n actionsRegistry.register({\n name: 'get-kubernetes-clusters',\n title: 'Get Kubernetes Clusters',\n description: `\nLists all Kubernetes clusters registered with this Backstage instance.\n\nEach cluster entry includes its internal \\`name\\` (unique identifier used in other actions and config),\nan optional human-readable \\`title\\`, an optional \\`dashboardUrl\\` to its Kubernetes dashboard,\nand an optional \\`dashboardApp\\` indicating the dashboard type (e.g. \"standard\", \"gke\", \"eks\", \"aks\",\n\"rancher\", \"openshift\").\n\n## When to use\n\nUse this action to discover which clusters are available before looking up resources on a specific\ncluster. The \\`name\\` returned here is the identifier to use when describing which cluster a resource\nbelongs to.\n `,\n attributes: {\n destructive: false,\n readOnly: true,\n idempotent: true,\n },\n visibilityPermission: kubernetesClustersReadPermission,\n schema: {\n input: z => z.object({}),\n output: z =>\n z.object({\n clusters: z\n .array(\n z.object({\n name: z\n .string()\n .describe(\n 'Unique internal name of the cluster, used as an identifier in other actions.',\n ),\n title: z\n .string()\n .optional()\n .describe(\n 'Human-readable display name for the cluster, if configured.',\n ),\n dashboardUrl: z\n .string()\n .optional()\n .describe(\n 'URL to the Kubernetes dashboard for this cluster.',\n ),\n dashboardApp: z\n .string()\n .optional()\n .describe(\n 'Dashboard type, e.g. \"standard\", \"gke\", \"eks\", \"aks\", \"rancher\", \"openshift\".',\n ),\n }),\n )\n .describe('List of all registered Kubernetes clusters.'),\n }),\n },\n examples: [\n {\n title: 'List all clusters',\n input: {},\n output: {\n clusters: [\n { name: 'production', title: 'Production Cluster' },\n {\n name: 'staging',\n title: 'Staging Cluster',\n dashboardApp: 'standard',\n dashboardUrl: 'https://dashboard.staging.example.com',\n },\n ],\n },\n },\n ],\n action: async ({ credentials, logger }) => {\n logger.info('Fetching Kubernetes clusters');\n\n const clusterDetails = await clusterSupplier.getClusters({ credentials });\n\n return {\n output: {\n clusters: clusterDetails.map(cd => ({\n name: cd.name,\n ...(cd.title && { title: cd.title }),\n ...(cd.dashboardUrl && { dashboardUrl: cd.dashboardUrl }),\n ...(cd.dashboardApp && { dashboardApp: cd.dashboardApp }),\n })),\n },\n };\n },\n });\n};\n"],"names":["kubernetesClustersReadPermission"],"mappings":";;;;AAmBO,MAAM,oCAAoC,CAAC;AAAA,EAChD,eAAA;AAAA,EACA;AACF,CAAA,KAGM;AACJ,EAAA,eAAA,CAAgB,QAAA,CAAS;AAAA,IACvB,IAAA,EAAM,yBAAA;AAAA,IACN,KAAA,EAAO,yBAAA;AAAA,IACP,WAAA,EAAa;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,IAcb,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,KAAA;AAAA,MACb,QAAA,EAAU,IAAA;AAAA,MACV,UAAA,EAAY;AAAA,KACd;AAAA,IACA,oBAAA,EAAsBA,uDAAA;AAAA,IACtB,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,EAAE,CAAA;AAAA,MACvB,MAAA,EAAQ,CAAA,CAAA,KACN,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,UAAU,CAAA,CACP,KAAA;AAAA,UACC,EAAE,MAAA,CAAO;AAAA,YACP,IAAA,EAAM,CAAA,CACH,MAAA,EAAO,CACP,QAAA;AAAA,cACC;AAAA,aACF;AAAA,YACF,KAAA,EAAO,CAAA,CACJ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,cACC;AAAA,aACF;AAAA,YACF,YAAA,EAAc,CAAA,CACX,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,cACC;AAAA,aACF;AAAA,YACF,YAAA,EAAc,CAAA,CACX,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,cACC;AAAA;AACF,WACH;AAAA,SACH,CACC,SAAS,6CAA6C;AAAA,OAC1D;AAAA,KACL;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,QACE,KAAA,EAAO,mBAAA;AAAA,QACP,OAAO,EAAC;AAAA,QACR,MAAA,EAAQ;AAAA,UACN,QAAA,EAAU;AAAA,YACR,EAAE,IAAA,EAAM,YAAA,EAAc,KAAA,EAAO,oBAAA,EAAqB;AAAA,YAClD;AAAA,cACE,IAAA,EAAM,SAAA;AAAA,cACN,KAAA,EAAO,iBAAA;AAAA,cACP,YAAA,EAAc,UAAA;AAAA,cACd,YAAA,EAAc;AAAA;AAChB;AACF;AACF;AACF,KACF;AAAA,IACA,MAAA,EAAQ,OAAO,EAAE,WAAA,EAAa,QAAO,KAAM;AACzC,MAAA,MAAA,CAAO,KAAK,8BAA8B,CAAA;AAE1C,MAAA,MAAM,iBAAiB,MAAM,eAAA,CAAgB,WAAA,CAAY,EAAE,aAAa,CAAA;AAExE,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN,QAAA,EAAU,cAAA,CAAe,GAAA,CAAI,CAAA,EAAA,MAAO;AAAA,YAClC,MAAM,EAAA,CAAG,IAAA;AAAA,YACT,GAAI,EAAA,CAAG,KAAA,IAAS,EAAE,KAAA,EAAO,GAAG,KAAA,EAAM;AAAA,YAClC,GAAI,EAAA,CAAG,YAAA,IAAgB,EAAE,YAAA,EAAc,GAAG,YAAA,EAAa;AAAA,YACvD,GAAI,EAAA,CAAG,YAAA,IAAgB,EAAE,YAAA,EAAc,GAAG,YAAA;AAAa,WACzD,CAAE;AAAA;AACJ,OACF;AAAA,IACF;AAAA,GACD,CAAA;AACH;;"}
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@backstage/errors');
4
+ var pluginKubernetesCommon = require('@backstage/plugin-kubernetes-common');
5
+ var catalogModel = require('@backstage/catalog-model');
6
+
7
+ const createGetKubernetesResourcesForEntityAction = ({
8
+ objectsProvider,
9
+ catalog,
10
+ actionsRegistry
11
+ }) => {
12
+ actionsRegistry.register({
13
+ name: "get-kubernetes-resources-for-entity",
14
+ title: "Get Kubernetes Resources for Entity",
15
+ description: `
16
+ Fetches all Kubernetes resources associated with a Backstage catalog entity across all registered clusters.
17
+
18
+ The response groups results by cluster. Each cluster entry includes:
19
+ - \`cluster.name\`: the cluster identifier
20
+ - \`resources\`: list of Kubernetes resource groups, each with a \`type\` (e.g. "pods", "deployments",
21
+ "services", "configmaps", "replicasets", "statefulsets", "daemonsets", "jobs", "cronjobs",
22
+ "horizontalpodautoscalers", "ingresses") and a \`resources\` array containing the raw Kubernetes objects.
23
+ - \`podMetrics\`: CPU and memory usage per pod and container, if metrics-server is installed.
24
+ - \`errors\`: any fetch errors encountered for that cluster.
25
+
26
+ ## When to use
27
+
28
+ Use this action to inspect the live Kubernetes state of a service or component \u2014 for example to check
29
+ deployment rollout status, pod health, replica counts, or resource quotas.
30
+ `,
31
+ attributes: {
32
+ destructive: false,
33
+ readOnly: true,
34
+ idempotent: true
35
+ },
36
+ visibilityPermission: pluginKubernetesCommon.kubernetesResourcesReadPermission,
37
+ schema: {
38
+ input: (z) => z.object({
39
+ name: z.string().describe("The name of the catalog entity."),
40
+ kind: z.string().optional().describe(
41
+ 'The kind of the catalog entity. Defaults to "Component" if omitted.'
42
+ ),
43
+ namespace: z.string().optional().describe(
44
+ 'The namespace of the catalog entity. Defaults to "default" if omitted.'
45
+ )
46
+ }),
47
+ output: (z) => z.object({
48
+ items: z.array(z.unknown()).describe(
49
+ "List of ClusterObjects, one per cluster. Each entry has cluster info, resources grouped by type, pod metrics, and any errors."
50
+ )
51
+ })
52
+ },
53
+ examples: [
54
+ {
55
+ title: "Get Kubernetes resources for a component",
56
+ input: { name: "my-service" },
57
+ output: {
58
+ items: [
59
+ {
60
+ cluster: { name: "production" },
61
+ resources: [
62
+ {
63
+ type: "deployments",
64
+ resources: [
65
+ {
66
+ metadata: { name: "my-service", namespace: "default" },
67
+ spec: { replicas: 3 },
68
+ status: { readyReplicas: 3 }
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ type: "pods",
74
+ resources: [
75
+ {
76
+ metadata: {
77
+ name: "my-service-abc12",
78
+ namespace: "default"
79
+ },
80
+ status: { phase: "Running" }
81
+ }
82
+ ]
83
+ }
84
+ ],
85
+ podMetrics: [],
86
+ errors: []
87
+ }
88
+ ]
89
+ }
90
+ },
91
+ {
92
+ title: "Get Kubernetes resources for a specific kind and namespace",
93
+ input: { name: "my-worker", kind: "Service", namespace: "production" }
94
+ }
95
+ ],
96
+ action: async ({ input, credentials, logger }) => {
97
+ const entityRef = catalogModel.stringifyEntityRef({
98
+ kind: input.kind ?? "Component",
99
+ namespace: input.namespace ?? "default",
100
+ name: input.name
101
+ });
102
+ logger.info(`Fetching Kubernetes resources for entity "${entityRef}"`);
103
+ const entity = await catalog.getEntityByRef(
104
+ {
105
+ kind: input.kind ?? "Component",
106
+ namespace: input.namespace ?? "default",
107
+ name: input.name
108
+ },
109
+ { credentials }
110
+ );
111
+ if (!entity) {
112
+ throw new errors.NotFoundError(
113
+ `Entity "${entityRef}" not found in the catalog`
114
+ );
115
+ }
116
+ const response = await objectsProvider.getKubernetesObjectsByEntity(
117
+ {
118
+ entity,
119
+ // auth carries provider-specific tokens (e.g. OIDC) sent by browser
120
+ // clients. Server-side actions don't have these; passing an empty
121
+ // object tells the AuthenticationStrategy to use the server-side
122
+ // configured credentials (service account, etc.).
123
+ auth: {}
124
+ },
125
+ { credentials }
126
+ );
127
+ return {
128
+ output: {
129
+ items: response.items
130
+ }
131
+ };
132
+ }
133
+ });
134
+ };
135
+
136
+ exports.createGetKubernetesResourcesForEntityAction = createGetKubernetesResourcesForEntityAction;
137
+ //# sourceMappingURL=createGetKubernetesResourcesForEntityAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGetKubernetesResourcesForEntityAction.cjs.js","sources":["../../src/actions/createGetKubernetesResourcesForEntityAction.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { NotFoundError } from '@backstage/errors';\nimport { kubernetesResourcesReadPermission } from '@backstage/plugin-kubernetes-common';\nimport { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nexport const createGetKubernetesResourcesForEntityAction = ({\n objectsProvider,\n catalog,\n actionsRegistry,\n}: {\n objectsProvider: KubernetesObjectsProvider;\n catalog: CatalogService;\n actionsRegistry: ActionsRegistryService;\n}) => {\n actionsRegistry.register({\n name: 'get-kubernetes-resources-for-entity',\n title: 'Get Kubernetes Resources for Entity',\n description: `\nFetches all Kubernetes resources associated with a Backstage catalog entity across all registered clusters.\n\nThe response groups results by cluster. Each cluster entry includes:\n- \\`cluster.name\\`: the cluster identifier\n- \\`resources\\`: list of Kubernetes resource groups, each with a \\`type\\` (e.g. \"pods\", \"deployments\",\n \"services\", \"configmaps\", \"replicasets\", \"statefulsets\", \"daemonsets\", \"jobs\", \"cronjobs\",\n \"horizontalpodautoscalers\", \"ingresses\") and a \\`resources\\` array containing the raw Kubernetes objects.\n- \\`podMetrics\\`: CPU and memory usage per pod and container, if metrics-server is installed.\n- \\`errors\\`: any fetch errors encountered for that cluster.\n\n## When to use\n\nUse this action to inspect the live Kubernetes state of a service or component — for example to check\ndeployment rollout status, pod health, replica counts, or resource quotas.\n `,\n attributes: {\n destructive: false,\n readOnly: true,\n idempotent: true,\n },\n visibilityPermission: kubernetesResourcesReadPermission,\n schema: {\n input: z =>\n z.object({\n name: z.string().describe('The name of the catalog entity.'),\n kind: z\n .string()\n .optional()\n .describe(\n 'The kind of the catalog entity. Defaults to \"Component\" if omitted.',\n ),\n namespace: z\n .string()\n .optional()\n .describe(\n 'The namespace of the catalog entity. Defaults to \"default\" if omitted.',\n ),\n }),\n output: z =>\n z.object({\n items: z\n .array(z.unknown())\n .describe(\n 'List of ClusterObjects, one per cluster. Each entry has cluster info, resources grouped by type, pod metrics, and any errors.',\n ),\n }),\n },\n examples: [\n {\n title: 'Get Kubernetes resources for a component',\n input: { name: 'my-service' },\n output: {\n items: [\n {\n cluster: { name: 'production' },\n resources: [\n {\n type: 'deployments',\n resources: [\n {\n metadata: { name: 'my-service', namespace: 'default' },\n spec: { replicas: 3 },\n status: { readyReplicas: 3 },\n },\n ],\n },\n {\n type: 'pods',\n resources: [\n {\n metadata: {\n name: 'my-service-abc12',\n namespace: 'default',\n },\n status: { phase: 'Running' },\n },\n ],\n },\n ],\n podMetrics: [],\n errors: [],\n },\n ],\n },\n },\n {\n title: 'Get Kubernetes resources for a specific kind and namespace',\n input: { name: 'my-worker', kind: 'Service', namespace: 'production' },\n },\n ],\n action: async ({ input, credentials, logger }) => {\n const entityRef = stringifyEntityRef({\n kind: input.kind ?? 'Component',\n namespace: input.namespace ?? 'default',\n name: input.name,\n });\n\n logger.info(`Fetching Kubernetes resources for entity \"${entityRef}\"`);\n\n const entity = await catalog.getEntityByRef(\n {\n kind: input.kind ?? 'Component',\n namespace: input.namespace ?? 'default',\n name: input.name,\n },\n { credentials },\n );\n if (!entity) {\n throw new NotFoundError(\n `Entity \"${entityRef}\" not found in the catalog`,\n );\n }\n\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n {\n entity,\n // auth carries provider-specific tokens (e.g. OIDC) sent by browser\n // clients. Server-side actions don't have these; passing an empty\n // object tells the AuthenticationStrategy to use the server-side\n // configured credentials (service account, etc.).\n auth: {},\n },\n { credentials },\n );\n\n return {\n output: {\n items: response.items,\n },\n };\n },\n });\n};\n"],"names":["kubernetesResourcesReadPermission","stringifyEntityRef","NotFoundError"],"mappings":";;;;;;AAsBO,MAAM,8CAA8C,CAAC;AAAA,EAC1D,eAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAIM;AACJ,EAAA,eAAA,CAAgB,QAAA,CAAS;AAAA,IACvB,IAAA,EAAM,qCAAA;AAAA,IACN,KAAA,EAAO,qCAAA;AAAA,IACP,WAAA,EAAa;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,IAgBb,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,KAAA;AAAA,MACb,QAAA,EAAU,IAAA;AAAA,MACV,UAAA,EAAY;AAAA,KACd;AAAA,IACA,oBAAA,EAAsBA,wDAAA;AAAA,IACtB,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,SAAS,iCAAiC,CAAA;AAAA,QAC3D,IAAA,EAAM,CAAA,CACH,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,UACC;AAAA,SACF;AAAA,QACF,SAAA,EAAW,CAAA,CACR,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,UACC;AAAA;AACF,OACH,CAAA;AAAA,MACH,MAAA,EAAQ,CAAA,CAAA,KACN,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,OAAO,CAAA,CACJ,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS,CAAA,CACjB,QAAA;AAAA,UACC;AAAA;AACF,OACH;AAAA,KACL;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,QACE,KAAA,EAAO,0CAAA;AAAA,QACP,KAAA,EAAO,EAAE,IAAA,EAAM,YAAA,EAAa;AAAA,QAC5B,MAAA,EAAQ;AAAA,UACN,KAAA,EAAO;AAAA,YACL;AAAA,cACE,OAAA,EAAS,EAAE,IAAA,EAAM,YAAA,EAAa;AAAA,cAC9B,SAAA,EAAW;AAAA,gBACT;AAAA,kBACE,IAAA,EAAM,aAAA;AAAA,kBACN,SAAA,EAAW;AAAA,oBACT;AAAA,sBACE,QAAA,EAAU,EAAE,IAAA,EAAM,YAAA,EAAc,WAAW,SAAA,EAAU;AAAA,sBACrD,IAAA,EAAM,EAAE,QAAA,EAAU,CAAA,EAAE;AAAA,sBACpB,MAAA,EAAQ,EAAE,aAAA,EAAe,CAAA;AAAE;AAC7B;AACF,iBACF;AAAA,gBACA;AAAA,kBACE,IAAA,EAAM,MAAA;AAAA,kBACN,SAAA,EAAW;AAAA,oBACT;AAAA,sBACE,QAAA,EAAU;AAAA,wBACR,IAAA,EAAM,kBAAA;AAAA,wBACN,SAAA,EAAW;AAAA,uBACb;AAAA,sBACA,MAAA,EAAQ,EAAE,KAAA,EAAO,SAAA;AAAU;AAC7B;AACF;AACF,eACF;AAAA,cACA,YAAY,EAAC;AAAA,cACb,QAAQ;AAAC;AACX;AACF;AACF,OACF;AAAA,MACA;AAAA,QACE,KAAA,EAAO,4DAAA;AAAA,QACP,OAAO,EAAE,IAAA,EAAM,aAAa,IAAA,EAAM,SAAA,EAAW,WAAW,YAAA;AAAa;AACvE,KACF;AAAA,IACA,QAAQ,OAAO,EAAE,KAAA,EAAO,WAAA,EAAa,QAAO,KAAM;AAChD,MAAA,MAAM,YAAYC,+BAAA,CAAmB;AAAA,QACnC,IAAA,EAAM,MAAM,IAAA,IAAQ,WAAA;AAAA,QACpB,SAAA,EAAW,MAAM,SAAA,IAAa,SAAA;AAAA,QAC9B,MAAM,KAAA,CAAM;AAAA,OACb,CAAA;AAED,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,0CAAA,EAA6C,SAAS,CAAA,CAAA,CAAG,CAAA;AAErE,MAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,cAAA;AAAA,QAC3B;AAAA,UACE,IAAA,EAAM,MAAM,IAAA,IAAQ,WAAA;AAAA,UACpB,SAAA,EAAW,MAAM,SAAA,IAAa,SAAA;AAAA,UAC9B,MAAM,KAAA,CAAM;AAAA,SACd;AAAA,QACA,EAAE,WAAA;AAAY,OAChB;AACA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAM,IAAIC,oBAAA;AAAA,UACR,WAAW,SAAS,CAAA,0BAAA;AAAA,SACtB;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,4BAAA;AAAA,QACrC;AAAA,UACE,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAKA,MAAM;AAAC,SACT;AAAA,QACA,EAAE,WAAA;AAAY,OAChB;AAEA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN,OAAO,QAAA,CAAS;AAAA;AAClB,OACF;AAAA,IACF;AAAA,GACD,CAAA;AACH;;"}
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var createGetKubernetesClustersAction = require('./createGetKubernetesClustersAction.cjs.js');
4
+ var createGetKubernetesResourcesForEntityAction = require('./createGetKubernetesResourcesForEntityAction.cjs.js');
5
+
6
+ const createKubernetesActions = (options) => {
7
+ createGetKubernetesClustersAction.createGetKubernetesClustersAction(options);
8
+ createGetKubernetesResourcesForEntityAction.createGetKubernetesResourcesForEntityAction(options);
9
+ };
10
+
11
+ exports.createKubernetesActions = createKubernetesActions;
12
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../../src/actions/index.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport {\n KubernetesClustersSupplier,\n KubernetesObjectsProvider,\n} from '@backstage/plugin-kubernetes-node';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { createGetKubernetesClustersAction } from './createGetKubernetesClustersAction';\nimport { createGetKubernetesResourcesForEntityAction } from './createGetKubernetesResourcesForEntityAction';\n\nexport const createKubernetesActions = (options: {\n actionsRegistry: ActionsRegistryService;\n clusterSupplier: KubernetesClustersSupplier;\n objectsProvider: KubernetesObjectsProvider;\n catalog: CatalogService;\n}) => {\n createGetKubernetesClustersAction(options);\n createGetKubernetesResourcesForEntityAction(options);\n};\n"],"names":["createGetKubernetesClustersAction","createGetKubernetesResourcesForEntityAction"],"mappings":";;;;;AAwBO,MAAM,uBAAA,GAA0B,CAAC,OAAA,KAKlC;AACJ,EAAAA,mEAAA,CAAkC,OAAO,CAAA;AACzC,EAAAC,uFAAA,CAA4C,OAAO,CAAA;AACrD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AksStrategy.cjs.js","sources":["../../src/auth/AksStrategy.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class AksStrategy implements AuthenticationStrategy {\n public async getCredential(\n _: ClusterDetails,\n requestAuth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const token = requestAuth.aks;\n return token\n ? { type: 'bearer token', token: token as string }\n : { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,WAAA,CAA8C;AAAA,EACzD,MAAa,aAAA,CACX,CAAA,EACA,WAAA,EAC+B;AAC/B,IAAA,MAAM,QAAQ,WAAA,CAAY,GAAA;AAC1B,IAAA,OAAO,KAAA,GACH,EAAE,IAAA,EAAM,cAAA,EAAgB,OAAuB,GAC/C,EAAE,MAAM,WAAA,EAAY;AAAA,EAC1B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"AksStrategy.cjs.js","sources":["../../src/auth/AksStrategy.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class AksStrategy implements AuthenticationStrategy {\n public async getCredential(\n _: ClusterDetails,\n requestAuth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const token = requestAuth.aks;\n return token\n ? { type: 'bearer token', token: token as string }\n : { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,WAAA,CAA8C;AAAA,EACzD,MAAa,aAAA,CACX,CAAA,EACA,WAAA,EAC+B;AAC/B,IAAA,MAAM,QAAQ,WAAA,CAAY,GAAA;AAC1B,IAAA,OAAO,KAAA,GACH,EAAE,IAAA,EAAM,cAAA,EAAgB,OAAuB,GAC/C,EAAE,MAAM,WAAA,EAAY;AAAA,EAC1B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AnonymousStrategy.cjs.js","sources":["../../src/auth/AnonymousStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class AnonymousStrategy implements AuthenticationStrategy {\n public async getCredential(): Promise<KubernetesCredential> {\n return { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA0BO,MAAM,iBAAA,CAAoD;AAAA,EAC/D,MAAa,aAAA,GAA+C;AAC1D,IAAA,OAAO,EAAE,MAAM,WAAA,EAAY;AAAA,EAC7B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"AnonymousStrategy.cjs.js","sources":["../../src/auth/AnonymousStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class AnonymousStrategy implements AuthenticationStrategy {\n public async getCredential(): Promise<KubernetesCredential> {\n return { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA0BO,MAAM,iBAAA,CAAoD;AAAA,EAC/D,MAAa,aAAA,GAA+C;AAC1D,IAAA,OAAO,EAAE,MAAM,WAAA,EAAY;AAAA,EAC7B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AwsIamStrategy.cjs.js","sources":["../../src/auth/AwsIamStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { SignatureV4 } from '@smithy/signature-v4';\nimport { Sha256 } from '@aws-crypto/sha256-js';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport { Config } from '@backstage/config';\nimport {\n ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,\n ANNOTATION_KUBERNETES_AWS_CLUSTER_ID,\n ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nconst defaultRegion = 'us-east-1';\n\n/**\n *\n * @public\n */\nexport class AwsIamStrategy implements AuthenticationStrategy {\n private readonly credsManager: AwsCredentialsManager;\n\n constructor(opts: { config: Config }) {\n this.credsManager = DefaultAwsCredentialsManager.fromConfig(opts.config);\n }\n\n public async getCredential(\n clusterDetails: ClusterDetails,\n ): Promise<KubernetesCredential> {\n return {\n type: 'bearer token',\n token: await this.getBearerToken(\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_CLUSTER_ID] ??\n clusterDetails.name,\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE],\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID],\n ),\n };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n private async getBearerToken(\n clusterId: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const region = process.env.AWS_REGION ?? defaultRegion;\n\n let masterCredentials;\n if (assumeRole) {\n try {\n masterCredentials = (\n await this.credsManager.getCredentialProvider({ arn: assumeRole })\n ).sdkCredentialProvider;\n } catch (error) {\n if (\n !(error instanceof Error) ||\n !error.message.includes('There is no AWS integration that matches')\n ) {\n throw error;\n }\n masterCredentials = (await this.credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n } else {\n masterCredentials = (await this.credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const credentials = assumeRole\n ? fromTemporaryCredentials({\n masterCredentials,\n clientConfig: {\n region,\n },\n params: {\n RoleArn: assumeRole,\n ExternalId: externalId,\n },\n })\n : masterCredentials;\n\n const signer = new SignatureV4({\n credentials,\n region,\n service: 'sts',\n sha256: Sha256,\n });\n\n const request = await signer.presign(\n {\n headers: {\n host: `sts.${region}.amazonaws.com`,\n 'x-k8s-aws-id': clusterId,\n },\n hostname: `sts.${region}.amazonaws.com`,\n method: 'GET',\n path: '/',\n protocol: 'https:',\n query: {\n Action: 'GetCallerIdentity',\n Version: '2011-06-15',\n },\n },\n { expiresIn: 0 },\n );\n\n const query = Object.keys(request?.query ?? {})\n .map(\n q =>\n `${encodeURIComponent(q)}=${encodeURIComponent(\n request.query?.[q] as string,\n )}`,\n )\n .join('&');\n\n const url = `https://${request.hostname}${request.path}?${query}`;\n\n return `k8s-aws-v1.${Buffer.from(url).toString('base64url')}`;\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["DefaultAwsCredentialsManager","ANNOTATION_KUBERNETES_AWS_CLUSTER_ID","ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE","ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID","fromTemporaryCredentials","SignatureV4","Sha256"],"mappings":"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"}
1
+ {"version":3,"file":"AwsIamStrategy.cjs.js","sources":["../../src/auth/AwsIamStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { SignatureV4 } from '@smithy/signature-v4';\nimport { Sha256 } from '@aws-crypto/sha256-js';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport { Config } from '@backstage/config';\nimport {\n ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,\n ANNOTATION_KUBERNETES_AWS_CLUSTER_ID,\n ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nconst defaultRegion = 'us-east-1';\n\n/**\n *\n * @public\n */\nexport class AwsIamStrategy implements AuthenticationStrategy {\n private readonly credsManager: AwsCredentialsManager;\n\n constructor(opts: { config: Config }) {\n this.credsManager = DefaultAwsCredentialsManager.fromConfig(opts.config);\n }\n\n public async getCredential(\n clusterDetails: ClusterDetails,\n ): Promise<KubernetesCredential> {\n return {\n type: 'bearer token',\n token: await this.getBearerToken(\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_CLUSTER_ID] ??\n clusterDetails.name,\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE],\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID],\n ),\n };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n private async getBearerToken(\n clusterId: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const region = process.env.AWS_REGION ?? defaultRegion;\n\n let masterCredentials;\n if (assumeRole) {\n try {\n masterCredentials = (\n await this.credsManager.getCredentialProvider({ arn: assumeRole })\n ).sdkCredentialProvider;\n } catch (error) {\n if (\n !(error instanceof Error) ||\n !error.message.includes('There is no AWS integration that matches')\n ) {\n throw error;\n }\n masterCredentials = (await this.credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n } else {\n masterCredentials = (await this.credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const credentials = assumeRole\n ? fromTemporaryCredentials({\n masterCredentials,\n clientConfig: {\n region,\n },\n params: {\n RoleArn: assumeRole,\n ExternalId: externalId,\n },\n })\n : masterCredentials;\n\n const signer = new SignatureV4({\n credentials,\n region,\n service: 'sts',\n sha256: Sha256,\n });\n\n const request = await signer.presign(\n {\n headers: {\n host: `sts.${region}.amazonaws.com`,\n 'x-k8s-aws-id': clusterId,\n },\n hostname: `sts.${region}.amazonaws.com`,\n method: 'GET',\n path: '/',\n protocol: 'https:',\n query: {\n Action: 'GetCallerIdentity',\n Version: '2011-06-15',\n },\n },\n { expiresIn: 0 },\n );\n\n const query = Object.keys(request?.query ?? {})\n .map(\n q =>\n `${encodeURIComponent(q)}=${encodeURIComponent(\n request.query?.[q] as string,\n )}`,\n )\n .join('&');\n\n const url = `https://${request.hostname}${request.path}?${query}`;\n\n return `k8s-aws-v1.${Buffer.from(url).toString('base64url')}`;\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["DefaultAwsCredentialsManager","ANNOTATION_KUBERNETES_AWS_CLUSTER_ID","ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE","ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID","fromTemporaryCredentials","SignatureV4","Sha256"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AzureIdentityStrategy.cjs.js","sources":["../../src/auth/AzureIdentityStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\nimport {\n AuthenticationStrategy,\n AuthMetadata,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @public\n */\nexport class AzureIdentityStrategy implements AuthenticationStrategy {\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n private readonly logger: LoggerService;\n private readonly tokenCredential: TokenCredential;\n\n constructor(\n logger: LoggerService,\n tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {\n this.logger = logger;\n this.tokenCredential = tokenCredential;\n }\n\n public async getCredential(): Promise<KubernetesCredential> {\n if (!this.tokenRequiresRefresh()) {\n return { type: 'bearer token', token: this.accessToken.token };\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise\n ? { type: 'bearer token', token: await this.newTokenPromise }\n : { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["DefaultAzureCredential"],"mappings":";;;;AA4BA,MAAM,QAAA,GAAW,+CAAA;AAMV,MAAM,qBAAA,CAAwD;AAAA,EAC3D,WAAA,GAA2B,EAAE,KAAA,EAAO,EAAA,EAAI,oBAAoB,CAAA,EAAE;AAAA,EAC9D,eAAA;AAAA,EAES,MAAA;AAAA,EACA,eAAA;AAAA,EAEjB,WAAA,CACE,MAAA,EACA,eAAA,GAAmC,IAAIA,iCAAuB,EAC9D;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AAAA,EAEA,MAAa,aAAA,GAA+C;AAC1D,IAAA,IAAI,CAAC,IAAA,CAAK,oBAAA,EAAqB,EAAG;AAChC,MAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAO,IAAA,CAAK,YAAY,KAAA,EAAM;AAAA,IAC/D;AAEA,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,aAAA,EAAc;AAAA,IAC5C;AAEA,IAAA,OAAO,IAAA,CAAK,eAAA,GACR,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAO,MAAM,IAAA,CAAK,eAAA,EAAgB,GAC1D,EAAE,IAAA,EAAM,WAAA,EAAY;AAAA,EAC1B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEA,MAAc,aAAA,GAAiC;AAC7C,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kCAAkC,CAAA;AAEnD,MAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,eAAA,CAAgB,SAAS,QAAA,EAAU;AAAA,QACnE,cAAA,EAAgB,EAAE,OAAA,EAAS,GAAA;AAAO;AAAA,OACnC,CAAA;AACD,MAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,QAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,MACvC;AAEA,MAAA,IAAA,CAAK,WAAA,GAAc,cAAA;AAAA,IACrB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,6BAAA,EAA+B,GAAG,CAAA;AAGpD,MAAA,IAAI,IAAA,CAAK,cAAa,EAAG;AACvB,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,eAAA,GAAkB,MAAA;AACvB,IAAA,OAAO,KAAK,WAAA,CAAY,KAAA;AAAA,EAC1B;AAAA,EAEQ,oBAAA,GAAgC;AAEtC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,WAAA,CAAY,kBAAA,GAAqB,KAAK,EAAA,GAAK,GAAA;AAClE,IAAA,OAAO,IAAA,CAAK,KAAI,IAAK,SAAA;AAAA,EACvB;AAAA,EAEQ,YAAA,GAAwB;AAC9B,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,IAAK,IAAA,CAAK,WAAA,CAAY,kBAAA;AAAA,EACxC;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"AzureIdentityStrategy.cjs.js","sources":["../../src/auth/AzureIdentityStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\nimport {\n AuthenticationStrategy,\n AuthMetadata,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @public\n */\nexport class AzureIdentityStrategy implements AuthenticationStrategy {\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n private readonly logger: LoggerService;\n private readonly tokenCredential: TokenCredential;\n\n constructor(\n logger: LoggerService,\n tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {\n this.logger = logger;\n this.tokenCredential = tokenCredential;\n }\n\n public async getCredential(): Promise<KubernetesCredential> {\n if (!this.tokenRequiresRefresh()) {\n return { type: 'bearer token', token: this.accessToken.token };\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise\n ? { type: 'bearer token', token: await this.newTokenPromise }\n : { type: 'anonymous' };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["DefaultAzureCredential"],"mappings":";;;;AA4BA,MAAM,QAAA,GAAW,+CAAA;AAMV,MAAM,qBAAA,CAAwD;AAAA,EAC3D,WAAA,GAA2B,EAAE,KAAA,EAAO,EAAA,EAAI,oBAAoB,CAAA,EAAE;AAAA,EAC9D,eAAA;AAAA,EAES,MAAA;AAAA,EACA,eAAA;AAAA,EAEjB,WAAA,CACE,MAAA,EACA,eAAA,GAAmC,IAAIA,iCAAuB,EAC9D;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AAAA,EAEA,MAAa,aAAA,GAA+C;AAC1D,IAAA,IAAI,CAAC,IAAA,CAAK,oBAAA,EAAqB,EAAG;AAChC,MAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAO,IAAA,CAAK,YAAY,KAAA,EAAM;AAAA,IAC/D;AAEA,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,aAAA,EAAc;AAAA,IAC5C;AAEA,IAAA,OAAO,IAAA,CAAK,eAAA,GACR,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAO,MAAM,IAAA,CAAK,eAAA,EAAgB,GAC1D,EAAE,IAAA,EAAM,WAAA,EAAY;AAAA,EAC1B;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEA,MAAc,aAAA,GAAiC;AAC7C,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kCAAkC,CAAA;AAEnD,MAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,eAAA,CAAgB,SAAS,QAAA,EAAU;AAAA,QACnE,cAAA,EAAgB,EAAE,OAAA,EAAS,GAAA;AAAO;AAAA,OACnC,CAAA;AACD,MAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,QAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,MACvC;AAEA,MAAA,IAAA,CAAK,WAAA,GAAc,cAAA;AAAA,IACrB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,6BAAA,EAA+B,GAAG,CAAA;AAGpD,MAAA,IAAI,IAAA,CAAK,cAAa,EAAG;AACvB,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,eAAA,GAAkB,MAAA;AACvB,IAAA,OAAO,KAAK,WAAA,CAAY,KAAA;AAAA,EAC1B;AAAA,EAEQ,oBAAA,GAAgC;AAEtC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,WAAA,CAAY,kBAAA,GAAqB,KAAK,EAAA,GAAK,GAAA;AAClE,IAAA,OAAO,IAAA,CAAK,KAAI,IAAK,SAAA;AAAA,EACvB;AAAA,EAEQ,YAAA,GAAwB;AAC9B,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,IAAK,IAAA,CAAK,WAAA,CAAY,kBAAA;AAAA,EACxC;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DispatchStrategy.cjs.js","sources":["../../src/auth/DispatchStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n KubernetesRequestAuth,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport type DispatchStrategyOptions = {\n authStrategyMap: {\n [key: string]: AuthenticationStrategy;\n };\n};\n/**\n * used to direct a KubernetesAuthProvider to its corresponding AuthenticationStrategy\n * @public\n */\nexport class DispatchStrategy implements AuthenticationStrategy {\n private readonly strategyMap: { [key: string]: AuthenticationStrategy };\n\n constructor(options: DispatchStrategyOptions) {\n this.strategyMap = options.authStrategyMap;\n }\n\n public getCredential(\n clusterDetails: ClusterDetails,\n auth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const authProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n\n if (this.strategyMap[authProvider]) {\n return this.strategyMap[authProvider].getCredential(clusterDetails, auth);\n }\n throw new Error(\n `authProvider \"${authProvider}\" has no AuthenticationStrategy associated with it`,\n );\n }\n\n public validateCluster(authMetadata: AuthMetadata): Error[] {\n const authProvider = authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n const strategy = this.strategyMap[authProvider];\n if (!strategy) {\n return [\n new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n ),\n ];\n }\n return strategy.validateCluster(authMetadata);\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["ANNOTATION_KUBERNETES_AUTH_PROVIDER"],"mappings":";;;;AAwCO,MAAM,gBAAA,CAAmD;AAAA,EAC7C,WAAA;AAAA,EAEjB,YAAY,OAAA,EAAkC;AAC5C,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,eAAA;AAAA,EAC7B;AAAA,EAEO,aAAA,CACL,gBACA,IAAA,EAC+B;AAC/B,IAAA,MAAM,YAAA,GACJ,cAAA,CAAe,YAAA,CAAaA,0DAAmC,CAAA;AAEjE,IAAA,IAAI,IAAA,CAAK,WAAA,CAAY,YAAY,CAAA,EAAG;AAClC,MAAA,OAAO,KAAK,WAAA,CAAY,YAAY,CAAA,CAAE,aAAA,CAAc,gBAAgB,IAAI,CAAA;AAAA,IAC1E;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,iBAAiB,YAAY,CAAA,kDAAA;AAAA,KAC/B;AAAA,EACF;AAAA,EAEO,gBAAgB,YAAA,EAAqC;AAC1D,IAAA,MAAM,YAAA,GAAe,aAAaA,0DAAmC,CAAA;AACrE,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,YAAY,CAAA;AAC9C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO;AAAA,QACL,IAAI,KAAA;AAAA,UACF,iBAAiB,YAAY,CAAA,kCAAA;AAAA;AAC/B,OACF;AAAA,IACF;AACA,IAAA,OAAO,QAAA,CAAS,gBAAgB,YAAY,CAAA;AAAA,EAC9C;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"DispatchStrategy.cjs.js","sources":["../../src/auth/DispatchStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n KubernetesRequestAuth,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport type DispatchStrategyOptions = {\n authStrategyMap: {\n [key: string]: AuthenticationStrategy;\n };\n};\n/**\n * used to direct a KubernetesAuthProvider to its corresponding AuthenticationStrategy\n * @public\n */\nexport class DispatchStrategy implements AuthenticationStrategy {\n private readonly strategyMap: { [key: string]: AuthenticationStrategy };\n\n constructor(options: DispatchStrategyOptions) {\n this.strategyMap = options.authStrategyMap;\n }\n\n public getCredential(\n clusterDetails: ClusterDetails,\n auth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const authProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n\n if (this.strategyMap[authProvider]) {\n return this.strategyMap[authProvider].getCredential(clusterDetails, auth);\n }\n throw new Error(\n `authProvider \"${authProvider}\" has no AuthenticationStrategy associated with it`,\n );\n }\n\n public validateCluster(authMetadata: AuthMetadata): Error[] {\n const authProvider = authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n const strategy = this.strategyMap[authProvider];\n if (!strategy) {\n return [\n new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n ),\n ];\n }\n return strategy.validateCluster(authMetadata);\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["ANNOTATION_KUBERNETES_AUTH_PROVIDER"],"mappings":";;;;AAwCO,MAAM,gBAAA,CAAmD;AAAA,EAC7C,WAAA;AAAA,EAEjB,YAAY,OAAA,EAAkC;AAC5C,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,eAAA;AAAA,EAC7B;AAAA,EAEO,aAAA,CACL,gBACA,IAAA,EAC+B;AAC/B,IAAA,MAAM,YAAA,GACJ,cAAA,CAAe,YAAA,CAAaA,0DAAmC,CAAA;AAEjE,IAAA,IAAI,IAAA,CAAK,WAAA,CAAY,YAAY,CAAA,EAAG;AAClC,MAAA,OAAO,KAAK,WAAA,CAAY,YAAY,CAAA,CAAE,aAAA,CAAc,gBAAgB,IAAI,CAAA;AAAA,IAC1E;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,iBAAiB,YAAY,CAAA,kDAAA;AAAA,KAC/B;AAAA,EACF;AAAA,EAEO,gBAAgB,YAAA,EAAqC;AAC1D,IAAA,MAAM,YAAA,GAAe,aAAaA,0DAAmC,CAAA;AACrE,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,YAAY,CAAA;AAC9C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO;AAAA,QACL,IAAI,KAAA;AAAA,UACF,iBAAiB,YAAY,CAAA,kCAAA;AAAA;AAC/B,OACF;AAAA,IACF;AACA,IAAA,OAAO,QAAA,CAAS,gBAAgB,YAAY,CAAA;AAAA,EAC9C;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleServiceAccountStrategy.cjs.js","sources":["../../src/auth/GoogleServiceAccountStrategy.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport * as container from '@google-cloud/container';\nimport { Config } from '@backstage/config';\n\n/**\n * GoogleServiceAccountStrategy provides authentication using Google Service Account credentials.\n *\n * Credentials can be provided via configuration:\n * ```yaml\n * kubernetes:\n * googleServiceAccountCredentials: |\n * {\n * \"type\": \"service_account\",\n * \"project_id\": \"your-project-id\",\n * \"private_key_id\": \"key-id\",\n * \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\",\n * \"client_email\": \"your-service-account@your-project.iam.gserviceaccount.com\",\n * \"client_id\": \"client-id\",\n * \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n * \"token_uri\": \"https://oauth2.googleapis.com/token\",\n * \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n * \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/...\"\n * }\n * ```\n *\n * If no credentials are provided in config, falls back to GOOGLE_APPLICATION_CREDENTIALS or ADC.\n *\n * @public\n */\nexport class GoogleServiceAccountStrategy implements AuthenticationStrategy {\n private readonly credentials?: string;\n\n constructor(opts: { config: Config }) {\n this.credentials = opts.config.getOptionalString(\n 'kubernetes.googleServiceAccountCredentials',\n );\n }\n public async getCredential(): Promise<KubernetesCredential> {\n let client: container.v1.ClusterManagerClient;\n\n if (this.credentials) {\n // Use credentials from config\n try {\n const credentialsObject = JSON.parse(this.credentials);\n\n client = new container.v1.ClusterManagerClient({\n credentials: credentialsObject,\n });\n } catch (error) {\n throw new Error(\n `Failed to parse Google Service Account credentials from config: ${\n error instanceof Error ? error.message : 'Invalid JSON'\n }`,\n );\n }\n } else {\n // Fall back to Application Default Credentials or GOOGLE_APPLICATION_CREDENTIALS\n client = new container.v1.ClusterManagerClient();\n }\n\n const token = await client.auth.getAccessToken();\n\n if (!token) {\n throw new Error(\n 'Unable to obtain access token for Google Cloud authentication. Check your credentials configuration.',\n );\n }\n return { type: 'bearer token', token };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["container"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiDO,MAAM,4BAAA,CAA+D;AAAA,EACzD,WAAA;AAAA,EAEjB,YAAY,IAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,WAAA,GAAc,KAAK,MAAA,CAAO,iBAAA;AAAA,MAC7B;AAAA,KACF;AAAA,EACF;AAAA,EACA,MAAa,aAAA,GAA+C;AAC1D,IAAA,IAAI,MAAA;AAEJ,IAAA,IAAI,KAAK,WAAA,EAAa;AAEpB,MAAA,IAAI;AACF,QAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAErD,QAAA,MAAA,GAAS,IAAIA,oBAAA,CAAU,EAAA,CAAG,oBAAA,CAAqB;AAAA,UAC7C,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gEAAA,EACE,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,cAC3C,CAAA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,MAAA,GAAS,IAAIA,oBAAA,CAAU,EAAA,CAAG,oBAAA,EAAqB;AAAA,IACjD;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,IAAA,CAAK,cAAA,EAAe;AAE/C,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AAAA,EACvC;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"GoogleServiceAccountStrategy.cjs.js","sources":["../../src/auth/GoogleServiceAccountStrategy.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport * as container from '@google-cloud/container';\nimport { Config } from '@backstage/config';\n\n/**\n * GoogleServiceAccountStrategy provides authentication using Google Service Account credentials.\n *\n * Credentials can be provided via configuration:\n * ```yaml\n * kubernetes:\n * googleServiceAccountCredentials: |\n * {\n * \"type\": \"service_account\",\n * \"project_id\": \"your-project-id\",\n * \"private_key_id\": \"key-id\",\n * \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\",\n * \"client_email\": \"your-service-account@your-project.iam.gserviceaccount.com\",\n * \"client_id\": \"client-id\",\n * \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n * \"token_uri\": \"https://oauth2.googleapis.com/token\",\n * \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n * \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/...\"\n * }\n * ```\n *\n * If no credentials are provided in config, falls back to GOOGLE_APPLICATION_CREDENTIALS or ADC.\n *\n * @public\n */\nexport class GoogleServiceAccountStrategy implements AuthenticationStrategy {\n private readonly credentials?: string;\n\n constructor(opts: { config: Config }) {\n this.credentials = opts.config.getOptionalString(\n 'kubernetes.googleServiceAccountCredentials',\n );\n }\n public async getCredential(): Promise<KubernetesCredential> {\n let client: container.v1.ClusterManagerClient;\n\n if (this.credentials) {\n // Use credentials from config\n try {\n const credentialsObject = JSON.parse(this.credentials);\n\n client = new container.v1.ClusterManagerClient({\n credentials: credentialsObject,\n });\n } catch (error) {\n throw new Error(\n `Failed to parse Google Service Account credentials from config: ${\n error instanceof Error ? error.message : 'Invalid JSON'\n }`,\n );\n }\n } else {\n // Fall back to Application Default Credentials or GOOGLE_APPLICATION_CREDENTIALS\n client = new container.v1.ClusterManagerClient();\n }\n\n const token = await client.auth.getAccessToken();\n\n if (!token) {\n throw new Error(\n 'Unable to obtain access token for Google Cloud authentication. Check your credentials configuration.',\n );\n }\n return { type: 'bearer token', token };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["container"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiDO,MAAM,4BAAA,CAA+D;AAAA,EACzD,WAAA;AAAA,EAEjB,YAAY,IAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,WAAA,GAAc,KAAK,MAAA,CAAO,iBAAA;AAAA,MAC7B;AAAA,KACF;AAAA,EACF;AAAA,EACA,MAAa,aAAA,GAA+C;AAC1D,IAAA,IAAI,MAAA;AAEJ,IAAA,IAAI,KAAK,WAAA,EAAa;AAEpB,MAAA,IAAI;AACF,QAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAErD,QAAA,MAAA,GAAS,IAAIA,oBAAA,CAAU,EAAA,CAAG,oBAAA,CAAqB;AAAA,UAC7C,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gEAAA,EACE,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,cAC3C,CAAA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,MAAA,GAAS,IAAIA,oBAAA,CAAU,EAAA,CAAG,oBAAA,EAAqB;AAAA,IACjD;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,IAAA,CAAK,cAAA,EAAe;AAE/C,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AAAA,EACvC;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleStrategy.cjs.js","sources":["../../src/auth/GoogleStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class GoogleStrategy implements AuthenticationStrategy {\n public async getCredential(\n _: ClusterDetails,\n requestAuth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const token = requestAuth.google;\n if (!token) {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return { type: 'bearer token', token: token as string };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA4BO,MAAM,cAAA,CAAiD;AAAA,EAC5D,MAAa,aAAA,CACX,CAAA,EACA,WAAA,EAC+B;AAC/B,IAAA,MAAM,QAAQ,WAAA,CAAY,MAAA;AAC1B,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAuB;AAAA,EACxD;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"GoogleStrategy.cjs.js","sources":["../../src/auth/GoogleStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class GoogleStrategy implements AuthenticationStrategy {\n public async getCredential(\n _: ClusterDetails,\n requestAuth: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const token = requestAuth.google;\n if (!token) {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return { type: 'bearer token', token: token as string };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":[],"mappings":";;AA4BO,MAAM,cAAA,CAAiD;AAAA,EAC5D,MAAa,aAAA,CACX,CAAA,EACA,WAAA,EAC+B;AAC/B,IAAA,MAAM,QAAQ,WAAA,CAAY,MAAA;AAC1B,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAuB;AAAA,EACxD;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"OidcStrategy.cjs.js","sources":["../../src/auth/OidcStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { JsonObject } from '@backstage/types';\nimport {\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n KubernetesRequestAuth,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class OidcStrategy implements AuthenticationStrategy {\n public async getCredential(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const oidcTokenProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER];\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const token = (authConfig.oidc as JsonObject | null)?.[oidcTokenProvider];\n\n if (!token) {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return { type: 'bearer token', token: token as string };\n }\n\n public validateCluster(authMetadata: AuthMetadata): Error[] {\n const oidcTokenProvider =\n authMetadata[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER];\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n return [new Error(`Must specify a token provider for 'oidc' strategy`)];\n }\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER"],"mappings":";;;;AA+BO,MAAM,YAAA,CAA+C;AAAA,EAC1D,MAAa,aAAA,CACX,cAAA,EACA,UAAA,EAC+B;AAC/B,IAAA,MAAM,iBAAA,GACJ,cAAA,CAAe,YAAA,CAAaA,gEAAyC,CAAA;AAEvE,IAAA,IAAI,CAAC,iBAAA,IAAqB,iBAAA,KAAsB,EAAA,EAAI;AAClD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAS,UAAA,CAAW,IAAA,GAA6B,iBAAiB,CAAA;AAExE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,mCAAmC,iBAAiB,CAAA,gBAAA;AAAA,OACtD;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAuB;AAAA,EACxD;AAAA,EAEO,gBAAgB,YAAA,EAAqC;AAC1D,IAAA,MAAM,iBAAA,GACJ,aAAaA,gEAAyC,CAAA;AACxD,IAAA,IAAI,CAAC,iBAAA,IAAqB,iBAAA,KAAsB,EAAA,EAAI;AAClD,MAAA,OAAO,CAAC,IAAI,KAAA,CAAM,CAAA,iDAAA,CAAmD,CAAC,CAAA;AAAA,IACxE;AACA,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"OidcStrategy.cjs.js","sources":["../../src/auth/OidcStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { JsonObject } from '@backstage/types';\nimport {\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n KubernetesRequestAuth,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\n\n/**\n *\n * @public\n */\nexport class OidcStrategy implements AuthenticationStrategy {\n public async getCredential(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<KubernetesCredential> {\n const oidcTokenProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER];\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const token = (authConfig.oidc as JsonObject | null)?.[oidcTokenProvider];\n\n if (!token) {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return { type: 'bearer token', token: token as string };\n }\n\n public validateCluster(authMetadata: AuthMetadata): Error[] {\n const oidcTokenProvider =\n authMetadata[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER];\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n return [new Error(`Must specify a token provider for 'oidc' strategy`)];\n }\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER"],"mappings":";;;;AA+BO,MAAM,YAAA,CAA+C;AAAA,EAC1D,MAAa,aAAA,CACX,cAAA,EACA,UAAA,EAC+B;AAC/B,IAAA,MAAM,iBAAA,GACJ,cAAA,CAAe,YAAA,CAAaA,gEAAyC,CAAA;AAEvE,IAAA,IAAI,CAAC,iBAAA,IAAqB,iBAAA,KAAsB,EAAA,EAAI;AAClD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAS,UAAA,CAAW,IAAA,GAA6B,iBAAiB,CAAA;AAExE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,mCAAmC,iBAAiB,CAAA,gBAAA;AAAA,OACtD;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAuB;AAAA,EACxD;AAAA,EAEO,gBAAgB,YAAA,EAAqC;AAC1D,IAAA,MAAM,iBAAA,GACJ,aAAaA,gEAAyC,CAAA;AACxD,IAAA,IAAI,CAAC,iBAAA,IAAqB,iBAAA,KAAsB,EAAA,EAAI;AAClD,MAAA,OAAO,CAAC,IAAI,KAAA,CAAM,CAAA,iDAAA,CAAmD,CAAC,CAAA;AAAA,IACxE;AACA,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceAccountStrategy.cjs.js","sources":["../../src/auth/ServiceAccountStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport type { User } from '@kubernetes/client-node';\nimport fs from 'fs-extra';\n\n/**\n *\n * @public\n */\nexport class ServiceAccountStrategy implements AuthenticationStrategy {\n // Only used in tests\n private injectedKubernetesClient?: typeof import('@kubernetes/client-node');\n\n public async getCredential(\n clusterDetails: ClusterDetails,\n ): Promise<KubernetesCredential> {\n const { KubeConfig } =\n this.injectedKubernetesClient ??\n (await import('@kubernetes/client-node'));\n\n const token = clusterDetails.authMetadata.serviceAccountToken;\n if (token) {\n return { type: 'bearer token', token };\n }\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the user\n const user = kc.getCurrentUser() as User;\n\n return {\n type: 'bearer token',\n token: fs.readFileSync(user.authProvider.config.tokenFile).toString(),\n };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["fs"],"mappings":";;;;;;;;AA6BO,MAAM,sBAAA,CAAyD;AAAA;AAAA,EAE5D,wBAAA;AAAA,EAER,MAAa,cACX,cAAA,EAC+B;AAC/B,IAAA,MAAM,EAAE,UAAA,EAAW,GACjB,KAAK,wBAAA,IACJ,MAAM,OAAO,yBAAyB,CAAA;AAEzC,IAAA,MAAM,KAAA,GAAQ,eAAe,YAAA,CAAa,mBAAA;AAC1C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AAAA,IACvC;AACA,IAAA,MAAM,EAAA,GAAK,IAAI,UAAA,EAAW;AAC1B,IAAA,EAAA,CAAG,eAAA,EAAgB;AAEnB,IAAA,MAAM,IAAA,GAAO,GAAG,cAAA,EAAe;AAE/B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,cAAA;AAAA,MACN,KAAA,EAAOA,oBAAG,YAAA,CAAa,IAAA,CAAK,aAAa,MAAA,CAAO,SAAS,EAAE,QAAA;AAAS,KACtE;AAAA,EACF;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
1
+ {"version":3,"file":"ServiceAccountStrategy.cjs.js","sources":["../../src/auth/ServiceAccountStrategy.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthMetadata,\n AuthenticationStrategy,\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport type { User } from '@kubernetes/client-node';\nimport fs from 'fs-extra';\n\n/**\n *\n * @public\n */\nexport class ServiceAccountStrategy implements AuthenticationStrategy {\n // Only used in tests\n private injectedKubernetesClient?: typeof import('@kubernetes/client-node');\n\n public async getCredential(\n clusterDetails: ClusterDetails,\n ): Promise<KubernetesCredential> {\n const { KubeConfig } =\n this.injectedKubernetesClient ??\n (await import('@kubernetes/client-node'));\n\n const token = clusterDetails.authMetadata.serviceAccountToken;\n if (token) {\n return { type: 'bearer token', token };\n }\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the user\n const user = kc.getCurrentUser() as User;\n\n return {\n type: 'bearer token',\n token: fs.readFileSync(user.authProvider.config.tokenFile).toString(),\n };\n }\n\n public validateCluster(): Error[] {\n return [];\n }\n\n public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata {\n return {};\n }\n}\n"],"names":["fs"],"mappings":";;;;;;;;AA6BO,MAAM,sBAAA,CAAyD;AAAA;AAAA,EAE5D,wBAAA;AAAA,EAER,MAAa,cACX,cAAA,EAC+B;AAC/B,IAAA,MAAM,EAAE,UAAA,EAAW,GACjB,KAAK,wBAAA,IACJ,MAAM,OAAO,yBAAyB,CAAA;AAEzC,IAAA,MAAM,KAAA,GAAQ,eAAe,YAAA,CAAa,mBAAA;AAC1C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AAAA,IACvC;AACA,IAAA,MAAM,EAAA,GAAK,IAAI,UAAA,EAAW;AAC1B,IAAA,EAAA,CAAG,eAAA,EAAgB;AAEnB,IAAA,MAAM,IAAA,GAAO,GAAG,cAAA,EAAe;AAE/B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,cAAA;AAAA,MACN,KAAA,EAAOA,oBAAG,YAAA,CAAa,IAAA,CAAK,aAAa,MAAA,CAAO,SAAS,EAAE,QAAA;AAAS,KACtE;AAAA,EACF;AAAA,EAEO,eAAA,GAA2B;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEO,oBAAoB,aAAA,EAA2C;AACpE,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildDefaultAuthStrategyMap.cjs.js","sources":["../../src/auth/buildDefaultAuthStrategyMap.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node';\nimport { AksStrategy } from './AksStrategy';\nimport { AwsIamStrategy } from './AwsIamStrategy';\nimport { AzureIdentityStrategy } from './AzureIdentityStrategy';\nimport { GoogleStrategy } from './GoogleStrategy';\nimport { GoogleServiceAccountStrategy } from './GoogleServiceAccountStrategy';\nimport { AnonymousStrategy } from './AnonymousStrategy';\nimport { OidcStrategy } from './OidcStrategy';\nimport { ServiceAccountStrategy } from './ServiceAccountStrategy';\n\nexport const buildDefaultAuthStrategyMap = ({\n logger,\n config,\n}: {\n logger: LoggerService;\n config: RootConfigService;\n}): Map<string, AuthenticationStrategy> =>\n new Map([\n ['aks', new AksStrategy()],\n ['aws', new AwsIamStrategy({ config })],\n ['azure', new AzureIdentityStrategy(logger)],\n ['google', new GoogleStrategy()],\n ['googleServiceAccount', new GoogleServiceAccountStrategy({ config })],\n ['localKubectlProxy', new AnonymousStrategy()],\n ['oidc', new OidcStrategy()],\n ['serviceAccount', new ServiceAccountStrategy()],\n ]);\n"],"names":["AksStrategy","AwsIamStrategy","AzureIdentityStrategy","GoogleStrategy","GoogleServiceAccountStrategy","AnonymousStrategy","OidcStrategy","ServiceAccountStrategy"],"mappings":";;;;;;;;;;;AA6BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,MAAA;AAAA,EACA;AACF,CAAA,yBAIM,GAAA,CAAI;AAAA,EACN,CAAC,KAAA,EAAO,IAAIA,uBAAA,EAAa,CAAA;AAAA,EACzB,CAAC,KAAA,EAAO,IAAIC,8BAAe,EAAE,MAAA,EAAQ,CAAC,CAAA;AAAA,EACtC,CAAC,OAAA,EAAS,IAAIC,2CAAA,CAAsB,MAAM,CAAC,CAAA;AAAA,EAC3C,CAAC,QAAA,EAAU,IAAIC,6BAAA,EAAgB,CAAA;AAAA,EAC/B,CAAC,sBAAA,EAAwB,IAAIC,0DAA6B,EAAE,MAAA,EAAQ,CAAC,CAAA;AAAA,EACrE,CAAC,mBAAA,EAAqB,IAAIC,mCAAA,EAAmB,CAAA;AAAA,EAC7C,CAAC,MAAA,EAAQ,IAAIC,yBAAA,EAAc,CAAA;AAAA,EAC3B,CAAC,gBAAA,EAAkB,IAAIC,6CAAA,EAAwB;AACjD,CAAC;;;;"}
1
+ {"version":3,"file":"buildDefaultAuthStrategyMap.cjs.js","sources":["../../src/auth/buildDefaultAuthStrategyMap.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node';\nimport { AksStrategy } from './AksStrategy';\nimport { AwsIamStrategy } from './AwsIamStrategy';\nimport { AzureIdentityStrategy } from './AzureIdentityStrategy';\nimport { GoogleStrategy } from './GoogleStrategy';\nimport { GoogleServiceAccountStrategy } from './GoogleServiceAccountStrategy';\nimport { AnonymousStrategy } from './AnonymousStrategy';\nimport { OidcStrategy } from './OidcStrategy';\nimport { ServiceAccountStrategy } from './ServiceAccountStrategy';\n\nexport const buildDefaultAuthStrategyMap = ({\n logger,\n config,\n}: {\n logger: LoggerService;\n config: RootConfigService;\n}): Map<string, AuthenticationStrategy> =>\n new Map([\n ['aks', new AksStrategy()],\n ['aws', new AwsIamStrategy({ config })],\n ['azure', new AzureIdentityStrategy(logger)],\n ['google', new GoogleStrategy()],\n ['googleServiceAccount', new GoogleServiceAccountStrategy({ config })],\n ['localKubectlProxy', new AnonymousStrategy()],\n ['oidc', new OidcStrategy()],\n ['serviceAccount', new ServiceAccountStrategy()],\n ]);\n"],"names":["AksStrategy","AwsIamStrategy","AzureIdentityStrategy","GoogleStrategy","GoogleServiceAccountStrategy","AnonymousStrategy","OidcStrategy","ServiceAccountStrategy"],"mappings":";;;;;;;;;;;AA6BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,MAAA;AAAA,EACA;AACF,CAAA,yBAIM,GAAA,CAAI;AAAA,EACN,CAAC,KAAA,EAAO,IAAIA,uBAAA,EAAa,CAAA;AAAA,EACzB,CAAC,KAAA,EAAO,IAAIC,8BAAe,EAAE,MAAA,EAAQ,CAAC,CAAA;AAAA,EACtC,CAAC,OAAA,EAAS,IAAIC,2CAAA,CAAsB,MAAM,CAAC,CAAA;AAAA,EAC3C,CAAC,QAAA,EAAU,IAAIC,6BAAA,EAAgB,CAAA;AAAA,EAC/B,CAAC,sBAAA,EAAwB,IAAIC,0DAA6B,EAAE,MAAA,EAAQ,CAAC,CAAA;AAAA,EACrE,CAAC,mBAAA,EAAqB,IAAIC,mCAAA,EAAmB,CAAA;AAAA,EAC7C,CAAC,MAAA,EAAQ,IAAIC,yBAAA,EAAc,CAAA;AAAA,EAC3B,CAAC,gBAAA,EAAkB,IAAIC,6CAAA,EAAwB;AACjD,CAAC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"requirePermission.cjs.js","sources":["../../src/auth/requirePermission.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport {\n AuthorizeResult,\n type BasicPermission,\n} from '@backstage/plugin-permission-common';\n\nimport express from 'express';\n\nexport async function requirePermission(\n permissionApi: PermissionsService,\n permissionRequired: BasicPermission,\n httpAuth: HttpAuthService,\n req: express.Request,\n) {\n const decision = (\n await permissionApi.authorize(\n [\n {\n permission: permissionRequired,\n },\n ],\n {\n credentials: await httpAuth.credentials(req),\n },\n )\n )[0];\n\n if (decision.result === AuthorizeResult.ALLOW) {\n return;\n }\n throw new NotAllowedError('Unauthorized');\n}\n"],"names":["AuthorizeResult","NotAllowedError"],"mappings":";;;;;AA4BA,eAAsB,iBAAA,CACpB,aAAA,EACA,kBAAA,EACA,QAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAA,CACJ,MAAM,aAAA,CAAc,SAAA;AAAA,IAClB;AAAA,MACE;AAAA,QACE,UAAA,EAAY;AAAA;AACd,KACF;AAAA,IACA;AAAA,MACE,WAAA,EAAa,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG;AAAA;AAC7C,KAEF,CAAC,CAAA;AAEH,EAAA,IAAI,QAAA,CAAS,MAAA,KAAWA,sCAAA,CAAgB,KAAA,EAAO;AAC7C,IAAA;AAAA,EACF;AACA,EAAA,MAAM,IAAIC,uBAAgB,cAAc,CAAA;AAC1C;;;;"}
1
+ {"version":3,"file":"requirePermission.cjs.js","sources":["../../src/auth/requirePermission.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport {\n AuthorizeResult,\n type BasicPermission,\n} from '@backstage/plugin-permission-common';\n\nimport express from 'express';\n\nexport async function requirePermission(\n permissionApi: PermissionsService,\n permissionRequired: BasicPermission,\n httpAuth: HttpAuthService,\n req: express.Request,\n) {\n const decision = (\n await permissionApi.authorize(\n [\n {\n permission: permissionRequired,\n },\n ],\n {\n credentials: await httpAuth.credentials(req),\n },\n )\n )[0];\n\n if (decision.result === AuthorizeResult.ALLOW) {\n return;\n }\n throw new NotAllowedError('Unauthorized');\n}\n"],"names":["AuthorizeResult","NotAllowedError"],"mappings":";;;;;AA4BA,eAAsB,iBAAA,CACpB,aAAA,EACA,kBAAA,EACA,QAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAA,CACJ,MAAM,aAAA,CAAc,SAAA;AAAA,IAClB;AAAA,MACE;AAAA,QACE,UAAA,EAAY;AAAA;AACd,KACF;AAAA,IACA;AAAA,MACE,WAAA,EAAa,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG;AAAA;AAC7C,KAEF,CAAC,CAAA;AAEH,EAAA,IAAI,QAAA,CAAS,MAAA,KAAWA,sCAAA,CAAgB,KAAA,EAAO;AAC7C,IAAA;AAAA,EACF;AACA,EAAA,MAAM,IAAIC,uBAAgB,cAAc,CAAA;AAC1C;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogClusterLocator.cjs.js","sources":["../../src/cluster-locator/CatalogClusterLocator.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n} from '@backstage/plugin-kubernetes-node';\nimport { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS,\n} from '@backstage/plugin-kubernetes-common';\nimport { JsonObject } from '@backstage/types';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { filterCatalogClusterAuthMetadata } from './catalogClusterAuthMetadata';\nimport {\n CatalogClusterLocatorOptions,\n readCatalogClusterLocatorOptions,\n} from './CatalogClusterLocatorOptions';\nimport { validateClusterApiServerUrl } from './validateClusterApiServerUrl';\n\nfunction isObject(obj: unknown): obj is JsonObject {\n return typeof obj === 'object' && obj !== null && !Array.isArray(obj);\n}\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogService: CatalogService;\n private auth: AuthService;\n private readonly options: CatalogClusterLocatorOptions;\n private readonly logger: LoggerService;\n\n constructor(\n catalogService: CatalogService,\n auth: AuthService,\n options: CatalogClusterLocatorOptions,\n logger: LoggerService,\n ) {\n this.catalogService = catalogService;\n this.auth = auth;\n this.options = options;\n this.logger = logger;\n }\n\n static fromConfig(\n catalogApi: CatalogService,\n auth: AuthService,\n clusterLocatorConfig: Config,\n logger: LoggerService,\n ): CatalogClusterLocator {\n return new CatalogClusterLocator(\n catalogApi,\n auth,\n readCatalogClusterLocatorOptions(clusterLocatorConfig),\n logger,\n );\n }\n\n async getClusters(options?: {\n credentials: BackstageCredentials;\n }): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogService.getEntities(\n {\n filter: [filter],\n },\n {\n credentials:\n options?.credentials ?? (await this.auth.getNoneCredentials()),\n },\n );\n\n const clusterDetails: ClusterDetails[] = [];\n for (const entity of clusters.items) {\n const details = await this.toClusterDetails(entity);\n if (details) {\n clusterDetails.push(details);\n }\n }\n return clusterDetails;\n }\n\n private async toClusterDetails(\n entity: Awaited<ReturnType<CatalogService['getEntities']>>['items'][number],\n ): Promise<ClusterDetails | undefined> {\n const name = entity.metadata.name;\n const annotations = entity.metadata.annotations;\n if (!annotations) {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\" without annotations`,\n );\n return undefined;\n }\n\n const authProvider = annotations[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n if (authProvider === 'serviceAccount') {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\": catalog cluster locator does not support the serviceAccount auth provider`,\n );\n return undefined;\n }\n\n const apiServerUrl = annotations[ANNOTATION_KUBERNETES_API_SERVER];\n try {\n await validateClusterApiServerUrl(apiServerUrl, this.options);\n } catch (error) {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\": ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return undefined;\n }\n\n const allowSkipTlsVerify =\n this.options.dangerouslyAllowSkipTLSVerify ?? false;\n const skipTLSVerify =\n allowSkipTlsVerify &&\n annotations[ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY] === 'true';\n\n const clusterDetails: ClusterDetails = {\n name,\n title: entity.metadata.title,\n url: apiServerUrl,\n authMetadata: filterCatalogClusterAuthMetadata(annotations),\n caData: annotations[ANNOTATION_KUBERNETES_API_SERVER_CA],\n skipMetricsLookup:\n annotations[ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP] === 'true',\n skipTLSVerify,\n dashboardUrl: annotations[ANNOTATION_KUBERNETES_DASHBOARD_URL],\n dashboardApp: annotations[ANNOTATION_KUBERNETES_DASHBOARD_APP],\n dashboardParameters: this.getDashboardParameters(annotations),\n };\n\n return clusterDetails;\n }\n\n private getDashboardParameters(\n annotations: Record<string, string>,\n ): JsonObject | undefined {\n const dashboardParamsString =\n annotations[ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS];\n if (dashboardParamsString) {\n try {\n const dashboardParams = JSON.parse(dashboardParamsString);\n return isObject(dashboardParams) ? dashboardParams : undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n }\n}\n"],"names":["readCatalogClusterLocatorOptions","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","validateClusterApiServerUrl","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","filterCatalogClusterAuthMetadata","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS"],"mappings":"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"}
1
+ {"version":3,"file":"CatalogClusterLocator.cjs.js","sources":["../../src/cluster-locator/CatalogClusterLocator.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n} from '@backstage/plugin-kubernetes-node';\nimport { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS,\n} from '@backstage/plugin-kubernetes-common';\nimport { JsonObject } from '@backstage/types';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { filterCatalogClusterAuthMetadata } from './catalogClusterAuthMetadata';\nimport {\n CatalogClusterLocatorOptions,\n readCatalogClusterLocatorOptions,\n} from './CatalogClusterLocatorOptions';\nimport { validateClusterApiServerUrl } from './validateClusterApiServerUrl';\n\nfunction isObject(obj: unknown): obj is JsonObject {\n return typeof obj === 'object' && obj !== null && !Array.isArray(obj);\n}\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogService: CatalogService;\n private auth: AuthService;\n private readonly options: CatalogClusterLocatorOptions;\n private readonly logger: LoggerService;\n\n constructor(\n catalogService: CatalogService,\n auth: AuthService,\n options: CatalogClusterLocatorOptions,\n logger: LoggerService,\n ) {\n this.catalogService = catalogService;\n this.auth = auth;\n this.options = options;\n this.logger = logger;\n }\n\n static fromConfig(\n catalogApi: CatalogService,\n auth: AuthService,\n clusterLocatorConfig: Config,\n logger: LoggerService,\n ): CatalogClusterLocator {\n return new CatalogClusterLocator(\n catalogApi,\n auth,\n readCatalogClusterLocatorOptions(clusterLocatorConfig),\n logger,\n );\n }\n\n async getClusters(options?: {\n credentials: BackstageCredentials;\n }): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogService.getEntities(\n {\n filter: [filter],\n },\n {\n credentials:\n options?.credentials ?? (await this.auth.getNoneCredentials()),\n },\n );\n\n const clusterDetails: ClusterDetails[] = [];\n for (const entity of clusters.items) {\n const details = await this.toClusterDetails(entity);\n if (details) {\n clusterDetails.push(details);\n }\n }\n return clusterDetails;\n }\n\n private async toClusterDetails(\n entity: Awaited<ReturnType<CatalogService['getEntities']>>['items'][number],\n ): Promise<ClusterDetails | undefined> {\n const name = entity.metadata.name;\n const annotations = entity.metadata.annotations;\n if (!annotations) {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\" without annotations`,\n );\n return undefined;\n }\n\n const authProvider = annotations[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n if (authProvider === 'serviceAccount') {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\": catalog cluster locator does not support the serviceAccount auth provider`,\n );\n return undefined;\n }\n\n const apiServerUrl = annotations[ANNOTATION_KUBERNETES_API_SERVER];\n try {\n await validateClusterApiServerUrl(apiServerUrl, this.options);\n } catch (error) {\n this.logger.warn(\n `Ignoring kubernetes-cluster Resource \"${name}\": ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return undefined;\n }\n\n const allowSkipTlsVerify =\n this.options.dangerouslyAllowSkipTLSVerify ?? false;\n const skipTLSVerify =\n allowSkipTlsVerify &&\n annotations[ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY] === 'true';\n\n const clusterDetails: ClusterDetails = {\n name,\n title: entity.metadata.title,\n url: apiServerUrl,\n authMetadata: filterCatalogClusterAuthMetadata(annotations),\n caData: annotations[ANNOTATION_KUBERNETES_API_SERVER_CA],\n skipMetricsLookup:\n annotations[ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP] === 'true',\n skipTLSVerify,\n dashboardUrl: annotations[ANNOTATION_KUBERNETES_DASHBOARD_URL],\n dashboardApp: annotations[ANNOTATION_KUBERNETES_DASHBOARD_APP],\n dashboardParameters: this.getDashboardParameters(annotations),\n };\n\n return clusterDetails;\n }\n\n private getDashboardParameters(\n annotations: Record<string, string>,\n ): JsonObject | undefined {\n const dashboardParamsString =\n annotations[ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS];\n if (dashboardParamsString) {\n try {\n const dashboardParams = JSON.parse(dashboardParamsString);\n return isObject(dashboardParams) ? dashboardParams : undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n }\n}\n"],"names":["readCatalogClusterLocatorOptions","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","validateClusterApiServerUrl","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","filterCatalogClusterAuthMetadata","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","ANNOTATION_KUBERNETES_DASHBOARD_PARAMETERS"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogClusterLocatorOptions.cjs.js","sources":["../../src/cluster-locator/CatalogClusterLocatorOptions.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ValidateClusterApiServerUrlOptions } from './validateClusterApiServerUrl';\n\nexport type CatalogClusterLocatorOptions =\n ValidateClusterApiServerUrlOptions & {\n dangerouslyAllowSkipTLSVerify?: boolean;\n };\n\nexport function readCatalogClusterLocatorOptions(\n config: Config,\n): CatalogClusterLocatorOptions {\n return {\n dangerouslyAllowClusterUrls: config.getOptionalStringArray(\n 'dangerouslyAllowClusterUrls',\n ),\n dangerouslyAllowSkipTLSVerify: config.getOptionalBoolean(\n 'dangerouslyAllowSkipTLSVerify',\n ),\n };\n}\n"],"names":[],"mappings":";;AAwBO,SAAS,iCACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,6BAA6B,MAAA,CAAO,sBAAA;AAAA,MAClC;AAAA,KACF;AAAA,IACA,+BAA+B,MAAA,CAAO,kBAAA;AAAA,MACpC;AAAA;AACF,GACF;AACF;;;;"}
1
+ {"version":3,"file":"CatalogClusterLocatorOptions.cjs.js","sources":["../../src/cluster-locator/CatalogClusterLocatorOptions.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ValidateClusterApiServerUrlOptions } from './validateClusterApiServerUrl';\n\nexport type CatalogClusterLocatorOptions =\n ValidateClusterApiServerUrlOptions & {\n dangerouslyAllowSkipTLSVerify?: boolean;\n };\n\nexport function readCatalogClusterLocatorOptions(\n config: Config,\n): CatalogClusterLocatorOptions {\n return {\n dangerouslyAllowClusterUrls: config.getOptionalStringArray(\n 'dangerouslyAllowClusterUrls',\n ),\n dangerouslyAllowSkipTLSVerify: config.getOptionalBoolean(\n 'dangerouslyAllowSkipTLSVerify',\n ),\n };\n}\n"],"names":[],"mappings":";;AAwBO,SAAS,iCACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,6BAA6B,MAAA,CAAO,sBAAA;AAAA,MAClC;AAAA,KACF;AAAA,IACA,+BAA+B,MAAA,CAAO,kBAAA;AAAA,MACpC;AAAA;AACF,GACF;AACF;;"}