From 87737a8155075a1bf4e31a9c340c3d26b042dec0 Mon Sep 17 00:00:00 2001 From: armandocomellas1 Date: Fri, 12 Jan 2024 16:09:42 -0600 Subject: [PATCH 1/4] Added config.getString() method to check if kubernetes.config has googleServiceAccount property Signed-off-by: armandocomellas1 --- docs/features/kubernetes/configuration.md | 13 +++++++++++++ .../src/cluster-locator/GkeClusterLocator.ts | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index 494e51320a..dc135b995d 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -341,6 +341,7 @@ For example: - type: 'gke' projectId: 'gke-clusters' region: 'europe-west1' # optional + authProvider: 'google' # optional skipTLSVerify: false # optional skipMetricsLookup: false # optional exposeDashboard: false # optional @@ -365,6 +366,18 @@ The Google Cloud project to look for Kubernetes clusters in. The Google Cloud region to look for Kubernetes clusters in. Defaults to all regions. +##### `authProvider` (optional) + +Set the authentication method for discovering clusters and gathering information +about resources. + +Defaults to `google` which leverages the logged in user's Google OAuth credentials. + +Set to `googleServiceAccount` to leverage +Application Default Credentials (https://cloud.google.com/docs/authentication/application-default-credentials). +To use a service account JSON key (not recommended), set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable +on the Backstage backend to the path of the service account key file. + ##### `skipTLSVerify` (optional) This determines whether the Kubernetes client verifies the TLS certificate diff --git a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts index 74e7ebc9af..a3b39f2b08 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts @@ -29,6 +29,7 @@ interface MatchResourceLabelEntry { type GkeClusterLocatorOptions = { projectId: string; + authProvider: string; region?: string; skipTLSVerify?: boolean; skipMetricsLookup?: boolean; @@ -54,8 +55,21 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { return { key: mrl.getString('key'), value: mrl.getString('value') }; }) ?? []; + let storeAuthProviderString: string; + let getGkeProperty; + try { + getGkeProperty = config.getString('authProvider'); + } catch (err) { + getGkeProperty = 'google'; + } + if (getGkeProperty === 'googleServiceAccount') { + storeAuthProviderString = 'googleServiceAccount'; + } else { + storeAuthProviderString = 'google'; + } const options = { projectId: config.getString('projectId'), + authProvider: storeAuthProviderString, region: config.getOptionalString('region') ?? '-', skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false, skipMetricsLookup: @@ -97,6 +111,7 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { const { projectId, region, + authProvider, skipTLSVerify, skipMetricsLookup, exposeDashboard, @@ -121,7 +136,7 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { // TODO filter out clusters which don't have name or endpoint name: r.name ?? 'unknown', url: `https://${r.endpoint ?? ''}`, - authMetadata: { [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google' }, + authMetadata: { [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: authProvider }, skipTLSVerify, skipMetricsLookup, ...(exposeDashboard From 7278d80169bb9e9bf4f4c0491275b95a00bbe909 Mon Sep 17 00:00:00 2001 From: armandocomellas1 Date: Fri, 12 Jan 2024 18:53:19 -0600 Subject: [PATCH 2/4] Change add some lines in the script GkeClusterLocator.ts to make available login with googleServiceAccount Signed-off-by: armandocomellas1 --- .changeset/many-pugs-change.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/many-pugs-change.md diff --git a/.changeset/many-pugs-change.md b/.changeset/many-pugs-change.md new file mode 100644 index 0000000000..f16efb85aa --- /dev/null +++ b/.changeset/many-pugs-change.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Change add some lines in the script GkeClusterLocator.ts, the implementation consist in adding a piece of code starts in 58 adding some config.getString() method to find out if the app-config.yaml kubernetes config includes the type of Auth as googleServiceAccount From 5d06333af2899e3057d2b9909704afbc06ed8d54 Mon Sep 17 00:00:00 2001 From: armandocomellas1 Date: Mon, 15 Jan 2024 19:27:09 -0600 Subject: [PATCH 3/4] Add a descriptive description at the changeset and add some unit test for three different scenarios Signed-off-by: armandocomellas1 --- .changeset/many-pugs-change.md | 2 +- .../cluster-locator/GkeClusterLocator.test.ts | 103 ++++++++++++++++++ .../src/cluster-locator/GkeClusterLocator.ts | 17 +-- 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/.changeset/many-pugs-change.md b/.changeset/many-pugs-change.md index f16efb85aa..318c571891 100644 --- a/.changeset/many-pugs-change.md +++ b/.changeset/many-pugs-change.md @@ -2,4 +2,4 @@ '@backstage/plugin-kubernetes-backend': patch --- -Change add some lines in the script GkeClusterLocator.ts, the implementation consist in adding a piece of code starts in 58 adding some config.getString() method to find out if the app-config.yaml kubernetes config includes the type of Auth as googleServiceAccount +The purpose of this patch is to add a new login method which is `googleServiceAccount` configuring the kubernetes properties in the app-config.yaml file with authProvider key diff --git a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts index f919561490..849a7839e2 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts @@ -382,5 +382,108 @@ describe('GkeClusterLocator', () => { parent: 'projects/some-project/locations/some-region', }); }); + it('return google login when no authProvider is specified', async () => { + mockedListClusters.mockReturnValueOnce([ + { + clusters: [ + { + name: 'some-cluster', + endpoint: '1.2.3.4', + }, + ], + }, + ]); + + const config: Config = new ConfigReader({ + type: 'gke', + projectId: 'some-project', + }); + + const sut = GkeClusterLocator.fromConfigWithClient(config, { + listClusters: mockedListClusters, + } as any); + + const result = await sut.getClusters(); + + expect(result).toStrictEqual([ + { + name: 'some-cluster', + url: 'https://1.2.3.4', + authMetadata: { [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google' }, + skipTLSVerify: false, + skipMetricsLookup: false, + }, + ]); + }); + it('return googleServiceAccount login when authProvider is specified', async () => { + mockedListClusters.mockReturnValueOnce([ + { + clusters: [ + { + name: 'some-cluster', + endpoint: '1.2.3.4', + }, + ], + }, + ]); + + const config: Config = new ConfigReader({ + type: 'gke', + projectId: 'some-project', + authProvider: 'googleServiceAccount', + }); + + const sut = GkeClusterLocator.fromConfigWithClient(config, { + listClusters: mockedListClusters, + } as any); + + const result = await sut.getClusters(); + + expect(result).toStrictEqual([ + { + name: 'some-cluster', + url: 'https://1.2.3.4', + authMetadata: { + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'googleServiceAccount', + }, + skipTLSVerify: false, + skipMetricsLookup: false, + }, + ]); + }); + it('return google login when authProvider property has invalid value', async () => { + mockedListClusters.mockReturnValueOnce([ + { + clusters: [ + { + name: 'some-cluster', + endpoint: '1.2.3.4', + }, + ], + }, + ]); + + const config: Config = new ConfigReader({ + type: 'gke', + projectId: 'some-project', + authProvider: 'differentValue', + }); + + const sut = GkeClusterLocator.fromConfigWithClient(config, { + listClusters: mockedListClusters, + } as any); + + const result = await sut.getClusters(); + + expect(result).toStrictEqual([ + { + name: 'some-cluster', + url: 'https://1.2.3.4', + authMetadata: { [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google' }, + skipTLSVerify: false, + skipMetricsLookup: false, + }, + ]); + }); }); }); diff --git a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts index a3b39f2b08..03f5bda103 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts @@ -55,18 +55,11 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { return { key: mrl.getString('key'), value: mrl.getString('value') }; }) ?? []; - let storeAuthProviderString: string; - let getGkeProperty; - try { - getGkeProperty = config.getString('authProvider'); - } catch (err) { - getGkeProperty = 'google'; - } - if (getGkeProperty === 'googleServiceAccount') { - storeAuthProviderString = 'googleServiceAccount'; - } else { - storeAuthProviderString = 'google'; - } + const storeAuthProviderString = + config.getOptionalString('authProvider') === 'googleServiceAccount' + ? 'googleServiceAccount' + : 'google'; + const options = { projectId: config.getString('projectId'), authProvider: storeAuthProviderString, From 8e2043b27862dec1a63dd390a6e0adb0c8a069e6 Mon Sep 17 00:00:00 2001 From: armandocomellas1 Date: Wed, 17 Jan 2024 12:57:57 -0600 Subject: [PATCH 4/4] Updated with the new paramter in line 84 with the new paramter authProvider in the config schema Signed-off-by: armandocomellas1 --- plugins/kubernetes-backend/config.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/kubernetes-backend/config.d.ts b/plugins/kubernetes-backend/config.d.ts index e9b5878920..50b0e382b5 100644 --- a/plugins/kubernetes-backend/config.d.ts +++ b/plugins/kubernetes-backend/config.d.ts @@ -81,6 +81,8 @@ export interface Config { /** @visibility frontend */ region?: string; /** @visibility frontend */ + authProvider?: string; + /** @visibility frontend */ skipTLSVerify?: boolean; /** @visibility frontend */ skipMetricsLookup?: boolean;