Following queries are possible.
- SELECT * FROM policy_admin
- INSERT INTO policy_admin (name, uid) VALUES ('admin', 0)
- DELETE FROM policy_admin WHERE name = 'admin' AND uid = 0
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
--- /dev/null
+table_name("policy_admin")
+description("Policy administrator.")
+schema([
+ Column("name", TEXT, "Policy admin name"),
+ Column("uid", INTEGER, "Policy admin uid"),
+])
+implementation("tizen/policy_admin@genPolicyAdmin")
+implementation_delete("tizen/policy_admin@deletePolicyAdmin")
+implementation_insert("tizen/policy_admin@insertPolicyAdmin")
SET(TARGET_VIST_LIB vist)
ADD_SUBDIRECTORY(osquery)
-ADD_SUBDIRECTORY(vist)
IF(DEFINED GBS_BUILD)
+ ADD_SUBDIRECTORY(vist)
ADD_SUBDIRECTORY(policyd)
ENDIF(DEFINED GBS_BUILD)
--- /dev/null
+/*
+ * 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
+ */
+
+#include <string>
+#include <memory>
+#include <stdexcept>
+
+#include <osquery/sql.h>
+#include <osquery/tables.h>
+
+#include <policyd/api.h>
+#include <vist/common/audit/logger.h>
+
+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::pair<std::string, int> parseAdmin(const std::string& request, bool insert = true)
+{
+ rapidjson::Document document;
+ document.Parse(request.c_str());
+ if (document.HasParseError() || !document.IsArray())
+ throw std::runtime_error("Cannot parse request.");
+
+ if (document.Size() != 2)
+ throw std::runtime_error("Wrong request format.");
+
+ if (insert) {
+ return std::make_pair(document[0].GetString(), document[1].GetInt());
+ } else { /// osquery transforms int to string in 'where clause' internally.
+ std::string name, uid;
+ std::string value = getValue(document[0].GetString(), "name");
+ if (!value.empty()) {
+ name = value;
+ uid = getValue(document[1].GetString(), "uid");
+ } else {
+ name = getValue(document[1].GetString(), "name");
+ uid = getValue(document[0].GetString(), "uid");
+ }
+
+ return std::make_pair(name, std::stoi(uid));
+ }
+}
+
+} // anonymous namespace
+
+namespace osquery {
+namespace tables {
+
+QueryData genPolicyAdmin(QueryContext& context) try {
+ INFO(VIST, "Select query about policy-admin.");
+
+ QueryData results;
+ auto admins = policyd::API::Admin::GetAll();
+
+ for (auto& admin : admins) {
+ Row r;
+ r["name"] = SQL_TEXT(admin.first);
+ r["uid"] = INTEGER(admin.second);
+
+ DEBUG(VIST, "Admin info [name]: " << r["name"] << ", [uid]: " << r["uid"]);
+ results.emplace_back(std::move(r));
+ }
+
+ return results;
+} catch (...) {
+ ERROR(VIST, "Failed to select query on policy-admin.");
+ Row r;
+ return { r };
+}
+
+QueryData insertPolicyAdmin(QueryContext& context, const PluginRequest& request) try {
+ INFO(VIST, "Insert query about policy-admin.");
+ if (request.count("json_value_array") == 0)
+ throw std::runtime_error("Wrong request format. Not found json value.");
+
+ auto admin = parseAdmin(request.at("json_value_array"));
+ DEBUG(VIST, "Admin info [name]: " << admin.first << ", [uid]: " << admin.second);
+ policyd::API::Admin::Enroll(admin.first, admin.second);
+
+ Row r;
+ r["status"] = "success";
+ return { r };
+} catch (...) {
+ ERROR(VIST, "Failed to insert query on policy-admin.");
+ Row r;
+ return { r };
+}
+
+QueryData deletePolicyAdmin(QueryContext& context, const PluginRequest& request) try {
+ INFO(VIST, "Delete query about policy-admin.");
+ if (request.count("json_value_array") == 0)
+ throw std::runtime_error("Wrong request format. Not found json value.");
+
+ auto admin = parseAdmin(request.at("json_value_array"), false);
+ DEBUG(VIST, "Admin info [name]: " << admin.first << ", [uid]: " << admin.second);
+ policyd::API::Admin::Disenroll(admin.first, admin.second);
+
+ Row r;
+ r["status"] = "success";
+ return { r };
+} catch (...) {
+ ERROR(VIST, "Failed to delete query on policy-admin.");
+ Row r;
+ return { r };
+}
+
+} // namespace tables
+} // namespace osquery
EXPECT_TRUE(policies.size() > 0);
}
+
+TEST_F(PolicyTests, get_admin_all) {
+ auto admins = policyd::API::Admin::GetAll();
+ EXPECT_EQ(admins.size(), 0);
+
+ policyd::API::Admin::Enroll("testAdmin", 0);
+ admins = policyd::API::Admin::GetAll();
+ EXPECT_EQ(admins.size(), 1);
+
+ policyd::API::Admin::Enroll("testAdmin", 1);
+ admins = policyd::API::Admin::GetAll();
+ EXPECT_EQ(admins.size(), 2);
+
+ policyd::API::Admin::Disenroll("testAdmin", 0);
+ admins = policyd::API::Admin::GetAll();
+ EXPECT_EQ(admins.size(), 1);
+
+ policyd::API::Admin::Disenroll("testAdmin", 1);
+ admins = policyd::API::Admin::GetAll();
+ EXPECT_EQ(admins.size(), 0);
+}
#include <policyd/sdk/policy-value.h>
#include <string>
+#include <map>
#include <unordered_map>
namespace policyd {
static void Enroll(const std::string& admin, uid_t uid);
static void Disenroll(const std::string& admin, uid_t uid);
+
+ static std::multimap<std::string, int> GetAll();
};
};
PolicyManager::Instance().disenroll(admin, uid);
}
+std::multimap<std::string, int> API::Admin::GetAll()
+{
+ return PolicyManager::Instance().getAdmins();
+}
+
} // namespace policyd
return storage.strictest(uid);
}
+std::multimap<std::string, int> PolicyManager::getAdmins()
+{
+ return storage.getAdmins();
+}
+
} // namespace policyd
#include "policy-storage.h"
#include <exception>
+#include <map>
#include <memory>
#include <string>
#include <unordered_map>
void set(const std::string& policy, const PolicyValue& value,
const std::string& admin, uid_t uid = 0);
PolicyValue get(const std::string& policy, uid_t uid = 0);
-
std::unordered_map<std::string, PolicyValue> getAll(uid_t uid = 0);
+ std::multimap<std::string, int> getAdmins();
+
private:
explicit PolicyManager();
~PolicyManager() = default;
return policies;
}
+std::multimap<std::string, int> PolicyStorage::getAdmins()
+{
+ std::multimap<std::string, int> admins;
+ for (const auto& pair : this->admins) {
+ std::string alias = pair.first;
+ int uid = pair.second.uid;
+ /// Erase uid from alias(name + uid)
+ std::size_t pos = alias.rfind(std::to_string(uid));
+ alias.erase(pos, std::to_string(uid).size());
+
+ admins.emplace(std::move(alias), uid);
+ }
+
+ return admins;
+}
+
std::string PolicyStorage::getAlias(const std::string& name, uid_t uid) const noexcept
{
return name + std::to_string(uid);
#include "db-schema.h"
+#include <map>
#include <memory>
-#include <vector>
#include <unordered_map>
+#include <vector>
#include <klay/db/connection.h>
/// Return all strictest policy values
std::unordered_map<std::string, PolicyValue> strictest(uid_t uid = 0);
+ /// Admin name can be duplicated
+ std::multimap<std::string, int> getAdmins();
+
private:
std::string getScript(const std::string& name);
std::string getAlias(const std::string& name, uid_t uid) const noexcept;
storage->disenroll("testAdmin", 1);
}
+
+TEST_F(PolicyStorageTests, admin_list) {
+ auto storage = getStorage();
+
+ auto admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 0);
+
+ storage->enroll("testAdmin", 1);
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 1);
+
+ storage->enroll("testAdmin", 2);
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 2);
+
+ storage->disenroll("testAdmin", 2);
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 1);
+
+ storage->disenroll("testAdmin", 1);
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 0);
+}
EXPECT_TRUE(rows.size() > 0);
}
+
+TEST_F(ClientTests, admin_enrollment) {
+ auto rows = Query::Execute("INSERT INTO policy_admin (name, uid) "
+ "VALUES ('testAdmin', 0)");
+ EXPECT_EQ(rows.size(), 0);
+
+ rows = Query::Execute("SELECT * FROM policy_admin");
+ EXPECT_EQ(rows.size(), 1);
+
+ Query::Execute("INSERT INTO policy_admin (name, uid) VALUES ('testAdmin', 1)");
+ rows = Query::Execute("SELECT * FROM policy_admin");
+ EXPECT_EQ(rows.size(), 2);
+
+ rows = Query::Execute("DELETE FROM policy_admin WHERE uid = 0 AND name = 'testAdmin'");
+ EXPECT_EQ(rows.size(), 0);
+
+ rows = Query::Execute("SELECT * FROM policy_admin");
+ EXPECT_EQ(rows.size(), 1);
+
+ Query::Execute("DELETE FROM policy_admin WHERE name = 'testAdmin' AND uid = 1");
+ rows = Query::Execute("SELECT * FROM policy_admin");
+ EXPECT_EQ(rows.size(), 0);
+}