OSU-Net / cyder

Cyder
BSD 3-Clause "New" or "Revised" License
10 stars 12 forks source link

Object audit log #690

Open akeym opened 10 years ago

akeym commented 10 years ago

All DNS and DHCP related objects should have audit history (e.g. a changelog). This should include:

Additionally - objects should show the last time an object was edited, and the user who edited it, in the UI. Can be limted to an object's detail view.

Just wanted to start the planning/design phase on this feature - DNS-container privs should be considered priority over this.

murrown commented 10 years ago
  1. How should we handle deleted objects? By which I mean, how should the user be able to restore a deleted object? I assume we'll retain the log for deleted objects.
  2. What should we do if the restored object does not validate? There are many complex interdependence rules between objects, so saving and restoring an individual object is a non-trivial problem. A couple of examples...
    1. If Range X is associated with Domain A, then is changed to associate with Domain B, we will log that change in the audit history. Then, if someone deletes Domain A, that log entry in the history becomes nonsensical, particularly if we log things the intuitive way, by database key. Meaningful logs can be preserved by storing a human-readable representation of the object, but a former state can't easily be restored with either human-readable or machine-readable logs, as we'd have to write parsers and restoration procedures for each kind of object.
    2. Suppose there exists a PTR P and someone changes its IP address to a new value. Then someone creates a Static Interface S using that IP address. In this case, it is not just difficult to restore P, it is impossible, because it would conflict with S. The only way to restore it would be to delete S. The obvious solution is to disallow restoration whenever a validation error is raised, but in the case where errors are not raised, I don't know if I can guarantee that a restored object will behave as expected after it is restored in a different environment than it was made for.
murrown commented 10 years ago

the long and the short of it is, logs are easy, savestates are hard

murrown commented 10 years ago

As for the first example, I don't know, but maybe some of the tools available to us will automatically track foreign keys for changed and deleted objects? That way, we could restore both deleted objects simultaneously, without being forced to restore the entire state of the database at that time. So the first example would be a non-issue.

akeym commented 10 years ago

Sounds like a log is a better way to go, as long as a user can see what was changed, they can use that information to revert it if need be. As for restoring other dependencies if they've been deleted/changed, it sounds like that could cascade into hell very fast.

On Mon, May 5, 2014 at 4:43 PM, Nathan Murrow notifications@github.comwrote:

the long and the short of it is, logs are easy, savestates are hard

— Reply to this email directly or view it on GitHubhttps://github.com/OSU-Net/cyder/issues/690#issuecomment-42253951 .

zeeman commented 10 years ago

I'm going to look around and see if there are well-supported packages that already exist to do this sort of thing, but it occurs to me that we could try just dumping the API's JSON representation of an object into a log before changes are saved. That way you'd have a full snapshot of the object's fields and attributes. Once the API can handle writes on all records, it could also be used to restore previous states.

akeym commented 10 years ago

What if the model changes, will merely serializing the data be a good idea? Or am I thinking of something else..

zeeman commented 10 years ago

Good point. That could get ugly fast. I think as long as manual rollback is an option, then it would be fine, but if auto-rollback is a must, we'd have to do something else. I remember someone suggested using duplicate models to store previous revisions. That would be easier to migrate, but probably more complex to implement. Is automatic reversion a must-have?

akeym commented 10 years ago

no, I thought we already hashed this out anyway.. just a human-readable log will suffice so they can revert if need be.

On Tue, Jul 15, 2014 at 3:09 PM, zeeman notifications@github.com wrote:

Good point. That could get ugly fast. I think as long as manual rollback is an option, then it would be fine, but if auto-rollback is a must, we'd have to do something else. I remember someone suggested using duplicate models to store previous revisions. That would be easier to migrate, but probably more complex to implement. Is automatic reversion a must-have?

— Reply to this email directly or view it on GitHub https://github.com/OSU-Net/cyder/issues/690#issuecomment-49099862.

zeeman commented 10 years ago

How does this sound?

akeym commented 10 years ago

Are you saying that Attributes will not be logged, or that the attribute models won't have revision logs..?

On Tue, Jul 15, 2014 at 3:28 PM, zeeman notifications@github.com wrote:

How does this sound?

  • Add a TextField (edit_log) to the BaseModel that has the serialized representation of the model's data appended to it on save. Since objects with attributes have their attribute sets in their API representations, attribute models would probably be excluded.
  • Add a read-only field for the edit log to each model's detail view.
  • Create a new model (DeletionLog or something) that has fields for the model name, primary key, serialized data representation, and log field of every deleted object.
  • Add a view for the deletion log to the UI.

