This commit is contained in:
Manabu Mccloskey 2023-03-24 19:20:23 -07:00
parent 4db8bc3c48
commit ce89b04e32
6 changed files with 159 additions and 75 deletions

View file

@ -22,12 +22,13 @@ import {
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
import { UserSettingsPage } from '@backstage/plugin-user-settings';
import { apis } from './apis';
import {apis} from './apis';
import {keycloakOIDCAuthApiRef} from "@internal/plugin-workflows"
import { entityPage } from './components/catalog/EntityPage';
import { searchPage } from './components/search/SearchPage';
import { Root } from './components/Root';
import {AlertDisplay, OAuthRequestDialog, ProxiedSignInPage} from '@backstage/core-components';
import {AlertDisplay, OAuthRequestDialog, SignInPage} from '@backstage/core-components';
import { createApp } from '@backstage/app-defaults';
import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
@ -37,7 +38,19 @@ import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/
const app = createApp({
apis,
components: {
SignInPage: (props) => <ProxiedSignInPage {...props} provider="oauth2Proxy" />,
// SignInPage: (props) => <ProxiedSignInPage {...props} provider="oauth2Proxy" />,
SignInPage: props => (
<SignInPage
{...props}
auto
provider={{
id: 'keycloak-oidc',
title: 'Keycloak',
message: 'Sign in using Keycloak',
apiRef: keycloakOIDCAuthApiRef,
}}
/>
),
},
bindRoutes({ bind }) {
bind(catalogPlugin.externalRoutes, {

View file

@ -4,11 +4,26 @@ import {
ScmAuth,
} from '@backstage/integration-react';
import {
AnyApiFactory,
configApiRef,
createApiFactory,
AnyApiFactory,
ApiRef,
BackstageIdentityApi,
configApiRef,
createApiFactory,
createApiRef,
discoveryApiRef,
oauthRequestApiRef,
OpenIdConnectApi,
ProfileInfoApi,
SessionApi,
} from '@backstage/core-plugin-api';
import {OAuth2} from "@backstage/core-app-api";
import {keycloakOIDCAuthApiRef} from "@internal/plugin-workflows"
// export const keycloakOIDCAuthApiRef: ApiRef<
// OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
// > = createApiRef({
// id: 'auth.keycloak-oidc-provider',
// });
export const apis: AnyApiFactory[] = [
createApiFactory({
api: scmIntegrationsApiRef,
@ -16,4 +31,24 @@ export const apis: AnyApiFactory[] = [
factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi),
}),
ScmAuth.createDefaultApiFactory(),
createApiFactory({
api: keycloakOIDCAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'keycloak-oidc',
title: 'Keycloak OIDC',
icon: () => null,
},
environment: configApi.getOptionalString('auth.environment'),
defaultScopes: ['openid', 'profile', 'email', 'groups'],
}),
}),
];

View file

@ -18,70 +18,91 @@ export default async function createPlugin(
tokenManager: env.tokenManager,
providerFactories: {
...defaultAuthProviderFactories,
oauth2Proxy: providers.oauth2Proxy.create({
'keycloak-oidc': providers.oidc.create({
signIn: {
async resolver({ result }, ctx) {
console.log(result)
const name = result.getHeader('x-forwarded-preferred-username');
if (!name) {
throw new Error('Request did not contain a user');
}
try {
// Attempts to sign in existing user
const signedInUser = await ctx.signInWithCatalogUser({
entityRef: { name },
});
return Promise.resolve(signedInUser);
} catch (e) {
// Create stub user
const userEntityRef = stringifyEntityRef({
kind: 'User',
name: name,
namespace: DEFAULT_NAMESPACE,
});
return ctx.issueToken({
claims: {
sub: userEntityRef,
ent: [userEntityRef],
},
});
}
resolver(info, ctx) {
const userRef = stringifyEntityRef({
kind: 'User',
name: info.result.userinfo.sub,
namespace: DEFAULT_NAMESPACE,
});
console.log(info.result.userinfo.groups)
return ctx.issueToken({
claims: {
sub: userRef, // The user's own identity
ent: [userRef], // A list of identities that the user claims ownership through
},
});
},
},
}),
// This replaces the default GitHub auth provider with a customized one.
// The `signIn` option enables sign-in for this provider, using the
// identity resolution logic that's provided in the `resolver` callback.
//
// This particular resolver makes all users share a single "guest" identity.
// It should only be used for testing and trying out Backstage.
//
// If you want to use a production ready resolver you can switch to
// the one that is commented out below, it looks up a user entity in the
// catalog using the GitHub username of the authenticated user.
// That resolver requires you to have user entities populated in the catalog,
// for example using https://backstage.io/docs/integrations/github/org
//
// There are other resolvers to choose from, and you can also create
// your own, see the auth documentation for more details:
//
// https://backstage.io/docs/auth/identity-resolver
// github: providers.github.create({
// signIn: {
// resolver(_, ctx) {
// const userRef = 'user:default/guest'; // Must be a full entity reference
// return ctx.issueToken({
// claims: {
// sub: userRef, // The user's own identity
// ent: [userRef], // A list of identities that the user claims ownership through
// },
// });
// },
// // resolver: providers.github.resolvers.usernameMatchingUserEntityName(),
// },
// }),
},
// providerFactories: {
// ...defaultAuthProviderFactories,
// oauth2Proxy: providers.oauth2Proxy.create({
// signIn: {
// async resolver({ result }, ctx) {
// console.log(result)
// const name = result.getHeader('x-forwarded-preferred-username');
// if (!name) {
// throw new Error('Request did not contain a user');
// }
//
// try {
// // Attempts to sign in existing user
// const signedInUser = await ctx.signInWithCatalogUser({
// entityRef: { name },
// });
//
// return Promise.resolve(signedInUser);
// } catch (e) {
// // Create stub user
// const userEntityRef = stringifyEntityRef({
// kind: 'User',
// name: name,
// namespace: DEFAULT_NAMESPACE,
// });
// return ctx.issueToken({
// claims: {
// sub: userEntityRef,
// ent: [userEntityRef],
// },
// });
// }
// },
// },
// }),
// // This replaces the default GitHub auth provider with a customized one.
// // The `signIn` option enables sign-in for this provider, using the
// // identity resolution logic that's provided in the `resolver` callback.
// //
// // This particular resolver makes all users share a single "guest" identity.
// // It should only be used for testing and trying out Backstage.
// //
// // If you want to use a production ready resolver you can switch to
// // the one that is commented out below, it looks up a user entity in the
// // catalog using the GitHub username of the authenticated user.
// // That resolver requires you to have user entities populated in the catalog,
// // for example using https://backstage.io/docs/integrations/github/org
// //
// // There are other resolvers to choose from, and you can also create
// // your own, see the auth documentation for more details:
// //
// // https://backstage.io/docs/auth/identity-resolver
// // github: providers.github.create({
// // signIn: {
// // resolver(_, ctx) {
// // const userRef = 'user:default/guest'; // Must be a full entity reference
// // return ctx.issueToken({
// // claims: {
// // sub: userRef, // The user's own identity
// // ent: [userRef], // A list of identities that the user claims ownership through
// // },
// // });
// // },
// // // resolver: providers.github.resolvers.usernameMatchingUserEntityName(),
// // },
// // }),
// },
});
}

View file

@ -5,8 +5,8 @@ import useAsync from 'react-use/lib/useAsync';
import {
DiscoveryApi,
discoveryApiRef,
useApi,
discoveryApiRef, OpenIdConnectApi, fetchApiRef,
useApi, FetchApi,
} from '@backstage/core-plugin-api';
// eslint-disable-next-line no-restricted-imports
import {gunzipSync} from "zlib";
@ -22,8 +22,7 @@ import {
import DeleteIcon from "@material-ui/icons/Delete";
import ClearIcon from "@material-ui/icons/Clear";
import LinkOffRounded from "@material-ui/icons/LinkOffRounded";
const token = "..---"
import {keycloakOIDCAuthApiRef} from "../../plugin";
type TFState = {
terraform_version: string
@ -75,9 +74,11 @@ export const TFTable = (props: TFTableProps) => {
export const FetchTFState = () => {
const apiRef = useApi(discoveryApiRef)
const entity = useEntity()
const oidcApi = useApi(keycloakOIDCAuthApiRef)
const fetchApi = useApi(fetchApiRef)
const secretName = `tfstate-default-${entity.entity.metadata.name}`
const { value, loading, error } = useAsync((): Promise<TFState> => {
return getTFState(secretName, "admin", apiRef)
return getTFState(secretName, "admin", apiRef, oidcApi, fetchApi)
})
if (loading) {
return <Progress />
@ -125,7 +126,8 @@ type payload = {
}
}
async function getTFState(name: string, namespace: string, apiRef: DiscoveryApi): Promise<TFState> {
async function getTFState(name: string, namespace: string, apiRef: DiscoveryApi, oidcRef: OpenIdConnectApi, fetchRef: FetchApi ): Promise<TFState> {
const token = await oidcRef.getIdToken()
const baseUrl = await apiRef.getBaseUrl("kubernetes")
const proxyUrl = `${baseUrl}/proxy`
return new Promise(async (resolve, reject) => {
@ -133,7 +135,7 @@ async function getTFState(name: string, namespace: string, apiRef: DiscoveryApi)
method: 'GET',
headers: {
'X-Kubernetes-Cluster': "canoe-packaging",
Authorization: `Bearer ${token}`,
'Authorization': `Bearer ${token}`,
},
});
if (resp.ok) {

View file

@ -1 +1,2 @@
export { workflowsPlugin, EntityWorkflowsContent } from './plugin';
export { workflowsPlugin, EntityWorkflowsContent, keycloakOIDCAuthApiRef } from './plugin';

View file

@ -1,4 +1,10 @@
import { createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';
import {
ApiRef, BackstageIdentityApi, createApiRef,
createPlugin,
createRoutableExtension,
OpenIdConnectApi,
ProfileInfoApi, SessionApi
} from '@backstage/core-plugin-api';
import { rootCatalogWorkflowsRouteRef } from './routes';
@ -17,3 +23,9 @@ export const EntityWorkflowsContent = workflowsPlugin.provide(
mountPoint: rootCatalogWorkflowsRouteRef,
}),
);
export const keycloakOIDCAuthApiRef: ApiRef<
OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
> = createApiRef({
id: 'auth.keycloak-oidc-provider',
});