16 std::string audit_source_id)
17 : audit_source_id_(std::move(audit_source_id)),
22 : audit_source_id_(std::move(
other.audit_source_id_)),
23 transport_(std::move(
other.transport_)),
24 enabled_(
other.enabled_.load(std::memory_order_relaxed)),
25 events_sent_(
other.events_sent_.load(std::memory_order_relaxed)),
26 events_failed_(
other.events_failed_.load(std::memory_order_relaxed)) {}
31 audit_source_id_ = std::move(
other.audit_source_id_);
32 transport_ = std::move(
other.transport_);
33 enabled_.store(
other.enabled_.load(std::memory_order_relaxed),
34 std::memory_order_relaxed);
35 events_sent_.store(
other.events_sent_.load(std::memory_order_relaxed),
36 std::memory_order_relaxed);
38 other.events_failed_.load(std::memory_order_relaxed),
39 std::memory_order_relaxed);
49 const std::string& source_ae,
50 const std::string& dest_ae,
51 const std::string& study_uid,
52 const std::string& patient_id,
55 if (!
enabled_.load(std::memory_order_relaxed)) {
77 const std::string& calling_ae,
78 const std::string& called_ae,
79 const std::string& query_level,
82 if (!
enabled_.load(std::memory_order_relaxed)) {
94 "QueryLevel=" + query_level +
" CalledAE=" + called_ae,
102 const std::string& user_id,
106 if (!
enabled_.load(std::memory_order_relaxed)) {
124 const std::string& user_id,
125 const std::string& alert_description) {
127 if (!
enabled_.load(std::memory_order_relaxed)) {
149 "ITI-41",
"IHE Transactions",
"Provide and Register Document Set-b"};
150const atna_coded_value xds_event_type_rad_68{
151 "RAD-68",
"IHE Transactions",
"Provide and Register Imaging Document Set"};
152const atna_coded_value xds_event_type_iti_43{
153 "ITI-43",
"IHE Transactions",
"Retrieve Document Set"};
154const atna_coded_value xds_event_type_rad_69{
155 "RAD-69",
"IHE Transactions",
"Retrieve Imaging Document Set"};
158const atna_coded_value sop_instance_uid_type{
159 "110181",
"DCM",
"SOP Instance UID"};
162void append_sop_instance_objects(
163 atna_audit_message& msg,
164 const std::vector<std::string>& sop_instance_uids) {
165 for (
const auto&
uid : sop_instance_uids) {
166 if (
uid.empty())
continue;
167 atna_participant_object obj;
170 obj.object_id_type_code = sop_instance_uid_type;
172 msg.participant_objects.push_back(std::move(obj));
180 const std::string& source_ae,
181 const std::string& dest_ae,
182 const std::string& study_uid,
183 const std::string& patient_id,
184 const std::vector<std::string>& sop_instance_uids,
187 if (!
enabled_.load(std::memory_order_relaxed)) {
207 msg.event_type_codes.push_back(
209 ? xds_event_type_iti_41
210 : xds_event_type_rad_68);
214 append_sop_instance_objects(msg, sop_instance_uids);
221 const std::string& source_ae,
222 const std::string& dest_ae,
223 const std::string& study_uid,
224 const std::string& patient_id,
225 const std::vector<std::string>& sop_instance_uids,
228 if (!
enabled_.load(std::memory_order_relaxed)) {
251 msg.event_type_codes.push_back(
253 ? xds_event_type_iti_43
254 : xds_event_type_rad_69);
257 append_sop_instance_objects(msg, sop_instance_uids);
267 enabled_.store(enabled, std::memory_order_relaxed);
271 return enabled_.load(std::memory_order_relaxed);
305 if (!
enabled_.load(std::memory_order_relaxed)) {
319 if (result.is_ok()) {
High-level facade for ATNA audit logging in DICOM services.
static atna_audit_message build_dicom_instances_transferred(const std::string &source_id, const std::string &source_ae, const std::string &source_ip, const std::string &dest_ae, const std::string &dest_ip, const std::string &study_uid, const std::string &patient_id="", bool is_import=true, atna_event_outcome outcome=atna_event_outcome::success)
Build DICOM Instances Transferred audit message (C-STORE, C-MOVE)
static std::string to_xml(const atna_audit_message &message)
Serialize an audit message to RFC 3881 XML.
static atna_audit_message build_export(const std::string &source_id, const std::string &user_id, const std::string &user_ip, const std::string &dest_id, const std::string &study_uid, const std::string &patient_id="", atna_event_outcome outcome=atna_event_outcome::success)
Build Export audit message (media/network export)
static atna_audit_message build_security_alert(const std::string &source_id, const std::string &user_id, const std::string &user_ip, const std::string &alert_description, atna_event_outcome outcome=atna_event_outcome::serious_failure)
Build Security Alert audit message.
static atna_audit_message build_user_authentication(const std::string &source_id, const std::string &user_id, const std::string &user_ip, bool is_login, atna_event_outcome outcome=atna_event_outcome::success)
Build User Authentication audit message (login/logout)
static atna_audit_message build_query(const std::string &source_id, const std::string &user_id, const std::string &user_ip, const std::string &query_data, const std::string &patient_id="", atna_event_outcome outcome=atna_event_outcome::success)
Build Query audit message (C-FIND, QIDO-RS)
High-level facade for emitting ATNA audit events from DICOM services.
xds_consumer_transaction
XDS-I.b consumer-side transaction identifier.
@ iti_43
ITI-43 Retrieve Document Set.
size_t events_failed() const noexcept
Get the number of audit event send failures.
void audit_authentication(const std::string &user_id, bool is_login, bool success)
Audit a User Authentication event.
void set_enabled(bool enabled) noexcept
Enable or disable audit event emission.
virtual void audit_xds_retrieve(xds_consumer_transaction transaction, const std::string &source_ae, const std::string &dest_ae, const std::string &study_uid, const std::string &patient_id, const std::vector< std::string > &sop_instance_uids, bool success)
Audit an XDS-I.b Retrieve Document Set transaction.
size_t events_sent() const noexcept
Get the number of audit events successfully sent.
xds_source_transaction
XDS-I.b source-side transaction identifier.
@ iti_41
ITI-41 Provide and Register Document Set-b.
std::atomic< bool > enabled_
Whether audit is enabled.
bool is_enabled() const noexcept
Check if audit event emission is enabled.
std::string audit_source_id_
Audit source identifier (e.g., "PACS_SYSTEM_01")
void audit_query(const std::string &calling_ae, const std::string &called_ae, const std::string &query_level, bool success)
Audit a C-FIND (Query) event.
void send_audit(const atna_audit_message &message)
Send an audit message via syslog transport.
const atna_syslog_transport & transport() const noexcept
Get the underlying transport (for advanced use)
atna_service_auditor(const syslog_transport_config &config, std::string audit_source_id)
Construct an auditor with syslog transport configuration.
virtual void audit_xds_provide_and_register(xds_source_transaction transaction, const std::string &source_ae, const std::string &dest_ae, const std::string &study_uid, const std::string &patient_id, const std::vector< std::string > &sop_instance_uids, bool success)
Audit an XDS-I.b Provide and Register Document Set transaction.
void submit_audit_message(const atna_audit_message &message)
Emit a pre-built RFC 3881 audit message.
std::atomic< size_t > events_failed_
void audit_security_alert(const std::string &user_id, const std::string &alert_description)
Audit a Security Alert event (e.g., access denied)
const std::string & audit_source_id() const noexcept
Get the audit source identifier.
std::atomic< size_t > events_sent_
Statistics.
atna_service_auditor & operator=(const atna_service_auditor &)=delete
void reset_statistics() noexcept
Reset statistics counters.
atna_syslog_transport transport_
Syslog transport for sending audit messages.
void audit_instance_stored(const std::string &source_ae, const std::string &dest_ae, const std::string &study_uid, const std::string &patient_id, bool success)
Audit a C-STORE (DICOM Instances Transferred) event.
Sends ATNA audit messages via Syslog protocol.
kcenon::pacs::VoidResult send(const std::string &xml_message)
Send an RFC 3881 XML audit message via Syslog.
Complete RFC 3881 audit message.
A coded value with code, code system name, and display name.
Configuration for the Syslog transport.