Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

working with Threat dragon 2 #123

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions apps/client/src/components/board/board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ const Board: FC<BoardProps> = ({
onSelectDiagram={moves.selectDiagram}
onSelectComponent={moves.selectComponent}
/>
)}
{G.modelType === ModelType.THREAT_DRAGON_V2 && model !== undefined && (
<Model
model={model}
selectedDiagram={G.selectedDiagram}
selectedComponent={G.selectedComponent}
onSelectDiagram={moves.selectDiagram}
onSelectComponent={moves.selectComponent}
/>
)}
{G.modelType === ModelType.PRIVACY_ENHANCED && (
<PrivacyEnhancedModel modelReference={G.modelReference} />
Expand Down
13 changes: 13 additions & 0 deletions apps/client/src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ const Sidebar: FC<SidebarProps> = ({
Download Model
</DownloadButton>
)}
{G.modelType === ModelType.THREAT_DRAGON_V2 && (
<DownloadButton
matchID={matchID}
playerID={playerID}
secret={secret}
block
size="lg"
color="success"
apiEndpoint="download"
>
Download Model
</DownloadButton>
)}
<DownloadButton
matchID={matchID}
playerID={playerID}
Expand Down
44 changes: 43 additions & 1 deletion apps/client/src/pages/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ class Create extends React.Component<CreateProps, CreateState> {
}
}
if (
(this.state.modelType === ModelType.THREAT_DRAGON && !this.state.model) ||
(this.state.modelType === ModelType.THREAT_DRAGON && !this.state.model) ||
(this.state.modelType === ModelType.THREAT_DRAGON_V2 && !this.state.model) ||
(this.state.modelType === ModelType.IMAGE && !this.state.image)
) {
return false;
Expand Down Expand Up @@ -511,6 +512,47 @@ class Create extends React.Component<CreateProps, CreateState> {
to try it out.
</FormText>
</FormGroup>
<FormGroup>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does one need a dedicated form group for V2? Or could one validate the uploaded model and set a ModelType according to that?

<Label check>
<Input
type="radio"
name="model-type"
value={ModelType.THREAT_DRAGON_V2}
onChange={this.updateModelType.bind(this)}
/>
Provide model via Threat Dragon V2
</Label>
<Input
disabled={this.state.modelType !== ModelType.THREAT_DRAGON_V2}
type="file"
name="model-json"
id="model"
onChange={this.readJson.bind(this)}
checked={this.state.modelType === ModelType.THREAT_DRAGON_V2}
/>
<FormText color="muted">
Select the JSON model produced by{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://docs.threatdragon.org/"
>
Threat Dragon V2
</a>
.
</FormText>
<FormText color="muted">
Or download a{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://owasp.org/www-project-threat-dragon/assets/schemas/owasp.threat-dragon.schema.V2.json"
>
sample model
</a>{' '}
to try it out.
</FormText>
</FormGroup>
</Col>
</FormGroup>
<hr />
Expand Down
23 changes: 17 additions & 6 deletions apps/server/src/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import {
INTERNAL_API_PORT,
isSuit,
logEvent,
mapModel2toOldModel,
ModelType,
ThreatDragonModel,
ThreatDragonModel2,
ThreatDragonThreat,
gameName,
} from '@eop/shared';
Expand Down Expand Up @@ -86,10 +88,17 @@ export const createGame =
switch (body.modelType) {
case ModelType.THREAT_DRAGON: {
// TODO: validation
await gameServer.db.setModel(
matchID,
JSON.parse(body.model as string) as ThreatDragonModel,
);
logEvent(`printing body: ${body.model}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log statement should be removed. The model can potentially contain sensitive data that MUST NOT end up in the logs.

var model = JSON.parse(body.model as string) as ThreatDragonModel;
await gameServer.db.setModel(matchID,model);
break;
}

case ModelType.THREAT_DRAGON_V2: {
logEvent(`printing body: ${body.model}`);
var model2 = JSON.parse(body.model as string) as ThreatDragonModel2;
var model = mapModel2toOldModel(model2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand it correctly: The Input is a V2 model, but internally it gets mapped to a V1 model? This would mean that the model that can be downloaded is also V1? For the users this might be every unintuitive...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to agree. I know it's probably a decent amount of work, but I would prefer to actually support V2 properly, which likely means completely switching out the rendering logic of the diagrams. We might also have to deal with the fact that a threat dragon model can contain multiple diagrams. I'm not sure how this is handled right now (if it is at all).

But maybe this could be an interim solution, to unblock users who want to load a v2 model into EoP, until we have a proper solution?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. But if we use this as an interim solution, we should be transparent and rename the download button. Maybe add "(Threat Dragon V1)" tiny underneath the "Download Threats"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes @ChristophNiehoff i have mapped v2 model to v1 as workaround.
There is new diagram in V2 (box) which is handled. I am working on proper solution on v2.

await gameServer.db.setModel(matchID,model);
break;
}

Expand Down Expand Up @@ -222,7 +231,8 @@ export const downloadThreatDragonModel =

const isJsonModel =
state.G.modelType == ModelType.PRIVACY_ENHANCED ||
state.G.modelType == ModelType.THREAT_DRAGON;
state.G.modelType == ModelType.THREAT_DRAGON ||
state.G.modelType == ModelType.THREAT_DRAGON_V2;

const model = game.model;
if (!model || 'extension' in model || !isJsonModel) {
Expand Down Expand Up @@ -295,7 +305,8 @@ export const downloadThreatsMarkdownFile =

const isJsonModel =
state.G.modelType == ModelType.PRIVACY_ENHANCED ||
state.G.modelType == ModelType.THREAT_DRAGON;
state.G.modelType == ModelType.THREAT_DRAGON ||
state.G.modelType == ModelType.THREAT_DRAGON_V2;

const model = game.model;
const threats = getThreats(
Expand Down
3 changes: 2 additions & 1 deletion packages/shared/src/game/ThreatDragonModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ type CellType =
| 'tm.Store'
| 'tm.Actor'
| 'tm.Flow'
| 'tm.Boundary';
| 'tm.Boundary'
| 'tm.BoundaryBox';

export interface ThreatDragonThreat {
/**
Expand Down
233 changes: 233 additions & 0 deletions packages/shared/src/game/ThreatDragonModel2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/**
* The threat models used by OWASP Threat Dragon
*
* This type is based on the schema at https://owasp.org/www-project-threat-dragon/assets/schemas/owasp.threat-dragon.schema.V2.json
*/

export interface ThreatDragonModel2 {
summary: Summary
detail: Detail
version: string
}

export interface Summary {
title: string
owner: string
description: string
id: number
}

export interface Detail {
contributors: Contributor[]
diagrams: Diagram[]
reviewer: string
diagramTop: number
threatTop: number
}

export interface Contributor {
name: string
}

export interface Diagram {
cells: Cell[]
version: string
title: string
thumbnail: string
id: number
}

export interface Cell {
position?: {
/**
* The component horizontal position
*/
x: number;
/**
* The component vertical position
*/
y: number;
[k: string]: unknown;
};
size?: {
/**
* The component height
*/
height: number;
/**
* The component width
*/
width: number;
};
attrs?: Attrs
visible?: boolean
shape: string
zIndex: number
id: string
data: Data
width?: number
height?: number
connector?: string
labels?: Label[]
source?: Source
target?: Target
vertices?: {
/**
* The horizontal value of the curve point
*/
x: number;
/**
* The vertical value of the curve point
*/
y: number;
};
}

export interface Position {
x: number
y: number
}

export interface Size {
width: number
height: number
}

export interface Attrs {
line?: Line
text?: Text
topLine?: TopLine
bottomLine?: BottomLine
body?: Body
}

export interface Line {
stroke: string
strokeWidth?: number
targetMarker: TargetMarker
sourceMarker: SourceMarker
strokeDasharray?: string
}

export interface TargetMarker {
name: string
}

export interface SourceMarker {
name: string
}

export interface Text {
text: string
}

export interface TopLine {
stroke: string
strokeWidth: number
strokeDasharray: any
}

export interface BottomLine {
stroke: string
strokeWidth: number
strokeDasharray: any
}

export interface Body {
stroke: string
strokeWidth: number
strokeDasharray: any
}

export interface Data {
name: string
description: string
type: CellType
isTrustBoundary: boolean
outOfScope?: boolean
reasonOutOfScope?: string
threats?: Threat[]
hasOpenThreats: boolean
isALog?: boolean
storesCredentials?: boolean
isEncrypted?: boolean
isSigned?: boolean
providesAuthentication?: boolean
isBidirectional?: boolean
isPublicNetwork?: boolean
protocol?: string
}

export interface Threat {
status: Status
severity: string
title: string
type: string
description: string
mitigation: string
modelType: string
id: string
}

export interface Label {
/**
* The label position
*/
position: number;
/**
* The label text attributes
*/
attrs: {
/**
* The text attributes
*/
label: {
/**
* The text size
*/
// 'font-size': string;
/**
* The text weight
*/
// 'font-weight': string;
/**
* The text content
*/
text: string;
};
};
}

export interface Attrs2 {
label: Label2
}

export interface Label2 {
text: string
}

export interface Source {
x?: number
y?: number
cell?: string
}

export interface Target {
x?: number
y?: number
cell?: string
}

export interface Vertex {
x: number
y: number
}
export type CellType =
| 'tm.Process'
| 'tm.Store'
| 'tm.Actor'
| 'tm.Flow'
| 'tm.Boundary'
| 'tm.BoundaryBox';

type Status = 'NA' | 'Open' | 'Mitigated';
1 change: 1 addition & 0 deletions packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './game/eop';
export * from './game/gameState';
export * from './game/setupData';
export * from './game/ThreatDragonModel';
export * from './game/ThreatDragonModel2';

export * from './utils/serverConfig';
export * from './utils/constants';
Expand Down
Loading