From ba1dee7ad907ea841de7a6db51d924b885c5c484 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 15:04:55 +0530 Subject: [PATCH 1/6] added test coverage for the code --- test_app.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/test_app.py b/test_app.py index b65fc90..2ae9f4e 100644 --- a/test_app.py +++ b/test_app.py @@ -24,3 +24,79 @@ def test_pred_virginica(): # asserting the correct response is received assert response.status_code == 200 assert response.json() == {"flower_class": "Iris Virginica"} + + +# test to check if Iris Versicolour is classified correctly +def test_pred_versicolour(): + # defining a sample payload for the testcase + payload = { + "sepal_length": 3.1, + "sepal_width": 1, + "petal_length": 1, + "petal_width": 1, + } + with TestClient(app) as client: + response = client.post("/predict_flower", json=payload) + # asserting the correct response is received + assert response.status_code == 200 + assert response.json() == {"flower_class": "Iris Versicolour"} + + +# test to check if invalid param in payload is passed +def test_pred_invalid_payload(): + # defining a sample payload for the testcase + payload = { + "sepal_length": 2, + "sepal_wid": 3.5, + "petal_length": 1.4, + "petal_width": 0.2, + } + with TestClient(app) as client: + response = client.post("/predict_flower", json=payload) + # asserting the correct response is received + assert response.status_code == 422 + assert response.json() == {'detail': [{'loc': ['body', 'sepal_width'], 'msg': 'field required', 'type': 'value_error.missing'}]} + + +# test to check if invalid param in payload is passed +def test_pred_empty_payload(): + # defining a sample payload for the testcase + payload = { + + } + with TestClient(app) as client: + response = client.post("/predict_flower", json=payload) + # asserting the correct response is received + assert response.status_code == 422 + assert response.json() == {'detail': [{'loc': ['body', 'sepal_length'], 'msg': 'field required', 'type': 'value_error.missing'}, {'loc': ['body', 'sepal_width'], 'msg': 'field required', 'type': 'value_error.missing'}, {'loc': ['body', 'petal_length'], 'msg': 'field required', 'type': 'value_error.missing'}, {'loc': ['body', 'petal_width'], 'msg': 'field required', 'type': 'value_error.missing'}]} + + +# test to check if Iris Setosa is classified correctly +def test_pred_setosa(): + # defining a sample payload for the testcase + payload = { + "sepal_length": 5.1, + "sepal_width": 3.5, + "petal_length": 1.4, + "petal_width": 0.2, + } + with TestClient(app) as client: + response = client.post("/predict_flower", json=payload) + # asserting the correct response is received + assert response.status_code == 200 + assert response.json()["flower_class"] == "Iris Setosa" + +# test to check if Iris Virginica is classified correctly with different payload +# def test_pred_virginica_diff_payload(): +# # defining a sample payload for the testcase +# payload = { +# "sepal_length": 5.2, +# "sepal_width": 5.4, +# "petal_length": 10.4, +# "petal_width": 6.2, +# } +# with TestClient(app) as client: +# response = client.post("/predict_flower", json=payload) +# # asserting the correct response is received +# assert response.status_code == 200 +# assert response.json()["flower_class"] == "Iris Virginica" \ No newline at end of file From 67e4488de40dc39c4a02d35db8b869eaedb56b02 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 15:17:24 +0530 Subject: [PATCH 2/6] updated the badge in README file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 48be970..044638a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dev-Sec-Ops Demo/Assignment -[![codecov](https://codecov.io/gh/PGCSEDS-IIITH/devsecops-iris/branch/master/graph/badge.svg?token=EILEH8L7R5)](https://codecov.io/gh/PGCSEDS-IIITH/devsecops-iris) +[![codecov](https://codecov.io/gh/vineeth964/devsecops-iris/branch/master/graph/badge.svg?token=EILEH8L7R5)](https://codecov.io/gh/vineeth964/devsecops-iris) This repository contains code which demonstrates Dev-Sec-Ops using a `FastAPI` application which predicts the flower class using the IRIS dataset (https://scikit-learn.org/stable/auto_examples/datasets/plot_iris_dataset.html) From a0add595c91ef178e818d4a8d9a7da8417ebff80 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 15:27:51 +0530 Subject: [PATCH 3/6] added test coverage for feedback_loop and OS changes to matrix strategy --- .github/workflows/cicd.yml | 5 +++- test_app.py | 58 +++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index dba2125..7503a96 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -6,7 +6,10 @@ on: push jobs: # first job to test the application using pytest unittest: - runs-on: ubuntu-latest # choose the OS for running the action + runs-on: ${{ matrix.os }} # choose the OS for running the action + strategy: + matrix: + os: ['ubuntu-latest', 'windows-latest'] # define the individual sequential steps to be run steps: - name: Checkout the repository diff --git a/test_app.py b/test_app.py index 2ae9f4e..b5c1f94 100644 --- a/test_app.py +++ b/test_app.py @@ -87,16 +87,48 @@ def test_pred_setosa(): assert response.json()["flower_class"] == "Iris Setosa" # test to check if Iris Virginica is classified correctly with different payload -# def test_pred_virginica_diff_payload(): -# # defining a sample payload for the testcase -# payload = { -# "sepal_length": 5.2, -# "sepal_width": 5.4, -# "petal_length": 10.4, -# "petal_width": 6.2, -# } -# with TestClient(app) as client: -# response = client.post("/predict_flower", json=payload) -# # asserting the correct response is received -# assert response.status_code == 200 -# assert response.json()["flower_class"] == "Iris Virginica" \ No newline at end of file +def test_pred_virginica_diff_payload(): + # defining a sample payload for the testcase + payload = { + "sepal_length": 5.2, + "sepal_width": 5.4, + "petal_length": 10.4, + "petal_width": 6.2, + } + with TestClient(app) as client: + response = client.post("/predict_flower", json=payload) + # asserting the correct response is received + assert response.status_code == 200 + assert response.json()["flower_class"] == "Iris Virginica" + +#test to check feedback_loop method for Iris Virginica +def test_feedback_loop_virginica(): +# defining a sample payload for the testcase + payload = [{ + "sepal_length": 3, + "sepal_width": 5, + "petal_length": 3.2, + "petal_width": 4.4, + "flower_class":"Iris Virginica" + }] + with TestClient(app) as client: + response = client.post("/feedback_loop", json=payload) + # asserting the correct response is received + assert response.status_code == 200 + assert response.json() == {"detail": "Feedback loop successful"} + +#test to check feedback_loop method +def test_feedback_loop(): +# defining a sample payload for the testcase + payload = [{ + "sepal_length": 3.8, + "sepal_width": 8, + "petal_length": 5.2, + "petal_width": 4.4, + "flower_class":"Iris Setosa" + }] + with TestClient(app) as client: + response = client.post("/feedback_loop", json=payload) + # asserting the correct response is received + assert response.status_code == 200 + assert response.json() == {"detail": "Feedback loop successful"} \ No newline at end of file From 50c90e154bf42c7473cf37344c8f0e49b1cdb975 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 15:32:50 +0530 Subject: [PATCH 4/6] fixing failure --- .github/workflows/cicd.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 7503a96..dba2125 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -6,10 +6,7 @@ on: push jobs: # first job to test the application using pytest unittest: - runs-on: ${{ matrix.os }} # choose the OS for running the action - strategy: - matrix: - os: ['ubuntu-latest', 'windows-latest'] + runs-on: ubuntu-latest # choose the OS for running the action # define the individual sequential steps to be run steps: - name: Checkout the repository From 07a506e5f97e916fee0eb8895fda14920b515fd5 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 18:14:40 +0530 Subject: [PATCH 5/6] changed testcase --- test_app.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test_app.py b/test_app.py index b5c1f94..4c733d0 100644 --- a/test_app.py +++ b/test_app.py @@ -26,20 +26,20 @@ def test_pred_virginica(): assert response.json() == {"flower_class": "Iris Virginica"} -# test to check if Iris Versicolour is classified correctly -def test_pred_versicolour(): +# test to check if Iris Virginica is classified correctly +def test_pred_virginica_diff(): # defining a sample payload for the testcase payload = { "sepal_length": 3.1, - "sepal_width": 1, - "petal_length": 1, - "petal_width": 1, + "sepal_width": 5.7, + "petal_length": 6, + "petal_width": 6, } with TestClient(app) as client: response = client.post("/predict_flower", json=payload) # asserting the correct response is received assert response.status_code == 200 - assert response.json() == {"flower_class": "Iris Versicolour"} + assert response.json() == {"flower_class": "Iris Virginica"} # test to check if invalid param in payload is passed From 5a55131e6cd5b4c792db9542de417959d08fac35 Mon Sep 17 00:00:00 2001 From: vineeth964 Date: Tue, 21 Dec 2021 18:19:06 +0530 Subject: [PATCH 6/6] sariff changes --- results.sariff | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 results.sariff diff --git a/results.sariff b/results.sariff new file mode 100644 index 0000000..3fa5331 --- /dev/null +++ b/results.sariff @@ -0,0 +1,89 @@ +{ + "runs": [ + { + "tool": { + "driver": { + "name": "Bandit", + "rules": [ + { + "id": "B104", + "name": "hardcoded_bind_all_interfaces", + "helpUri": "https://bandit.readthedocs.io/en/latest/plugins/b104_hardcoded_bind_all_interfaces.html" + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true, + "endTimeUtc": "2021-09-25T13:05:38Z" + } + ], + "properties": { + "metrics": { + "_totals": { + "loc": 33, + "nosec": 0, + "SEVERITY.UNDEFINED": 0.0, + "CONFIDENCE.UNDEFINED": 0.0, + "SEVERITY.LOW": 0.0, + "CONFIDENCE.LOW": 0.0, + "SEVERITY.MEDIUM": 1.0, + "CONFIDENCE.MEDIUM": 1.0, + "SEVERITY.HIGH": 0.0, + "CONFIDENCE.HIGH": 0.0 + }, + "./main.py": { + "loc": 33, + "nosec": 0, + "SEVERITY.UNDEFINED": 0.0, + "SEVERITY.LOW": 0.0, + "SEVERITY.MEDIUM": 1.0, + "SEVERITY.HIGH": 0.0, + "CONFIDENCE.UNDEFINED": 0.0, + "CONFIDENCE.LOW": 0.0, + "CONFIDENCE.MEDIUM": 1.0, + "CONFIDENCE.HIGH": 0.0 + } + } + }, + "results": [ + { + "message": { + "text": "Possible binding to all interfaces." + }, + "locations": [ + { + "physicalLocation": { + "region": { + "snippet": { + "text": " uvicorn.run(\"main:app\", host=\"0.0.0.0\", port=8888, reload=True)\n" + }, + "startLine": 64 + }, + "artifactLocation": { + "uri": "main.py" + }, + "contextRegion": { + "snippet": { + "text": " # Uvicorn is used to run the server and listen for incoming API requests on 0.0.0.0:8888\n uvicorn.run(\"main:app\", host=\"0.0.0.0\", port=8888, reload=True)\n" + }, + "endLine": 64, + "startLine": 63 + } + } + } + ], + "properties": { + "issue_confidence": "MEDIUM", + "issue_severity": "MEDIUM" + }, + "ruleId": "B104", + "ruleIndex": 0 + } + ] + } + ], + "version": "2.1.0", + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json" +} \ No newline at end of file