Skip to content

Commit fc1dcb8

Browse files
jeaaustxzamiseck
andauthored
Audit Log: Rebase service audit log (#1218)
Rebase and squashed all 1110 bmcweb commits to support service audit log. 1110 commits included: ``` 957cc79 Audit Log: Rebase service audit log (#820) 5fd2e37 Audit Log: Correct logging of sessions (#1129) 2cc4e01 Reduce memory usage during Firmware update (#739) ``` Includes restructure of the code to split into audit-events.hpp and audit-events.cpp files. Only the .cpp file will include libaudit.h and will only be built if audit-events is enabled. This allows use of constexpr for calls to auditEvent(). This introduces a new bmcweb meson option, audit-events, which is defaulted to disabled. Recipe changes in GHE openbmc/openbmc enable audit logging. When audit-events is enabled all bmcweb PATCH, POST, PUT, and DELETE events are logged using the Linux kernel auditd subsystem. Additionally, login events coming through bmcweb are also recorded. The body of the events is recorded as well except in the following cases: - /redfish/v1/AccountService/Accounts PATCH/POST events - body is not recorded as it may contain clear text password - /ibm/v1 PATCH/POST/PUT events - body is not recorded as it contains HMC config file binary data - Limit size of body recorded to avoid flooding log or using too much memory. Events are recorded in /var/log/audit/. User type dreport will gather these log files. Tested: - Enabled auditing then initiated a variety of Redfish events using curl. - Confirmed the events were recorded and confirmed the data recorded was accurate. - Confirmed password was not included in audit data recorded. Signed-off-by: Myung Bae <[email protected]> Signed-off-by: Janet Adkins <[email protected]> Co-authored-by: zamiseck <[email protected]>
1 parent 82c5b74 commit fc1dcb8

File tree

9 files changed

+605
-0
lines changed

9 files changed

+605
-0
lines changed

config/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
conf_data = configuration_data()
44

55
feature_options = [
6+
'audit-events',
67
'basic-auth',
78
'cookie-auth',
89
'experimental-http2',

http/http_connection.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "bmcweb_config.h"
55

66
#include "async_resp.hpp"
7+
#include "audit_events.hpp"
78
#include "authentication.hpp"
89
#include "complete_response_fields.hpp"
910
#include "forward_unauthorized.hpp"
@@ -489,6 +490,31 @@ class Connection :
489490
res = std::move(thisRes);
490491
res.keepAlive(keepAlive);
491492

493+
if constexpr (BMCWEB_AUDIT_EVENTS)
494+
{
495+
if (audit::wantAudit(*req))
496+
{
497+
if (userSession != nullptr)
498+
{
499+
bool requestSuccess = false;
500+
// Look for good return codes and if so we know the
501+
// operation passed
502+
if ((res.resultInt() >= 200) && (res.resultInt() < 300))
503+
{
504+
requestSuccess = true;
505+
}
506+
507+
audit::auditEvent(*req, userSession->username,
508+
requestSuccess);
509+
}
510+
else
511+
{
512+
BMCWEB_LOG_DEBUG(
513+
"UserSession is null, not able to log audit event!");
514+
}
515+
}
516+
}
517+
492518
completeResponseFields(accept, res);
493519
res.addHeader(boost::beast::http::field::date, getCachedDateStr());
494520

include/audit_events.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
#include "http_request.hpp"
4+
5+
#include <boost/beast/http/verb.hpp>
6+
7+
#include <cstring>
8+
#include <string>
9+
10+
namespace audit
11+
{
12+
13+
int auditGetFD();
14+
void auditClose();
15+
bool auditOpen();
16+
bool auditReopen();
17+
void auditSetState(bool enable);
18+
bool wantDetail(const crow::Request& req);
19+
bool appendItemToBuf(std::string& strBuf, size_t maxBufSize,
20+
const std::string& item);
21+
22+
/**
23+
* @brief Checks if POST request is a user connection event
24+
*
25+
* Login and Session requests are audited when the authentication is attempted.
26+
* This allows failed requests to be audited with the user detail.
27+
*
28+
* @return True if request is a user connection event
29+
*/
30+
inline bool checkPostUser(const crow::Request& req)
31+
{
32+
return (req.target() == "/redfish/v1/SessionService/Sessions") ||
33+
(req.target() == "/redfish/v1/SessionService/Sessions/") ||
34+
(req.target() == "/login");
35+
}
36+
37+
/**
38+
* @brief Checks if request should be audited after completion
39+
* @return True if request should be audited
40+
*/
41+
inline bool wantAudit(const crow::Request& req)
42+
{
43+
return (req.method() == boost::beast::http::verb::patch) ||
44+
(req.method() == boost::beast::http::verb::put) ||
45+
(req.method() == boost::beast::http::verb::delete_) ||
46+
((req.method() == boost::beast::http::verb::post) &&
47+
!checkPostUser(req));
48+
}
49+
50+
void auditEvent(const crow::Request& req, const std::string& userName,
51+
bool success);
52+
53+
} // namespace audit

include/login_routes.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
33
#pragma once
44

5+
#include "bmcweb_config.h"
6+
57
#include "app.hpp"
68
#include "async_resp.hpp"
9+
#include "audit_events.hpp"
710
#include "cookies.hpp"
811
#include "http_request.hpp"
912
#include "http_response.hpp"
@@ -170,6 +173,10 @@ inline void handleLogin(const crow::Request& req,
170173
if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly)
171174
{
172175
asyncResp->res.result(boost::beast::http::status::unauthorized);
176+
if constexpr (BMCWEB_AUDIT_EVENTS)
177+
{
178+
audit::auditEvent(req, std::string(username), false);
179+
}
173180
}
174181
else
175182
{
@@ -183,6 +190,10 @@ inline void handleLogin(const crow::Request& req,
183190

184191
// if content type is json, assume json token
185192
asyncResp->res.jsonValue["token"] = session->sessionToken;
193+
if constexpr (BMCWEB_AUDIT_EVENTS)
194+
{
195+
audit::auditEvent(req, std::string(username), true);
196+
}
186197
}
187198
}
188199
else

meson.build

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,12 @@ srcfiles_bmcweb = files(
396396
'src/webserver_run.cpp',
397397
)
398398

399+
if (get_option('audit-events').allowed())
400+
audit_dep = dependency('audit')
401+
bmcweb_dependencies += audit_dep
402+
srcfiles_bmcweb += files('src/audit_events.cpp')
403+
endif
404+
399405
bmcweblib = static_library(
400406
'bmcweblib',
401407
srcfiles_bmcweb,
@@ -483,6 +489,10 @@ srcfiles_unittest = files(
483489
'test/redfish-core/lib/update_service_test.cpp',
484490
)
485491

492+
if (get_option('audit-events').allowed())
493+
srcfiles_unittest += files('test/include/audit_events_test.cpp')
494+
endif
495+
486496
if (get_option('tests').allowed())
487497
gtest = dependency(
488498
'gtest_main',

meson.options

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,14 @@ option(
461461
behavior changes or be removed at any time.''',
462462
)
463463

464+
# BMCWEB_AUDIT_EVENTS
465+
option(
466+
'audit-events',
467+
type: 'feature',
468+
value: 'disabled',
469+
description: 'Enable audit events support for bmcweb',
470+
)
471+
464472
# Insecure options. Every option that starts with a `insecure` flag should
465473
# not be enabled by default for any platform, unless the author fully comprehends
466474
# the implications of doing so.In general, enabling these options will cause security

redfish-core/lib/redfish_sessions.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
44
#pragma once
55

6+
#include "bmcweb_config.h"
7+
68
#include "account_service.hpp"
79
#include "app.hpp"
810
#include "async_resp.hpp"
11+
#include "audit_events.hpp"
912
#include "cookies.hpp"
1013
#include "dbus_privileges.hpp"
1114
#include "error_messages.hpp"
@@ -225,6 +228,12 @@ inline void processAfterSessionCreation(
225228
asyncResp->res.addHeader(
226229
"Location", "/redfish/v1/SessionService/Sessions/" + session->uniqueId);
227230
asyncResp->res.result(boost::beast::http::status::created);
231+
232+
if constexpr (BMCWEB_AUDIT_EVENTS)
233+
{
234+
audit::auditEvent(req, session->username, true);
235+
}
236+
228237
if (session->isConfigureSelfOnly)
229238
{
230239
messages::passwordChangeRequired(
@@ -282,6 +291,10 @@ inline void handleSessionCollectionPost(
282291
{
283292
messages::resourceAtUriUnauthorized(asyncResp->res, req.url(),
284293
"Invalid username or password");
294+
if constexpr (BMCWEB_AUDIT_EVENTS)
295+
{
296+
audit::auditEvent(req, std::string(username), false);
297+
}
285298
return;
286299
}
287300

0 commit comments

Comments
 (0)