diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md
index 7b3124ab0f..98f769e9f3 100644
--- a/plugins/pagerduty/README.md
+++ b/plugins/pagerduty/README.md
@@ -6,7 +6,7 @@
# How it Works
- The Backstage PagerDuty plugin allows PagerDuty information about a Backstage entity to be displayed within Backstage. This includes active incidents, recent change events, as well as the current on-call responders' names, email addresses, and links to their profiles in PagerDuty.
-- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders.
+- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders (Alternatively, the plugin can be configured with an optional `readOnly` property to suppress the ability to trigger incidents from the plugin).
- _Note: This feature is only available when providing the `pagerduty.com/integration-key` annotation_
- Change events will be displayed in a separate tab. If the change event payload has additional links the first link only will be rendered.
@@ -145,6 +145,24 @@ pagerduty:
eventsBaseUrl: 'https://events.pagerduty.com/v2'
```
+To suppress the rendering of the actionable incident-creation button, the `PagerDutyCard` can also be instantiated in `readOnly` mode:
+
+```ts
+
+```
+
+**WARNING**: In current implementation, the PagerDuty plugin requires the `/pagerduty` proxy endpoint be exposed by the Backstage backend as an unprotected endpoint, in effect enabling PagerDuty API access using the configured `PAGERDUTY_TOKEN` for any user or process with access to the `/pagerduty` Backstage backend endpoint. If you regard this as problematic, consider using the plugin in `readOnly` mode (``) using the following proxy configuration:
+
+```yaml
+proxy:
+ '/pagerduty':
+ target: https://api.pagerduty.com
+ headers:
+ Authorization: Token token=${PAGERDUTY_TOKEN}
+ # prohibit the `/pagerduty` proxy endpoint from servicing non-GET requests
+ allowedMethods: ['GET']
+```
+
# How to Uninstall
1. Remove any configuration added in Backstage yaml files, such as the proxy configuration in `app-config.yaml` and the integration key in an entity's annotations.
diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx
index 85202a9cfc..34c8914fde 100644
--- a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx
+++ b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx
@@ -356,4 +356,27 @@ describe('PageDutyCard', () => {
expect(getByText('Empty escalation policy')).toBeInTheDocument();
});
});
+
+ describe('when entity has all annotations but the plugin has been configured to be "read only"', () => {
+ it('queries by integration key but does not render the "Create Incident" button', async () => {
+ mockPagerDutyApi.getServiceByEntity = jest
+ .fn()
+ .mockImplementationOnce(async () => ({ service }));
+
+ const { getByText, queryByTestId } = render(
+ wrapInTestApp(
+
+
+
+
+ ,
+ ),
+ );
+ await waitFor(() => !queryByTestId('progress'));
+ expect(getByText('Service Directory')).toBeInTheDocument();
+ expect(getByText('Nice! No incidents found!')).toBeInTheDocument();
+ expect(getByText('Empty escalation policy')).toBeInTheDocument();
+ expect(() => getByText('Create Incident')).toThrow();
+ });
+ });
});
diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx
index 15967fae01..fd23166d88 100644
--- a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx
+++ b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx
@@ -54,7 +54,13 @@ export const isPluginApplicableToEntity = (entity: Entity) =>
);
/** @public */
-export const PagerDutyCard = () => {
+export type PagerDutyCardProps = {
+ readOnly?: boolean;
+};
+
+/** @public */
+export const PagerDutyCard = (props: PagerDutyCardProps) => {
+ const { readOnly } = props;
const { entity } = useEntity();
const pagerDutyEntity = getPagerDutyEntity(entity);
const api = useApi(pagerDutyApiRef);
@@ -156,7 +162,11 @@ export const PagerDutyCard = () => {
title="PagerDuty"
subheader={
}
/>