From 5f435833f161f042f3779bcb71d952e894aa3fc8 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Tue, 13 Feb 2024 15:19:15 -0500 Subject: [PATCH 01/14] Documented the way to add a new KubernetesAuthStrategy Signed-off-by: Andres Mauricio Gomez P --- docs/features/kubernetes/authstrategies.md | 314 +++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 docs/features/kubernetes/authstrategies.md diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md new file mode 100644 index 0000000000..d151bac986 --- /dev/null +++ b/docs/features/kubernetes/authstrategies.md @@ -0,0 +1,314 @@ +--- +id: authenticationstrategy +title: Kubernetes Authentication Strategies +description: Authentication Strategies in Kubernetes plugin +--- + +# Kubernetes Auth Strategies + +A Kubernetes Auth Strategy specifies the authentication steps executed on the **server side** to authenticate against a Kubernetes Cluster, +it also defines what authentication metadata info of a kubernetes cluster configuration could be returned to the front-end in case a +**client side auth provider** requires it. + +## Context + +Backstage includes by default some [Kubernetes Auth Providers](./authentication.md) to ease the authentication proccess to +kubernetes clusters, it includes: + +- `Server Side Providers` like `localKubectlProxy` or `serviceAccount` where the same set + of kubernetes permissions are shared and granted among the Backstage users and plugins. +- `Client Side Providers` like `aks` or `oidc` where the user is authenticated with the cluster, getting only the + kubernetes permissions granted to that specific user. + +Although there are `Server Side Providers` and `Client Side Providers`, an auth provider requires to have code on both sides, perhaps one of them doing +most of the authentication job, but notice that not all steps to authenticate against a Kubernetes Cluster are always executed exclusively on the server side or client side. +A Kubernetes authentication flow could require to split the authentication process among steps on the client side **and** steps on the server side. + +## AuthenticationStrategy interface + +This is how the [`AuthenticationStrategy`][2] interface has been defined to state the signature that the Kubernetes AuthStrategy +instances should implement, it defines the authentication steps executed on the **server side** to authenticate against a Kubernetes Cluster. It is similar to [KubernetesAuthProvider](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts#L21) interface who defines the authentication steps on the **client side**. + +```ts title="plugins/kubernetes-node/src/types/types.ts" +export interface AuthenticationStrategy { + getCredential( + clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, + ): Promise; + + presentAuthMetadata(authMetadata: AuthMetadata): AuthMetadata; + + validateCluster(authMetadata: AuthMetadata): Error[]; +} +``` + +The `AuthenticationStrategy` interface defines the following signature: + +- `getCredential`: Executes the steps require on the server side to authenticate against a Kubernetes Cluster. It receives the cluster info on the `clusterDetails` parameter and the authentication data provided from the Client Side on the `authConfig` parameter. +- `presentAuthMetadata`: A Kubernetes Cluster configuration could define authMetadata info (like the [aws provider](authentication.md#aws) does). The `presentAuthMetadata` receives that authMetadata and filters/adds information that could be required by the Front-end in a Client Side authentication process. The Front-end gets this info each time the clusters endpoint is [invoked](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L379). +- `validateCluster`: Applies custom validations on the cluster authMetadata info from the AuthenticationStrategy perspective when it is [being reading](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts#L96) from the Backstage config yaml. + +### KubernetesCredential type + +Something to highlight is that `AuthenticationStrategies` will return a [`KubernetesCredential`](https://github.com/backstage/backstage/blob/0226d424f5a3104239eb9e1eaa9f0cbf29cc1f1c/plugins/kubernetes-node/src/types/types.ts#L140) object from the `getCredential` method with the authentication data to consume a kubernetes cluster, it could be: + +- A bearer token +- A x509 client certificate and key +- It could be an anonymous authentication + +```ts title="plugins/kubernetes-node/src/types/types.ts" +export type KubernetesCredential = + | { type: 'bearer token'; token: string } + | { type: 'x509 client certificate'; cert: string; key: string } + | { type: 'anonymous' }; +``` + +## AuthenticationStrategies examples + +### AksStrategy + +Some kubernetes Authentication Strategies are pretty simple, since the Authentication process was executed on the client side by the `KubernetesAuthProvider`, +So Authentication Strategies like [AksStrategy](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/AksStrategy.ts#L28) or [googleStrategy](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/GoogleStrategy.ts#L29C14-L29C28) are only mapping the info that the respective `KubernetesAuthProvider` was able to get in the client side authentication flow. + +```ts title="plugins/kubernetes-backend/src/auth/AksStrategy.ts" +export class AksStrategy implements AuthenticationStrategy { + public async getCredential( + _: ClusterDetails, + requestAuth: KubernetesRequestAuth, + ): Promise { + const token = requestAuth.aks; + return token + ? { type: 'bearer token', token: token as string } + : { type: 'anonymous' }; + } + + public validateCluster(): Error[] { + return []; + } + + public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata { + return {}; + } +} +``` + +The `AksStrategy` is pretty simple, it is only mapping the token that [`AksKubernetesAuthProvider.ts`](https://github.com/backstage/backstage/blob/f0ffd38136163edd75ae340e5653cf6b349dcbc1/plugins/kubernetes-react/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts#L21) was able to get in the Client Side authentication flow. + +### AwsIamStrategy + +Another AuthenticationStrategy is [`AwsIamStrategy`][3], it is more complex than `AksStrategy`, since it consumes some AWS APIs to get a kubernetes token. + +```ts title="plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts" +export class AwsIamStrategy implements AuthenticationStrategy { + // ... code ... + + public async getCredential( + clusterDetails: ClusterDetails, + ): Promise { + return { + type: 'bearer token', + token: await this.getBearerToken( + clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_CLUSTER_ID] ?? + clusterDetails.name, + clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE], + clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID], + ), + }; + } + + private async getBearerToken( + clusterId: string, + assumeRole?: string, + externalId?: string, + ): Promise { + // ... code ... + + const request = await signer.presign( + { + headers: { + host: `sts.${region}.amazonaws.com`, + 'x-k8s-aws-id': clusterId, + }, + hostname: `sts.${region}.amazonaws.com`, + method: 'GET', + path: '/', + protocol: 'https:', + query: { + Action: 'GetCallerIdentity', + Version: '2011-06-15', + }, + }, + { expiresIn: 0 }, + ); + + // ... code ... + } + + public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata { + return {}; + } + public validateCluster(): Error[] { + return []; + } +} +``` + +## Custom AuthStrategy + +Sometimes you need to add a new way to authenticate against a kubernetes cluster not support by default by Backstage. This is how integrators can bring their own kubernetes auth strategies through the use of the [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder` or through the [AuthStrategyExtensionPoint](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/plugin.ts#L112). So, on the following sections, we are going to introduce a new AuthStrategy for [Pinniped](1), an authentication service for Kubernetes clusters. + +### Custom Pinniped auth strategy in the new backend system + +To add a new AuthStrategy, we need to create a new Pinniped [backend module](../../../backend-system/building-plugins-and-modules/01-index.md#modules) to extend the Kubernetes-Backend plugin. The Pinniped module will interact with the Kubernetes-Backend plugin through the [extension points](../../../backend-system/architecture/05-extension-points.md) registered by the plugin. The Kubernetes-Backend plugin [registers](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-backend/src/plugin.ts#L155) multiple extension points like `kubernetesObjectsProvider`, `kubernetesClusterSupplier`, `kubernetesFetcher`, `kubernetesServiceLocator` and the `kubernetesAuthStrategy`. + +Notice that this guide assumes that you already installed the [Kubernetes Plugin](../installation.md). + +To create the Backend module, run `yarn new`, select `backend-module`. Then fill out: + +``` +? What do you want to create? backend-module - A new backend module +? Enter the ID of the plugin [required] kubernetes +? Enter the ID of the module [required] pinniped +``` + +This will create a new package at `plugins/kubernetes-backend-module-pinniped`. We are going to need also the `@backstage/plugin-kubernetes-node` and `@backstage/plugin-kubernetes-common` dependencies, the `@backstage/plugin-kubernetes-node` houses the [kubernetesAuthStrategyExtensionPoint](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-node/src/extensions.ts#L77) and a [Pinniped Helper](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-node/src/auth/PinnipedHelper.ts#L53) class. + +```bash +# From your Backstage root directory +yarn --cwd plugins/kubernetes-backend-module-pinniped add @backstage/plugin-kubernetes-node +yarn --cwd plugins/kubernetes-backend-module-pinniped add @backstage/plugin-kubernetes-common +``` + +Let's create a new file to house the Pinniped authentication strategy which will implement the `AuthenticationStrategy` interface. + +```ts title="plugins/kubernetes-backend-module-pinniped/src/PinnipedStrategy.ts" +import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; +import { Logger } from 'winston'; +import { + AuthMetadata, + AuthenticationStrategy, + ClusterDetails, + KubernetesCredential, + PinnipedClientCerts, + PinnipedHelper, + PinnipedParameters, +} from '@backstage/plugin-kubernetes-node'; + +export class PinnipedStrategy implements AuthenticationStrategy { + private pinnipedHelper: PinnipedHelper; + + constructor(private readonly logger: Logger) { + this.pinnipedHelper = new PinnipedHelper(logger); + } + + public async getCredential( + clusterDetails: ClusterDetails, + requestAuth: KubernetesRequestAuth, + ): Promise { + const params: PinnipedParameters = { + token: requestAuth.token as string, + authenticator: { + apiGroup: 'authentication.concierge.pinniped.dev', + kind: 'JWTAuthenticator', + name: 'supervisor', + }, + tokenCredentialRequest: { + apiGroup: 'login.concierge.pinniped.dev/v1alpha1', + }, + }; + + const x509Data: PinnipedClientCerts = + await this.pinnipedHelper.tokenCredentialRequest(clusterDetails, params); + return { + type: 'x509 client certificate', + cert: x509Data.cert, + key: x509Data.key, + }; + } + + public validateCluster(): Error[] { + return []; + } + + public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata { + return {}; + } +} +``` + +The `PinnipedStrategy` implements the `AuthenticationStrategy` interface, it uses the PinnipedHelper class to exchange the clusterIdToken ( created by a custom Pinniped client-side `KubernetesAuthProvider` ) for a x509 certificate, certificate that will allow us to consume the kubernetes cluster. + +> Notice that the PinnipedHelper class will help you only to exchange the token, It doesn't introduce a cache layer, something that your strategy could introduce. + +Finally we could use the `kubernetesAuthStrategyExtensionPoint` to register our new PinnipedStrategy. + +```ts title="plugins/kubernetes-backend-module-pinniped/src/module.ts" +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { + AuthenticationStrategy, + kubernetesAuthStrategyExtensionPoint, +} from '@backstage/plugin-kubernetes-node'; +import { PinnipedStrategy } from './PinnipedStrategy'; +import { loggerToWinstonLogger } from '@backstage/backend-common'; + +export const kubernetesModulePinniped = createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'pinniped', + register(reg) { + reg.registerInit({ + deps: { + logger: coreServices.logger, + authStrategy: kubernetesAuthStrategyExtensionPoint, + }, + async init({ logger, authStrategy }) { + const winstonLogger = loggerToWinstonLogger(logger); + const pinnipedStrategy: AuthenticationStrategy = new PinnipedStrategy( + winstonLogger, + ); + authStrategy.addAuthStrategy('pinniped', pinnipedStrategy); + }, + }); + }, +}); +``` + +### Custom Pinniped auth strategy in the old backend system + +To add a new AuthStrategy, You could use [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder`. +We are going to reuse the `PinnipedStrategy` created on the previous section. So when setting up the [Kubernetes Backend plugin](../installation.md#adding-kubernetes-backend-plugin), you could add a new Strategy: + +```ts title="packages/backend/src/plugins/kubernetes.ts" +import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; +import { Router } from 'express'; +import { PluginEnvironment } from '../types'; +import { CatalogClient } from '@backstage/catalog-client'; +import { loggerToWinstonLogger } from '@backstage/backend-common'; +import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; +import { PinnipedStrategy } from '@internal/plugin-kubernetes-backend-module-pinniped'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const catalogApi = new CatalogClient({ discoveryApi: env.discovery }); + const winstonLogger = loggerToWinstonLogger(env.logger); + const pinnipedStrategy: AuthenticationStrategy = new PinnipedStrategy( + winstonLogger, + ); + const { router } = await KubernetesBuilder.createBuilder({ + logger: env.logger, + config: env.config, + catalogApi, + permissions: env.permissions, + }) + .addAuthStrategy('pinniped', pinnipedStrategy) + .build(); + return router; +} +``` + +[1]: https://pinniped.dev/ +[2]: https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-node/src/types/types.ts#L149 +[3]: https://github.com/backstage/backstage/blob/f0ffd38136163edd75ae340e5653cf6b349dcbc1/plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts#L52C40-L52C62 From ab5b7eebccd569b204a326fb618ab85fb318f2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:28:25 -0500 Subject: [PATCH 02/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index d151bac986..f95a202bf6 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -6,7 +6,7 @@ description: Authentication Strategies in Kubernetes plugin # Kubernetes Auth Strategies -A Kubernetes Auth Strategy specifies the authentication steps executed on the **server side** to authenticate against a Kubernetes Cluster, +A Kubernetes Auth Strategy specifies the authentication steps executed on the **server side** to authenticate against a Kubernetes cluster, it also defines what authentication metadata info of a kubernetes cluster configuration could be returned to the front-end in case a **client side auth provider** requires it. From e293e41ad5ca4c6db0340982ed8b273eaf82c0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:28:48 -0500 Subject: [PATCH 03/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index f95a202bf6..6b8ee45fc4 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -7,7 +7,7 @@ description: Authentication Strategies in Kubernetes plugin # Kubernetes Auth Strategies A Kubernetes Auth Strategy specifies the authentication steps executed on the **server side** to authenticate against a Kubernetes cluster, -it also defines what authentication metadata info of a kubernetes cluster configuration could be returned to the front-end in case a +it also defines what authentication metadata about a Kubernetes cluster is returned to the front-end in case a **client side auth provider** requires it. ## Context From a27d7d3bd58ec64c852d14ee2bde8aaea1a18d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:29:29 -0500 Subject: [PATCH 04/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index 6b8ee45fc4..e6e43ab1cf 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -20,9 +20,9 @@ kubernetes clusters, it includes: - `Client Side Providers` like `aks` or `oidc` where the user is authenticated with the cluster, getting only the kubernetes permissions granted to that specific user. -Although there are `Server Side Providers` and `Client Side Providers`, an auth provider requires to have code on both sides, perhaps one of them doing -most of the authentication job, but notice that not all steps to authenticate against a Kubernetes Cluster are always executed exclusively on the server side or client side. -A Kubernetes authentication flow could require to split the authentication process among steps on the client side **and** steps on the server side. +Although there are `Server Side Providers` and `Client Side Providers`, authenticating with a cluster requires code on both sides. Perhaps one of them does +most of the job, but in general not all steps to authenticate against a Kubernetes cluster are always executed exclusively on the server side or client side. +A Kubernetes authentication flow could require splitting the authentication process among steps on the client side **and** steps on the server side. ## AuthenticationStrategy interface From 5adfbb4cf08897b9caabd5bdcde8d2696da568c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:30:10 -0500 Subject: [PATCH 05/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index e6e43ab1cf..6556472d55 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -45,8 +45,8 @@ export interface AuthenticationStrategy { The `AuthenticationStrategy` interface defines the following signature: - `getCredential`: Executes the steps require on the server side to authenticate against a Kubernetes Cluster. It receives the cluster info on the `clusterDetails` parameter and the authentication data provided from the Client Side on the `authConfig` parameter. -- `presentAuthMetadata`: A Kubernetes Cluster configuration could define authMetadata info (like the [aws provider](authentication.md#aws) does). The `presentAuthMetadata` receives that authMetadata and filters/adds information that could be required by the Front-end in a Client Side authentication process. The Front-end gets this info each time the clusters endpoint is [invoked](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L379). -- `validateCluster`: Applies custom validations on the cluster authMetadata info from the AuthenticationStrategy perspective when it is [being reading](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts#L96) from the Backstage config yaml. +- `presentAuthMetadata`: A Kubernetes cluster configuration could include extra metadata specific to a given authentication flow (like [AWS clusters](authentication.md#aws) do). The `presentAuthMetadata` method receives that metadata and filters/adds information that could be required by the front-end in a client side authentication process. The front-end gets this info via the [`/clusters` endpoint](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L379). +- `validateCluster`: Allows strategies to reject clusters if they have invalid metadata. Currently this method only gets invoked when [reading](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts#L96) clusters from the app-config. ### KubernetesCredential type From 377a0a95067e70970672f55f90c7a282441d5947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:30:34 -0500 Subject: [PATCH 06/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index 6556472d55..6d33ff0769 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -50,7 +50,7 @@ The `AuthenticationStrategy` interface defines the following signature: ### KubernetesCredential type -Something to highlight is that `AuthenticationStrategies` will return a [`KubernetesCredential`](https://github.com/backstage/backstage/blob/0226d424f5a3104239eb9e1eaa9f0cbf29cc1f1c/plugins/kubernetes-node/src/types/types.ts#L140) object from the `getCredential` method with the authentication data to consume a kubernetes cluster, it could be: +Something to highlight is that the `getCredential` method on an `AuthenticationStrategy` will return a [`KubernetesCredential`](https://github.com/backstage/backstage/blob/0226d424f5a3104239eb9e1eaa9f0cbf29cc1f1c/plugins/kubernetes-node/src/types/types.ts#L140) object representing a single method of authenticating with a Kubernetes cluster. This value can be: - A bearer token - A x509 client certificate and key From e3fdcec252d34bc3a55c2f32de3d9639d4d172b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:30:42 -0500 Subject: [PATCH 07/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index 6d33ff0769..af2da6bdfd 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -54,7 +54,7 @@ Something to highlight is that the `getCredential` method on an `AuthenticationS - A bearer token - A x509 client certificate and key -- It could be an anonymous authentication +- Anonymous authentication ```ts title="plugins/kubernetes-node/src/types/types.ts" export type KubernetesCredential = From 18fe10f7d8898c79b03b5c8925a26e4b9ee48add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:31:11 -0500 Subject: [PATCH 08/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index af2da6bdfd..d8291ccb93 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -26,8 +26,7 @@ A Kubernetes authentication flow could require splitting the authentication proc ## AuthenticationStrategy interface -This is how the [`AuthenticationStrategy`][2] interface has been defined to state the signature that the Kubernetes AuthStrategy -instances should implement, it defines the authentication steps executed on the **server side** to authenticate against a Kubernetes Cluster. It is similar to [KubernetesAuthProvider](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts#L21) interface who defines the authentication steps on the **client side**. +The [`AuthenticationStrategy`][2] interface defines the steps executed on the **server side** to authenticate against a Kubernetes cluster. It is similar to the [`KubernetesAuthProvider`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts#L21) interface, which defines corresponding steps on the **client side**. ```ts title="plugins/kubernetes-node/src/types/types.ts" export interface AuthenticationStrategy { From 7c8aa9871983f263dd7182194e33590fd93c6b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Wed, 21 Feb 2024 17:31:39 -0500 Subject: [PATCH 09/14] Update docs/features/kubernetes/authstrategies.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authstrategies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authstrategies.md index d8291ccb93..3c3630225f 100644 --- a/docs/features/kubernetes/authstrategies.md +++ b/docs/features/kubernetes/authstrategies.md @@ -67,7 +67,7 @@ export type KubernetesCredential = ### AksStrategy Some kubernetes Authentication Strategies are pretty simple, since the Authentication process was executed on the client side by the `KubernetesAuthProvider`, -So Authentication Strategies like [AksStrategy](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/AksStrategy.ts#L28) or [googleStrategy](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/GoogleStrategy.ts#L29C14-L29C28) are only mapping the info that the respective `KubernetesAuthProvider` was able to get in the client side authentication flow. +So Authentication Strategies like [`AksStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/AksStrategy.ts#L28) or [`GoogleStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/auth/GoogleStrategy.ts#L29C14-L29C28) only map the info that the corresponding `KubernetesAuthProvider` returned on the client side. ```ts title="plugins/kubernetes-backend/src/auth/AksStrategy.ts" export class AksStrategy implements AuthenticationStrategy { From 52c97b56986b8c194bec5bcb31b90caa6738d08b Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Thu, 22 Feb 2024 11:14:55 -0500 Subject: [PATCH 10/14] Renaming authenticationstrategy file Signed-off-by: Andres Mauricio Gomez P --- .../kubernetes/{authstrategies.md => authenticationstrategy.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/features/kubernetes/{authstrategies.md => authenticationstrategy.md} (100%) diff --git a/docs/features/kubernetes/authstrategies.md b/docs/features/kubernetes/authenticationstrategy.md similarity index 100% rename from docs/features/kubernetes/authstrategies.md rename to docs/features/kubernetes/authenticationstrategy.md From 575b35d5be715122967206f4604643b6b46eb530 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Thu, 22 Feb 2024 11:16:37 -0500 Subject: [PATCH 11/14] Adding authenticationstrategy to sidebar Signed-off-by: Andres Mauricio Gomez P --- microsite/sidebars.json | 1 + 1 file changed, 1 insertion(+) diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 3c6eedf7c1..f82a7d1e9a 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -107,6 +107,7 @@ "features/kubernetes/installation", "features/kubernetes/configuration", "features/kubernetes/authentication", + "features/kubernetes/authenticationstrategy", "features/kubernetes/troubleshooting", "features/kubernetes/proxy" ] From 61250364fb0147ed06f37953732503180b7eedd1 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Thu, 22 Feb 2024 13:36:11 -0500 Subject: [PATCH 12/14] Fixing references in authenticationstrategy docs Signed-off-by: Andres Mauricio Gomez P --- docs/features/kubernetes/authenticationstrategy.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/features/kubernetes/authenticationstrategy.md b/docs/features/kubernetes/authenticationstrategy.md index 3c3630225f..ab79970eeb 100644 --- a/docs/features/kubernetes/authenticationstrategy.md +++ b/docs/features/kubernetes/authenticationstrategy.md @@ -1,6 +1,7 @@ --- id: authenticationstrategy title: Kubernetes Authentication Strategies +sidebar_label: Authentication Strategies description: Authentication Strategies in Kubernetes plugin --- @@ -154,13 +155,13 @@ export class AwsIamStrategy implements AuthenticationStrategy { ## Custom AuthStrategy -Sometimes you need to add a new way to authenticate against a kubernetes cluster not support by default by Backstage. This is how integrators can bring their own kubernetes auth strategies through the use of the [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder` or through the [AuthStrategyExtensionPoint](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/plugin.ts#L112). So, on the following sections, we are going to introduce a new AuthStrategy for [Pinniped](1), an authentication service for Kubernetes clusters. +Sometimes you need to add a new way to authenticate against a kubernetes cluster not support by default by Backstage. This is how integrators can bring their own kubernetes auth strategies through the use of the [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder` or through the [AuthStrategyExtensionPoint](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/plugin.ts#L112). So, on the following sections, we are going to introduce a new AuthStrategy for [Pinniped][1], an authentication service for Kubernetes clusters. ### Custom Pinniped auth strategy in the new backend system -To add a new AuthStrategy, we need to create a new Pinniped [backend module](../../../backend-system/building-plugins-and-modules/01-index.md#modules) to extend the Kubernetes-Backend plugin. The Pinniped module will interact with the Kubernetes-Backend plugin through the [extension points](../../../backend-system/architecture/05-extension-points.md) registered by the plugin. The Kubernetes-Backend plugin [registers](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-backend/src/plugin.ts#L155) multiple extension points like `kubernetesObjectsProvider`, `kubernetesClusterSupplier`, `kubernetesFetcher`, `kubernetesServiceLocator` and the `kubernetesAuthStrategy`. +To add a new AuthStrategy, we need to create a new Pinniped [backend module](../../backend-system/building-plugins-and-modules/01-index.md#modules) to extend the Kubernetes-Backend plugin. The Pinniped module will interact with the Kubernetes-Backend plugin through the [extension points](../../backend-system/architecture/05-extension-points.md) registered by the plugin. The Kubernetes-Backend plugin [registers](https://github.com/backstage/backstage/blob/ebe7afad9d19f279469168ca0d4feceb92c1ad36/plugins/kubernetes-backend/src/plugin.ts#L155) multiple extension points like `kubernetesObjectsProvider`, `kubernetesClusterSupplier`, `kubernetesFetcher`, `kubernetesServiceLocator` and the `kubernetesAuthStrategy`. -Notice that this guide assumes that you already installed the [Kubernetes Plugin](../installation.md). +Notice that this guide assumes that you already installed the [Kubernetes Plugin](./installation.md). To create the Backend module, run `yarn new`, select `backend-module`. Then fill out: @@ -277,7 +278,7 @@ export const kubernetesModulePinniped = createBackendModule({ ### Custom Pinniped auth strategy in the old backend system To add a new AuthStrategy, You could use [`addAuthStrategy`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts#L211) method on `KubernetesBuilder`. -We are going to reuse the `PinnipedStrategy` created on the previous section. So when setting up the [Kubernetes Backend plugin](../installation.md#adding-kubernetes-backend-plugin), you could add a new Strategy: +We are going to reuse the `PinnipedStrategy` created on the previous section. So when setting up the [Kubernetes Backend plugin](./installation.md#adding-kubernetes-backend-plugin), you could add a new Strategy: ```ts title="packages/backend/src/plugins/kubernetes.ts" import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; @@ -308,6 +309,6 @@ export default async function createPlugin( } ``` -[1]: https://pinniped.dev/ +[1]: https://pinniped.dev [2]: https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/kubernetes-node/src/types/types.ts#L149 [3]: https://github.com/backstage/backstage/blob/f0ffd38136163edd75ae340e5653cf6b349dcbc1/plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts#L52C40-L52C62 From 08ae12aaac715f0d78cfd9b670878e552dcfa216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Tue, 27 Feb 2024 09:08:16 -0500 Subject: [PATCH 13/14] Update docs/features/kubernetes/authenticationstrategy.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Vincenzo Scamporlino Signed-off-by: Andrés Mauricio Gómez P --- docs/features/kubernetes/authenticationstrategy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/kubernetes/authenticationstrategy.md b/docs/features/kubernetes/authenticationstrategy.md index ab79970eeb..864c45ed3c 100644 --- a/docs/features/kubernetes/authenticationstrategy.md +++ b/docs/features/kubernetes/authenticationstrategy.md @@ -1,5 +1,5 @@ --- -id: authenticationstrategy +id: authentication-strategies title: Kubernetes Authentication Strategies sidebar_label: Authentication Strategies description: Authentication Strategies in Kubernetes plugin From 692cccd58299b4e98072e71fc298af87f9c433ac Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Tue, 27 Feb 2024 09:38:11 -0500 Subject: [PATCH 14/14] Changing sidebars to use the new name for authentication-strategies Signed-off-by: Andres Mauricio Gomez P --- docs/features/kubernetes/authenticationstrategy.md | 14 +++++++++----- microsite/sidebars.json | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/features/kubernetes/authenticationstrategy.md b/docs/features/kubernetes/authenticationstrategy.md index 864c45ed3c..a7d093248a 100644 --- a/docs/features/kubernetes/authenticationstrategy.md +++ b/docs/features/kubernetes/authenticationstrategy.md @@ -193,6 +193,7 @@ import { PinnipedHelper, PinnipedParameters, } from '@backstage/plugin-kubernetes-node'; +import { JsonObject } from '@backstage/types'; export class PinnipedStrategy implements AuthenticationStrategy { private pinnipedHelper: PinnipedHelper; @@ -206,7 +207,8 @@ export class PinnipedStrategy implements AuthenticationStrategy { requestAuth: KubernetesRequestAuth, ): Promise { const params: PinnipedParameters = { - token: requestAuth.token as string, + token: + ((requestAuth.pinniped as JsonObject)?.clusteridtoken as string) || '', authenticator: { apiGroup: 'authentication.concierge.pinniped.dev', kind: 'JWTAuthenticator', @@ -230,13 +232,15 @@ export class PinnipedStrategy implements AuthenticationStrategy { return []; } - public presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata { - return {}; - } + presentAuthMetadata: (authMetadata: AuthMetadata): AuthMetadata => { + return { + audience: authMetadata['kubernetes.io/x-pinniped-audience'], + }; + }, } ``` -The `PinnipedStrategy` implements the `AuthenticationStrategy` interface, it uses the PinnipedHelper class to exchange the clusterIdToken ( created by a custom Pinniped client-side `KubernetesAuthProvider` ) for a x509 certificate, certificate that will allow us to consume the kubernetes cluster. +The `PinnipedStrategy` implements the `AuthenticationStrategy` interface, it uses the PinnipedHelper class to exchange the clusterIdToken ( created by a custom Pinniped client-side `KubernetesAuthProvider` ) for a x509 certificate, certificate that will allow us to consume the kubernetes cluster. It also returns the audience value to the front-end through `presentAuthMetadata`. > Notice that the PinnipedHelper class will help you only to exchange the token, It doesn't introduce a cache layer, something that your strategy could introduce. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index f82a7d1e9a..0d5dc37b46 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -107,7 +107,7 @@ "features/kubernetes/installation", "features/kubernetes/configuration", "features/kubernetes/authentication", - "features/kubernetes/authenticationstrategy", + "features/kubernetes/authentication-strategies", "features/kubernetes/troubleshooting", "features/kubernetes/proxy" ]