Add proxy method to KubernetesBackendClient
Signed-off-by: Ruben Vallejo <rvallejo@vmware.com>
This commit is contained in:
@@ -23,17 +23,22 @@ import {
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
|
||||
export class KubernetesBackendClient implements KubernetesApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
private readonly kubernetesAuthProvidersApi: KubernetesAuthProvidersApi;
|
||||
|
||||
constructor(options: {
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
kubernetesAuthProvidersApi: KubernetesAuthProvidersApi;
|
||||
}) {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
this.identityApi = options.identityApi;
|
||||
this.kubernetesAuthProvidersApi = options.kubernetesAuthProvidersApi;
|
||||
}
|
||||
|
||||
private async handleResponse(response: Response): Promise<any> {
|
||||
@@ -110,4 +115,68 @@ export class KubernetesBackendClient implements KubernetesApi {
|
||||
|
||||
return (await this.handleResponse(response)).items;
|
||||
}
|
||||
|
||||
async proxy(
|
||||
clusterName: string,
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
): Promise<Response> {
|
||||
const { authProvider } = await this.getCluster(clusterName);
|
||||
const token = await this.getBearerToken(authProvider);
|
||||
|
||||
const url = `${await this.discoveryApi.getBaseUrl(
|
||||
'kubernetes',
|
||||
)}/proxy${path}`;
|
||||
const headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
...init?.headers,
|
||||
[`X-Kubernetes-Cluster`]: clusterName,
|
||||
};
|
||||
const response = await fetch(url, { ...init, headers });
|
||||
return this.handleResponse(response);
|
||||
}
|
||||
|
||||
private async getCluster(
|
||||
clusterName: string,
|
||||
): Promise<{ name: string; authProvider: string }> {
|
||||
const cluster = await this.getClusters().then(clusters =>
|
||||
clusters.find(c => c.name === clusterName),
|
||||
);
|
||||
if (!cluster) {
|
||||
throw new NotFoundError(`Cluster ${clusterName} not found`);
|
||||
}
|
||||
return cluster;
|
||||
}
|
||||
|
||||
private async getBearerToken(authProvider: string): Promise<string> {
|
||||
// const { auth } =
|
||||
// await this.kubernetesAuthProvidersApi.decorateRequestBodyForAuth(
|
||||
// authProvider,
|
||||
// {
|
||||
// entity: {
|
||||
// apiVersion: 'v1',
|
||||
// kind: 'Pods',
|
||||
// metadata: {
|
||||
// name: 'podName',
|
||||
// annotations: {
|
||||
// 'backstage.io/kubernetes-label-selector': 'k8s-app=kube-dns',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
return await this.kubernetesAuthProvidersApi.getBearerToken(authProvider);
|
||||
|
||||
// if (auth) {
|
||||
// if (authProvider === 'google' && auth.google) {
|
||||
// return auth.google;
|
||||
// } else if (authProvider.startsWith('oidc.') && auth.oidc) {
|
||||
// const oidcTokenProvider = authProvider.replace(/^oidc\./, '');
|
||||
// return auth.oidc[oidcTokenProvider];
|
||||
// } else {
|
||||
// throw new Error(`invalid auth provider '${authProvider}'`);
|
||||
// }
|
||||
// }
|
||||
// return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,4 +43,9 @@ export interface KubernetesApi {
|
||||
getCustomObjectsByEntity(
|
||||
request: CustomObjectsByEntityRequest,
|
||||
): Promise<ObjectsByEntityResponse>;
|
||||
proxy(
|
||||
clusterName: string,
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
): Promise<Response>;
|
||||
}
|
||||
|
||||
@@ -38,4 +38,9 @@ export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {
|
||||
}
|
||||
return requestBody;
|
||||
}
|
||||
async getBearerToken(): Promise<string> {
|
||||
return await this.authProvider.getAccessToken(
|
||||
'https://www.googleapis.com/auth/cloud-platform',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
|
||||
import {
|
||||
KubernetesRequestAuth,
|
||||
KubernetesRequestBody,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { KubernetesAuthProvider, KubernetesAuthProvidersApi } from './types';
|
||||
import { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider';
|
||||
import { ServerSideKubernetesAuthProvider } from './ServerSideAuthProvider';
|
||||
@@ -91,4 +94,22 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi {
|
||||
`authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`,
|
||||
);
|
||||
}
|
||||
|
||||
async getBearerToken(authProvider: string): Promise<string> {
|
||||
const kubernetesAuthProvider: KubernetesAuthProvider | undefined =
|
||||
this.kubernetesAuthProviderMap.get(authProvider);
|
||||
|
||||
if (kubernetesAuthProvider) {
|
||||
return await kubernetesAuthProvider.getBearerToken();
|
||||
}
|
||||
|
||||
if (authProvider.startsWith('oidc.')) {
|
||||
throw new Error(
|
||||
`KubernetesAuthProviders has no oidcProvider configured for ${authProvider}`,
|
||||
);
|
||||
}
|
||||
throw new Error(
|
||||
`authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,8 @@ export class OidcKubernetesAuthProvider implements KubernetesAuthProvider {
|
||||
requestBody.auth = auth;
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
async getBearerToken(): Promise<string> {
|
||||
return await this.authProvider.getIdToken();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,8 @@ export class ServerSideKubernetesAuthProvider
|
||||
// No-op, auth will be taken care of on the server-side
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
async getBearerToken(): Promise<string> {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
|
||||
import {
|
||||
KubernetesRequestAuth,
|
||||
KubernetesRequestBody,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export interface KubernetesAuthProvider {
|
||||
decorateRequestBodyForAuth(
|
||||
requestBody: KubernetesRequestBody,
|
||||
): Promise<KubernetesRequestBody>;
|
||||
getBearerToken(): Promise<string>;
|
||||
}
|
||||
|
||||
export const kubernetesAuthProvidersApiRef =
|
||||
@@ -33,4 +37,5 @@ export interface KubernetesAuthProvidersApi {
|
||||
authProvider: string,
|
||||
requestBody: KubernetesRequestBody,
|
||||
): Promise<KubernetesRequestBody>;
|
||||
getBearerToken(authProvider: string): Promise<string>;
|
||||
}
|
||||
|
||||
@@ -43,9 +43,14 @@ export const kubernetesPlugin = createPlugin({
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
identityApi: identityApiRef,
|
||||
kubernetesAuthProvidersApi: kubernetesAuthProvidersApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, identityApi }) =>
|
||||
new KubernetesBackendClient({ discoveryApi, identityApi }),
|
||||
factory: ({ discoveryApi, identityApi, kubernetesAuthProvidersApi }) =>
|
||||
new KubernetesBackendClient({
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
kubernetesAuthProvidersApi,
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: kubernetesAuthProvidersApiRef,
|
||||
|
||||
Reference in New Issue
Block a user