— Reply to this email directly or view it on GitHub https://github.com/OSU-Net/cyder/issues/690#issuecomment-49101518.

zeeman commented 10 years ago

Hm, actually that's kind of tricky. What I meant was that an object's serialized representation includes the contents of its attribute set like so:

        {
            "created": "2013-11-07T12:48:45",
            "id": 13,
            "modified": "2013-11-07T12:48:45",
            "name": "voledev",
            "systemav_set": [
                {
                    "attribute": "Hardware type",
                    "id": "https://cyder.nws.oregonstate.edu/api/v1/core/system/attributes/16/",
                    "value": "VM"
                },
                {
                    "attribute": "Operating system",
                    "id": "https://cyder.nws.oregonstate.edu/api/v1/core/system/attributes/17/",
                    "value": "Linux"
                }
            ]
        }

Because the AVs would be represented in the edit log already, I thought it seemed extraneous to have a separate log for them. However, AVs can change independently of their corresponding entities, so my initial idea is flawed because it wouldn't store updates to AVs. My first thought is that AV changes could trigger the creation of a new log entry for their corresponding entity model, but if the number of changes to store is low enough, updating multiple AVs on an entity could completely wipe out its edit history.

Now I'm thinking the most straightforward way is to store the entity logs like I was planning and also keep logs of AV updates so they could be reverted independently. That way, every change is tracked and a series of AV updates can't wipe out the entity's edit history.

akeym commented 10 years ago

I'm not sure the monolithic method is a bad idea, I mean, if someone is deliberately trying to cover their change by doing it 5 times or more or whatever the threshold is... then oh well, I'm not sure we'd care at that point

On Tue, Jul 15, 2014 at 3:49 PM, zeeman notifications@github.com wrote:

Hm, actually that's kind of tricky. What I meant was that an object's serialized representation includes the contents of its attribute set like so:

    {
        "created": "2013-11-07T12:48:45",
        "id": 13,
        "modified": "2013-11-07T12:48:45",
        "name": "voledev",
        "systemav_set": [
            {
                "attribute": "Hardware type",
                "id": "https://cyder.nws.oregonstate.edu/api/v1/core/system/attributes/16/",
                "value": "VM"
            },
            {
                "attribute": "Operating system",
                "id": "https://cyder.nws.oregonstate.edu/api/v1/core/system/attributes/17/",
                "value": "Linux"
            }
        ]
    }

Because the AVs would be represented in the edit log already, I thought it seemed extraneous to have a separate log for them. However, AVs can change independently of their corresponding entities, so my initial idea is flawed because it wouldn't store updates to AVs. My first thought is that AV changes could trigger the creation of a new log entry for their corresponding entity model, but if the number of changes to store is low enough, updating multiple AVs on an entity could completely wipe out its edit history.

Now I'm thinking the most straightforward way is to store the entity logs like I was planning and also keep logs of AV updates so they could be reverted independently. That way, every change is tracked and a series of AV updates can't wipe out the entity's edit history.

— Reply to this email directly or view it on GitHub https://github.com/OSU-Net/cyder/issues/690#issuecomment-49103275.

zeeman commented 10 years ago

Well, my concern is less about bad actors and more about dumb actors. Ex: someone makes a stupid change on an object and subsequently alters all of its attributes, causing the log of the last good version to be deleted. Still, given that most objects seem to have a handful of attributes at most, this could probably be avoided just by limiting the number of log entries to 10 or so.

akeym commented 10 years ago

I suppose that depends on how often saves happen from the user... Which it appears we still edit em one at a time. le sigh. which I guess does make the problem you mention a realistic one.

On Tue, Jul 15, 2014 at 3:57 PM, zeeman notifications@github.com wrote:

Well, my concern is less about bad actors and more about dumb actors. Ex: someone makes a stupid change on an object and subsequently alters all of its attributes, causing the last valid log to be deleted. Still, given that most objects seem to have a handful of attributes at most, this could probably be avoided just by limiting the number of log entries to 10 or so.

— Reply to this email directly or view it on GitHub https://github.com/OSU-Net/cyder/issues/690#issuecomment-49103950.

zeeman commented 10 years ago

I think even some kind of bulk update feature would still trigger multiple save events, since each AV is a distinct model entity in the ORM's view. There would probably be some hackery involved in grouping multiple AV changes so they wouldn't each create a separate log entry. Plus, it's not even a feature yet. Seems like separate logs for entities and AV's are the safest way to go for now.

akeym commented 9 years ago

See #944