Coverage Report

Created: 2025-01-09 07:36

/src/osquery/plugins/config/filesystem_config.cpp
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (c) 2014-present, The osquery authors
3
 *
4
 * This source code is licensed as defined by the LICENSE file found in the
5
 * root directory of this source tree.
6
 *
7
 * SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
8
 */
9
10
#include <vector>
11
12
#include <boost/filesystem/operations.hpp>
13
#include <boost/property_tree/json_parser.hpp>
14
#include <boost/property_tree/ptree.hpp>
15
16
#include <osquery/config/config.h>
17
#include <osquery/core/flags.h>
18
#include <osquery/filesystem/filesystem.h>
19
#include <osquery/logger/logger.h>
20
#include <osquery/registry/registry_factory.h>
21
#include <osquery/utils/config/default_paths.h>
22
23
#include <osquery/utils/json/json.h>
24
25
namespace errc = boost::system::errc;
26
namespace fs = boost::filesystem;
27
namespace pt = boost::property_tree;
28
29
namespace osquery {
30
31
CLI_FLAG(string,
32
         config_path,
33
         (fs::path(OSQUERY_HOME) / "osquery.conf").make_preferred().string(),
34
         "Path to JSON config file");
35
36
class FilesystemConfigPlugin : public ConfigPlugin {
37
 public:
38
  Status genConfig(std::map<std::string, std::string>& config);
39
  Status genPack(const std::string& name,
40
                 const std::string& value,
41
                 std::string& pack);
42
};
43
44
REGISTER(FilesystemConfigPlugin, "config", "filesystem");
45
46
Status FilesystemConfigPlugin::genConfig(
47
0
    std::map<std::string, std::string>& config) {
48
0
  boost::system::error_code ec;
49
0
  if (!fs::is_regular_file(FLAGS_config_path, ec) ||
50
0
      ec.value() != errc::success) {
51
0
    return Status::failure("config file does not exist: " + FLAGS_config_path);
52
0
  }
53
54
0
  std::vector<std::string> conf_files;
55
0
  resolveFilePattern(FLAGS_config_path + ".d/%.conf", conf_files);
56
0
  std::sort(conf_files.begin(), conf_files.end());
57
0
  conf_files.push_back(FLAGS_config_path);
58
59
0
  for (const auto& path : conf_files) {
60
0
    std::string content;
61
0
    if (readFile(path, content).ok()) {
62
0
      config[path] = content;
63
0
    }
64
0
  }
65
66
0
  return Status(0, "OK");
67
0
}
68
69
Status FilesystemConfigPlugin::genPack(const std::string& name,
70
                                       const std::string& value,
71
0
                                       std::string& pack) {
72
0
  if (name == "*") {
73
    // The config requested a multi-pack.
74
0
    std::vector<std::string> paths;
75
0
    resolveFilePattern(value, paths);
76
77
0
    pt::ptree multi_pack;
78
0
    for (const auto& path : paths) {
79
0
      std::string content;
80
0
      if (!readFile(path, content)) {
81
0
        LOG(WARNING) << "Cannot read multi-pack file: " << path;
82
0
        continue;
83
0
      }
84
85
      // Assemble an intermediate property tree for simplified parsing.
86
0
      pt::ptree single_pack;
87
0
      stripConfigComments(content);
88
0
      try {
89
0
        std::stringstream json_stream;
90
0
        json_stream << content;
91
0
        pt::read_json(json_stream, single_pack);
92
0
      } catch (const pt::json_parser::json_parser_error& /* e */) {
93
0
        LOG(WARNING) << "Cannot read multi-pack JSON: " << path;
94
0
        continue;
95
0
      }
96
97
0
      multi_pack.put_child(fs::path(path).stem().string(), single_pack);
98
0
    }
99
100
    // We should have a property tree of pack content mimicking embedded
101
    // configuration packs, ready to parse as a string.
102
0
    std::ostringstream output;
103
0
    pt::write_json(output, multi_pack, false);
104
0
    pack = output.str();
105
0
    if (pack.empty()) {
106
0
      return Status(1, "Multi-pack content empty");
107
0
    }
108
109
0
    return Status(0);
110
0
  }
111
112
0
  boost::system::error_code ec;
113
0
  if (!fs::is_regular_file(value, ec) || ec.value() != errc::success) {
114
0
    return Status(1, value + " is not a valid path");
115
0
  }
116
117
0
  return readFile(value, pack);
118
0
}
119
} // namespace osquery