Installation & Setup
Prerequisites
The RBAC plugin depends on a few other Backstage systems and features. It's possible that your Backstage instance already have some portion of these steps set up. If any of these are not yet set up, you'll need to set them up before installing RBAC.
Enable Service to Service Auth
Service-to-service authentication lets backend code in Backstage securely verify that a given request originates from another part of the backend, rather than from a user. This is useful for tasks like indexing catalog entities for search. Service to service authentication is enabled by default in the new backend system.
If you are using the legacy backend then you will need to setup Service to Service authentication following the legacy Service to Service Auth documentation.
Identity Resolver
Like many other parts of Backstage, both the permission framework and the RBAC policy rely on group membership. This allows the RBAC configuration to have groups as members of a role, rather than exhaustively listing each person in the desired groups.
Group membership is also useful for policy decisions — for example, allowing someone to act on an entity when they are a member of the group that owns it.
When populating groups, include any groups that you plan to assign an RBAC role, and any groups that have a corresponding catalog entity.
The IdentityResolver docs on backstage.io describe the process for resolving group membership on sign in. If you can see a reference to a sensible entity and groups on your Backstage profile, you're ready to go.
Set up the permission framework
Before you can use RBAC, you'll need to set up the permission framework in Backstage. Since we'll be replacing the policy with the dynamic one supplied by RBAC, you don't need to complete the steps associated with policy authoring -- you can stop once you've enabled and tested the permissions system.
Backend Installation
The following sections will get the RBAC backend configured and installed.
Configure RBAC administrator users
The ability to view and adjust the RBAC policy configuration is granted to a fixed set of users and groups specified by the configuration property permission.rbac.authorizedUsers
. Any other users visiting /rbac
will see an error.
Add the entity references for the Backstage users and groups who should be permitted to configure RBAC to your app-config.yaml as follows:
permission:
enabled: true
rbac:
authorizedUsers:
- group:default/admins
- user:default/alice
- user:default/bob
Configure permissioned plugins
In order for the RBAC UI to aggregate information about the available permissions in Backstage, it's necessary to provide a list of plugins which include permissions in the RBAC configuration. At time of writing, the only first-party Backstage plugins which include permissions are catalog
and scaffolder
. If you're using third-party (e.g. Insights, Soundcheck, etc.) or in-house plugins which include permissions, you should include those plugins as well.
permission:
enabled: true
permissionedPlugins:
- catalog
- scaffolder
rbac:
authorizedUsers:
- group:default/admins
- user:default/alice
- user:default/bob
Install RBAC backend
The RBAC backend handles storing policy configuration in the database and exposing it to the RBAC UI and to the RBAC policy running inside the permission framework.
First we need to add the @spotify/backstage-plugin-rbac-backend
and @spotify/backstage-plugin-permission-backend-module-rbac
packages by running the following command:
yarn workspace backend add @spotify/backstage-plugin-rbac-backend @spotify/backstage-plugin-permission-backend-module-rbac
Then we add the following:
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend/alpha'));
backend.add(import('@spotify/backstage-plugin-rbac-backend'));
backend.add(import('@spotify/backstage-plugin-permission-backend-module-rbac'));
// ...
backend.start();
You may have this line in your backend:
backend.add(
import('@backstage/plugin-permission-backend-module-allow-all-policy'),
);
Make sure to remove this as it will prevent RBAC from working.
Legacy Backend
If you are still using the Legacy Backend you can follow these instructions but we highly recommend migrating to the New Backend System.
- First we need to add the
@spotify/backstage-plugin-rbac-backend
package by running the following command:
yarn workspace backend add @spotify/backstage-plugin-rbac-backend
- Then add the following to a new file,
packages/backend/src/plugins/rbac.ts
:
import { createRouter } from '@spotify/backstage-plugin-rbac-backend';
import { Router } from 'express';
import type { PluginEnvironment } from '../types';
export default function createPlugin(env: PluginEnvironment): Promise<Router> {
return createRouter(env);
}
- Wire up the RBAC backend in
packages/backend/src/index.ts
. You’ll need to import the module from the previous step, create a plugin environment, and add the router to the express app:
import proxy from './plugins/proxy';
import techdocs from './plugins/techdocs';
import search from './plugins/search';
import permission from './plugins/permission';
import rbac from './plugins/rbac';
...
const techdocsEnv = createEnv('techdocs');
const searchEnv = createEnv('search');
const appEnv = createEnv('app');
const permissionEnv = createEnv('permission');
const rbacEnv = createEnv('rbac');
const rbacEnv = createEnv('rbac');
...
apiRouter.use('/techdocs', await techdocs(techdocsEnv));
apiRouter.use('/proxy', await proxy(proxyEnv));
apiRouter.use('/search', await search(searchEnv));
apiRouter.use('/permission', await permission(permissionEnv));
apiRouter.use('/rbac', await rbac(rbacEnv));
Frontend Installation
Getting the plugin
Add the RBAC packages as dependencies to your Backstage instance:
yarn workspace app add @spotify/backstage-plugin-rbac
Install RBAC frontend
First install the RBAC routes in the app within the packages/app/src/App.tsx
. This will provide the UI for authoring your RBAC policy under the /rbac
route. Note that this route can only be accessed by the authorizedUsers
configured above.
import { RBACRoot } from '@spotify/backstage-plugin-rbac';
...
const routes = (
<FlatRoutes>
...
<Route path="/rbac" element={<RBACRoot />} />
</FlatRoutes>
);
RBAC also provides a sidebar item that will only be visible to RBAC authorizedUsers
. This is an optional step, but it provides an easy way for RBAC authorized users to access the plugin.
import { RBACSidebarItem } from '@spotify/backstage-plugin-rbac';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarLogo />
...
<SidebarScrollWrapper>
<SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />
<SidebarItem
icon={SkillExchangeIcon}
to="skill-exchange"
text="Skill Exchange"
/>
<SidebarItem icon={SoundcheckIcon} to="soundcheck" text="Soundcheck" />
<RBACSidebarItem />
</SidebarScrollWrapper>
</Sidebar>
</SidebarPage>
);
Configure an initial policy with the RBAC UI
When there is no published RBAC policy, the default behaviour of RBAC is to deny all authorization requests sent to the permission framework. With this in mind, it's preferable to publish a simple RBAC policy before proceeding to install RBAC in the permission framework.
You can define a default policy in your
app-config.yaml
which will be used upon Backstage starting up if an RBAC policy has NOT yet been previously published. For instructions see the Default policy documentation.
The following instructions configure RBAC with a policy that allows all authorization requests. If you want to start with something more complex, refer to later sections of this documentation.
- Open the RBAC UI by visiting the
/rbac
path in your Backstage instance, or clicking the RBAC item in the sidebar (if you've installed theRBACSidebarItem
). - Click "New Version" to start working on a new draft policy, and choose a name for it.
- Click "New Role" to create a role within the policy, and give that a name too.
- Click the "New Permission Decision" button in the Permission Decisions table on the right hand side.
- In the dialog, select "Match All Permissions".
- Confirm that "Allow" is already selected at the bottom of the dialog.
- Click "Save".
- Confirm that the Members table on the left hand side contains a row for "All" users.
- Click "Back to Policy"
- Click "Save Draft"
- Click "Publish", and confirm publishing in the confirmation dialog.
Check everything is working
If you've followed all the steps up to this point, the RBAC policy is now in place! You should find that Backstage adheres to the policy you configured in the above step. If you have any problems, please reach out to us via our support page and we'll be happy to provide support.
Import and export a policy
The RBAC UI allows users to import and export a policy in the form of a yaml
file. Some users choose to create/ edit and test a policy in a development
or staging
environment, export that policy, and import it into their production
environment to ensure consistency.
To export a policy, select a policy (current, draft, or previous), click the ellipses in the top right and select "Export".
To import a policy, select the "Import" button in the top right of the RBAC plugin.
Once imported, the roles and permissions will be extracted and become editable in the UI. Once you are happy with the policy settings, you can "save and publish" to start enforcing the policy.
Note: Make sure you click Save & Publish on the policy after importing it otherwise the existing, published policy will remain in place and your new, imported policy will remain in "draft" status.
Here is a basic sample Any-allow
policy to to allow all permissions:
name: Sample Initial Policy
description: null
options:
resolutionStrategy: any-allow
roles:
- name: Default User
members: '*'
permissions:
- match: '*'
decision: allow
Appendix
Add RBAC policy in the permission framework
This step is not required when using the new backend system. If you're still using the old backend system consider migrating.
To use RBAC policies in the Backstage (when using the old backend system), we replace the TestPermissionPolicy
that you might have created when initially setting up the permission framework with an RBACPolicy
instance which uses the roles we will define in the UI in the following step Configuring an initial policy.
Adjust packages/backend/src/plugins/permission.ts
as follows:
import { createRouter } from '@backstage/plugin-permission-backend';
- import {
- AuthorizeResult,
- PolicyDecision,
- } from '@backstage/plugin-permission-common';
- import { PermissionPolicy } from '@backstage/plugin-permission-node';
+ import { RBACPolicyBuilder } from '@spotify/backstage-plugin-rbac-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
- class TestPermissionPolicy implements PermissionPolicy {
- async handle(): Promise<PolicyDecision> {
- return { result: AuthorizeResult.ALLOW };
- }
- }
-
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
config: env.config,
logger: env.logger,
discovery: env.discovery,
- policy: new TestPermissionPolicy(),
+ policy: await RBACPolicyBuilder.create(env).build(),
identity: env.identity,
});
}