Skip to content

Commit

Permalink
reflect new IR workflow in osim
Browse files Browse the repository at this point in the history
Signed-off-by: Conrado Costa <[email protected]>
  • Loading branch information
costaconrado committed Oct 24, 2023
1 parent 39af4ba commit 211d8ff
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 74 deletions.
4 changes: 2 additions & 2 deletions apps/osim/tests/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ def test_workflows_uuid_adjusting(self, auth_client, test_api_uri):
workflow_framework = WorkflowFramework()
state_new = State(
{
"name": WorkflowModel.OSIMState.DRAFT,
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}
)
state_first = State(
{
"name": WorkflowModel.OSIMState.ANALYSIS,
"name": WorkflowModel.OSIMState.TRIAGE,
"requirements": ["has description"],
}
)
Expand Down
12 changes: 6 additions & 6 deletions apps/osim/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ def test_healthy(self, auth_client, test_scheme_host):
def test_adjust(self, auth_client, test_api_uri):
"""test refreshing/adjusting a flaw state through API"""
state_new = {
"name": WorkflowModel.OSIMState.DRAFT,
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}
state_first = {
"name": WorkflowModel.OSIMState.ANALYSIS,
"name": WorkflowModel.OSIMState.TRIAGE,
"requirements": ["has cwe"],
}

Expand All @@ -246,7 +246,7 @@ def test_adjust(self, auth_client, test_api_uri):
flaw.cwe_id = ""
flaw.save(raise_validation_error=False)
flaw.adjust_classification()
assert flaw.classification["state"] == WorkflowModel.OSIMState.DRAFT
assert flaw.classification["state"] == WorkflowModel.OSIMState.NEW

flaw.cwe_id = "CWE-1"
flaw.save(raise_validation_error=False)
Expand All @@ -260,11 +260,11 @@ def test_adjust(self, auth_client, test_api_uri):

json_body = response.json()
assert str(flaw.uuid) == json_body["flaw"]
assert WorkflowModel.OSIMState.ANALYSIS == json_body["classification"]["state"]
assert WorkflowModel.OSIMState.TRIAGE == json_body["classification"]["state"]

def test_classification(self, auth_client, test_api_uri):
state_new = {
"name": WorkflowModel.OSIMState.DRAFT,
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}

Expand Down Expand Up @@ -295,7 +295,7 @@ def test_classification(self, auth_client, test_api_uri):
assert "state" in json_body["classification"]

assert json_body["classification"]["workflow"] == "main workflow"
assert json_body["classification"]["state"] == WorkflowModel.OSIMState.DRAFT
assert json_body["classification"]["state"] == WorkflowModel.OSIMState.NEW

