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

FOGL-3125, FOGL-5121: Update audit entries tests #322

Merged
merged 27 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
00ad952
FOGL-3125: fix for adding audit entries in Postgres
pintomax Mar 9, 2021
f544efc
Merge branch 'develop' into FOGL-3125
pintomax Mar 11, 2021
1cd004a
Review feedback
pintomax Mar 11, 2021
0fe90f7
Merge remote-tracking branch 'origin/develop' into FOGL-3125
praveen-garg Mar 25, 2021
4d0a797
test updates per storage engine for audit. This should be tested wit…
praveen-garg Mar 25, 2021
ccb73db
test updates per storage engine for audit. This should be tested wit…
praveen-garg Mar 25, 2021
bd24cb4
indent fix
praveen-garg Mar 25, 2021
76ee1f2
fix param
praveen-garg Mar 25, 2021
0cc7119
audit entry details check should be timestamp based, not by index. JS…
praveen-garg Mar 25, 2021
6dcc5db
audit entry details check should be timestamp based, not by index. JS…
praveen-garg Mar 25, 2021
d2bede5
correct handling of 5xx error - fixed unit test
praveen-garg Mar 25, 2021
8830fb6
import fix
praveen-garg Mar 25, 2021
1416960
patch fix
praveen-garg Mar 25, 2021
503bba2
patch fix
praveen-garg Mar 25, 2021
e2e0703
http code for error handling
praveen-garg Mar 25, 2021
17c2032
http code for error handling
praveen-garg Mar 25, 2021
1b4e15f
http code for error handling
praveen-garg Mar 25, 2021
743ace0
http code for error handling
praveen-garg Mar 25, 2021
a558859
fix error return
praveen-garg Mar 26, 2021
9b8d794
added test scenario
praveen-garg Mar 26, 2021
34f459f
fixed err message
praveen-garg Mar 26, 2021
402772c
Merge branch 'develop' into FOGL-3125
praveen-garg Mar 26, 2021
6eac526
review feedback fixes
praveen-garg Mar 26, 2021
e710ee2
review feedback fixes
praveen-garg Mar 26, 2021
29f1579
review feedback fixes
praveen-garg Mar 26, 2021
54f13f1
review feedback fixes
praveen-garg Mar 26, 2021
f3acf47
revert wait fix
praveen-garg Mar 26, 2021
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
10 changes: 5 additions & 5 deletions docs/rest_api_guide/02_RESTadmin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ The request payload is a JSON object with the audit trail entry minus the timest
+-----------+-----------+-----------------------------------------------+---------------------------+
| Name | Type | Description | Example |
+===========+===========+===============================================+===========================+
| source | string | The source of the audit trail entry. | LocalMonitor |
| source | string | The source of the audit trail entry. | LOGGN |
+-----------+-----------+-----------------------------------------------+---------------------------+
| severity | string | The severity of the event that triggered |br| | FAILURE |
| | | the audit trail entry to be written. |br| | |
Expand All @@ -142,7 +142,7 @@ The response payload is the newly created audit trail entry.
| timestamp | timestamp | The timestamp when the audit trail |br| | 2018-04-16 14:33:18.215 |
| | | item was written. | |
+-----------+-----------+-----------------------------------------------+---------------------------+
| source | string | The source of the audit trail entry. | LocalMonitor |
| source | string | The source of the audit trail entry. | LOGGN |
+-----------+-----------+-----------------------------------------------+---------------------------+
| severity | string | The severity of the event that triggered |br| | FAILURE |
| | | the audit trail entry to be written. |br| | |
Expand All @@ -159,8 +159,8 @@ The response payload is the newly created audit trail entry.
.. code-block:: console

