Coverage Report

Created: 2025-01-09 07:36

/src/osquery/plugins/logger/tls_logger.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
// clang-format off
11
// Keep it on top of all other includes to fix double include WinSock.h header file
12
// which is windows specific boost build problem
13
#include <osquery/remote/utility.h>
14
// clang-format on
15
16
#include "tls_logger.h"
17
18
#include <boost/property_tree/ptree.hpp>
19
20
#include <osquery/remote/enroll/enroll.h>
21
#include <osquery/core/flags.h>
22
#include <osquery/core/flagalias.h>
23
#include <osquery/registry/registry.h>
24
25
#include <osquery/remote/serializers/json.h>
26
27
#include <plugins/config/parsers/decorators.h>
28
#include <osquery/utils/json/json.h>
29
30
namespace osquery {
31
32
FLAG(uint64,
33
     logger_tls_max_lines,
34
     1024,
35
     "Max number of logs to send per period");
36
37
FLAG(string, logger_tls_endpoint, "", "TLS/HTTPS endpoint for results logging");
38
39
FLAG(uint64,
40
     logger_tls_period,
41
     4,
42
     "Seconds between flushing logs over TLS/HTTPS");
43
44
FLAG(uint64,
45
     logger_tls_backoff_max,
46
     60 * 60,
47
     "Maximum seconds to wait before flushing logs over TLS/HTTPS. Backoff "
48
     "kicks in when regular flush fails. Should be a multiple of "
49
     "logger_tls_period. 0 disables backoff");
50
51
FLAG(uint64,
52
     logger_tls_max_linesize,
53
     1 * 1024 * 1024,
54
     "Max size in bytes allowed per log line");
55
56
FLAG(bool, tls_disable_status_log, false, "Disable sending status logs");
57
58
// The flag name logger_tls_max is deprecated.
59
FLAG_ALIAS(google::uint64, logger_tls_max, logger_tls_max_linesize);
60
61
FLAG(bool, logger_tls_compress, false, "GZip compress TLS/HTTPS request body");
62
63
REGISTER(TLSLoggerPlugin, "logger", "tls");
64
65
TLSLogForwarder::TLSLogForwarder()
66
0
    : BufferedLogForwarder("TLSLogForwarder",
67
0
                           "tls",
68
0
                           std::chrono::seconds(FLAGS_logger_tls_period),
69
0
                           FLAGS_logger_tls_max_lines,
70
0
                           std::chrono::seconds(FLAGS_logger_tls_backoff_max)) {
71
0
  uri_ = TLSRequestHelper::makeURI(FLAGS_logger_tls_endpoint);
72
0
}
73
74
0
Status TLSLoggerPlugin::logString(const std::string& s) {
75
0
  return forwarder_->logString(s);
76
0
}
77
78
0
Status TLSLoggerPlugin::logStatus(const std::vector<StatusLogLine>& log) {
79
0
  return forwarder_->logStatus(log);
80
0
}
81
82
0
Status TLSLoggerPlugin::setUp() {
83
  // Start the log forwarding/flushing thread.
84
0
  forwarder_ = std::make_shared<TLSLogForwarder>();
85
0
  Status s = forwarder_->setUp();
86
0
  if (!s.ok()) {
87
0
    LOG(ERROR) << "Error initializing TLS logger: " << s.getMessage();
88
0
    return s;
89
0
  }
90
91
0
  auto node_key = getNodeKey("tls");
92
0
  if (!FLAGS_disable_enrollment && node_key.size() == 0) {
93
    // Could not generate a node key, continue logging to stderr.
94
0
    return Status(1, "No node key, TLS logging disabled.");
95
0
  }
96
97
0
  Dispatcher::addService(forwarder_);
98
99
0
  return Status(0);
100
0
}
101
102
void TLSLoggerPlugin::init(const std::string& name,
103
0
                           const std::vector<StatusLogLine>& log) {
104
0
  logStatus(log);
105
0
}
106
107
0
void TLSLoggerPlugin::configure() {
108
0
  if (forwarder_ != nullptr) {
109
0
    std::unique_lock<decltype(forwarder_->configuration_mutex)> lock(
110
0
        forwarder_->configuration_mutex);
111
0
    forwarder_->configuration_updated = true;
112
0
    forwarder_->updated_uri =
113
0
        TLSRequestHelper::makeURI(FLAGS_logger_tls_endpoint);
114
0
    forwarder_->updated_log_period =
115
0
        std::chrono::seconds(FLAGS_logger_tls_period);
116
0
    forwarder_->updated_max_log_lines = FLAGS_logger_tls_max_lines;
117
0
    forwarder_->updated_max_backoff_period =
118
0
        std::chrono::seconds(FLAGS_logger_tls_backoff_max);
119
0
  }
120
0
}
121
122
Status TLSLogForwarder::send(std::vector<std::string>& log_data,
123
0
                             const std::string& log_type) {
124
  // Skip sending status logs to remote server if disabled
125
0
  if (FLAGS_tls_disable_status_log && log_type == "status") {
126
0
    return Status::success();
127
0
  }
128
129
0
  JSON params;
130
0
  params.add("node_key", getNodeKey("tls"));
131
0
  params.add("log_type", log_type);
132
133
0
  {
134
    // Read each logged line into JSON and populate a list of lines.
135
    // The result list will use the 'data' key.
136
0
    auto children = params.newArray();
137
0
    iterate(log_data, ([&params, &children](std::string& item) {
138
              // Enforce a max log line size for TLS logging.
139
0
              if (item.size() > FLAGS_logger_tls_max_linesize) {
140
0
                LOG(WARNING)
141
0
                    << "Linesize exceeds TLS logger maximum: " << item.size();
142
0
                return;
143
0
              }
144
145
0
              JSON child;
146
0
              Status s = child.fromString(item);
147
0
              if (!s.ok()) {
148
                // The log line entered was not valid JSON, skip it.
149
0
                return;
150
0
              }
151
0
              std::string().swap(item);
152
0
              params.push(child.doc(), children.doc());
153
0
            }));
154
0
    params.add("data", children.doc());
155
0
  }
156
157
  // The response body is ignored (status is set appropriately by
158
  // TLSRequestHelper::go())
159
0
  std::string response;
160
0
  if (FLAGS_logger_tls_compress) {
161
0
    params.add("_compress", true);
162
0
  }
163
0
  return TLSRequestHelper::go<JSONSerializer>(uri_, params, response);
164
0
}
165
166
0
void TLSLogForwarder::applyNewConfiguration() {
167
0
  std::unique_lock<decltype(configuration_mutex)> lock(configuration_mutex);
168
0
  if (configuration_updated) {
169
0
    uri_ = updated_uri;
170
0
    log_period_ = updated_log_period;
171
0
    max_log_lines_ = updated_max_log_lines;
172
0
    max_backoff_period_ = updated_max_backoff_period;
173
0
  }
174
0
  configuration_updated = false;
175
0
}
176
177
} // namespace osquery