Merge pull request #22232 from armandocomellas1/gke-service-account

Kubernetes cluster type 'gke' not respecting backend auth
This commit is contained in:
Jamie Klassen
2024-01-18 14:58:49 -05:00
committed by GitHub
5 changed files with 132 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-kubernetes-backend': patch
---
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
+13
View File
@@ -393,6 +393,7 @@ For example:
- type: 'gke'
projectId: 'gke-clusters'
region: 'europe-west1' # optional
authProvider: 'google' # optional
skipTLSVerify: false # optional
skipMetricsLookup: false # optional
exposeDashboard: false # optional
@@ -417,6 +418,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
+2
View File
@@ -84,6 +84,8 @@ export interface Config {
/** @visibility frontend */
region?: string;
/** @visibility frontend */
authProvider?: string;
/** @visibility frontend */
skipTLSVerify?: boolean;
/** @visibility frontend */
skipMetricsLookup?: boolean;
@@ -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,
},
]);
});
});
});
@@ -29,6 +29,7 @@ interface MatchResourceLabelEntry {
type GkeClusterLocatorOptions = {
projectId: string;
authProvider: string;
region?: string;
skipTLSVerify?: boolean;
skipMetricsLookup?: boolean;
@@ -54,8 +55,14 @@ export class GkeClusterLocator implements KubernetesClustersSupplier {
return { key: mrl.getString('key'), value: mrl.getString('value') };
}) ?? [];
const storeAuthProviderString =
config.getOptionalString('authProvider') === 'googleServiceAccount'
? 'googleServiceAccount'
: 'google';
const options = {
projectId: config.getString('projectId'),
authProvider: storeAuthProviderString,
region: config.getOptionalString('region') ?? '-',
skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,
skipMetricsLookup:
@@ -97,6 +104,7 @@ export class GkeClusterLocator implements KubernetesClustersSupplier {
const {
projectId,
region,
authProvider,
skipTLSVerify,
skipMetricsLookup,
exposeDashboard,
@@ -121,7 +129,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