Improve checksum checks for each file content
authorMichael Friedrich <michael.friedrich@icinga.com>
Fri, 26 Oct 2018 14:05:21 +0000 (16:05 +0200)
committerMichael Friedrich <michael.friedrich@icinga.com>
Wed, 19 Jun 2019 12:46:11 +0000 (14:46 +0200)
lib/remote/apilistener-filesync.cpp
lib/remote/apilistener.hpp

index 206eac61b1f20f317bcf7b1e48bd30b46ba16cbb..12d718a2d6ee2fbe7d3ee5ff0bfc690a2ba7f42c 100644 (file)
@@ -336,17 +336,12 @@ Value ApiListener::ConfigUpdateHandler(const MessageOrigin::Ptr& origin, const D
                 * Otherwise do the old timestamp dance for versions < 2.11.
                 */
                if (checksums) {
-                       /* Calculate and compare the checksums. */
-                       String productionConfigChecksum = GetGlobalChecksum(productionConfigInfo);
-                       String newConfigChecksum = GetGlobalChecksum(newConfigInfo);
-
                        Log(LogInformation, "ApiListener")
                                << "Received configuration for zone '" << zoneName << "' from endpoint '"
-                               << fromEndpointName << "' with checksum '" << newConfigChecksum << "'."
-                               << " Our production configuration has checksum '" << productionConfigChecksum << "'.";
+                               << fromEndpointName << "'. Comparing the checksums.";
 
                        /* TODO: Do this earlier in hello-handshakes. */
-                       if (newConfigChecksum != productionConfigChecksum)
+                       if (CheckConfigChange(productionConfigInfo, newConfigInfo))
                                configChange = true;
                } else {
                        /* TODO: Figure out whether we always need to rely on the timestamp flags when there are checksums involved. */
@@ -608,17 +603,23 @@ String ApiListener::GetChecksum(const String& content)
        return SHA256(content);
 }
 
-String ApiListener::GetGlobalChecksum(const ConfigDirInformation& config)
+bool ApiListener::CheckConfigChange(const ConfigDirInformation& oldConfig, const ConfigDirInformation& newConfig)
 {
-       Dictionary::Ptr checksums = config.Checksums;
+       Dictionary::Ptr oldChecksums = oldConfig.Checksums;
+       Dictionary::Ptr newChecksums = newConfig.Checksums;
 
-       String result;
+       Log(LogCritical, "Comparing old: '")
+               << JsonEncode(oldChecksums)
+               << "' to new '" << JsonEncode(newChecksums) << "'.";
 
-       ObjectLock olock(checksums);
-       for (const Dictionary::Pair& kv : checksums) {
-               String path = kv.first;
-               String checksum = kv.second;
+       /* Different length means that either one or the other side added or removed something. */
+       if (oldChecksums->GetLength() != newChecksums->GetLength())
+               return true;
 
+       /* Both dictionaries have an equal size. */
+       ObjectLock olock(oldChecksums);
+       for (const Dictionary::Pair& kv : oldChecksums) {
+               String path = kv.first;
                /* Only use configuration files for checksum calculation. */
                //if (!Utility::Match("*.conf", path))
                //      continue;
@@ -630,11 +631,14 @@ String ApiListener::GetGlobalChecksum(const ConfigDirInformation& config)
                        continue;
 
                Log(LogCritical, "ApiListener")
-                       << "Adding checksum for " << kv.first << ": " << kv.second;
-               result += kv.second;
+                       << "Checking " << path << " for checksum: " << kv.second;
+
+               /* Check whether our key exists in the new checksums, and they have an equal value. */
+               if (newChecksums->Get(path) != kv.second)
+                       return true;
        }
 
-       return GetChecksum(result);
+       return false;
 }
 
 /**
index 393933ace0223f2d2656d8cf4bf44427fe382ff7..0f552e984898485edc72d32bfd42d1d83a5f66b9 100644 (file)
@@ -186,7 +186,7 @@ private:
        static void AsyncTryActivateZonesStage(const std::vector<String>& relativePaths);
 
        static String GetChecksum(const String& content);
-       static String GetGlobalChecksum(const ConfigDirInformation& config);
+       static bool CheckConfigChange(const ConfigDirInformation& oldConfig, const ConfigDirInformation& newConfig);
 
        void UpdateLastFailedZonesStageValidation(const String& log);
        void ClearLastFailedZonesStageValidation();