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

Initial audit logging, for review. #1006

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
16 changes: 14 additions & 2 deletions assignment-client/src/entities/EntityServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,24 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
bool wantEditLogging = false;
readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging);
qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging));

bool wantAuditEditLogging = false;
readOptionBool(QString("wantAuditEditLogging"), settingsSectionObject, wantAuditEditLogging);
qDebug("wantAuditEditLogging=%s", debug::valueOf(wantAuditEditLogging));

EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);

int auditEditLoggingInterval;
if (readOptionInt("auditEditLoggingInterval", settingsSectionObject, auditEditLoggingInterval)) {
tree->setAuditEditLoggingInterval(auditEditLoggingInterval);
} else {
tree->setAuditEditLoggingInterval(EntityTree::DEFAULT_AUDIT_EDIT_INTERVAL);
}

bool wantTerseEditLogging = false;
readOptionBool(QString("wantTerseEditLogging"), settingsSectionObject, wantTerseEditLogging);
qDebug("wantTerseEditLogging=%s", debug::valueOf(wantTerseEditLogging));

EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);

int maxTmpEntityLifetime;
if (readOptionInt("maxTmpLifetime", settingsSectionObject, maxTmpEntityLifetime)) {
tree->setEntityMaxTmpLifetime(maxTmpEntityLifetime);
Expand All @@ -337,6 +348,7 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
startDynamicDomainVerification();

tree->setWantEditLogging(wantEditLogging);
tree->setWantAuditEditLogging(wantAuditEditLogging);
tree->setWantTerseEditLogging(wantTerseEditLogging);

QString entityScriptSourceWhitelist;
Expand Down
2 changes: 1 addition & 1 deletion assignment-client/src/entities/EntityServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class EntityServer : public OctreeServer, public NewlyCreatedEntityHook {
virtual PacketType getMyEditNackType() const override { return PacketType::EntityEditNack; }
virtual QString getMyDomainSettingsKey() const override { return QString("entity_server_settings"); }

// subclass may implement these method
// subclass may implement these methods
virtual void beforeRun() override;
virtual bool hasSpecialPacketsToSend(const SharedNodePointer& node) override;
virtual int sendSpecialPackets(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) override;
Expand Down
16 changes: 16 additions & 0 deletions domain-server/resources/describe-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,22 @@
"default": false,
"advanced": true
},
{
"name": "wantAuditEditLogging",
"type": "checkbox",
"label": "Audit Edit Logging",
"help": "Log edits with audit information.",
"default": false,
"advanced": true
},
{
"name": "auditEditLoggingInterval",
"label": "Audit Entity Edit Logging Interval",
"help": "Milliseconds between the outputting and clearing of audit logs for entity edits/adds.",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
"help": "Milliseconds between the outputting and clearing of audit logs for entity edits/adds.",
"help": "Milliseconds between the outputting and clearing of audit logs for entity adds/edits.",

"placeholder": "10000",
"default": "10000",
"advanced": true
},
{
"name": "verboseDebug",
"type": "checkbox",
Expand Down
84 changes: 84 additions & 0 deletions libraries/entities/src/EntitiesAuditLogging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// EntitiesAuditLogging.cpp
// libraries/entities/src
//
// Created by Kalila L on Feb 5 2021.
// Copyright 2021 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

#include "EntitiesAuditLogging.h"

#include <QJsonObject>
#include <QTimer>

Q_LOGGING_CATEGORY(entities_audit, "vircadia.entities.audit");

QJsonObject auditLogAddBuffer;
QJsonObject auditLogEditBuffer;
digisomni marked this conversation as resolved.
Show resolved Hide resolved
QTimer* auditLogProcessorTimer;
digisomni marked this conversation as resolved.
Show resolved Hide resolved

void EntitiesAuditLogging::processAuditLogBuffers() {
if (!auditLogAddBuffer.isEmpty()) {
QJsonObject objectToOutput;
objectToOutput.insert("add", auditLogAddBuffer);
qCDebug(entities_audit) << objectToOutput;
auditLogAddBuffer = QJsonObject();
}
if (!auditLogEditBuffer.isEmpty()) {
QJsonObject objectToOutput;
objectToOutput.insert("edit", auditLogEditBuffer);
qCDebug(entities_audit) << objectToOutput;
auditLogEditBuffer = QJsonObject();
}
}

void EntitiesAuditLogging::startAuditLogProcessor() {
auditLogProcessorTimer = new QTimer(this);
digisomni marked this conversation as resolved.
Show resolved Hide resolved
connect(auditLogProcessorTimer, &QTimer::timeout, this, &EntitiesAuditLogging::processAuditLogBuffers);
auditLogProcessorTimer->start(_auditEditLoggingInterval);
}

void EntitiesAuditLogging::stopAuditLogProcessor() {
auditLogProcessorTimer->stop();
}

bool EntitiesAuditLogging::isProcessorRunning() {
if (!auditLogProcessorTimer) {
digisomni marked this conversation as resolved.
Show resolved Hide resolved
return false;
} else {
return true;
}
}

void EntitiesAuditLogging::processAddEntityPacket(const QString& sender, const QString& entityID, const QString& entityType) {
QJsonValue findExisting = auditLogAddBuffer.take(sender);
if (!findExisting.isUndefined()) {
QJsonObject existingObject = findExisting.toObject();
if (!existingObject.contains(entityID)) {
existingObject.insert(entityID, entityType);
}
auditLogAddBuffer.insert(sender, existingObject);
} else {
QJsonObject newEntry{ { entityID, entityType } };
auditLogAddBuffer.insert(sender, newEntry);
}
}

void EntitiesAuditLogging::processEditEntityPacket(const QString& sender, const QString& entityID) {
QJsonValue findExisting = auditLogEditBuffer.take(sender);
if (!findExisting.isUndefined()) {
QJsonObject existingObject = findExisting.toObject();
if (!existingObject.contains(entityID)) {
existingObject.insert(entityID, 1);
} else {
existingObject[entityID] = existingObject[entityID].toInt() + 1;
}
auditLogEditBuffer.insert(sender, existingObject);
} else {
QJsonObject newEntry{ { entityID, 1 } };
auditLogEditBuffer.insert(sender, newEntry);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing CR at EOF.

35 changes: 35 additions & 0 deletions libraries/entities/src/EntitiesAuditLogging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// EntitiesAuditLogging.h
// libraries/entities/src
//
// Created by Kalila L on Feb 5 2021.
// Copyright 2021 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

#ifndef vircadia_EntitiesAuditLogging_h
#define vircadia_EntitiesAuditLogging_h

#include <QLoggingCategory>

Q_DECLARE_LOGGING_CATEGORY(entities_audit);

class EntitiesAuditLogging : public QObject {
Q_OBJECT
public:
bool isProcessorRunning();
void startAuditLogProcessor();
void stopAuditLogProcessor();
void setAuditEditLoggingInterval(float interval) { _auditEditLoggingInterval = interval; };
void processAddEntityPacket(const QString& sender, const QString& entityID, const QString& entityType);
void processEditEntityPacket(const QString& sender, const QString& entityID);

private:
void processAuditLogBuffers();

float _auditEditLoggingInterval;
};

#endif // vircadia_EntitiesAuditLogging_h
2 changes: 1 addition & 1 deletion libraries/entities/src/EntitiesLogging.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@

#include <QLoggingCategory>

Q_DECLARE_LOGGING_CATEGORY(entities)
Q_DECLARE_LOGGING_CATEGORY(entities);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
Q_DECLARE_LOGGING_CATEGORY(entities);
Q_DECLARE_LOGGING_CATEGORY(entities)


#endif // hifi_EntitiesLogging_h
21 changes: 20 additions & 1 deletion libraries/entities/src/EntityTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "UpdateEntityOperator.h"
#include "QVariantGLM.h"
#include "EntitiesLogging.h"
#include "EntitiesAuditLogging.h"
#include "RecurseOctreeToMapOperator.h"
#include "RecurseOctreeToJSONOperator.h"
#include "LogHandler.h"
Expand All @@ -45,6 +46,7 @@

static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50;
const float EntityTree::DEFAULT_MAX_TMP_ENTITY_LIFETIME = 60 * 60; // 1 hour
const float EntityTree::DEFAULT_AUDIT_EDIT_INTERVAL = 10000; // 10 seconds
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const float EntityTree::DEFAULT_AUDIT_EDIT_INTERVAL = 10000; // 10 seconds
const float EntityTree::DEFAULT_AUDIT_EDIT_LOGGING_INTERVAL = 10000; // 10 seconds

Choose a reason for hiding this comment

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

These names are unfortunately long.

static const QString DOMAIN_UNLIMITED = "domainUnlimited";

EntityTree::EntityTree(bool shouldReaverage) :
Expand Down Expand Up @@ -1795,6 +1797,10 @@ void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const
}
}

void EntityTree::setAuditEditLoggingInterval(float interval) {
entitiesAuditLogProcessor.setAuditEditLoggingInterval(interval);
}

// NOTE: Caller must lock the tree before calling this.
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode) {
Expand All @@ -1803,6 +1809,10 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
return 0;
}

if (wantAuditEditLogging() && !entitiesAuditLogProcessor.isProcessorRunning()) {
entitiesAuditLogProcessor.startAuditLogProcessor();
}

int processedBytes = 0;
bool isAdd = false;
bool isClone = false;
Expand All @@ -1829,6 +1839,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
quint64 startFilter = 0, endFilter = 0;
quint64 startLogging = 0, endLogging = 0;


bool suppressDisallowedClientScript = false;
bool suppressDisallowedServerScript = false;
bool suppressDisallowedPrivateUserData = false;
Expand Down Expand Up @@ -2003,6 +2014,10 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
qCDebug(entities) << "User [" << senderNode->getUUID() << "] editing entity. ID:" << entityItemID;
qCDebug(entities) << " properties:" << properties;
}
if (wantAuditEditLogging()) {
entitiesAuditLogProcessor.processEditEntityPacket(senderNode->getPublicSocket().toString(),
entityItemID.toString());
Comment on lines +2025 to +2026
Copy link
Collaborator

Choose a reason for hiding this comment

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

Indenting seems a bit arbitrary.

}
if (wantTerseEditLogging()) {
QList<QString> changedProperties = properties.listChangedProperties();
fixupTerseEditLogging(properties, changedProperties);
Expand Down Expand Up @@ -2082,6 +2097,11 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
<< newEntity->getEntityItemID();
qCDebug(entities) << " properties:" << properties;
}
if (wantAuditEditLogging()) {
entitiesAuditLogProcessor.processAddEntityPacket(senderNode->getPublicSocket().toString(),
entityItemID.toString(),
EntityTypes::getEntityTypeName(properties.getType()));
Comment on lines +2108 to +2110
Copy link
Collaborator

Choose a reason for hiding this comment

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

Indenting seems a bit arbitrary.

}
if (wantTerseEditLogging()) {
QList<QString> changedProperties = properties.listChangedProperties();
fixupTerseEditLogging(properties, changedProperties);
Expand All @@ -2105,7 +2125,6 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
}
}


