changeset 4375:208029732d51 varian

New config option "DeidentifyDimseQueryLogs"
author Mark Poscablo <Mark.Poscablo@varian.com>
date Tue, 15 Dec 2020 13:59:01 -0500
parents 79ef2b6d8e76
children b002f9abe802
files OrthancServer/Resources/Configuration.json OrthancServer/Sources/OrthancFindRequestHandler.cpp OrthancServer/Sources/OrthancGetRequestHandler.cpp OrthancServer/Sources/OrthancMoveRequestHandler.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h
diffstat 6 files changed, 68 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Resources/Configuration.json	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Resources/Configuration.json	Tue Dec 15 13:59:01 2020 -0500
@@ -630,4 +630,15 @@
   // option to "0" doesn't call mallopt()", which was the behavior of
   // Orthanc <= 1.8.1.
   "MallocArenaMax" : 5 
+
+  // Deidentify/anonymize the contents of C-Find, C-Get, and C-Move
+  // queries submitted to Orthanc according to Table E.1-1 of the
+  // DICOM standard
+  "DeidentifyDimseQueryLogs": true,
+
+  // If DeidentifyDimseQueryLogs is true, this sets the DICOM standard
+  // to follow for the deintification/anonymization of the query
+  // contents. Possible values are those that are specified in the
+  // definition of Orthanc::StringToDicomVersion
+  "DeidentifyDimseQueryLogsDicomVersion": "2017c",
 }
--- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Tue Dec 15 13:59:01 2020 -0500
@@ -639,7 +639,7 @@
       {
         CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                           << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                          << " = " << query.GetElement(i).GetValue().GetContent();
+                          << " = " << context_.GetDeidentifiedQueryContent(query.GetElement(i));
       }
     }
 
--- a/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Tue Dec 15 13:59:01 2020 -0500
@@ -507,7 +507,7 @@
         {
           CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                             << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                            << " = " << query.GetElement(i).GetValue().GetContent();
+                            << " = " << context_.GetDeidentifiedQueryContent(query.GetElement(i));
         }
       }
     }
--- a/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Tue Dec 15 13:59:01 2020 -0500
@@ -344,7 +344,7 @@
         {
           CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                             << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                            << " = " << query.GetElement(i).GetValue().GetContent();
+                            << " = " << context_.GetDeidentifiedQueryContent(query.GetElement(i));
         }
       }
     }
--- a/OrthancServer/Sources/ServerContext.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Tue Dec 15 13:59:01 2020 -0500
@@ -35,7 +35,9 @@
 #include "ServerContext.h"
 
 #include "../../OrthancFramework/Sources/Cache/SharedArchive.h"
+#include "../../OrthancFramework/Sources/DicomFormat/DicomElement.h"
 #include "../../OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h"
+#include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
 #include "../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h"
 #include "../../OrthancFramework/Sources/FileStorage/StorageAccessor.h"
@@ -267,7 +269,9 @@
     isExecuteLuaEnabled_(false),
     overwriteInstances_(false),
     dcmtkTranscoder_(new DcmtkTranscoder),
-    isIngestTranscoding_(false)
+    isIngestTranscoding_(false),
+    deidentifyDimseQueryLogs_(false),
+    deidentifyDimseQueryLogsDicomVersion_(DicomVersion_2017c)
   {
     try
     {
@@ -318,6 +322,22 @@
           isIngestTranscoding_ = false;
           LOG(INFO) << "Automated transcoding of incoming DICOM instances is disabled";
         }
+
+        if (lock.GetConfiguration().GetBooleanParameter("DeidentifyDimseQueryLogs", false))
+        {
+          deidentifyDimseQueryLogs_ = true;
+          CLOG(INFO, DICOM) << "Deidentification of DIMSE query log contents is enabled";
+
+          deidentifyDimseQueryLogsDicomVersion_ = StringToDicomVersion(
+              lock.GetConfiguration().GetStringParameter("DeidentifyDimseQueryLogsDicomVersion", "2017c"));
+          CLOG(INFO, DICOM) << "Version of DICOM standard used for deidentification is "
+                            << EnumerationToString(deidentifyDimseQueryLogsDicomVersion_);
+        }
+        else
+        {
+          deidentifyDimseQueryLogs_ = false;
+          CLOG(INFO, DICOM) << "Deidentification of DIMSE query log contents is disabled";
+        }
       }
 
       jobsEngine_.SetThreadSleep(unitTesting ? 20 : 200);
@@ -326,6 +346,11 @@
       changeThread_ = boost::thread(ChangeThread, this, (unitTesting ? 20 : 100));
     
       dynamic_cast<DcmtkTranscoder&>(*dcmtkTranscoder_).SetLossyQuality(lossyQuality);
+
+      if (deidentifyDimseQueryLogs_)
+      {
+        logsDeidentifierRules_.SetupAnonymization(deidentifyDimseQueryLogsDicomVersion_);
+      }
     }
     catch (OrthancException&)
     {
@@ -1627,4 +1652,22 @@
       return false;
     }
   }
+
+  const std::string& ServerContext::GetDeidentifiedQueryContent(const DicomElement &element) const
+  {
+    static const std::string redactedContent = "*** POTENTIAL PHI ***";
+
+    const DicomTag& tag = element.GetTag();
+    if (deidentifyDimseQueryLogs_ && (
+            logsDeidentifierRules_.IsCleared(tag) ||
+            logsDeidentifierRules_.IsRemoved(tag) ||
+            logsDeidentifierRules_.IsReplaced(tag)))
+    {
+      return redactedContent;
+    }
+    else
+    {
+      return element.GetValue().GetContent();
+    }
+  }
 }
--- a/OrthancServer/Sources/ServerContext.h	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Tue Dec 15 13:59:01 2020 -0500
@@ -40,6 +40,8 @@
 #include "ServerJobs/IStorageCommitmentFactory.h"
 
 #include "../../OrthancFramework/Sources/Cache/MemoryCache.h"
+#include "../../OrthancFramework/Sources/DicomFormat/DicomElement.h"
+#include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
 #include "../../OrthancFramework/Sources/DicomParsing/IDicomTranscoder.h"
 
 
@@ -245,6 +247,12 @@
                        size_t since,
                        size_t limit);
 
+    // This DicomModification object is intended to be used as a "rules engine"
+    // when de-identifying logs for C-Find, C-Get, and C-Move queries
+    DicomModification logsDeidentifierRules_;
+    bool deidentifyDimseQueryLogs_;
+    DicomVersion deidentifyDimseQueryLogsDicomVersion_;
+
   public:
     class DicomCacheLocker : public boost::noncopyable
     {
@@ -500,5 +508,7 @@
     {
       return transcodeDicomProtocol_;
     }
+
+    const std::string& GetDeidentifiedQueryContent(const DicomElement& element) const;
   };
 }