mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-06 17:45:22 +00:00
232 lines
7.5 KiB
C++
232 lines
7.5 KiB
C++
/*
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <osquery/enroll.h>
|
|
#include <osquery/flags.h>
|
|
|
|
#include "osquery/remote/requests.h"
|
|
#include "osquery/remote/transports/tls.h"
|
|
|
|
#include "osquery/core/process.h"
|
|
|
|
namespace osquery {
|
|
|
|
DECLARE_string(tls_enroll_override);
|
|
DECLARE_string(tls_hostname);
|
|
DECLARE_bool(tls_node_api);
|
|
DECLARE_bool(tls_secret_always);
|
|
DECLARE_bool(disable_reenrollment);
|
|
|
|
/**
|
|
* @brief Helper class for allowing TLS plugins to easily kick off requests
|
|
*
|
|
* There are many static functions in this class that have very similar
|
|
* behaviour, which allow them to be used in many context. Some methods accept
|
|
* parameters, some don't require them. Some have built-in retry logic, some
|
|
* don't. Some return results in a ptree, some return results in JSON, etc.
|
|
*/
|
|
class TLSRequestHelper : private boost::noncopyable {
|
|
public:
|
|
/**
|
|
* @brief Using the `tls_hostname` flag and an endpoint, construct a URI
|
|
*
|
|
* @param endpoint is the URI endpoint to be combined with `tls_hostname`
|
|
* @return a string representing the uri
|
|
*/
|
|
static std::string makeURI(const std::string& endpoint) {
|
|
auto node_key = getNodeKey("tls");
|
|
auto uri = "https://" + FLAGS_tls_hostname;
|
|
if (FLAGS_tls_node_api) {
|
|
// The TLS API should treat clients as nodes.
|
|
// In this case the node_key acts as an identifier (node) and the
|
|
// endpoints
|
|
// (if provided) are treated as edges from the nodes.
|
|
uri += "/" + node_key;
|
|
}
|
|
uri += endpoint;
|
|
|
|
// Some APIs may require persistent identification.
|
|
if (FLAGS_tls_secret_always) {
|
|
uri += ((uri.find("?") != std::string::npos) ? "&" : "?") +
|
|
FLAGS_tls_enroll_override + "=" + getEnrollSecret();
|
|
}
|
|
return uri;
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param params is a ptree of the params to send to the server. This isn't
|
|
* const because it will be modified to include node_key.
|
|
* @param output is the ptree which will be populated with the deserialized
|
|
* results
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri,
|
|
boost::property_tree::ptree& params,
|
|
boost::property_tree::ptree& output) {
|
|
auto node_key = getNodeKey("tls");
|
|
|
|
// If using a GET request, append the node_key to the URI variables.
|
|
std::string uri_suffix;
|
|
if (FLAGS_tls_node_api) {
|
|
uri_suffix = "&node_key=" + node_key;
|
|
} else {
|
|
params.put<std::string>("node_key", node_key);
|
|
}
|
|
|
|
// Again check for GET to call with/without parameters.
|
|
auto request = Request<TLSTransport, TSerializer>(uri + uri_suffix);
|
|
request.setOption("hostname", FLAGS_tls_hostname);
|
|
|
|
// The caller-supplied parameters may force a POST request.
|
|
bool force_post = false;
|
|
if (params.count("verb")) {
|
|
force_post = (params.get<std::string>("verb") == "POST");
|
|
params.erase("verb");
|
|
}
|
|
auto status = (FLAGS_tls_node_api && !force_post) ? request.call()
|
|
: request.call(params);
|
|
if (!status.ok()) {
|
|
return status;
|
|
}
|
|
|
|
// The call succeeded, store the enrolled key.
|
|
status = request.getResponse(output);
|
|
if (!status.ok()) {
|
|
return status;
|
|
}
|
|
|
|
// Receive config or key rejection
|
|
if (output.count("error") > 0) {
|
|
return Status(1, "Request failed: " + output.get("error", "<unknown>"));
|
|
} else if (output.count("node_invalid") > 0) {
|
|
auto invalid = output.get("node_invalid", "");
|
|
if (invalid == "1" || invalid == "true" || invalid == "True") {
|
|
if (!FLAGS_disable_reenrollment) {
|
|
clearNodeKey();
|
|
}
|
|
return Status(1, "Request failed: Invalid node key");
|
|
}
|
|
}
|
|
return Status(0, "OK");
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param params is a ptree of the params to send to the server. This isn't
|
|
* const because it will be modified to include node_key.
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri,
|
|
boost::property_tree::ptree& output) {
|
|
boost::property_tree::ptree params;
|
|
return TLSRequestHelper::go<TSerializer>(uri, params, output);
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param params is a ptree of the params to send to the server. This isn't
|
|
* const because it will be modified to include node_key.
|
|
* @param output is the string which will be populated with the deserialized
|
|
* results
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri,
|
|
boost::property_tree::ptree& params,
|
|
std::string& output) {
|
|
boost::property_tree::ptree recv;
|
|
auto s = TLSRequestHelper::go<TSerializer>(uri, params, recv);
|
|
if (s.ok()) {
|
|
auto serializer = TSerializer();
|
|
return serializer.serialize(recv, output);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param output is the string which will be populated with the deserialized
|
|
* results
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri, std::string& output) {
|
|
boost::property_tree::ptree params;
|
|
return TLSRequestHelper::go<TSerializer>(uri, params, output);
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param params is a ptree of the params to send to the server. This isn't
|
|
* const because it will be modified to include node_key.
|
|
* @param output is the string which will be populated with the deserialized
|
|
* results
|
|
* @param attempts is the number of attempts to make if the request fails
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri,
|
|
boost::property_tree::ptree& params,
|
|
std::string& output,
|
|
const size_t attempts) {
|
|
Status s;
|
|
for (size_t i = 1; i <= attempts; i++) {
|
|
s = TLSRequestHelper::go<TSerializer>(uri, params, output);
|
|
if (s.ok()) {
|
|
return s;
|
|
}
|
|
if (i == attempts) {
|
|
break;
|
|
}
|
|
sleepFor(i * i);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @brief Send a TLS request
|
|
*
|
|
* @param uri is the URI to send the request to
|
|
* @param output is the string which will be populated with the deserialized
|
|
* results
|
|
* @param attempts is the number of attempts to make if the request fails
|
|
*
|
|
* @return a Status object indicating the success or failure of the operation
|
|
*/
|
|
template <class TSerializer>
|
|
static Status go(const std::string& uri,
|
|
std::string& output,
|
|
const size_t attempts) {
|
|
boost::property_tree::ptree params;
|
|
return TLSRequestHelper::go<TSerializer>(uri, params, output, attempts);
|
|
}
|
|
};
|
|
}
|