-
Notifications
You must be signed in to change notification settings - Fork 7
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
Add security logging base class #1
Add security logging base class #1
Conversation
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
* @note Definition in DDS-Sec v1.1 9.6 | ||
*/ | ||
struct BuiltinLoggingType final { | ||
octet facility; // Set to 0x0A (10). Indicates sec/auth msgs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fast RTPS seems to use four spaces for indentation. This only seems to be a single space, and elsewhere in the PR there are two. We should probably follow their established format. Try to make the code look like it was written by them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I will take care of 'fixing' all indentations...
/** | ||
* @brief The EventLogLevel enum | ||
* | ||
* @note Definition in DDS-Sec v1.1 8.6.2.1.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section seems to outline the same information as 9.6, but with different names. I suspect we can remove this struct and use LoggingLevel
instead, which seems to be what RTI has done. We should say something on the RTI forums or ping eProsima to make sure we're right, and to raise awareness of the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
*/ | ||
class Logging | ||
{ | ||
public: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check other classes in Fast RTPS, make sure we're following the same format (I think these are indented).
/** | ||
* @brief set_log_options | ||
* @param log_options | ||
* @return TRUE if successful |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could probably flesh out the descriptions using the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will document properly once the actual implementation is done.
//TODO(artivis): set up DataWriter/Publisher | ||
} | ||
|
||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we handle the case where a log file wasn't provided, and distribute is false? Does that seem like an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's an error but maybe we should warn somehow.
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
* @brief Whether the options are set or not. | ||
* @return True if the options are set. | ||
*/ | ||
inline bool options_set() const { return options_set_; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a use-case for having this public instead of protected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options must be set before calling enable
. This seemed like a handy way to assert that options are indeed set. But maybe it is not necessary at all.
, thread_([this]() { | ||
BuiltinLoggingType msg; | ||
for (;;) | ||
{ | ||
// Put the thread asleep until there is | ||
// something to process | ||
MessagePtr p = queue_.wait_pop(); | ||
|
||
if (!p) | ||
{ | ||
if (stop_) | ||
{ | ||
return; | ||
} | ||
continue; | ||
} | ||
|
||
msg = convert(*p); | ||
|
||
publish(msg); | ||
} | ||
}) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be easier to maintain if this were a standalone function in an anonymous namespace as opposed to a lambda.
std::unique_lock<std::mutex> lock(mutex_); | ||
while (queue_.empty()) | ||
{ | ||
has_data_.wait(lock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, I suggest getting rid of the while
and just using the predicate, e.g.
has_data_.wait(lock, [&]{ return !queue_.empty(); });
However, this design requires all users of this class to utilize the hack that you have in the BuiltinLogging
class' destructor, pushing an empty message on to force a thread wakeup. I recommend a few things that could help this limitation.
First of all, add a stop_
atomic bool member variable (default false, obviously). Then update the predicate here to be:
has_data_.wait(lock, [&]{ return !stop_.load() && !queue_.empty(); });
Second, add another public member function for stopping:
void ConcurrentQueue::stop()
{
stop_ = true;
has_data_.notify_all();
}
Finally, add a destructor that looks something like:
ConcurrentQueue::~ConcurrentQueue()
{
stop();
}
These together will cause all clients waiting on data from this to wake up and realize that no further data will be forthcoming once the queue is destroyed without hack needed. Sadly, in your case, given that you own the thread and the queue in the same scope, without a refactor you'll need to use the stop()
function before waiting for the thread to join.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the while
as suggested although it is equivalent.
While the current schema may look hacky, it allows for a desirable feature, the possibility to log all messages stored in the queue prior to the 'stop' call. Given that the logging is the last security object to be destroyed, other security plugins may still have messages to log upon destruction, which is possible here.
Furthermore, I don't like adding a stop
mechanism to the queue, it seems very odd to 'stop' a container...
We could abstract the queue and thread in a class but that only make sense if it is re-used somewhere else. I'll leave it as is for now but re-visit it later on see if there is a better design.
|
||
if (!p) | ||
{ | ||
if (stop_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you follow my advice about the queue's destructor and notification, you should be able to do away with this member variable entirely and just use the invalid return value as the signal that the thread should shutdown.
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
LoggingLevel& l, | ||
SecurityException& e) | ||
{ | ||
//TODO(artivis): use an array of const char to avoid strings? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest going the other way and extracting this whole logic into a map.
Signed-off-by: artivis <jeremie.deray@canonical.com>
template <typename Stream> | ||
bool compose_header(Stream& header, | ||
const BuiltinLoggingType& builtin_msg, | ||
SecurityException& exception) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume DDS support will also be streamable? Or do you plan on streaming to an sstream or something? Because that would also work for the file logging. Do we really gain much by having this be a template?
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
Signed-off-by: artivis <jeremie.deray@canonical.com>
* Add security logging (canonical#1) * add security logging to file as per dds-spec * add set/get logger to security plugin base classes * logging integration to SecurityManager * add SECURITY_LOGGING macros Signed-off-by: artivis <jeremie.deray@canonical.com> * handle empty filename Signed-off-by: artivis <jeremie.deray@canonical.com> * post-master-merge fix Signed-off-by: artivis <jeremie.deray@canonical.com> * handle empty filename Signed-off-by: artivis <jeremie.deray@canonical.com> * fix typo test filename Signed-off-by: artivis <jeremie.deray@canonical.com> * fix linking error * some doc fixes Signed-off-by: artivis <jeremie.deray@canonical.com> * some doc fixes Signed-off-by: artivis <jeremie.deray@canonical.com> * support logging in SecurityPluginFactory Mock Signed-off-by: artivis <jeremie.deray@canonical.com> * include log in security logging for macro support & cleanup Signed-off-by: artivis <jeremie.deray@canonical.com> * add missing source Signed-off-by: artivis <jeremie.deray@canonical.com> * replace 'library' includes with 'system' Signed-off-by: artivis <jeremie.deray@canonical.com> * uncrustify Signed-off-by: artivis <jeremie.deray@canonical.com> * add log to file test Signed-off-by: artivis <jeremie.deray@canonical.com> * fix warnings Signed-off-by: artivis <jeremie.deray@canonical.com> * fix error msg typo Signed-off-by: artivis <jeremie.deray@canonical.com> * fix linking error Signed-off-by: artivis <jeremie.deray@canonical.com> * fix warning Signed-off-by: artivis <jeremie.deray@canonical.com> * add verbosity level to file logs Signed-off-by: artivis <jeremie.deray@canonical.com> * test file logs header Signed-off-by: artivis <jeremie.deray@canonical.com> * use logging in Permission Signed-off-by: artivis <jeremie.deray@canonical.com> * use logging in PKIDH Signed-off-by: artivis <jeremie.deray@canonical.com> * use logging in SecurityManager Signed-off-by: artivis <jeremie.deray@canonical.com>
Add security logging plugin base class and accompanying basic classes as defined in DDS-Sec specs.
Note: whereas specs define some
long
-basedenum
I went ahead and usedlong
-basedenum struct
instead.Signed-off-by: artivis jeremie.deray@canonical.com