Add oidc authProvider to kubernetes-backend plugin
Signed-off-by: Daniel Bravo <dbravo@vmware.com>
This commit is contained in:
+3
-1
@@ -52,7 +52,9 @@ export interface Config {
|
||||
/** @visibility secret */
|
||||
serviceAccountToken?: string;
|
||||
/** @visibility frontend */
|
||||
authProvider: 'aws' | 'google' | 'serviceAccount' | 'azure';
|
||||
authProvider: 'aws' | 'google' | 'serviceAccount' | 'azure' | 'oidc';
|
||||
/** @visibility frontend */
|
||||
oidcTokenProvider?: string;
|
||||
/** @visibility frontend */
|
||||
skipTLSVerify?: boolean;
|
||||
}>;
|
||||
|
||||
@@ -64,6 +64,11 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier {
|
||||
case 'azure': {
|
||||
return clusterDetails;
|
||||
}
|
||||
case 'oidc': {
|
||||
const oidcTokenProvider = c.getString('oidcTokenProvider');
|
||||
|
||||
return { oidcTokenProvider, ...clusterDetails };
|
||||
}
|
||||
case 'serviceAccount': {
|
||||
return clusterDetails;
|
||||
}
|
||||
|
||||
+7
@@ -19,6 +19,7 @@ import { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator
|
||||
import { KubernetesAuthTranslatorGenerator } from './KubernetesAuthTranslatorGenerator';
|
||||
import { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernetesAuthTranslator';
|
||||
import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';
|
||||
import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';
|
||||
|
||||
describe('getKubernetesAuthTranslatorInstance', () => {
|
||||
const sut = KubernetesAuthTranslatorGenerator;
|
||||
@@ -43,6 +44,12 @@ describe('getKubernetesAuthTranslatorInstance', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('can return an auth translator for oidc auth', () => {
|
||||
const authTranslator: KubernetesAuthTranslator =
|
||||
sut.getKubernetesAuthTranslatorInstance('oidc');
|
||||
expect(authTranslator instanceof OidcKubernetesAuthTranslator).toBe(true);
|
||||
});
|
||||
|
||||
it('throws an error when asked for an auth translator for an unsupported auth type', () => {
|
||||
expect(() => sut.getKubernetesAuthTranslatorInstance('linode')).toThrow(
|
||||
'authProvider "linode" has no KubernetesAuthTranslator associated with it',
|
||||
|
||||
+4
@@ -20,6 +20,7 @@ import { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernet
|
||||
import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';
|
||||
import { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';
|
||||
import { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';
|
||||
import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';
|
||||
|
||||
export class KubernetesAuthTranslatorGenerator {
|
||||
static getKubernetesAuthTranslatorInstance(
|
||||
@@ -41,6 +42,9 @@ export class KubernetesAuthTranslatorGenerator {
|
||||
case 'googleServiceAccount': {
|
||||
return new GoogleServiceAccountAuthTranslator();
|
||||
}
|
||||
case 'oidc': {
|
||||
return new OidcKubernetesAuthTranslator();
|
||||
}
|
||||
default: {
|
||||
throw new Error(
|
||||
`authProvider "${authProvider}" has no KubernetesAuthTranslator associated with it`,
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
describe('OidcKubernetesAuthTranslator tests', () => {
|
||||
const at = new OidcKubernetesAuthTranslator();
|
||||
const entity: Entity = {
|
||||
apiVersion: 'v1',
|
||||
kind: 'service',
|
||||
metadata: { name: 'test' },
|
||||
};
|
||||
const baseClusterDetails: ClusterDetails = {
|
||||
name: 'test',
|
||||
authProvider: 'oidc',
|
||||
url: '',
|
||||
};
|
||||
|
||||
it('returns cluster details with auth token', async () => {
|
||||
const details = await at.decorateClusterDetailsWithAuth(
|
||||
{
|
||||
oidcTokenProvider: 'okta',
|
||||
...baseClusterDetails,
|
||||
},
|
||||
{
|
||||
auth: { okta: 'fakeToken' },
|
||||
entity,
|
||||
},
|
||||
);
|
||||
|
||||
expect(details.serviceAccountToken).toBe('fakeToken');
|
||||
});
|
||||
|
||||
it('returns error when oidcTokenProvider is not configured', async () => {
|
||||
await expect(
|
||||
at.decorateClusterDetailsWithAuth(baseClusterDetails, { entity }),
|
||||
).rejects.toThrow(
|
||||
'oidc authProvider requires a configured oidcTokenProvider',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error when token is not included in request body', async () => {
|
||||
await expect(
|
||||
at.decorateClusterDetailsWithAuth(
|
||||
{ oidcTokenProvider: 'okta', ...baseClusterDetails },
|
||||
{ entity },
|
||||
),
|
||||
).rejects.toThrow('Auth token not found under auth.okta in request body');
|
||||
});
|
||||
});
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { KubernetesAuthTranslator } from './types';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
|
||||
|
||||
export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
||||
async decorateClusterDetailsWithAuth(
|
||||
clusterDetails: ClusterDetails,
|
||||
requestBody: KubernetesRequestBody,
|
||||
): Promise<ClusterDetails> {
|
||||
const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(
|
||||
{},
|
||||
clusterDetails,
|
||||
);
|
||||
|
||||
const { oidcTokenProvider } = clusterDetails;
|
||||
|
||||
if (!oidcTokenProvider || oidcTokenProvider === '') {
|
||||
throw new Error(
|
||||
`oidc authProvider requires a configured oidcTokenProvider`,
|
||||
);
|
||||
}
|
||||
|
||||
const authToken: string | undefined = requestBody.auth?.[oidcTokenProvider];
|
||||
|
||||
if (authToken) {
|
||||
clusterDetailsWithAuthToken.serviceAccountToken = authToken;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Auth token not found under auth.${oidcTokenProvider} in request body`,
|
||||
);
|
||||
}
|
||||
return clusterDetailsWithAuthToken;
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,10 @@ export interface ClusterDetails {
|
||||
url: string;
|
||||
authProvider: string;
|
||||
serviceAccountToken?: string | undefined;
|
||||
/**
|
||||
* oidc provider used to get id tokens to authenticate against kubernetes
|
||||
*/
|
||||
oidcTokenProvider?: string | undefined;
|
||||
skipTLSVerify?: boolean;
|
||||
/**
|
||||
* Whether to skip the lookup to the metrics server to retrieve pod resource usage.
|
||||
|
||||
@@ -30,7 +30,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export interface KubernetesRequestBody {
|
||||
auth?: {
|
||||
google?: string;
|
||||
[key: string]: string;
|
||||
};
|
||||
entity: Entity;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user