[BUG] Tag writes that weren't permitted to write due to user permissions still get recorded in audit log

An end user just noticed that if a tag has write permissions set on it and the tag is bidirectionally bound to a toggle switch (in Perspective for example), and a user who doesn't have the write permission tries to toggle the switch, it correctly doesn't write and shows a warning message. However if you check the audit log, there will be a "tag write" action for that tag and user indicating the write went through which is extremely deceptive and can destroy the credibility of the log.

Yes, I reproduced this problem on 8.1.48.

1 Like

Did you open a support ticket?

1 Like

Yes I did :ok_hand:

2 Likes

Can you please provide an update and/or link to the support ticket? I’ve just encountered this same issue.

To me, this points to an issue in the UI or project configuration. The audit log shouldn’t be used as a source of verification that a write was successful, only that the write was attempted. In my opinion, that action SHOULD be recorded.

Fair about recording an attempt, but then a log for the rejection of the write should be present as well which I take it is not the case.

Perhaps. However, there’s a thousand ways that a write could ā€˜fail’. Tag permissions, provider permissions, service security, poor network connection to an end device, rejection by the end device, accepted but immediately overwritten in the end device…

Right but if we go with your idea that the attempt should be recorded no matter what (which I do agree with) what there must be some indication if it was not succesful otherwise @nminchin original point stands that the log becomes unreliable. Reason can be whatever, but tell me it didn’t go through. A lot of those reasons are probably catchable and recordable too, certainly permissions ones, and if its not then a ā€œfailed write reason unknownā€ at least keeps the audit trail 100% truthful about what happened, user tried to write, something bad happened we don’t know what but the write didn’t go through. Without that it just looks like the user wrote when they didn’t.

1 Like

Confirmation is covered by historization. Capturing write rejection reasons is near impossible, since some can be external. There's no replacement for proper use of try clauses and inspection of returned quality codes.

Sounds like the best thing to do is just write your own writeTags function that examines the result and audits failures appropriately and call that for all your tag writes instead? In scripts at least

Though that doesn’t really help in the OP case where it was due to tag binding on a UI component.

Are you saying if you have audit trails enabled without the historian module your SOL to create such a trail (user wrote and the confirmation of if the write went through or not)?

1 Like

In my opinion, the first step is to update the UI to disallow the write in the first place. The user should know whether-or-not they have permission to write before they attempt to do so. Tags have a ā€œ.CanWriteā€ property (value is unique per-client) and can be bound in the UI to disable the entry in the first place. Note that this doesn’t capture all possible scenarios as might be required from a proper audit trail (those previously listed, also tag deadband preventing a value update, floating point representation error after successful write, etc.).

I’ve not built a proper audit tool personally (despite my own empty threats to do so). But, I have spent enough time compiling data for other parties (managers, engineers, lawyers) that I’ve resolved that:

  1. It’s a difficult problem to solve for ā€˜all users’ & ā€˜all use-cases’.
  2. I’m grateful that I have too much data to work with, instead of not enough.
  3. Despite 1 & 2, I’m still frustrated every time I have to handle all of the useless data in the audit logs.
3 Likes

I agree to your point in regard to the UI not even being allowed to write and using a that to not allow a non-permissable user to even attempt to write.

Though as you said there are a ton of reasons something could fail not related to any permissions. So you could have a person who does have permissions try to wirte, it fails and the audit trail looks all good.

I personally don’t particulary care about why being logged to the audit trail for UI binding writes personally just if it failed because what I am I thinking about is getting a call to come in the day(s) after to check something out - Hey we pressed this button but the process didn’t start. If I look at the audit logs and see a tag write and nothing else what else can I interpret but that the tag was written to and something happened on the PLC side of things.

But If i see tag write and a failure (without any reason listed), I would start elsewhere - how is the opc-ua server, the ignition connection to the opc-ua, the network etc. I can’t say anything for certain just off the audit trail but it would help me not go on a wild goose chase immediately where I assumed the tag was written to when it was not.

Thats why I think even without auditing a reason if possible it would be nice to record a failure. Though unfortunately doesn’t seem feasible according to Phil.

1 Like

Unsolicited, yet unapologetic tangent:

I do wish there were an optional argument on system.tag.write* functions which resembles the functionality of skipAudit arg on the system.db.runPrepUpdate function. I envision that this arg would give someone a better ability to build an audit system which matches their needs.

I believe @nminchin has a post about this feature request:

Psssssst! Not implemented!

:thinking:

I just tested and confirm that running the runPrepUpdate function with skipAudit=False DOES add an entry to the audit log. I also confirm that running the same script with skipAudit=True DOES NOT add an entry to the audit log.

I suppose there is some ambiguity in his statement:

There’s a recent post on lack of audit w.r.t. named queries:

1 Like

What scope were you calling from?

(I will obviously have to revisit this in my toolkit.)

Yeah, my earlier post was ambiguous. Calling scope matters.
DB functions from client/designer scope hit special RPC methods that "understand" the skipAudit flag.
Direct DB system function calls when you're already in gateway scope don't do anything with the skipAudit parameter.

4 Likes

Good to know! As can be assumed, I did execute from script console for my quick test above. Somewhat unrelated - but I’ve also confirmed audit entries via Database Query Browser (Designer) when query type is ā€œUpdateā€.

1 Like