Redesign policy management logic 70/238770/2
authorSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 17 Jul 2020 06:22:20 +0000 (15:22 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 17 Jul 2020 07:08:21 +0000 (16:08 +0900)
[AS-IS]
- Policy Schema: Struct-based schema
- Policy Provider: Plugin Loader
- Policy Management: Virtual Table (static)

[TO-BE]
- Policy Schema: Struct-based schema
- Policy Provider & Management: Dynamic Virtual Table

Change-Id: I705ffee9e0d3368ac187c5498bd102f8d942a7d8
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
29 files changed:
CMake/Definition.cmake
CMakeLists.txt
packaging/vist.spec
plugins/CMakeLists.txt [deleted file]
src/vist/CMakeLists.txt
src/vist/common/dynamic-loader.cpp
src/vist/policy/api.cpp
src/vist/policy/api.hpp
src/vist/policy/policy-manager.cpp
src/vist/policy/policy-manager.hpp
src/vist/policy/tests/core.cpp
src/vist/service/tests/core.cpp
src/vist/service/vistd.cpp
src/vist/service/vistd.hpp
src/vist/table/CMakeLists.txt
src/vist/table/bluetooth.cpp [deleted file]
src/vist/table/bluetooth.hpp [deleted file]
src/vist/table/dynamic-table.hpp [new file with mode: 0644]
src/vist/table/policy-admin.cpp [deleted file]
src/vist/table/policy-admin.hpp [deleted file]
src/vist/table/policy.cpp [deleted file]
src/vist/table/policy.hpp [deleted file]
src/vist/table/policy/policy-admin.cpp [new file with mode: 0644]
src/vist/table/policy/policy-admin.hpp [new file with mode: 0644]
src/vist/table/policy/policy.cpp [new file with mode: 0644]
src/vist/table/policy/policy.hpp [new file with mode: 0644]
src/vist/table/policy/sample/CMakeLists.txt [new file with mode: 0644]
src/vist/table/policy/sample/sample.cpp [new file with mode: 0644]
src/vist/table/policy/sample/sample.hpp [new file with mode: 0644]

index a210f32e1fe0838a23b7800d5c02e3d48132c97b..52bfa5a389e72520ffccd455bebdd77e2be17a53 100644 (file)
@@ -25,12 +25,14 @@ SET(VIST_RW_DIR "${RW_DIR}/vist")
 
 SET(VIST_DB_DIR     "${VIST_RW_DIR}/db")
 SET(VIST_PLUGIN_DIR "${VIST_RO_DIR}/plugin")
+SET(VIST_TABLE_DIR  "${VIST_RO_DIR}/table")
 SET(VIST_SCRIPT_DIR "${VIST_RO_DIR}/script")
 
 SET(DEFAULT_POLICY_ADMIN "vist-cli")
-SET(DB_INSTALL_DIR     "${VIST_DB_DIR}")
-SET(PLUGIN_INSTALL_DIR "${VIST_PLUGIN_DIR}")
-SET(SCRIPT_INSTALL_DIR "${VIST_SCRIPT_DIR}")
+SET(DB_INSTALL_DIR       "${VIST_DB_DIR}")
+SET(PLUGIN_INSTALL_DIR   "${VIST_PLUGIN_DIR}")
+SET(TABLE_INSTALL_DIR    "${VIST_TABLE_DIR}")
+SET(SCRIPT_INSTALL_DIR   "${VIST_SCRIPT_DIR}")
 
 EXECUTE_PROCESS(COMMAND mkdir -p "${VIST_DB_DIR}")
 EXECUTE_PROCESS(COMMAND mkdir -p "${VIST_PLUGIN_DIR}")
index 5714bc4deaf7d4c43d65f1dfd7437a5822c44a15..995e690c7f865b3731703894ba7b85a64445f39f 100644 (file)
@@ -28,6 +28,11 @@ IF(NOT CMAKE_BUILD_TYPE)
        SET(CMAKE_BUILD_TYPE "DEBUG")
 ENDIF(NOT CMAKE_BUILD_TYPE)
 
+message("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
+message("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
+message("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
+message("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
+
 SET(CMAKE_CXX_FLAGS_DEBUG   "-g -std=c++1z -O0 -ggdb -Wp,-U_FORTIFY_SOURCE")
 SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=c++1z -O2 -DNDEBUG")
 
@@ -45,7 +50,6 @@ ENABLE_TESTING()
 
 ADD_SUBDIRECTORY(data)
 ADD_SUBDIRECTORY(src)
-ADD_SUBDIRECTORY(plugins)
 
 IF(DEFINED GBS_BUILD)
        ADD_SUBDIRECTORY(systemd)
index 535d8f02403505b24ba156125c1c8c03bdcc5500..e28e68463ad560358d154de7eba8f847d9164c40 100644 (file)
@@ -38,6 +38,7 @@ Requires: libsystemd
 
 %global vist_db_dir     %{vist_rw_dir}/db
 %global vist_plugin_dir %{vist_ro_dir}/plugin
+%global vist_table_dir %{vist_ro_dir}/table
 %global vist_script_dir %{vist_ro_dir}/script
 
 %description
@@ -67,6 +68,7 @@ cp %SOURCE1 .
                 -DDEFAULT_POLICY_ADMIN=vist-cli \
                 -DDB_INSTALL_DIR:PATH=%{vist_db_dir} \
                 -DPLUGIN_INSTALL_DIR:PATH=%{vist_plugin_dir} \
+                -DTABLE_INSTALL_DIR:PATH=%{vist_table_dir} \
                 -DSCRIPT_INSTALL_DIR:PATH=%{vist_script_dir} \
                 -DSYSTEMD_UNIT_DIR:PATH=%{_unitdir}
 
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
deleted file mode 100644 (file)
index 09d1fe8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack")
-
-ADD_SUBDIRECTORY(sample)
-
-IF(DEFINED GBS_BUILD)
-       ADD_SUBDIRECTORY(bluetooth)
-       ADD_SUBDIRECTORY(wifi)
-ENDIF(DEFINED GBS_BUILD)
index 6bd80e794ebf5dff71236de7eeaf4f5da30cd7c8..b96f0e4f12b7a0cb26d83e31a9b1c12089dafe5f 100644 (file)
@@ -35,6 +35,7 @@ INCLUDE_DIRECTORIES(SYSTEM . common ${VIST_COMMON_DEPS_INCLUDE_DIRS})
 ADD_DEFINITIONS(-DDB_PATH="${DB_INSTALL_DIR}/.vist.db"
                                -DDEFAULT_POLICY_ADMIN="${DEFAULT_POLICY_ADMIN}"
                                -DPLUGIN_INSTALL_DIR="${PLUGIN_INSTALL_DIR}"
+                               -DTABLE_INSTALL_DIR="${TABLE_INSTALL_DIR}"
                                -DSCRIPT_INSTALL_DIR="${SCRIPT_INSTALL_DIR}")
 
 ADD_DEFINITIONS("-Werror")
index 92a71773154df6ddb974124ed03a88f7bb10d95b..11113bac3d72a5b4b144c61f981cca2010565eb9 100644 (file)
@@ -39,11 +39,14 @@ DynamicLoader::ScopedHandle DynamicLoader::init(const std::string& path, int fla
                return handle;
        };
 
-       auto close = [&](void* handle) {
+       auto close = [&](void* /*handle*/) {
                ::dlerror();
 
-               if (::dlclose(handle) != 0)
-                       THROW(ErrCode::RuntimeError) << "Failed to close library: " << ::dlerror();
+// Calling symbol & code after dlclose() makes SEGFAULT.
+// TODO: Sync dynamic loading's life-cycle with program.
+//
+//             if (::dlclose(handle) != 0)
+//                     THROW(ErrCode::RuntimeError) << "Failed to close library: " << ::dlerror();
        };
 
        return ScopedHandle(open(), close);
index 98e6b6b6baf37a224f618f92759ebf3b8d098212..90ae565fd69007e2f8c16dc4ab5b702391bfa74c 100644 (file)
@@ -56,6 +56,11 @@ void API::Admin::Disenroll(const std::string& admin)
        PolicyManager::Instance().disenroll(admin);
 }
 
+void API::Admin::AddProvider(std::shared_ptr<PolicyProvider>&& provider)
+{
+       PolicyManager::Instance().addProvider(std::move(provider));
+}
+
 void API::Admin::Activate(const std::string& admin, bool state)
 {
        PolicyManager::Instance().activate(admin, state);
index 2998c1f9544b2c414dcf4c48030da14eba7b4bb2..80b03f2a007e72cee0158aee39a3bcafa38b55cb 100644 (file)
 
 #pragma once
 
+#include <vist/sdk/policy-provider.hpp>
 #include <vist/sdk/policy-value.hpp>
 
+#include <memory>
 #include <string>
 #include <unordered_map>
 
@@ -37,6 +39,8 @@ struct API {
                static void Activate(const std::string& admin, bool state = true);
                static bool IsActivated();
 
+               static void AddProvider(std::shared_ptr<PolicyProvider>&& provider);
+
                static std::unordered_map<std::string, int> GetAll();
        };
 };
index 7a63afb963b88e84181abec9c8ecf7b23762edfb..8a67a35e178838a9ec30e9e137e3e5996660245e 100644 (file)
@@ -32,8 +32,6 @@ PolicyManager::PolicyManager() : storage(DB_PATH)
        loadProviders(PLUGIN_INSTALL_DIR);
        int cnt = loadPolicies();
        INFO(VIST) << std::to_string(cnt) << "-policies loaded";
-
-       this->storage.enroll(DEFAULT_POLICY_ADMIN);
 }
 
 std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
@@ -75,6 +73,27 @@ std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
        return std::make_pair(passed, failed);
 }
 
+void PolicyManager::addProvider(std::shared_ptr<PolicyProvider>&& provider)
+{
+       for (const auto& p : this->providers) {
+               if (p->getName() == provider->getName()) {
+                       INFO(VIST) << "Previous added provider: " << provider->getName();
+                       return;
+               }
+       }
+
+       for (const auto& [name, policy] : provider->policies) {
+               this->policies[name] = provider->getName();
+
+               if (!storage.exists(name))
+                       storage.define(name, policy->getInitial());
+       }
+
+       INFO(VIST) << "Added " << provider->policies.size()
+                          << "-policies from " << provider->getName();
+       this->providers.emplace_back(std::move(provider));
+}
+
 int PolicyManager::loadPolicies()
 {
        /// Make policy-provider map for performance
@@ -151,7 +170,7 @@ const std::shared_ptr<PolicyModel>& PolicyManager::getPolicy(const std::string&
 
        auto provider = this->policies[name];
        auto iter = std::find_if(this->providers.begin(), this->providers.end(),
-       [&provider](const std::unique_ptr<PolicyProvider>& p) {
+       [&provider](const std::shared_ptr<PolicyProvider>& p) {
                return p->getName() == provider;
        });
        if (iter == this->providers.end())
index 3eda4d7c228f9c7889764110737949363c5514cd..ea46d941681e4ba022de65dd8406cdd8d112aebe 100644 (file)
@@ -51,6 +51,8 @@ public:
        void activate(const std::string& admin, bool state);
        bool isActivated();
 
+       void addProvider(std::shared_ptr<PolicyProvider>&& provider);
+
        void set(const std::string& policy,
                         const PolicyValue& value,
                         const std::string& admin);
@@ -67,7 +69,7 @@ private:
        int loadPolicies();
 
        PolicyStorage storage;
-       std::vector<std::unique_ptr<PolicyProvider>> providers;
+       std::vector<std::shared_ptr<PolicyProvider>> providers;
 
        const std::shared_ptr<PolicyModel>& getPolicy(const std::string& name);
 
index 083ea95d503d2d3e07541e5a80ff8494987be35d..98b5d5b24a7686400a748aca3672c468c717dbfe 100644 (file)
@@ -33,17 +33,17 @@ TEST(PolicyCoreTests, policy_set_get_int)
 {
        auto& manager = PolicyManager::Instance();
        manager.enroll("testAdmin");
-       manager.set("sample-int-policy", PolicyValue(5), "testAdmin");
+       manager.set("sample_int_policy", PolicyValue(5), "testAdmin");
 
        /// Default Admin's policy is more strict. (Because of initial value: 7)
-       auto policy = manager.get("sample-int-policy");
+       auto policy = manager.get("sample_int_policy");
        EXPECT_EQ(static_cast<int>(policy), 7);
 
        manager.enroll("testAdmin1");
-       manager.set("sample-int-policy", PolicyValue(10), "testAdmin1");
+       manager.set("sample_int_policy", PolicyValue(10), "testAdmin1");
 
        /// Manager should return the strongest policy.
-       policy = manager.get("sample-int-policy");
+       policy = manager.get("sample_int_policy");
        EXPECT_EQ(static_cast<int>(policy), 10);
 
        manager.disenroll("testAdmin");
@@ -80,8 +80,8 @@ TEST(PolicyCoreTests, policy_get_all)
 TEST(PolicyCoreTests, policy_get_policy)
 {
        auto& manager = PolicyManager::Instance();
-       const auto& policy = manager.getPolicy("sample-int-policy");
-       EXPECT_EQ(policy->getName(), "sample-int-policy");
+       const auto& policy = manager.getPolicy("sample_int_policy");
+       EXPECT_EQ(policy->getName(), "sample_int_policy");
 
        bool raised = false;
        try {
index 83d6f730293b5b762cf9ca04dbf89f54063fe73a..7b5c505d8a403d6117502bf1c13a97d3f78a02c2 100644 (file)
@@ -32,27 +32,29 @@ TEST_F(CoreTests, query_select)
 
        EXPECT_TRUE(rows.size() > 0);
 
-       std::string statement = "SELECT * FROM policy WHERE name = 'sample-int-policy'";
+       std::string statement = "SELECT * FROM policy WHERE name = 'sample_int_policy'";
        rows = Vistd::Query(statement);
 
-       EXPECT_EQ(rows.size(), 1);
-       EXPECT_EQ(rows[0]["name"], "sample-int-policy");
+       if (rows.size() == 1)
+               EXPECT_EQ(rows[0]["name"], "sample_int_policy");
+       else
+               EXPECT_TRUE(false);
 }
 
 TEST_F(CoreTests, query_update)
 {
        policy::API::Admin::Enroll("vist-test");
 
-       std::string statement = "SELECT * FROM policy WHERE name = 'sample-int-policy'";
+       std::string statement = "SELECT * FROM policy WHERE name = 'sample_int_policy'";
        auto rows = Vistd::Query(statement);
        /// Initial policy value
        EXPECT_EQ(rows[0]["value"], "I/7");
 
-       statement = "UPDATE policy SET value = 'I/10' WHERE name = 'sample-int-policy'";
+       statement = "UPDATE policy SET value = 'I/10' WHERE name = 'sample_int_policy'";
        rows = Vistd::Query(statement);
        EXPECT_EQ(rows.size(), 0);
 
-       statement = "SELECT * FROM policy WHERE name = 'sample-int-policy'";
+       statement = "SELECT * FROM policy WHERE name = 'sample_int_policy'";
        rows = Vistd::Query(statement);
        EXPECT_EQ(rows[0]["value"], "I/10");
 
index 695dc53e1880019a474ad6fed17a99a54e167649..c2fffbbf5943f33f12b4a8240f1da3c3ce71eddc 100644 (file)
 
 #include "vistd.hpp"
 
+#include <vist/dynamic-loader.hpp>
 #include <vist/exception.hpp>
 #include <vist/logger.hpp>
+#include <vist/policy/api.hpp>
 #include <vist/policy/policy-manager.hpp>
 #include <vist/rmi/gateway.hpp>
 
-#include <vist/table/bluetooth.hpp>
-#include <vist/table/policy-admin.hpp>
-#include <vist/table/policy.hpp>
+#include <vist/table/dynamic-table.hpp>
+#include <vist/table/policy/policy-admin.hpp>
+#include <vist/table/policy/policy.hpp>
 
 #include <osquery/registry_interface.h>
 #include <osquery/sql.h>
 
+#include <filesystem>
+
 namespace {
 const std::string SOCK_ADDR = "/tmp/.vist";
 } // anonymous namespace
@@ -38,9 +42,10 @@ Vistd::Vistd()
 {
        osquery::registryAndPluginInit();
 
-       table::BluetoothTable::Init();
-       table::PolicyAdminTable::Init();
-       table::PolicyTable::Init();
+       this->loadStaticTable();
+       this->loadDynamicTable();
+
+       policy::API::Admin::Enroll(DEFAULT_POLICY_ADMIN);
 }
 
 void Vistd::start()
@@ -71,6 +76,7 @@ void Vistd::start()
 
 Rows Vistd::query(const std::string& statement)
 {
+       DEBUG(VIST) << "Excute query: " << statement;
        osquery::SQL sql(statement, true);
        if (!sql.ok())
                THROW(ErrCode::RuntimeError) << "Faild to execute query: " << sql.getMessageString();
@@ -78,4 +84,25 @@ Rows Vistd::query(const std::string& statement)
        return sql.rows();
 }
 
+void Vistd::loadStaticTable()
+{
+       table::PolicyAdminTable::Init();
+       table::PolicyTable::Init();
+}
+
+void Vistd::loadDynamicTable()
+{
+       for (auto& iter : std::filesystem::directory_iterator(TABLE_INSTALL_DIR)) {
+               DEBUG(VIST) << "Load dynamic table: " << iter.path();
+               DynamicLoader loader(iter.path());
+               auto factory = loader.load<table::DynamicTable::FactoryType>("DynamicTableFactory");
+               if (auto table = (*factory)(); table != nullptr) {
+                       table->init();
+                       delete table;
+               } else {
+                       ERROR(VIST) << "Failed to load table.";
+               }
+       }
+}
+
 } // namespace vist
index 818684a2ad48707ab9608fe117586faa95d8c41c..87c5162c2ae527b759102e5a0e12752a2e022bc4 100644 (file)
@@ -58,6 +58,9 @@ private:
        ~Vistd() = default;
 
        void start();
+
+       void loadStaticTable();
+       void loadDynamicTable();
 };
 
 } // namespace vist
index 77e5f5013e00c6f48a2642493fbfb4e9a64429b0..f05ce017251a04983a224c8143e1f49b4bd226c3 100644 (file)
@@ -12,6 +12,9 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License
 
-ADD_VIST_LIBRARY(vist_table bluetooth.cpp
-                                                       policy-admin.cpp
-                                                       policy.cpp)
+## static virtual table
+ADD_VIST_LIBRARY(vist_table policy/policy-admin.cpp
+                                                       policy/policy.cpp)
+
+## dynamic virtual table
+ADD_SUBDIRECTORY(policy/sample)
diff --git a/src/vist/table/bluetooth.cpp b/src/vist/table/bluetooth.cpp
deleted file mode 100644 (file)
index 25cf78f..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include "bluetooth.hpp"
-
-#include <vist/exception.hpp>
-#include <vist/json.hpp>
-#include <vist/logger.hpp>
-#include <vist/policy/api.hpp>
-
-#include <osquery/registry.h>
-#include <osquery/sql/dynamic_table_row.h>
-
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-namespace vist {
-namespace table {
-
-namespace {
-
-std::map<std::string, std::string> ALIAS = {
-       { "state", "bluetooth" },
-       { "desktopConnectivity", "bluetooth-desktop-connectivity" },
-       { "pairing", "bluetooth-pairing" },
-       { "tethering", "bluetooth-tethering"}
-};
-
-void setPolicy(const std::string& name, int value)
-{
-       vist::policy::API::Admin::Set(name, vist::policy::PolicyValue(value));
-}
-
-} // anonymous namespace
-
-void BluetoothTable::Init()
-{
-       auto tables = RegistryFactory::get().registry("table");
-       tables->add("bluetooth", std::make_shared<BluetoothTable>());
-}
-
-TableColumns BluetoothTable::columns() const
-{
-       return {
-               std::make_tuple("state", INTEGER_TYPE, ColumnOptions::DEFAULT),
-               std::make_tuple("desktopConnectivity", INTEGER_TYPE, ColumnOptions::DEFAULT),
-               std::make_tuple("pairing", INTEGER_TYPE, ColumnOptions::DEFAULT),
-               std::make_tuple("tethering", INTEGER_TYPE, ColumnOptions::DEFAULT),
-       };
-}
-
-TableRows BluetoothTable::generate(QueryContext&) try
-{
-       INFO(VIST) << "Select query about bluetooth table.";
-
-       QueryData results;
-
-       Row row;
-
-       for (const auto&[schemaName, policyName] : ALIAS) {
-               int value = vist::policy::API::Get(policyName);
-               row[schemaName] = std::to_string(value);
-       }
-
-       results.emplace_back(std::move(row));
-
-       return osquery::tableRowsFromQueryData(std::move(results));
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-}
-
-QueryData BluetoothTable::update(QueryContext&, const PluginRequest& request) try
-{
-       INFO(VIST) << "Update query about bluetooth table.";
-       if (request.count("json_values") == 0)
-               throw std::runtime_error("Wrong request format. Not found json value.");
-
-       DEBUG(VIST) << "Request values: " << request.at("json_values");
-       json::Json document = json::Json::Parse(request.at("json_values"));
-       json::Array values = document.get<json::Array>("values");
-       if (values.size() != 4)
-               throw std::runtime_error("Wrong request format.");
-
-       /// TODO(Sangwan): Sync vtab schema with policy definition
-       setPolicy("bluetooth", static_cast<int>(values.at(0)));
-       setPolicy("bluetooth-desktop-connectivity", static_cast<int>(values.at(1)));
-       setPolicy("bluetooth-pairing", static_cast<int>(values.at(2)));
-       setPolicy("bluetooth-tethering", static_cast<int>(values.at(3)));
-
-       Row r;
-       r["status"] = "success";
-       return { r };
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return { r };
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return { r };
-}
-
-} // namespace table
-} // namespace vist
diff --git a/src/vist/table/bluetooth.hpp b/src/vist/table/bluetooth.hpp
deleted file mode 100644 (file)
index 883468a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include <osquery/tables.h>
-
-namespace vist {
-namespace table {
-
-using namespace osquery;
-
-class BluetoothTable final : public TablePlugin {
-public:
-       static void Init();
-
-private:
-       TableColumns columns() const override;
-       TableRows generate(QueryContext&) override;
-       QueryData update(QueryContext&, const PluginRequest& request) override;
-};
-
-} // namespace table
-} // namespace vist
diff --git a/src/vist/table/dynamic-table.hpp b/src/vist/table/dynamic-table.hpp
new file mode 100644 (file)
index 0000000..b04de07
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <osquery/tables.h>
+
+namespace vist {
+namespace table {
+
+class DynamicTable : public osquery::TablePlugin {
+public:
+       using FactoryType = DynamicTable* (*)();
+
+       virtual void init() = 0;
+};
+
+} // namespace table
+} // namespace vist
diff --git a/src/vist/table/policy-admin.cpp b/src/vist/table/policy-admin.cpp
deleted file mode 100644 (file)
index 9edc0d0..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- *  Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include "policy-admin.hpp"
-
-#include <vist/exception.hpp>
-#include <vist/json.hpp>
-#include <vist/logger.hpp>
-#include <vist/policy/api.hpp>
-
-#include <osquery/registry.h>
-#include <osquery/sql/dynamic_table_row.h>
-
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-namespace vist {
-namespace table {
-
-namespace {
-
-std::string getValue(std::string&& alias, const std::string& key)
-{
-       auto pos = alias.find(";");
-       auto token = alias.substr(0, pos);
-
-       if (token == key)
-               return alias.erase(0, pos + 1);
-       else
-               return std::string();
-}
-
-std::string parseAdmin(const std::string& request, bool insert = true)
-{
-       json::Json document = json::Json::Parse(request);
-       json::Array values = document.get<json::Array>("values");
-
-       if (insert)
-               return values.at(0);
-       else
-               return getValue(values.at(0), "name");
-}
-
-} // anonymous namespace
-
-void PolicyAdminTable::Init()
-{
-       auto tables = RegistryFactory::get().registry("table");
-       tables->add("policy_admin", std::make_shared<PolicyAdminTable>());
-}
-
-TableColumns PolicyAdminTable::columns() const
-{
-       return {
-               std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
-               std::make_tuple("activated", INTEGER_TYPE, ColumnOptions::DEFAULT),
-       };
-}
-
-TableRows PolicyAdminTable::generate(QueryContext& context) try
-{
-       INFO(VIST) << "Select query about policy-admin table.";
-
-       QueryData results;
-       auto admins = vist::policy::API::Admin::GetAll();
-
-       for (auto& admin : admins) {
-               if (context.constraints["name"].exists(EQUALS)) { /// where clause
-                       auto names = context.constraints["name"].getAll(EQUALS);
-                       for (const auto& name : names) {
-                               if (name == admin.first) {
-                                       Row row;
-                                       row["name"] = admin.first;
-                                       row["activated"] = std::to_string(admin.second);
-
-                                       DEBUG(VIST) << "Admin info [name]: " << row["name"]
-                                                               << ", [activated]:" << row["activated"];
-
-                                       results.emplace_back(std::move(row));
-                               }
-                       }
-               } else { /// select *;
-                       Row row;
-                       row["name"] = admin.first;
-                       row["activated"] = std::to_string(admin.second);
-
-                       DEBUG(VIST) << "Admin info [name]: " << row["name"]
-                                               << ", [activated]:" << row["activated"];
-                       results.emplace_back(std::move(row));
-               }
-       }
-
-       return osquery::tableRowsFromQueryData(std::move(results));
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-}
-
-QueryData PolicyAdminTable::insert(QueryContext&, const PluginRequest& request) try
-{
-       INFO(VIST) << "Insert query about policy-admin table.";
-       if (request.count("json_values") == 0)
-               throw std::runtime_error("Wrong request format. Not found json value.");
-
-       DEBUG(VIST) << "Request values: " << request.at("json_values");
-       auto admin = parseAdmin(request.at("json_values"));
-       DEBUG(VIST) << "Admin info [name]: " << admin;
-       vist::policy::API::Admin::Enroll(admin);
-
-       Row r;
-       r["status"] = "success";
-       return { r };
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return { r };
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return { r };
-}
-
-QueryData PolicyAdminTable::delete_(QueryContext&, const PluginRequest& request) try
-{
-       INFO(VIST) << "Delete query about policy-admin table.";
-       if (request.count("json_values") == 0)
-               throw std::runtime_error("Wrong request format. Not found json value.");
-
-       DEBUG(VIST) << "Request values: " << request.at("json_values");
-       auto admin = parseAdmin(request.at("json_values"), false);
-       DEBUG(VIST) << "Admin info [name]: " << admin;
-       vist::policy::API::Admin::Disenroll(admin);
-
-       Row r;
-       r["status"] = "success";
-       return { r };
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return { r };
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return { r };
-}
-
-QueryData PolicyAdminTable::update(QueryContext&, const PluginRequest& request) try
-{
-       INFO(VIST) << "Update query about policy-admin table.";
-       if (request.count("json_values") == 0)
-               throw std::runtime_error("Wrong request format. Not found json value.");
-
-       DEBUG(VIST) << "Request values: " << request.at("json_values");
-       json::Json document = json::Json::Parse(request.at("json_values"));
-       json::Array values = document.get<json::Array>("values");
-       if (values.size() != 2)
-               throw std::runtime_error("Wrong request format.");
-
-       std::string name = static_cast<std::string>(values.at(0));
-       int activated = static_cast<int>(values.at(1));
-
-       vist::policy::API::Admin::Activate(name, activated);
-
-       Row r;
-       r["status"] = "success";
-       return { r };
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return { r };
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return { r };
-}
-
-} // namespace tables
-} // namespace osquery
diff --git a/src/vist/table/policy-admin.hpp b/src/vist/table/policy-admin.hpp
deleted file mode 100644 (file)
index d8a8a7e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include <osquery/tables.h>
-
-namespace vist {
-namespace table {
-
-using namespace osquery;
-
-class PolicyAdminTable final : public TablePlugin {
-public:
-       static void Init();
-
-private:
-       TableColumns columns() const override;
-       TableRows generate(QueryContext&) override;
-       QueryData delete_(QueryContext&, const PluginRequest& request) override;
-       QueryData insert(QueryContext&, const PluginRequest& request) override;
-       QueryData update(QueryContext&, const PluginRequest& request) override;
-};
-
-} // namespace table
-} // namespace vist
diff --git a/src/vist/table/policy.cpp b/src/vist/table/policy.cpp
deleted file mode 100644 (file)
index ca0060b..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include "policy.hpp"
-
-#include <vist/exception.hpp>
-#include <vist/json.hpp>
-#include <vist/logger.hpp>
-#include <vist/policy/api.hpp>
-
-#include <osquery/registry.h>
-#include <osquery/sql/dynamic_table_row.h>
-
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-namespace vist {
-namespace table {
-
-namespace {
-
-Row convert(const std::string& name, const vist::policy::PolicyValue& value)
-{
-       Row r;
-       r["name"] = name;
-       r["value"] = value.dump();
-
-       return r;
-}
-
-} // anonymous namespace
-
-void PolicyTable::Init()
-{
-       auto tables = RegistryFactory::get().registry("table");
-       tables->add("policy", std::make_shared<PolicyTable>());
-}
-
-TableColumns PolicyTable::columns() const
-{
-       return {
-               std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
-               std::make_tuple("value", TEXT_TYPE, ColumnOptions::DEFAULT),
-       };
-}
-
-TableRows PolicyTable::generate(QueryContext& context) try
-{
-       INFO(VIST) << "Select query about policy table.";
-
-       QueryData results;
-       if (context.constraints["name"].exists(EQUALS)) { /// where clause
-               auto names = context.constraints["name"].getAll(EQUALS);
-               for (const auto& name : names) {
-                       auto value = vist::policy::API::Get(name);
-                       auto row = convert(name, value);
-
-                       results.emplace_back(std::move(row));
-               }
-       } else { /// select *;
-               auto policies = vist::policy::API::GetAll();
-               for (auto& policy : policies) {
-                       auto row = convert(policy.first, policy.second);
-
-                       results.emplace_back(std::move(row));
-               }
-       }
-
-       return osquery::tableRowsFromQueryData(std::move(results));
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return osquery::tableRowsFromQueryData({ r });
-}
-
-QueryData PolicyTable::update(QueryContext&, const PluginRequest& request) try
-{
-       INFO(VIST) << "Update query about policy table.";
-       if (request.count("json_values") == 0)
-               throw std::runtime_error("Wrong request format. Not found json value.");
-
-       DEBUG(VIST) << "Request values: " << request.at("json_values");
-       json::Json document = json::Json::Parse(request.at("json_values"));
-       json::Array values = document.get<json::Array>("values");
-       if (values.size() != 2)
-               throw std::runtime_error("Wrong request format.");
-
-       std::string name = static_cast<std::string>(values.at(0));
-       std::string dumpedValue = static_cast<std::string>(values.at(1));
-
-       vist::policy::API::Admin::Set(name, vist::policy::PolicyValue(dumpedValue, true));
-
-       Row r;
-       r["status"] = "success";
-       return { r };
-} catch (const vist::Exception<ErrCode>& e)
-{
-       ERROR(VIST) << "Failed to query: " << e.what();
-       Row r;
-       return { r };
-} catch (...)
-{
-       ERROR(VIST) << "Failed to query with unknown exception.";
-       Row r;
-       return { r };
-}
-
-} // namespace table
-} // namespace vist
diff --git a/src/vist/table/policy.hpp b/src/vist/table/policy.hpp
deleted file mode 100644 (file)
index f96c473..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License
- */
-
-#include <osquery/tables.h>
-
-namespace vist {
-namespace table {
-
-using namespace osquery;
-
-class PolicyTable final : public TablePlugin {
-public:
-       static void Init();
-
-private:
-       TableColumns columns() const override;
-       TableRows generate(QueryContext&) override;
-       QueryData update(QueryContext&, const PluginRequest& request) override;
-};
-
-} // namespace table
-} // namespace vist
diff --git a/src/vist/table/policy/policy-admin.cpp b/src/vist/table/policy/policy-admin.cpp
new file mode 100644 (file)
index 0000000..9edc0d0
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include "policy-admin.hpp"
+
+#include <vist/exception.hpp>
+#include <vist/json.hpp>
+#include <vist/logger.hpp>
+#include <vist/policy/api.hpp>
+
+#include <osquery/registry.h>
+#include <osquery/sql/dynamic_table_row.h>
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+namespace vist {
+namespace table {
+
+namespace {
+
+std::string getValue(std::string&& alias, const std::string& key)
+{
+       auto pos = alias.find(";");
+       auto token = alias.substr(0, pos);
+
+       if (token == key)
+               return alias.erase(0, pos + 1);
+       else
+               return std::string();
+}
+
+std::string parseAdmin(const std::string& request, bool insert = true)
+{
+       json::Json document = json::Json::Parse(request);
+       json::Array values = document.get<json::Array>("values");
+
+       if (insert)
+               return values.at(0);
+       else
+               return getValue(values.at(0), "name");
+}
+
+} // anonymous namespace
+
+void PolicyAdminTable::Init()
+{
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("policy_admin", std::make_shared<PolicyAdminTable>());
+}
+
+TableColumns PolicyAdminTable::columns() const
+{
+       return {
+               std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
+               std::make_tuple("activated", INTEGER_TYPE, ColumnOptions::DEFAULT),
+       };
+}
+
+TableRows PolicyAdminTable::generate(QueryContext& context) try
+{
+       INFO(VIST) << "Select query about policy-admin table.";
+
+       QueryData results;
+       auto admins = vist::policy::API::Admin::GetAll();
+
+       for (auto& admin : admins) {
+               if (context.constraints["name"].exists(EQUALS)) { /// where clause
+                       auto names = context.constraints["name"].getAll(EQUALS);
+                       for (const auto& name : names) {
+                               if (name == admin.first) {
+                                       Row row;
+                                       row["name"] = admin.first;
+                                       row["activated"] = std::to_string(admin.second);
+
+                                       DEBUG(VIST) << "Admin info [name]: " << row["name"]
+                                                               << ", [activated]:" << row["activated"];
+
+                                       results.emplace_back(std::move(row));
+                               }
+                       }
+               } else { /// select *;
+                       Row row;
+                       row["name"] = admin.first;
+                       row["activated"] = std::to_string(admin.second);
+
+                       DEBUG(VIST) << "Admin info [name]: " << row["name"]
+                                               << ", [activated]:" << row["activated"];
+                       results.emplace_back(std::move(row));
+               }
+       }
+
+       return osquery::tableRowsFromQueryData(std::move(results));
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+}
+
+QueryData PolicyAdminTable::insert(QueryContext&, const PluginRequest& request) try
+{
+       INFO(VIST) << "Insert query about policy-admin table.";
+       if (request.count("json_values") == 0)
+               throw std::runtime_error("Wrong request format. Not found json value.");
+
+       DEBUG(VIST) << "Request values: " << request.at("json_values");
+       auto admin = parseAdmin(request.at("json_values"));
+       DEBUG(VIST) << "Admin info [name]: " << admin;
+       vist::policy::API::Admin::Enroll(admin);
+
+       Row r;
+       r["status"] = "success";
+       return { r };
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return { r };
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return { r };
+}
+
+QueryData PolicyAdminTable::delete_(QueryContext&, const PluginRequest& request) try
+{
+       INFO(VIST) << "Delete query about policy-admin table.";
+       if (request.count("json_values") == 0)
+               throw std::runtime_error("Wrong request format. Not found json value.");
+
+       DEBUG(VIST) << "Request values: " << request.at("json_values");
+       auto admin = parseAdmin(request.at("json_values"), false);
+       DEBUG(VIST) << "Admin info [name]: " << admin;
+       vist::policy::API::Admin::Disenroll(admin);
+
+       Row r;
+       r["status"] = "success";
+       return { r };
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return { r };
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return { r };
+}
+
+QueryData PolicyAdminTable::update(QueryContext&, const PluginRequest& request) try
+{
+       INFO(VIST) << "Update query about policy-admin table.";
+       if (request.count("json_values") == 0)
+               throw std::runtime_error("Wrong request format. Not found json value.");
+
+       DEBUG(VIST) << "Request values: " << request.at("json_values");
+       json::Json document = json::Json::Parse(request.at("json_values"));
+       json::Array values = document.get<json::Array>("values");
+       if (values.size() != 2)
+               throw std::runtime_error("Wrong request format.");
+
+       std::string name = static_cast<std::string>(values.at(0));
+       int activated = static_cast<int>(values.at(1));
+
+       vist::policy::API::Admin::Activate(name, activated);
+
+       Row r;
+       r["status"] = "success";
+       return { r };
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return { r };
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return { r };
+}
+
+} // namespace tables
+} // namespace osquery
diff --git a/src/vist/table/policy/policy-admin.hpp b/src/vist/table/policy/policy-admin.hpp
new file mode 100644 (file)
index 0000000..d8a8a7e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <osquery/tables.h>
+
+namespace vist {
+namespace table {
+
+using namespace osquery;
+
+class PolicyAdminTable final : public TablePlugin {
+public:
+       static void Init();
+
+private:
+       TableColumns columns() const override;
+       TableRows generate(QueryContext&) override;
+       QueryData delete_(QueryContext&, const PluginRequest& request) override;
+       QueryData insert(QueryContext&, const PluginRequest& request) override;
+       QueryData update(QueryContext&, const PluginRequest& request) override;
+};
+
+} // namespace table
+} // namespace vist
diff --git a/src/vist/table/policy/policy.cpp b/src/vist/table/policy/policy.cpp
new file mode 100644 (file)
index 0000000..ca0060b
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include "policy.hpp"
+
+#include <vist/exception.hpp>
+#include <vist/json.hpp>
+#include <vist/logger.hpp>
+#include <vist/policy/api.hpp>
+
+#include <osquery/registry.h>
+#include <osquery/sql/dynamic_table_row.h>
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+namespace vist {
+namespace table {
+
+namespace {
+
+Row convert(const std::string& name, const vist::policy::PolicyValue& value)
+{
+       Row r;
+       r["name"] = name;
+       r["value"] = value.dump();
+
+       return r;
+}
+
+} // anonymous namespace
+
+void PolicyTable::Init()
+{
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("policy", std::make_shared<PolicyTable>());
+}
+
+TableColumns PolicyTable::columns() const
+{
+       return {
+               std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
+               std::make_tuple("value", TEXT_TYPE, ColumnOptions::DEFAULT),
+       };
+}
+
+TableRows PolicyTable::generate(QueryContext& context) try
+{
+       INFO(VIST) << "Select query about policy table.";
+
+       QueryData results;
+       if (context.constraints["name"].exists(EQUALS)) { /// where clause
+               auto names = context.constraints["name"].getAll(EQUALS);
+               for (const auto& name : names) {
+                       auto value = vist::policy::API::Get(name);
+                       auto row = convert(name, value);
+
+                       results.emplace_back(std::move(row));
+               }
+       } else { /// select *;
+               auto policies = vist::policy::API::GetAll();
+               for (auto& policy : policies) {
+                       auto row = convert(policy.first, policy.second);
+
+                       results.emplace_back(std::move(row));
+               }
+       }
+
+       return osquery::tableRowsFromQueryData(std::move(results));
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+}
+
+QueryData PolicyTable::update(QueryContext&, const PluginRequest& request) try
+{
+       INFO(VIST) << "Update query about policy table.";
+       if (request.count("json_values") == 0)
+               throw std::runtime_error("Wrong request format. Not found json value.");
+
+       DEBUG(VIST) << "Request values: " << request.at("json_values");
+       json::Json document = json::Json::Parse(request.at("json_values"));
+       json::Array values = document.get<json::Array>("values");
+       if (values.size() != 2)
+               throw std::runtime_error("Wrong request format.");
+
+       std::string name = static_cast<std::string>(values.at(0));
+       std::string dumpedValue = static_cast<std::string>(values.at(1));
+
+       vist::policy::API::Admin::Set(name, vist::policy::PolicyValue(dumpedValue, true));
+
+       Row r;
+       r["status"] = "success";
+       return { r };
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return { r };
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return { r };
+}
+
+} // namespace table
+} // namespace vist
diff --git a/src/vist/table/policy/policy.hpp b/src/vist/table/policy/policy.hpp
new file mode 100644 (file)
index 0000000..f96c473
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <osquery/tables.h>
+
+namespace vist {
+namespace table {
+
+using namespace osquery;
+
+class PolicyTable final : public TablePlugin {
+public:
+       static void Init();
+
+private:
+       TableColumns columns() const override;
+       TableRows generate(QueryContext&) override;
+       QueryData update(QueryContext&, const PluginRequest& request) override;
+};
+
+} // namespace table
+} // namespace vist
diff --git a/src/vist/table/policy/sample/CMakeLists.txt b/src/vist/table/policy/sample/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d97eea6
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SET(TARGET "vist-plugin-sample")
+
+INCLUDE_DIRECTORIES(SYSTEM)
+
+ADD_LIBRARY(${TARGET} SHARED sample.cpp)
+TARGET_LINK_LIBRARIES(${TARGET} vist-common ${TARGET_VIST_POLICY_LIB})
+
+INSTALL(TARGETS ${TARGET} DESTINATION ${TABLE_INSTALL_DIR})
diff --git a/src/vist/table/policy/sample/sample.cpp b/src/vist/table/policy/sample/sample.cpp
new file mode 100644 (file)
index 0000000..f5d02a2
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (c) 2019-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include "sample.hpp"
+
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-value.hpp>
+#include <vist/sdk/policy-provider.hpp>
+
+#include <vist/logger.hpp>
+#include <vist/policy/api.hpp>
+
+#include <osquery/registry.h>
+#include <osquery/sql/dynamic_table_row.h>
+
+extern "C" vist::table::DynamicTable* DynamicTableFactory()
+{
+       return new vist::table::SamplePolicyTable;
+}
+
+namespace vist {
+namespace table {
+
+using namespace osquery;
+
+void SamplePolicyTable::init()
+{
+       // Register virtual table to sqlite3
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("sample_policy", std::make_shared<SamplePolicyTable>());
+
+       // Register policy to policy-manager
+       auto provider = std::make_shared<policy::Sample>("sample-provider");
+       provider->add(std::make_shared<policy::SampleIntPolicy>());
+       provider->add(std::make_shared<policy::SampleStrPolicy>());
+
+       policy::API::Admin::AddProvider(std::move(provider));
+
+       INFO(VIST_PLUGIN) << "Sample plugin loaded.";
+}
+
+TableColumns SamplePolicyTable::columns() const
+{
+       return {
+               std::make_tuple("sample_int_policy", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               std::make_tuple("sample_str_policy", TEXT_TYPE, ColumnOptions::DEFAULT),
+       };
+}
+
+TableRows SamplePolicyTable::generate(QueryContext&) try
+{
+       INFO(VIST) << "Select query about sample-policy table.";
+
+       Row row;
+       int intPolicy = vist::policy::API::Get("sample_int_policy");
+       row["sample_int_policy"] = std::to_string(intPolicy);
+
+       std::string strPolicy = vist::policy::API::Get("sample_str_policy");
+       row["sample_str_policy"] = strPolicy;
+
+       QueryData results;
+       results.emplace_back(std::move(row));
+
+       return osquery::tableRowsFromQueryData(std::move(results));
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return osquery::tableRowsFromQueryData({ r });
+}
+
+QueryData SamplePolicyTable::update(QueryContext&, const PluginRequest& request) try
+{
+       INFO(VIST) << "Update query about sample-policy table.";
+       if (request.count("json_values") == 0)
+               throw std::runtime_error("Wrong request format. Not found json value.");
+
+       DEBUG(VIST) << "Request values: " << request.at("json_values");
+       json::Json document = json::Json::Parse(request.at("json_values"));
+       json::Array values = document.get<json::Array>("values");
+       if (values.size() != 2)
+               throw std::runtime_error("Wrong request format.");
+
+       policy::API::Admin::Set("sample_int_policy",
+                       policy::PolicyValue(static_cast<int>(values.at(0))));
+       policy::API::Admin::Set("sample_str_policy",
+                       policy::PolicyValue(static_cast<std::string>(values.at(1))));
+
+       Row r;
+       r["status"] = "success";
+       return { r };
+} catch (const vist::Exception<ErrCode>& e)
+{
+       ERROR(VIST) << "Failed to query: " << e.what();
+       Row r;
+       return { r };
+} catch (...)
+{
+       ERROR(VIST) << "Failed to query with unknown exception.";
+       Row r;
+       return { r };
+}
+
+} // namespace table
+} // namespace vist
diff --git a/src/vist/table/policy/sample/sample.hpp b/src/vist/table/policy/sample/sample.hpp
new file mode 100644 (file)
index 0000000..3b241f5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  Copyright (c) 2020-present Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * Query example
+ * - SELECT * FROM sample_policy
+ * - UPDATE sample_policy SET sample_int_policy = 99
+ * - UPDATE sample_policy SET sample_str_policy = 'TEST_VALUE'
+ */
+
+#include <vist/logger.hpp>
+#include <vist/table/dynamic-table.hpp>
+
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-value.hpp>
+
+#include <osquery/tables.h>
+
+#include <memory>
+#include <string>
+
+namespace vist {
+namespace policy {
+
+class SampleIntPolicy : public PolicyModel {
+public:
+       SampleIntPolicy() : PolicyModel("sample_int_policy", PolicyValue(7))
+       {
+       }
+
+       void onChanged(const PolicyValue& value) override
+       {
+               INFO(VIST_PLUGIN) << "sample_int_policy is changed to "
+                                                 << static_cast<int>(value);
+       }
+};
+
+class SampleStrPolicy : public PolicyModel {
+public:
+       SampleStrPolicy() : PolicyModel("sample_str_policy", PolicyValue("TEST"))
+       {
+       }
+
+       void onChanged(const PolicyValue& value) override
+       {
+               INFO(VIST_PLUGIN) << "sample_str_policy is changed to "
+                                                 << static_cast<std::string>(value);
+       }
+
+       int compare(const PolicyValue& lhs, const PolicyValue& rhs) const override
+       {
+               std::string lvalue = lhs;
+               std::string rvalue = rhs;
+
+               INFO(VIST_PLUGIN) << "Custom compare method is called with [" << lvalue
+                                                 << "], [" << rvalue << "]";
+
+               return lvalue.compare(rvalue);
+       }
+};
+
+class Sample : public PolicyProvider {
+public:
+       Sample(const std::string& name) : PolicyProvider(name)
+       {
+       }
+
+       ~Sample()
+       {
+       }
+};
+} // namespace policy
+
+namespace table {
+
+using namespace osquery;
+
+class SamplePolicyTable final : public DynamicTable {
+public:
+       void init();
+
+private:
+       TableColumns columns() const override;
+       TableRows generate(QueryContext&) override;
+       QueryData update(QueryContext&, const PluginRequest& request) override;
+};
+
+} // namespace table
+} // namespace vist