$ curl -X POST http://localhost:8081/fledge/audit \
-d '{ "severity": "FAILURE", "details": { "message": "Internal System Error" }, "source": "LocalMonitor" }'
{ "source": "LocalMonitor",
-d '{ "severity": "FAILURE", "details": { "message": "Internal System Error" }, "source": "LOGGN" }'
{ "source": "LOGGN",
"timestamp": "2018-04-17 11:49:55.480",
"severity": "FAILURE",
"details": { "message": "Internal System Error" }
Expand All @@ -169,7 +169,7 @@ The response payload is the newly created audit trail entry.
$ curl -X GET http://localhost:8081/fledge/audit?severity=FAILURE
{ "totalCount": 1,
"audit": [ { "timestamp": "2018-04-16 18:32:28.427",
"source" : "LocalMonitor",
"source" : "LOGGN",
"details" : { "message": "Internal System Error" },
"severity" : "FAILURE" }
]
Expand Down
16 changes: 13 additions & 3 deletions python/fledge/services/core/api/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
from datetime import datetime
from enum import IntEnum
from aiohttp import web
import json

from fledge.common.storage_client.payload_builder import PayloadBuilder
from fledge.common.storage_client.exceptions import StorageServerError
from fledge.services.core import connect
from fledge.common.audit_logger import AuditLogger
from fledge.common import logger
Expand Down Expand Up @@ -114,14 +116,22 @@ async def create_audit_entry(request):
'severity': severity,
'details': details
}
return web.json_response(message)
except AttributeError as e:
# Return error for wrong severity method
err_msg = "severity type {} is not supported".format(severity)
_logger.error("Error in create_audit_entry(): %s | %s", err_msg, str(e))
raise web.HTTPNotFound(reason=err_msg)
raise web.HTTPNotFound(reason=err_msg, body=json.dumps({"message": err_msg}))
except StorageServerError as ex:
if int(ex.code) in range(400, 500):
err_msg = 'Audit entry cannot be logged. {}'.format(ex.error['message'])
raise web.HTTPBadRequest(body=json.dumps({"message": err_msg}))
else:
err_msg = 'Failed to log audit entry. {}'.format(ex.error['message'])
raise web.HTTPInternalServerError(body=json.dumps({"message": err_msg}))
except Exception as ex:
raise web.HTTPInternalServerError(reason=str(ex))
raise web.HTTPInternalServerError(reason=str(ex), body=json.dumps({"message": str(ex)}))
else:
return web.json_response(message)


async def get_audit_entries(request):
Expand Down
111 changes: 87 additions & 24 deletions tests/system/python/api/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,46 +53,87 @@ def test_get_severity(self, fledge_url):
index = [idx['index'] for idx in log_severity]
assert Counter([0, 1, 2, 4]) == Counter(index)

@pytest.mark.parametrize("request_params, total_count, audit_count, cat_name", [
('', 11, 11, ''),
('?limit=1', 11, 1, ''),
('?skip=4', 11, 7, 'Installation'),
('?limit=1&skip=8', 11, 1, 'SCHEDULER'),
('?source=START', 1, 1, ''),
('?source=CONAD', 10, 10, 'Utilities'),
('?source=CONAD&limit=1', 10, 1, 'Utilities'),
('?source=CONAD&skip=1', 10, 9, 'General'),
('?source=CONAD&skip=6&limit=1', 10, 1, 'SMNTR'),
('?severity=INFORMATION', 11, 11, ''),
('?severity=failure', 0, 0, ''),
('?source=CONAD&severity=failure', 0, 0, ''),
('?source=START&severity=INFORMATION', 1, 1, ''),
('?source=START&severity=information&limit=1', 1, 1, ''),
('?source=START&severity=information&limit=1&skip=1', 1, 0, '')
@pytest.mark.parametrize("request_params, total_count, audit_count", [
('', 11, 11),
('?limit=1', 11, 1),
('?skip=4', 11, 7),
('?limit=1&skip=8', 11, 1),
('?source=START', 1, 1),
('?source=CONAD', 10, 10),
('?source=CONAD&limit=1', 10, 1),
('?source=CONAD&skip=1', 10, 9),
('?source=CONAD&skip=6&limit=1', 10, 1),
('?severity=INFORMATION', 11, 11),
('?severity=failure', 0, 0),
('?source=CONAD&severity=failure', 0, 0),
('?source=START&severity=INFORMATION', 1, 1),
('?source=START&severity=information&limit=1', 1, 1),
('?source=START&severity=information&limit=1&skip=1', 1, 0)
])
def test_default_get_audit(self, fledge_url, wait_time, request_params, total_count, audit_count, cat_name):
def test_default_get_audit_sqlite(self, fledge_url, wait_time, request_params, total_count, audit_count, storage_plugin):
if storage_plugin == 'postgres':
pytest.skip('Test is for SQLite only. Storage category when with SQLite plugin, creates a child category `sqlite` hence one additional CONAD entry.')

# wait for Fledge start, first test only, once in the iteration before start
if request_params == '':
time.sleep(wait_time)
praveen-garg marked this conversation as resolved.
Show resolved Hide resolved

conn = http.client.HTTPConnection(fledge_url)
conn.request("GET", '/fledge/audit{}'.format(request_params))
r = conn.getresponse()
assert 200 == r.status
r = r.read().decode()
jdoc = json.loads(r)
elems = jdoc['audit']
assert len(jdoc), "No data found"
assert total_count == jdoc['totalCount']
assert audit_count == len(jdoc['audit'])
if audit_count:
if jdoc['audit'][0]['details']:
assert cat_name == jdoc['audit'][0]['details']['name']
assert audit_count == len(elems)


@pytest.mark.parametrize("request_params, total_count, audit_count", [
('', 10, 10),
('?limit=1', 10, 1),
('?skip=4', 10, 6),
('?limit=1&skip=8', 10, 1),
('?source=START', 1, 1),
('?source=CONAD', 9, 9),
('?source=CONAD&limit=1', 9, 1),
('?source=CONAD&skip=1', 9, 8),
('?source=CONAD&skip=6&limit=1', 9, 1),
('?severity=INFORMATION', 10, 10),
('?severity=failure', 0, 0),
('?source=CONAD&severity=failure', 0, 0),
('?source=START&severity=INFORMATION', 1, 1),
('?source=START&severity=information&limit=1', 1, 1),
('?source=START&severity=information&limit=1&skip=1', 1, 0)
])
def test_default_get_audit_postgres(self, fledge_url, wait_time, request_params, total_count, audit_count, storage_plugin):
if storage_plugin == 'sqlite':
pytest.skip('Test is for PostgreSQL only. Storage category when with SQLite plugin, creates a child category `sqlite` hence one additional CONAD entry.')

# wait for Fledge start, first test only, once in the iteration before start
if request_params == '':
time.sleep(wait_time)

conn = http.client.HTTPConnection(fledge_url)
conn.request("GET", '/fledge/audit{}'.format(request_params))
r = conn.getresponse()
assert 200 == r.status
r = r.read().decode()
jdoc = json.loads(r)
audit_entries = jdoc['audit']
assert len(jdoc), "No data found"
assert total_count == jdoc['totalCount']
assert audit_count == len(audit_entries)


@pytest.mark.parametrize("payload, total_count", [
({"source": "LMTR", "severity": "warning", "details": {"message": "Engine oil pressure low"}}, 12),
({"source": "LMTR", "severity": "success", "details": {}}, 13),
({"source": "LOGGN", "severity": "warning", "details": {"message": "Engine oil pressure low"}}, 12),
({"source": "NHCOM", "severity": "success", "details": {}}, 13),
({"source": "START", "severity": "information", "details": {"message": "fledge started"}}, 14),
({"source": "CONCH", "severity": "failure", "details": {"message": "Scheduler configuration failed"}}, 15)
])
def test_create_audit_entry(self, fledge_url, payload, total_count):
def test_create_audit_entry(self, fledge_url, payload, total_count, storage_plugin):
conn = http.client.HTTPConnection(fledge_url)
conn.request('POST', '/fledge/audit', body=json.dumps(payload))
r = conn.getresponse()
Expand All @@ -110,5 +151,27 @@ def test_create_audit_entry(self, fledge_url, payload, total_count):
assert 200 == r.status
r = r.read().decode()
jdoc = json.loads(r)

# Storage category when with SQLite plugin, creates a child category `sqlite` hence one additional CONAD entry.
# CONAD, INFORMATION, '{{"name":"sqlite", ...}'
# so total_count is being decresed in case of 'postgres' storage engine
ashish-jabble marked this conversation as resolved.
Show resolved Hide resolved
if storage_plugin == 'postgres':
total_count = total_count -1

assert len(jdoc), "No data found"
assert total_count == jdoc['totalCount']

@pytest.mark.parametrize("payload", [
({"source": "LOGGN_X", "severity": "warning", "details": {"message": "Engine oil pressure low"}}),
({"source": "LOG_X", "severity": "information", "details": {"message": "Engine oil pressure is okay."}})
])
def test_create_nonexistent_log_code_audit_entry(self, fledge_url, payload):
conn = http.client.HTTPConnection(fledge_url)
conn.request('POST', '/fledge/audit', body=json.dumps(payload))
r = conn.getresponse()
assert 400 == r.status
praveen-garg marked this conversation as resolved.
Show resolved Hide resolved
assert 'Bad Request' in r.reason
r = r.read().decode()
jdoc = json.loads(r)
print(jdoc)
Copy link
Member

Choose a reason for hiding this comment

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

remove print statement

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking, we can keep such; for diagnosis using -vv such help. May be we can --verbose fixture in conftest and for system tests we can keep print for that if block?

assert "Audit entry cannot be logged" in jdoc['message']