_totalDecodeTime += endDecode - startDecode;
_totalLookupTime += endLookup - startLookup;
_totalUpdateTime += endUpdate - startUpdate;
Expand Down
12 changes: 12 additions & 0 deletions libraries/entities/src/EntityTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "AddEntityOperator.h"
#include "EntityTreeElement.h"
#include "EntitiesAuditLogging.h"
#include "DeleteEntityOperator.h"
#include "MovingEntitiesOperator.h"

Expand Down Expand Up @@ -190,6 +191,11 @@ class EntityTree : public Octree, public SpatialParentTree {

bool wantEditLogging() const { return _wantEditLogging; }
void setWantEditLogging(bool value) { _wantEditLogging = value; }

bool wantAuditEditLogging() const { return _wantAuditEditLogging; }
void setWantAuditEditLogging(bool value) { _wantAuditEditLogging = value; }

void setAuditEditLoggingInterval(float value);

bool wantTerseEditLogging() const { return _wantTerseEditLogging; }
void setWantTerseEditLogging(bool value) { _wantTerseEditLogging = value; }
Expand Down Expand Up @@ -250,6 +256,8 @@ class EntityTree : public Octree, public SpatialParentTree {
void notifyNewCollisionSoundURL(const QString& newCollisionSoundURL, const EntityItemID& entityID);

static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME;

static const float DEFAULT_AUDIT_EDIT_INTERVAL;

QByteArray computeNonce(const EntityItemID& entityID, const QString ownerKey);
bool verifyNonce(const EntityItemID& entityID, const QString& nonce);
Expand Down Expand Up @@ -339,6 +347,8 @@ class EntityTree : public Octree, public SpatialParentTree {
EntitySimulationPointer _simulation;

bool _wantEditLogging = false;
bool _wantAuditEditLogging = true;
digisomni marked this conversation as resolved.
Show resolved Hide resolved
float _auditEditLoggingInterval { DEFAULT_AUDIT_EDIT_INTERVAL };
bool _wantTerseEditLogging = false;


Expand Down Expand Up @@ -401,6 +411,8 @@ class EntityTree : public Octree, public SpatialParentTree {

bool _serverlessDomain { false };

EntitiesAuditLogging entitiesAuditLogProcessor;

std::map<QString, QString> _namedPaths;

// Return an AACube containing object and all its entity descendants
Expand Down