initial implementation
This commit is contained in:
parent
d001ee0c17
commit
f581e1a45d
2 changed files with 62 additions and 23 deletions
|
@ -8,7 +8,7 @@ export const GetK8sOIDCTokenExtension = scaffolderPlugin.provide(
|
|||
{
|
||||
name: 'GetK8sOIDCToken',
|
||||
component: GetK8sOIDCToken,
|
||||
schema: ClusterPickerSchema
|
||||
schema: ClusterPickerSchema,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,40 +1,78 @@
|
|||
import React from 'react';
|
||||
import React, {useCallback, useEffect} from 'react';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import {useApi} from "@backstage/core-plugin-api";
|
||||
import {kubernetesApiRef, kubernetesAuthProvidersApiRef} from "@backstage/plugin-kubernetes";
|
||||
import {FormHelperText} from "@material-ui/core";
|
||||
import {
|
||||
useApi, configApiRef, discoveryApiRef, oauthRequestApiRef
|
||||
} from "@backstage/core-plugin-api";
|
||||
import { kubernetesApiRef } from "@backstage/plugin-kubernetes";
|
||||
import { FormHelperText } from "@material-ui/core";
|
||||
import {Progress, Select} from "@backstage/core-components";
|
||||
import useAsync from "react-use/lib/useAsync";
|
||||
import {useTemplateSecrets} from "@backstage/plugin-scaffolder-react";
|
||||
import {ClusterPickerProps} from "./schema";
|
||||
import {OAuth2} from "@backstage/core-app-api";
|
||||
|
||||
|
||||
export const GetK8sOIDCToken = (props: ClusterPickerProps) => {
|
||||
|
||||
const k8sApi = useApi(kubernetesApiRef)
|
||||
const k8sAuthProviderApi = useApi(kubernetesAuthProvidersApiRef)
|
||||
const { setSecrets } = useTemplateSecrets();
|
||||
const { setSecrets, secrets } = useTemplateSecrets();
|
||||
|
||||
const {uiSchema, onChange, rawErrors, formData, required} = props
|
||||
const getToken = async () => {
|
||||
const {requestUserCredentials} = uiSchema?.['ui:options'] ?? {}
|
||||
if (!requestUserCredentials) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clusters = await k8sApi.getClusters()
|
||||
const cluster = clusters.find(c => {
|
||||
return c.name === formData
|
||||
})
|
||||
const creds = await k8sAuthProviderApi.getCredentials(cluster!.oidcTokenProvider!)
|
||||
setSecrets({ [requestUserCredentials.secretKey]: creds.token! })
|
||||
}
|
||||
const discoveryApi = useApi(discoveryApiRef)
|
||||
const oauthRequestApi = useApi(oauthRequestApiRef)
|
||||
const configApi = useApi(configApiRef)
|
||||
|
||||
const {uiSchema, required} = props
|
||||
let {rawErrors} = props
|
||||
const {value: {clusters} = {clusters: []}, loading } = useAsync(
|
||||
async () => {
|
||||
const c = await k8sApi.getClusters()
|
||||
return {clusters: c.map(i => ({ label: i.name, value: i.name}))}
|
||||
}
|
||||
)
|
||||
if (!rawErrors) {
|
||||
rawErrors = []
|
||||
}
|
||||
|
||||
const getToken = useCallback( async (clusterName: string) => {
|
||||
const {requestUserCredentials} = uiSchema?.['ui:options'] ?? {}
|
||||
if (!requestUserCredentials) {
|
||||
return;
|
||||
}
|
||||
const cs = await k8sApi.getClusters()
|
||||
const cluster = cs.find(c => {
|
||||
return c.name === clusterName
|
||||
})
|
||||
if (cluster?.oidcTokenProvider === undefined) {
|
||||
throw new Error("no oidc provider defined for this cluster")
|
||||
}
|
||||
|
||||
const oidc = OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
provider: {
|
||||
id: cluster.oidcTokenProvider,
|
||||
title: 'OIDC',
|
||||
icon: () => null,
|
||||
},
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
defaultScopes: ['openid', 'profile', 'email', 'groups'],
|
||||
})
|
||||
const token = await oidc.getIdToken()
|
||||
|
||||
setSecrets({ [requestUserCredentials.secretKey]: token })
|
||||
}, [configApi, discoveryApi, k8sApi, oauthRequestApi, setSecrets, uiSchema]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const {requestUserCredentials} = uiSchema?.['ui:options'] ?? {}
|
||||
if (!requestUserCredentials?.secretKey || secrets[requestUserCredentials?.secretKey!]) {
|
||||
return
|
||||
}
|
||||
|
||||
if (clusters.length) {
|
||||
getToken(clusters[0].value).catch(console.error)
|
||||
}
|
||||
}, [clusters, getToken, secrets, uiSchema])
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
|
@ -44,13 +82,14 @@ export const GetK8sOIDCToken = (props: ClusterPickerProps) => {
|
|||
<FormControl
|
||||
margin="normal"
|
||||
required={required}
|
||||
error={rawErrors?.length > 0 && !formData}
|
||||
error={rawErrors?.length > 0}
|
||||
>
|
||||
<Select
|
||||
native
|
||||
label="Cluster"
|
||||
items={clusters}
|
||||
onChange={getToken}
|
||||
onChange={e => getToken(e.toString())}
|
||||
placeholder="select one"
|
||||
/>
|
||||
<FormHelperText id="entityName">
|
||||
Kubernetes Cluster Name
|
||||
|
|
Loading…
Reference in a new issue