Skip to content

Commit

Permalink
fix(ui): RHIDP-2044 enable frontend plugin loading (#1226)
Browse files Browse the repository at this point in the history
* fix(ui): RHIDP-2044 enable frontend plugin loading

This change removes the authentication requirement for the scalprum
backend as it's used to serve static javascript content and related
manifests.  This commit also adds identity support to the dynamic
plugins info list frontend and migrates the backend to use the httpAuth
service.

Signed-off-by: Stan Lewis <gashcrumb@gmail.com>

* fix(ui): RHIDP-2043 add guest auth provider

This change adds the new upstream guest authentication provider to the
backend.  This provider is enabled by adding a "guest" entry to the
`auth.providers` map, like:

```yaml
auth:
  providers:
    guest: {}

auth:
  providers:
    guest:
      dangerouslyAllowOutsideDevelopment: true
```

This change also removes the dynamic-plugins-info-backend e2e test, as
it relies on an unauthenticated endpoint that isn't available anymore.
This functionaly is already covered by the UI e2e test and the
component's unit test.

Signed-off-by: Stan Lewis <gashcrumb@gmail.com>

---------

Signed-off-by: Stan Lewis <gashcrumb@gmail.com>
  • Loading branch information
gashcrumb committed May 6, 2024
1 parent f866c5a commit 1b1c0a5
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ data:
title: Red Hat Developer Hub
backend:
auth:
dangerouslyDisableDefaultAuthPolicy: true # TODO - Remove it after https://issues.redhat.com/browse/RHIDP-2043. A Dynamic plugin for Guest Authentication Provider needs to be created
keys:
- secret: temp
integrations:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ data:
title: Red Hat Developer Hub
backend:
auth:
dangerouslyDisableDefaultAuthPolicy: true # TODO - Remove it after https://issues.redhat.com/browse/RHIDP-2043. A Dynamic plugin for Guest Authentication Provider needs to be created
keys:
- secret: temp
integrations:
Expand Down Expand Up @@ -45,6 +44,8 @@ data:
development:
clientId: ${GOOGLE_CLIENT_ID}
clientSecret: ${GOOGLE_CLIENT_SECRET}
guest:
dangerouslyAllowOutsideDevelopment: true
proxy:
skipInvalidProxies: true
Expand Down

This file was deleted.

3 changes: 2 additions & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@backstage/integration": "1.9.1",
"@backstage/plugin-app-backend": "0.3.64",
"@backstage/plugin-auth-backend": "0.22.3",
"@backstage/plugin-auth-backend-module-guest-provider": "^0.1.3",
"@backstage/plugin-auth-node": "0.4.11",
"@backstage/plugin-catalog-backend": "1.21.0",
"@backstage/plugin-catalog-backend-module-openapi": "0.1.34",
Expand All @@ -45,13 +46,13 @@
"@backstage/plugin-search-backend-module-catalog": "0.1.21",
"@backstage/plugin-search-backend-module-pg": "0.5.25",
"@backstage/plugin-search-backend-node": "1.2.20",
"@internal/plugin-auth-backend-module-oidc-provider": "*",
"@internal/plugin-dynamic-plugins-info-backend": "*",
"@internal/plugin-scalprum-backend": "*",
"@janus-idp/backstage-plugin-rbac-backend": "2.6.2",
"@janus-idp/backstage-plugin-rbac-node": "1.0.6",
"@manypkg/get-packages": "1.1.3",
"app": "*",
"@internal/plugin-auth-backend-module-oidc-provider": "*",
"better-sqlite3": "9.3.0",
"express": "4.19.2",
"express-prom-bundle": "6.6.0",
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ backend.add(pluginIDProviderService);
backend.add(rbacDynamicPluginsProvider);

backend.add(import('@backstage/plugin-auth-backend'));
backend.add(import('@backstage/plugin-auth-backend-module-guest-provider'));
backend.add(import('./modules/authProvidersModule'));

backend.add(import('@internal/plugin-dynamic-plugins-info-backend'));
Expand Down
11 changes: 7 additions & 4 deletions packages/backend/src/modules/authProvidersModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,13 @@ const authProvidersModule = createBackendModule({
async init({ config, authProviders, logger }) {
const providersConfig = config.getConfig('auth.providers');
const authFactories: ProviderFactories = {};
providersConfig.keys().forEach(providerId => {
const factory = getAuthProviderFactory(providerId);
authFactories[providerId] = factory;
});
providersConfig
.keys()
.filter(key => key !== 'guest')
.forEach(providerId => {
const factory = getAuthProviderFactory(providerId);
authFactories[providerId] = factory;
});

const providerFactories: ProviderFactories = {
...defaultAuthProviderFactories,
Expand Down
5 changes: 3 additions & 2 deletions plugins/dynamic-plugins-info-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@
"winston": "3.11.0"
},
"devDependencies": {
"@backstage/backend-test-utils": "0.3.6",
"@backstage/cli": "0.26.2",
"@types/supertest": "6.0.2",
"supertest": "6.3.4",
"msw": "2.2.13"
"msw": "2.2.13",
"supertest": "6.3.4"
},
"files": [
"dist"
Expand Down
6 changes: 4 additions & 2 deletions plugins/dynamic-plugins-info-backend/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export const dynamicPluginsInfoPlugin = createBackendPlugin({
deps: {
http: coreServices.httpRouter,
pluginProvider: dynamicPluginsServiceRef,
httpAuth: coreServices.httpAuth,
discovery: coreServices.discovery,
},
async init({ http, pluginProvider }) {
http.use(await createRouter({ pluginProvider }));
async init({ http, pluginProvider, httpAuth, discovery }) {
http.use(await createRouter({ pluginProvider, httpAuth, discovery }));
},
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { plugins } from '../../__fixtures__/data';
import { expectedList } from '../../__fixtures__/expected_result';
import { createRouter } from './router';
import { DynamicPluginManager } from '@backstage/backend-dynamic-feature-service';
import { mockServices } from '@backstage/backend-test-utils';

describe('createRouter', () => {
let app: express.Express;
Expand All @@ -14,6 +15,8 @@ describe('createRouter', () => {

const router = await createRouter({
pluginProvider: pluginManager,
discovery: mockServices.discovery(),
httpAuth: mockServices.httpAuth(),
});

app = express();
Expand Down
15 changes: 13 additions & 2 deletions plugins/dynamic-plugins-info-backend/src/service/router.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { errorHandler } from '@backstage/backend-common';
import {
createLegacyAuthAdapters,
errorHandler,
} from '@backstage/backend-common';
import {
BaseDynamicPlugin,
DynamicPluginProvider,
} from '@backstage/backend-dynamic-feature-service';
import {
DiscoveryService,
HttpAuthService,
} from '@backstage/backend-plugin-api';
import express, { Router } from 'express';

export interface RouterOptions {
pluginProvider: DynamicPluginProvider;
discovery: DiscoveryService;
httpAuth?: HttpAuthService;
}

export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
const { pluginProvider } = options;
const { httpAuth } = createLegacyAuthAdapters(options);

const router = Router();
router.use(express.json());
Expand All @@ -26,7 +36,8 @@ export async function createRouter(
}
return p as BaseDynamicPlugin;
});
router.get('/loaded-plugins', (_, response) => {
router.get('/loaded-plugins', async (req, response) => {
await httpAuth.credentials(req, { allow: ['user'] });
response.send(dynamicPlugins);
});
router.use(errorHandler());
Expand Down
14 changes: 12 additions & 2 deletions plugins/dynamic-plugins-info/src/api/DynamicPluginsInfoClient.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
import {
DiscoveryApi,
FetchApi,
IdentityApi,
} from '@backstage/core-plugin-api';

import { DynamicPluginInfo, DynamicPluginsInfoApi } from './types';

export interface DynamicPluginsInfoClientOptions {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
identityApi: IdentityApi;
}

const loadedPluginsEndpoint = '/loaded-plugins';

export class DynamicPluginsInfoClient implements DynamicPluginsInfoApi {
private readonly discoveryApi: DiscoveryApi;
private readonly fetchApi: FetchApi;
private readonly identityApi: IdentityApi;

constructor(options: DynamicPluginsInfoClientOptions) {
this.discoveryApi = options.discoveryApi;
this.fetchApi = options.fetchApi;
this.identityApi = options.identityApi;
}
async listLoadedPlugins(): Promise<DynamicPluginInfo[]> {
const baseUrl = await this.discoveryApi.getBaseUrl('dynamic-plugins-info');
const targetUrl = `${baseUrl}${loadedPluginsEndpoint}`;
const response = await this.fetchApi.fetch(targetUrl);
const { token } = await this.identityApi.getCredentials();
const response = await this.fetchApi.fetch(targetUrl, {
...(token ? { headers: { Authorization: `Bearer ${token}` } } : {}),
});
const data = await response.json();
if (!response.ok) {
throw new Error(`${data.message}`);
Expand Down
6 changes: 4 additions & 2 deletions plugins/dynamic-plugins-info/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
createRoutableExtension,
discoveryApiRef,
fetchApiRef,
identityApiRef,
} from '@backstage/core-plugin-api';

import { DynamicPluginsInfoClient } from './api/DynamicPluginsInfoClient';
Expand All @@ -21,9 +22,10 @@ export const dynamicPluginsInfoPlugin = createPlugin({
deps: {
discoveryApi: discoveryApiRef,
fetchApi: fetchApiRef,
identityApi: identityApiRef,
},
factory: ({ discoveryApi, fetchApi }) =>
new DynamicPluginsInfoClient({ discoveryApi, fetchApi }),
factory: ({ discoveryApi, fetchApi, identityApi }) =>
new DynamicPluginsInfoClient({ discoveryApi, fetchApi, identityApi }),
}),
],
});
Expand Down
4 changes: 4 additions & 0 deletions plugins/scalprum-backend/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export const scalprumPlugin = createBackendPlugin({
discovery,
}),
);
http.addAuthPolicy({
path: '/',
allow: 'unauthenticated',
});
},
});
},
Expand Down
21 changes: 19 additions & 2 deletions showcase-docs/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,25 @@ After selecting the authentication provider you wish to use with your Backstage
signInPage: <provider-id>
```

### Disabling the guest login
### Enabling/Disabling the guest provider and login

We also offer an option to disable the Guest Login provider that disable the ability for guests to login to your Backstage Showcase instance.
The guest login is provided by a special authentication provider that must be explicitly enabled. This authentication provider should be used for development purposes only and is not intended for production, as it creates a default user that has user-level access to the Backstage instance.

- To enable the guest provider for local development:

```yaml
auth:
providers:
guest: {}
```

- To enable the guest provider when running the container:

```yaml
auth:
providers:
guest:
dangerouslyAllowOutsideDevelopment: true
```

- To disable the guest login set `auth.environment` to `production`.
14 changes: 13 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3643,6 +3643,18 @@
google-auth-library "^9.0.0"
passport-google-oauth20 "^2.0.0"

"@backstage/plugin-auth-backend-module-guest-provider@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@backstage/plugin-auth-backend-module-guest-provider/-/plugin-auth-backend-module-guest-provider-0.1.3.tgz#bcc75c2cdd71744fa1789b93ea2eb45e78c30dd7"
integrity sha512-SDCv0nimjKOigeQzFupZlT/3VmDdje6AVdt0cO87UqoKhBjNlsr1IkA2hoHmdxQ20hGu/sE+x7RNHD4oLCW/OQ==
dependencies:
"@backstage/backend-common" "^0.21.7"
"@backstage/backend-plugin-api" "^0.6.17"
"@backstage/catalog-model" "^1.4.5"
"@backstage/errors" "^1.2.4"
"@backstage/plugin-auth-node" "^0.4.12"
passport-oauth2 "^1.7.0"

"@backstage/plugin-auth-backend-module-microsoft-provider@^0.1.11":
version "0.1.11"
resolved "https://registry.yarnpkg.com/@backstage/plugin-auth-backend-module-microsoft-provider/-/plugin-auth-backend-module-microsoft-provider-0.1.11.tgz#3bbcd401beb5c30e38b28b01ee0698c0fe01784e"
Expand Down Expand Up @@ -22652,7 +22664,7 @@ passport-oauth2@1.6.1:
uid2 "0.0.x"
utils-merge "1.x.x"

passport-oauth2@1.x.x, passport-oauth2@^1.1.2, passport-oauth2@^1.4.0, passport-oauth2@^1.6.0, passport-oauth2@^1.6.1:
passport-oauth2@1.x.x, passport-oauth2@^1.1.2, passport-oauth2@^1.4.0, passport-oauth2@^1.6.0, passport-oauth2@^1.6.1, passport-oauth2@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.8.0.tgz#55725771d160f09bbb191828d5e3d559eee079c8"
integrity sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==
Expand Down

0 comments on commit 1b1c0a5

Please sign in to comment.