Skip to content

Commit

Permalink
feat(ThreatPacks): Add threat packs and mitigation packs support (#125)
Browse files Browse the repository at this point in the history
* feat(ThreatPacks): Add threat packs and mitigation packs support

* chore: Remove the unused file

* chore: Fix typo

* chore: Adjust the threat pack table

* docs: Update readme
  • Loading branch information
jessieweiyi authored Jul 19, 2024
1 parent 61022ac commit 42ede80
Show file tree
Hide file tree
Showing 24 changed files with 2,543 additions and 233 deletions.
14 changes: 12 additions & 2 deletions .projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

125 changes: 124 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ The Threat composer tool has been built for the following reasons:
- Capture and store mitigation candidates and mapping to threats.
- Create a threat model document based on user-supplied input.
- Help users answer "Did we do a good enough job" by providing insights and suggestions for bar-raising actions via an 'Insights dashboard'
- Threat packs to find and add bulk or selected threat statements to your current workspace (Self-hosted deployments only). You can author and deploy custom packs - [Learn more...](#customising-reference-data-in-your-build)
- Mitigation packs to find and add bulk or selected mitigations to your current workspace. You can author and deploy custom packs (Self-hosted deployments only) - [Learn more...](#customising-reference-data-in-your-build)
- Data persisted only client-side within the browser (100% local storage).
- JSON import/export capabilities to enable persistent storage, sharing, and version control outside of the web browser (e.g. by using git).
- Markdown and PDF static downloads of the threat model document.
- Markdown, DOCX, and PDF static downloads of the threat model document.
- Workspace separation to allow working on multiple threat models.



## Threat model example

We've included an example of how you could use Threat composer to create a threat model, we have chosen the threat composer tool itself as an example to illustrate this. This threat model does not claim to be 100% complete for every possible interaction. It aims to give the reader an example of what a set of threats, assumptions and mitigations could look like. We've chosen to share this example as it provides a common reference point for people who are starting off with Threat composer. You may have different perspectives on the assumptions, threats and mitigations. This is ok, and could be used to start conversations in your organization with the context of your risk appetite. You may want to use this as he base threat model as a starting point to generate a contextualised threat model for your own specific needs and deployment of Threat composer. You are responsible for making your own independent assessment of this threat model and its applicability to your organization.
Expand Down Expand Up @@ -356,6 +360,125 @@ The repository is defined and maintained using [projen](https://github.com/proje

- For the browser extension (Chrome and Firefox) please see [this README](./packages/threat-composer-app-browser-extension/README.md)

## **Customising reference data in your build**

> [!NOTE]
> The following section is only applicable in self-hosting deployment scenarios.
You can customize the reference data used within Threat Composer to better suit your specific needs. The following sections details the types of customisations possible and how to use them.

### Reference or example threat models

Reference or example threat models are available directly in the Workspace selector for quick review and reference. The following steps describe how you can create and include a reference or example threat model in your own deployment.

1. Author your content using Threat Composer, and export as `.tc.json` file
1. Rename the file to a descriptive name, e.g. `ServerlessAPI.tc.json`
1. Place the `.tc.json` file into the `packages/threat-composer/src/data/workspaceExamples` directory.
1. Update `packages/threat-composer/src/data/workspaceExamples/workspaceExamples.ts` file to import the `.tc.json` file. e.g. `import serverlessAPI from './ServerlessAPI.tc.json'` and add it to the `workspaceExamples` array - for example:

```
const workspaceExamples = [
{
name: 'Threat Composer',
value: threatComposer,
},
{
name: 'Serverless API',
value: serverlessAPI,
},
] as WorkspaceExample[];
```
1. Build the project.


### Threat packs

Threat packs allow you to quickly find and add bulk or selected threat statements to your current workspace. The following steps describe how you can create and include a custom Threat Pack in your own deployment.

1. Author your content using Threat Composer, and export as `.tc.json` file
1. Rename the file to a descriptive name, e.g. `AuthenticationThreats.tc.json`
1. Place the `.tc.json` into the `packages/threat-composer/src/data/threatPacks` directory. Or if it's it's already a reference threat model (see section prior to this) there is no need to also add file at this location.
1. Create a `.metadata.json` file for your pack (e.g. `AuthenticationThreats.metadata.json`) in the `packages/threat-composer/src/data/threatPacks` directory
1. Paste the following schema in the file:

```
{
"schema": 1,
"namespace": "threat-composer",
"type": "threatpack-pack-metadata",
"id": "<REPLACE WITH SHORT HUMAN READABLE IDENTIFIER>",
"name": "<REPLACE WITH NAME OF THE THREAT PACK>",
"description": "<REPLACE WITH DESCRIPTION OF THE THREAT PACK>",
"path": "<REPLACE WITH RELATIVE PATH TO .TC.JSON FILE>"
}
```

1. Update the value of `id` to be a short human readable indentier for the pack (e.g. `AuthThreats`)
1. Update the value of `description` to describe the contents of the pack (e.g. `This pack contains common authentication threats`)
1. Update the value of `path` to point to the _relative_ path of the source `.tc.json` file (e.g. `./AuthenticationThreats.tc.json`)
1. Generate the threat pack file by running `yarn run build:pack` from the root of the local repository
1. Update `packages/threat-composer/src/data/threatPacks/threatPacks.ts` file to import the generated file. e.g. `import authenticationThreatPack './generated/AuthThreats.json';` and add it to the `threatPacks` array - for example:
```
const threatPacks = [
authenticationThreatPack,
GenAIChatbot,
] as ThreatPack[];
```
1. Build the project.

### Mitigation packs

Mitigation packs allow you to quickly find and add bulk or selected mitigation candidates to your current workspace. The following steps describe how you can create and include a custom Mitigation Pack in your own deployment.

1. Author your content using Threat Composer, and export as `.tc.json` file
1. Rename the file to a descriptive name, e.g. `BaselineControls.tc.json`
1. Place the `.tc.json` into the `packages/threat-composer/src/data/mitigationPacks` directory. Or if it's it's already a reference threat model (see section prior to this) there is no need to also add file at this location.
1. Create a `.metadata.json` file for your pack (e.g. `BaselineControls.metadata.json`) in the `packages/threat-composer/src/data/mitigationPacks` directory
1. Paste the following schema in the file:

```
{
"schema": 1,
"namespace": "threat-composer",
"type": "mitigationpack-pack-metadata",
"id": "<REPLACE WITH SHORT HUMAN READABLE IDENTIFIER>",
"name": "<REPLACE WITH NAME OF THE MITIGATION PACK>",
"description": "<REPLACE WITH DESCRIPTION OF THE MITIGATION PACK>",
"path": "<REPLACE WITH RELATIVE PATH TO .TC.JSON FILE>"
}
```

1. Update the value of `id` to be a short human readable indentier for the pack (e.g. `BaselineControls`)
1. Update the value of `description` to describe the contents of the pack (e.g. `This pack contains our organizations baseline controls`)
1. Update the value of `path` to point to the _relative_ path of the source `.tc.json` file (e.g. `./BaselineControls.tc.json`)
1. Generate the threat pack file by running `yarn run build:pack` from the root of the local repository
1. Update `packages/threat-composer/src/data/mitigationPacks/mitigationPacks.ts` file to import the generated file. e.g. `import ourBaselineControlsMitigationPack './generated/BaselineControls.json';` and add it to the `mitigationPacks` array - for example:
```
const mitigationPacks = [
ourBaselineControlsMitigationPack,
GenAIChatbot,
] as ThreatPack[];
```
1. Build the project.

### Threat examples

Threats that are included in the example threats data are made make available to users of your deployment of Threat Composer within the 'Full Examples' list within the threat statement editor, and are used at random when a user presses the 'Give me a random example' button in the editor. The following steps describe how you can customise the threats that are included:

1. Open the `packages/threat-composer/src/data/threatStatementExamples.json` file in your editor of choice
1. Add or edit existing entries ensuring to using the expected schema.
- `id` (string) - A unique ID for your example (e.g. `"EXAMPLE_000001"`)
- `numberId` (string) - This should aways have a value of `"-1"`
- `threatSource` (string) - The entity taking action (e.g. `"internal threat actor"`)
- `prerequistes` (string) - Conditions or requirements that must be met for a threat source's action to be viable. (e.g. `"who can register a vehicle"`)
- `threatAction` (string) - The action being performed by the threat source (e.g. `"claim they did not do so"`)
- `threatImpact` (string) - The direct impact of a successful threat action (e.g. `"the actor disputing financial charges related to the registration of a vehicle"`)
- `impactedGoal` - (Array of strings) - The information security or business objective that is negatively affected. (e.g. `["integrity"]`)
- `impactedAssets` - (Array of strings) - The assets affected by a successful threat action (e.g. `["billing"]`)
- `metadata` - (Array of objects) (e.g. `[ "key": "STRIDE", "value" : [ "T"] ]`)

1. Build the project.

## **Contribution guide**

Contribution guide are available at the [Contributing Guidelines](https://github.com/awslabs/threat-composer/blob/main/CONTRIBUTING.md).
Expand Down
1 change: 1 addition & 0 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 3 additions & 11 deletions packages/threat-composer-app/src/containers/AppLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
******************************************************************************************************************** */
import {
DEFAULT_WORKSPACE_ID,
useGlobalSetupContext,
} from '@aws/threat-composer';
import { SideNavigationProps } from '@cloudscape-design/components/side-navigation';
import { FC, PropsWithChildren, useMemo } from 'react';
Expand Down Expand Up @@ -46,12 +45,6 @@ const AppLayout: FC<PropsWithChildren<{}>> = ({
const notifications = useNotifications();
const [searchParams] = useSearchParams();

const { features } = useGlobalSetupContext();

const isThreatPackFeatureOn = useMemo(() => {
return features.includes('threatPacks');
}, [features]);

const navigationItems: SideNavigationProps.Item[] = useMemo(() => {
const navItems: SideNavigationProps.Item[] = [
{
Expand Down Expand Up @@ -95,8 +88,6 @@ const AppLayout: FC<PropsWithChildren<{}>> = ({
href: generateUrl(ROUTE_VIEW_THREAT_MODEL_PATH, searchParams, workspaceId),
type: 'link',
},
];
return isThreatPackFeatureOn ? navItems.concat([
{ type: 'divider' },
{
type: 'section',
Expand All @@ -114,9 +105,10 @@ const AppLayout: FC<PropsWithChildren<{}>> = ({
},
],
},
]) : navItems;
];

}, [searchParams, workspaceId, isThreatPackFeatureOn]);
return navItems;
}, [searchParams, workspaceId]);

return (<AppLayoutComponent
title='threat-composer'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
limitations under the License.
******************************************************************************************************************** */
import Container from '@cloudscape-design/components/container';
import Header from '@cloudscape-design/components/header';
import { FC } from 'react';
import { MitigationPack } from '../../../../../customTypes';

Expand All @@ -25,15 +24,7 @@ export interface GeneralInfoProps {
const GeneralInfo: FC<GeneralInfoProps> = ({
mitigationPack,
}) => {
return (<Container
header={
<Header
variant="h2"
>
Mitigation Pack - {mitigationPack.name}
</Header>
}
>
return (<Container>
{mitigationPack.description}
</Container>);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
limitations under the License.
******************************************************************************************************************** */
import Button from '@cloudscape-design/components/button';
import ContentLayout from '@cloudscape-design/components/content-layout';
import Header from '@cloudscape-design/components/header';
import SpaceBetween from '@cloudscape-design/components/space-between';
import { useMemo, FC, useCallback, useState } from 'react';
import GeneralInfo from './components/GeneralInfo';
Expand Down Expand Up @@ -92,18 +94,24 @@ const MitigationPack: FC<MitigationPackProp> = ({
return null;
}

return (<SpaceBetween direction='vertical' size='s'>
<GeneralInfo mitigationPack={mitigationPack} />
<Table
columnDefinitions={colDef}
actions={actions}
header="Mitigations"
items={mitigationPack.mitigations || []}
wrapLines={true}
isItemDisabled={isItemDisabled}
selectedItems={totalSelectedItems}
onSelectionChange={({ detail }) => setSelectedItems([...detail.selectedItems])}
/></SpaceBetween>);
return (<ContentLayout header={
<Header
variant="h2"
>
Mitigation Pack - {mitigationPack.name}
</Header>
}><SpaceBetween direction='vertical' size='s'>
<GeneralInfo mitigationPack={mitigationPack} />
<Table
columnDefinitions={colDef}
actions={actions}
header="Mitigations"
items={mitigationPack.mitigations || []}
wrapLines={true}
isItemDisabled={isItemDisabled}
selectedItems={totalSelectedItems}
onSelectionChange={({ detail }) => setSelectedItems([...detail.selectedItems])}
/></SpaceBetween></ContentLayout>);
};

export default MitigationPack;

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
******************************************************************************************************************** */
import Box from '@cloudscape-design/components/box';
import Button from '@cloudscape-design/components/button';
import ContentLayout from '@cloudscape-design/components/content-layout';
import Header from '@cloudscape-design/components/header';
import SpaceBetween from '@cloudscape-design/components/space-between';
import { FC, useMemo } from 'react';
import GeneralInfo from './components/GeneralInfo';
import { useMitigationPacksContext } from '../../../contexts/MitigationPacksContext';
import { MitigationPack } from '../../../customTypes/referencePacks';
import Table, { ColumnDefinition } from '../../generic/Table';


export interface MitigationPacksProps {
onMitigationPackLinkClicked?: (id: string) => void;
}
Expand All @@ -34,7 +36,7 @@ const MitigationPacks: FC<MitigationPacksProps> = ({
const colDef: ColumnDefinition<MitigationPack>[] = useMemo(() => [
{
id: 'id',
minWidth: 100,
minWidth: 150,
header: 'Id',
cell: (data) => (<Button variant="inline-link" onClick={() => onMitigationPackLinkClicked?.(data.id)}>
{data.id}
Expand Down Expand Up @@ -68,16 +70,21 @@ const MitigationPacks: FC<MitigationPacksProps> = ({
},
], [mitigationPackUsage, onMitigationPackLinkClicked]);

return (<SpaceBetween direction='vertical' size='s'>
<GeneralInfo />
<Table
columnDefinitions={colDef}
header="Mitigation packs"
items={mitigationPacks}
disableRowSelect={true}
wrapLines={true}

/></SpaceBetween>);
return (<ContentLayout header={<Header
variant="h2"
description="Allow you to quickly find and add bulk or selected mitigation candidates to your current workspace"
counter={`(${mitigationPacks.length})`}
>
Mitigation Packs
</Header>}>
<SpaceBetween direction='vertical' size='s'>
<Table
columnDefinitions={colDef}
items={mitigationPacks}
disableRowSelect={true}
wrapLines={true}
/></SpaceBetween>
</ContentLayout>);
};

export default MitigationPacks;
Loading

0 comments on commit 42ede80

Please sign in to comment.