/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 |