Example #1
0
Status OptionsConfigParserPlugin::update(const std::string& source,
                                         const ParserConfig& config) {
  if (config.count("options") > 0) {
    data_ = pt::ptree();
    data_.put_child("options", config.at("options"));
  }

  const auto& options = data_.get_child("options");
  for (const auto& option : options) {
    std::string value = options.get<std::string>(option.first, "");
    if (value.empty()) {
      continue;
    }

    Flag::updateValue(option.first, value);
    // There is a special case for supported Gflags-reserved switches.
    if (option.first == "verbose" || option.first == "verbose_debug" ||
        option.first == "debug") {
      setVerboseLevel();
      if (Flag::getValue("verbose") == "true") {
        VLOG(1) << "Verbose logging enabled by config option";
      }
    }
  }

  return Status(0, "OK");
}
Example #2
0
Status ViewsConfigParserPlugin::update(const std::string& source,
                                       const ParserConfig& config) {
  auto cv = config.find("views");
  if (cv == config.end()) {
    return Status(1);
  }

  auto obj = data_.getObject();
  data_.copyFrom(cv->second.doc(), obj);
  data_.add("views", obj);

  const auto& views = data_.doc()["views"];

  // We use a restricted scope below to change the data structure from
  // an array to a set. This lets us do deletes much more efficiently
  std::vector<std::string> created_views;
  std::set<std::string> erase_views;
  {
    std::vector<std::string> old_views_vec;
    scanDatabaseKeys(kQueries, old_views_vec, kConfigViews);
    for (const auto& view : old_views_vec) {
      erase_views.insert(view.substr(kConfigViews.size()));
    }
  }

  QueryData r;
  for (const auto& view : views.GetObject()) {
    std::string name = view.name.GetString();
    std::string query = view.value.GetString();
    if (query.empty()) {
      continue;
    }

    std::string old_query = "";
    getDatabaseValue(kQueries, kConfigViews + name, old_query);
    erase_views.erase(name);
    if (old_query == query) {
      continue;
    }

    // View has been updated
    osquery::query("DROP VIEW " + name, r);
    auto s = osquery::query("CREATE VIEW " + name + " AS " + query, r);
    if (s.ok()) {
      setDatabaseValue(kQueries, kConfigViews + name, query);
    } else {
      LOG(INFO) << "Error creating view (" << name << "): " << s.getMessage();
    }
  }

  // Any views left are views that don't exist in the new configuration file
  // so we tear them down and remove them from the database.
  for (const auto& old_view : erase_views) {
    osquery::query("DROP VIEW " + old_view, r);
    deleteDatabaseValue(kQueries, kConfigViews + old_view);
  }
  return Status(0, "OK");
}
Status PrometheusMetricsConfigParserPlugin::update(const std::string& source,
                                                   const ParserConfig& config) {
  if (config.count(kConfigParserRootKey) > 0) {
    data_ = boost::property_tree::ptree();
    data_.put_child(kConfigParserRootKey, config.at(kConfigParserRootKey));
  }

  return Status(0, "OK");
}
Example #4
0
Status FeatureVectorsConfigParserPlugin::update(const std::string& source,
                                                const ParserConfig& config) {
  auto fv = config.find(kFeatureVectorsRootKey);
  if (fv == config.end()) {
    return Status();
  }

  auto obj = data_.getObject();
  data_.copyFrom(fv->second.doc(), obj);
  data_.add(kFeatureVectorsRootKey, obj);
  return Status();
}
Example #5
0
Status LoggerConfigParserPlugin::update(const std::string& /* source */,
                                        const ParserConfig& config) {
  rj::Document& doc = data_.doc();

  auto it = doc.FindMember(kLoggerKey);
  if (it != doc.MemberEnd()) {
    doc.EraseMember(it);
  }

  auto cv = config.find(kLoggerKey);
  if (cv != config.end()) {
    auto obj = data_.getObject();
    data_.copyFrom(cv->second.doc(), obj);
    data_.add(kLoggerKey, obj);
  }

  return Status();
}
Example #6
0
Status FilePathsConfigParserPlugin::update(const std::string& source,
                                           const ParserConfig& config) {
  if (config.count("file_paths") > 0) {
    data_.put_child("file_paths", config.at("file_paths"));
  }

  auto& accesses = data_.get_child("file_accesses");
  if (config.count("file_accesses") > 0) {
    if (access_map_.count(source) > 0) {
      access_map_.erase(source);
    }

    for (const auto& category : config.at("file_accesses")) {
      auto path = category.second.get_value<std::string>("");
      access_map_[source].push_back(path);
    }
    // Regenerate the access:
    for (const auto& access_source : access_map_) {
      for (const auto& category : access_source.second) {
        accesses.put(category, access_source.first);
      }
    }
  }

  Config::getInstance().removeFiles(source);
  for (const auto& category : data_.get_child("file_paths")) {
    for (const auto& path : category.second) {
      auto pattern = path.second.get_value<std::string>("");
      if (pattern.empty()) {
        continue;
      }
      replaceGlobWildcards(pattern);
      Config::getInstance().addFile(source, category.first, pattern);
    }
  }

  return Status(0, "OK");
}
Status ATCConfigParserPlugin::update(const std::string& source,
                                     const ParserConfig& config) {
  auto cv = config.find(kParserKey);
  if (cv == config.end()) {
    return Status(1, "No configuration for ATC (Auto Table Construction)");
  }
  auto obj = data_.getObject();

  data_.copyFrom(cv->second.doc(), obj);
  data_.add(kParserKey, obj);

  const auto& ac_tables = data_.doc()[kParserKey];
  auto tables = RegistryFactory::get().registry("table");
  auto registered = registeredATCTables();

  for (const auto& ac_table : ac_tables.GetObject()) {
    std::string table_name{ac_table.name.GetString()};
    auto params = ac_table.value.GetObject();

    std::string query{params.HasMember("query") && params["query"].IsString()
                          ? params["query"].GetString()
                          : ""};
    std::string path{params.HasMember("path") && params["path"].IsString()
                         ? params["path"].GetString()
                         : ""};
    std::string platform{params.HasMember("platform") &&
                                 params["platform"].IsString()
                             ? params["platform"].GetString()
                             : ""};

    if (query.empty() || path.empty()) {
      LOG(WARNING) << "ATC Table: " << table_name << " is misconfigured";
      continue;
    }

    if (!checkPlatform(platform)) {
      VLOG(1) << "Skipping ATC table: " << table_name
              << " because platform doesn't match";
      continue;
    }

    TableColumns columns;
    std::string columns_value;
    columns_value.reserve(256);

    for (const auto& column : params["columns"].GetArray()) {
      columns.push_back(make_tuple(
          std::string(column.GetString()), TEXT_TYPE, ColumnOptions::DEFAULT));
      columns_value += std::string(column.GetString()) + ",";
    }

    registered.erase(table_name);
    std::string table_settings{table_name + query + columns_value + path};
    std::string old_setting;
    auto s = getDatabaseValue(
        kPersistentSettings, kDatabaseKeyPrefix + table_name, old_setting);

    // The ATC table hasn't changed so we skip ahead
    if (table_settings == old_setting) {
      continue;
    }

    // Remove the old table to replace with the new one
    s = removeATCTables({table_name});
    if (!s.ok()) {
      LOG(WARNING) << "ATC table overrides core table; Refusing registration";
      continue;
    }

    s = setDatabaseValue(
        kPersistentSettings, kDatabaseKeyPrefix + table_name, table_settings);

    if (!s.ok()) {
      LOG(WARNING) << "Could not write to database";
      continue;
    }

    s = tables->add(
        table_name, std::make_shared<ATCPlugin>(path, columns, query), true);

    if (!s.ok()) {
      LOG(WARNING) << s.getMessage();
      deleteDatabaseValue(kPersistentSettings, kDatabaseKeyPrefix + table_name);
      continue;
    }

    PluginResponse resp;
    Registry::call(
        "sql", "sql", {{"action", "attach"}, {"table", table_name}}, resp);
    LOG(INFO) << "Registered ATC table: " << table_name;
  }

  if (registered.size() > 0) {
    VLOG(1)
        << "Removing any ATC tables that were removed in this configuration "
           "change";
    removeATCTables(registered);
  }
  return Status();
}