/src/osquery/plugins/config/parsers/views.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 <set> |
11 | | |
12 | | #include <osquery/config/config.h> |
13 | | #include <osquery/database/database.h> |
14 | | #include <osquery/logger/logger.h> |
15 | | #include <osquery/registry/registry_factory.h> |
16 | | #include <osquery/sql/sql.h> |
17 | | |
18 | | namespace osquery { |
19 | | |
20 | | /** |
21 | | * @brief A simple ConfigParserPlugin for a "views" dictionary key. |
22 | | */ |
23 | | class ViewsConfigParserPlugin : public ConfigParserPlugin { |
24 | | public: |
25 | 0 | std::vector<std::string> keys() const override { |
26 | 0 | return {"views"}; |
27 | 0 | } |
28 | | |
29 | | Status update(const std::string& source, const ParserConfig& config) override; |
30 | | |
31 | | private: |
32 | | const std::string kConfigViews = "config_views."; |
33 | | std::atomic<bool> first_time_{true}; |
34 | | }; |
35 | | |
36 | | Status ViewsConfigParserPlugin::update(const std::string& source, |
37 | 0 | const ParserConfig& config) { |
38 | 0 | auto cv = config.find("views"); |
39 | 0 | if (cv == config.end()) { |
40 | 0 | return Status(1); |
41 | 0 | } |
42 | | |
43 | 0 | { |
44 | 0 | auto doc = JSON::newObject(); |
45 | 0 | auto obj = doc.getObject(); |
46 | 0 | doc.copyFrom(cv->second.doc(), obj); |
47 | 0 | doc.add("views", obj); |
48 | 0 | data_ = std::move(doc); |
49 | 0 | } |
50 | |
|
51 | 0 | const auto& views = data_.doc()["views"]; |
52 | | |
53 | | // We use a restricted scope below to change the data structure from |
54 | | // an array to a set. This lets us do deletes much more efficiently |
55 | 0 | std::vector<std::string> created_views; |
56 | 0 | std::set<std::string> erase_views; |
57 | 0 | { |
58 | 0 | std::vector<std::string> old_views_vec; |
59 | 0 | scanDatabaseKeys(kQueries, old_views_vec, kConfigViews); |
60 | 0 | for (const auto& view : old_views_vec) { |
61 | 0 | erase_views.insert(view.substr(kConfigViews.size())); |
62 | 0 | } |
63 | 0 | } |
64 | |
|
65 | 0 | QueryData r; |
66 | 0 | if (views.IsObject()) { |
67 | 0 | for (const auto& view : views.GetObject()) { |
68 | 0 | std::string name = view.name.GetString(); |
69 | 0 | if (!view.value.IsString()) { |
70 | 0 | continue; |
71 | 0 | } |
72 | 0 | std::string query = view.value.GetString(); |
73 | 0 | if (query.empty()) { |
74 | 0 | continue; |
75 | 0 | } |
76 | | |
77 | 0 | std::string old_query; |
78 | 0 | getDatabaseValue(kQueries, kConfigViews + name, old_query); |
79 | 0 | erase_views.erase(name); |
80 | | |
81 | | // If query exists in the store, view would already have been |
82 | | // created and we don't need to create it. Except, at startup, |
83 | | // the view always needs to be created. |
84 | 0 | if (!first_time_ && old_query == query) { |
85 | 0 | continue; |
86 | 0 | } |
87 | | |
88 | 0 | #ifdef OSQUERY_IS_FUZZING |
89 | 0 | auto s = Status::success(); |
90 | | #else |
91 | | // View has been updated |
92 | | osquery::query("DROP VIEW " + name, r); |
93 | | auto s = osquery::query("CREATE VIEW " + name + " AS " + query, r); |
94 | | #endif |
95 | 0 | if (s.ok()) { |
96 | 0 | setDatabaseValue(kQueries, kConfigViews + name, query); |
97 | 0 | } else { |
98 | 0 | LOG(INFO) << "Error creating view (" << name << "): " << s.getMessage(); |
99 | 0 | } |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | // Any views left are views that don't exist in the new configuration file |
104 | | // so we tear them down and remove them from the database. |
105 | 0 | for (const auto& old_view : erase_views) { |
106 | | #ifndef OSQUERY_IS_FUZZING |
107 | | osquery::query("DROP VIEW " + old_view, r); |
108 | | #endif |
109 | 0 | deleteDatabaseValue(kQueries, kConfigViews + old_view); |
110 | 0 | } |
111 | |
|
112 | 0 | first_time_ = false; |
113 | 0 | return Status(0, "OK"); |
114 | 0 | } |
115 | | |
116 | | REGISTER_INTERNAL(ViewsConfigParserPlugin, "config_parser", "views"); |
117 | | } // namespace osquery |