def test_workflows(self, auth_client, test_api_uri):
response = auth_client.get(
Expand Down
55 changes: 49 additions & 6 deletions apps/osim/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,11 @@ def test_classify_priority(self):
def test_classify_complete(self):
"""test flaw classification in both workflow and state"""
state_new = {
"name": WorkflowModel.OSIMState.DRAFT,
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}
state_first = {
"name": WorkflowModel.OSIMState.ANALYSIS,
"name": WorkflowModel.OSIMState.TRIAGE,
"requirements": ["has description"],
}
state_second = {
Expand All @@ -423,7 +423,7 @@ def test_classify_complete(self):
)

state_not_affected = {
"name": WorkflowModel.OSIMState.REVIEW,
"name": WorkflowModel.OSIMState.REJECTED,
"requirements": [],
}

Expand Down Expand Up @@ -538,6 +538,50 @@ def test_init(self):

def test_classification(self):
"""test flaw classification property"""
state_new = {
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}
state_first = {
"name": WorkflowModel.OSIMState.TRIAGE,
"requirements": ["has description"],
}
state_second = {
"name": WorkflowModel.OSIMState.DONE,
"requirements": ["has title"],
}

workflow_main = Workflow(
{
"name": "main workflow",
"description": "a three step workflow to test classification",
"priority": 0,
"conditions": [],
"states": [state_new, state_first, state_second],
}
)

state_not_affected = {
"name": WorkflowModel.OSIMState.REJECTED,
"requirements": [],
}

workflow_reject = Workflow(
{
"name": "reject workflow",
"description": "a worflow for rejected flaws",
"priority": 1,
"conditions": ["has affects", "affects notaffected"],
"states": [state_not_affected],
}
)

workflow_framework = WorkflowFramework()
# remove yml workflows
workflow_framework._workflows = []
workflow_framework.register_workflow(workflow_main)
workflow_framework.register_workflow(workflow_reject)

flaw = Flaw()

# stored classification
Expand All @@ -548,7 +592,6 @@ def test_classification(self):
old_computed_state = flaw.classify()["state"]
assert flaw.osim_workflow == old_computed_workflow
assert flaw.osim_state == old_computed_state

# assing new and different classification
for workflow in WorkflowFramework().workflows:
if workflow.name != flaw.osim_workflow:
Expand Down Expand Up @@ -583,13 +626,13 @@ def test_adjust(self):

state_new = State(
{
"name": WorkflowModel.OSIMState.DRAFT,
"name": WorkflowModel.OSIMState.NEW,
"requirements": [],
}
)
state_first = State(
{
"name": WorkflowModel.OSIMState.ANALYSIS,
"name": WorkflowModel.OSIMState.TRIAGE,
"requirements": ["has description"],
}
)
Expand Down
10 changes: 5 additions & 5 deletions apps/osim/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ class WorkflowModel(models.Model):
class OSIMState(models.TextChoices):
"""allowable workflow states"""

DRAFT = "DRAFT"
NEW = "NEW"
ANALYSIS = "ANALYSIS"
REVIEW = "REVIEW"
FIX = "FIX"
TRIAGE = "TRIAGE"
PRE_SECOND_ASSESSMENT = "PRE_SECONDARY_ASSESSMENT"
SECOND_ASSESSMENT = "SECONDARY_ASSESSMENT"
DONE = "DONE"
REJECTED = "REJECTED"

# workflow metadata
osim_workflow = models.CharField(max_length=50, blank=True)
osim_state = models.CharField(choices=OSIMState.choices, max_length=10, blank=True)
osim_state = models.CharField(choices=OSIMState.choices, max_length=24, blank=True)

class Meta:
abstract = True
Expand Down
70 changes: 51 additions & 19 deletions apps/osim/workflows/default.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,66 @@
---
name: DEFAULT
description: default vulnerability analysis
description: default vulnerability workflow.
priority: 0
conditions: []
enter_automatically: true
states:
- name: DRAFT
- name: NEW
description: >
A new ticket arrived from incoming queue without any validation
or analysis performed yet.
jira_state: New
jira_resolution: null
enter_automatically: true
requirements: []

- name: ANALYSIS
- name: TRIAGE
description: >
Queue captain has taken a ticket off the incoming queue and will
evalute if it should be rejected or qualified for further steps in
the workflow.
jira_state: Refinement
jira_resolution: null
enter_automatically: true
requirements:
- has owner

- name: PRE_SECONDARY_ASSESSMENT
description: >
Task qualified for further work and has initial data filled, triage
trackers have been filled and product team has been identified.
jira_state: To Do
jira_resolution: null
enter_automatically: true
requirements:
- has affects
- has description
- has impact
- has source
- has team
- has title
- has trackers

- name: REVIEW
requirements:
- affects resolved
- has cve
- has cwe

- name: FIX
- name: SECONDARY_ASSESSMENT
description: An analyst assigned the task to themselves.
jira_state: In Progress
jira_resolution: null
enter_automatically: true
requirements:
- trackers filed
- has owner

# you can freely comment as you wish
# maybe about that this is the final state
- name: DONE
requirements:
# TODO embargoed is not model attribute any more but annotation
# so this currently errors out and we need to accout for the change
#- not embargoed
- trackers resolved
description: >
Task is done. We commonly expect that a CVE will be
published, but it is not a requirement.
jira_state: Closed
jira_resolution: Done
enter_automatically: false
requirements: []

- name: REJECTED
description: >
Task were rejected either by the queue captain or the analyst.
jira_state: Closed
jira_resolution: Won't Do
enter_automatically: false
requirements: []
25 changes: 0 additions & 25 deletions apps/osim/workflows/not-affected.yml

This file was deleted.

3 changes: 0 additions & 3 deletions apps/taskman/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Deprecate various cvss fields in Flaw and Affect APIs (OSIDB-1105)
- Update CORS policy to allow bugzilla-api-key request header (OSIDB-1425)
- Change workflows to reflect current IR workflow (OSIDB-1319)

### Fixed
- Fix schema wrongly showing status code for DELETE methods being 204
Expand Down
16 changes: 8 additions & 8 deletions openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8013,12 +8013,12 @@ components:
state:
type: string
enum:
- DRAFT
- NEW
- ANALYSIS
- REVIEW
- FIX
- TRIAGE
- PRE_SECONDARY_ASSESSMENT
- SECONDARY_ASSESSMENT
- DONE
- REJECTED
readOnly: true
required:
- acknowledgments
Expand Down Expand Up @@ -8689,12 +8689,12 @@ components:
state:
type: string
enum:
- DRAFT
- NEW
- ANALYSIS
- REVIEW
- FIX
- TRIAGE
- PRE_SECONDARY_ASSESSMENT
- SECONDARY_ASSESSMENT
- DONE
- REJECTED
readOnly: true
required:
- acknowledgments
Expand Down
18 changes: 18 additions & 0 deletions osidb/migrations/0101_alter_flaw_osim_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.20 on 2023-10-24 00:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('osidb', '0100_fix_affectcvss'),
]

operations = [
migrations.AlterField(
model_name='flaw',
name='osim_state',
field=models.CharField(blank=True, choices=[('NEW', 'New'), ('TRIAGE', 'Triage'), ('PRE_SECONDARY_ASSESSMENT', 'Pre Second Assessment'), ('SECONDARY_ASSESSMENT', 'Second Assessment'), ('DONE', 'Done'), ('REJECTED', 'Rejected')], max_length=24),
),
]
10 changes: 10 additions & 0 deletions osidb/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,16 @@ def trackers_filed(self):
for affect in self.affects.filter(resolution=Affect.AffectResolution.FIX)
)

@property
def task_owner(self):
"""return the current task owner in Jira"""
return self.task.owner if hasattr(self, "task") else ""

@property
def task_team_id(self):
"""return the current team id in Jira"""
return self.task.team_id if hasattr(self, "task") else ""

@property
def trackers_resolved(self):
"""check that all trackers have resolution"""
Expand Down

0 comments on commit 211d8ff

Please sign in to comment.