Refine vist-policy database schema
authorSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 1 Nov 2019 07:20:07 +0000 (16:20 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Fri, 8 Nov 2019 05:39:18 +0000 (14:39 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
data/script/create-schema.sql
src/vist/policy/core/db-schema.h
src/vist/policy/core/policy-storage.cpp
src/vist/policy/core/policy-storage.h

index 3266cc8b335053e94f781c2c385a9cbaa8ae63d5..2f2f6ef156c60e9a51cb9b91e84a31b28339950b 100644 (file)
  *  limitations under the License
  */
 
-CREATE TABLE IF NOT EXISTS admin (
-    id        INTEGER PRIMARY KEY AUTOINCREMENT,
-    pkg       TEXT NOT NULL,
-    key       TEXT,
-    removable INTEGER
+CREATE TABLE IF NOT EXISTS ADMIN (
+       name TEXT NOT NULL,
+
+       PRIMARY KEY(name)
 );
 
-CREATE TABLE IF NOT EXISTS managed_policy (
-    id        INTEGER PRIMARY KEY AUTOINCREMENT,
-    aid       INTEGER,
-    pid       INTEGER,
-    value     INTEGER 
+CREATE TABLE IF NOT EXISTS POLICY_DEFINITION (
+       name TEXT NOT NULL,
+       ivalue INTEGER NOT NULL,
+
+       PRIMARY KEY(name)
 );
 
-CREATE TABLE IF NOT EXISTS policy_definition (
-    id        INTEGER PRIMARY KEY AUTOINCREMENT,
-    name      TEXT NOT NULL,
-    ivalue    INTEGER
+CREATE TABLE IF NOT EXISTS POLICY_ACTIVATED (
+       admin TEXT NOT NULL,
+       policy TEXT NOT NULL,
+       value INTEGER NOT NULL,
+
+       PRIMARY KEY(admin, policy),
+       FOREIGN KEY(admin) REFERENCES ADMIN(name),
+       FOREIGN KEY(policy) REFERENCES POLICY_DEFINITION(name)
 );
 
-CREATE TRIGGER IF NOT EXISTS prepare_storage AFTER INSERT ON admin
+CREATE TRIGGER IF NOT EXISTS ACTIVATE AFTER INSERT ON ADMIN
 FOR EACH ROW
 BEGIN
-       INSERT INTO managed_policy(aid, pid, value)
-               SELECT NEW.ID, policy_definition.id, policy_definition.ivalue
-               FROM policy_definition;
+       INSERT INTO POLICY_ACTIVATED(admin, policy, value)
+               SELECT NEW.name, POLICY_DEFINITION.name, POLICY_DEFINITION.ivalue
+               FROM POLICY_DEFINITION;
 END;
 
-CREATE TRIGGER IF NOT EXISTS remove_storage AFTER DELETE ON admin
+CREATE TRIGGER IF NOT EXISTS DEACTIVATE AFTER DELETE ON ADMIN
 FOR EACH ROW
 BEGIN
-       DELETE FROM managed_policy WHERE managed_policy.aid = OLD.ID;
+       DELETE FROM POLICY_ACTIVATED WHERE POLICY_ACTIVATED.admin = OLD.name;
 END;
index 6d41ccd42ae826f0b7c3633ed7d3445f8097f495..159dc568541c61df7ad052731ae797ae1110905d 100644 (file)
@@ -22,21 +22,16 @@ namespace policy {
 namespace schema {
 
 struct Admin {
-       int id = -1;
-       std::string pkg;
-       std::string key;
-       int removable = -1;
+       std::string name;
 };
 
-struct ManagedPolicy {
-       int id = -1;
-       int aid = -1;
-       int pid = -1;
+struct PolicyActivated {
+       std::string admin;
+       std::string policy;
        int value = -1;
 };
 
 struct PolicyDefinition {
-       int id = -1;
        std::string name;
        int ivalue = -1;
 };
index c8668a07faea45fdd70c398042a0815c52f432ca..4a1e3412833b593d48d45cd31177e47216612798 100644 (file)
 #include <klay/exception.h>
 
 #include <fstream>
+#include <algorithm>
 
 using namespace query_builder;
 using namespace vist::policy::schema;
 
 namespace {
 
-auto adminTable = make_table("admin",
-                                                        make_column("id", &Admin::id),
-                                                        make_column("pkg", &Admin::pkg),
-                                                        make_column("key", &Admin::key),
-                                                        make_column("removable", &Admin::removable));
+auto adminTable = make_table("ADMIN", make_column("name", &Admin::name));
 
-auto managedPolTable = make_table("managed_policy",
-                                                                 make_column("id", &ManagedPolicy::id),
-                                                                 make_column("aid", &ManagedPolicy::aid),
-                                                                 make_column("pid", &ManagedPolicy::pid),
-                                                                 make_column("value", &ManagedPolicy::value));
+auto polActivatedTable = make_table("POLICY_ACTIVATED",
+                                                                       make_column("admin", &PolicyActivated::admin),
+                                                                       make_column("policy", &PolicyActivated::policy),
+                                                                       make_column("value", &PolicyActivated::value));
 
-auto definitionTable = make_table("policy_definition",
-                                                                 make_column("id", &PolicyDefinition::id),
-                                                                 make_column("name", &PolicyDefinition::name),
-                                                                 make_column("ivalue", &PolicyDefinition::ivalue));
+auto polDefinitionTable = make_table("POLICY_DEFINITION",
+                                                                        make_column("name", &PolicyDefinition::name),
+                                                                        make_column("ivalue", &PolicyDefinition::ivalue));
 
 const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR;
 const std::string SCRIPT_CREATE_SCHEMA  = "create-schema";
@@ -69,25 +64,26 @@ PolicyStorage::PolicyStorage(const std::string& path) :
 void PolicyStorage::sync()
 {
        DEBUG(VIST, "Sync policy storage to cache object.");
-       syncPolicyDefinition();
        syncAdmin();
-       syncManagedPolicy();
+       syncPolicyActivated();
+       syncPolicyDefinition();
 }
 
 void PolicyStorage::syncPolicyDefinition()
 {
        this->definitions.clear();
-       std::string query = definitionTable.selectAll();
+       std::string query = polDefinitionTable.selectAll();
        database::Statement stmt(*database, query);
 
        while (stmt.step()) {
                PolicyDefinition pd;
-               pd.id = stmt.getColumn(0);
-               pd.name = std::string(stmt.getColumn(1));
-               pd.ivalue = stmt.getColumn(2);
+               pd.name = std::string(stmt.getColumn(0));
+               pd.ivalue = stmt.getColumn(1);
                DEBUG(VIST, "Defined policy:" + pd.name);
                this->definitions.emplace(pd.name, std::move(pd));
        }
+
+       DEBUG(VIST, definitions.size() << "- policies synced.");
 }
 
 void PolicyStorage::syncAdmin()
@@ -96,31 +92,27 @@ void PolicyStorage::syncAdmin()
        std::string query = adminTable.selectAll();
        database::Statement stmt(*database, query);
 
-       while (stmt.step()) {
-               Admin admin;
-               admin.id = stmt.getColumn(0);
-               admin.pkg = std::string(stmt.getColumn(1));
-               admin.key = std::string(stmt.getColumn(2));
-               admin.removable = stmt.getColumn(3);
+       while (stmt.step())
+               this->admins.emplace_back(std::string(stmt.getColumn(0)));
 
-               this->admins.emplace(admin.pkg, std::move(admin));
-       }
+       DEBUG(VIST, admins.size() << "-admins synced.");
 }
 
-void PolicyStorage::syncManagedPolicy()
+void PolicyStorage::syncPolicyActivated()
 {
-       this->managedPolicies.clear();
-       std::string query = managedPolTable.selectAll();
+       this->activatedPolicies.clear();
+       std::string query = polActivatedTable.selectAll();
        database::Statement stmt(*database, query);
 
        while (stmt.step()) {
-               ManagedPolicy mp;
-               mp.id = stmt.getColumn(0);
-               mp.aid = stmt.getColumn(1);
-               mp.pid = stmt.getColumn(2);
-               mp.value = stmt.getColumn(3);
-               this->managedPolicies.emplace(mp.pid, std::move(mp));
+               PolicyActivated pa;
+               pa.admin = std::string(stmt.getColumn(0));
+               pa.policy = std::string(stmt.getColumn(1));
+               pa.value = stmt.getColumn(2);
+               this->activatedPolicies.emplace(pa.policy, std::move(pa));
        }
+
+       DEBUG(VIST, activatedPolicies.size() << "- activated-policies synced.");
 }
 
 std::string PolicyStorage::getScript(const std::string& name)
@@ -149,9 +141,9 @@ void PolicyStorage::define(const std::string& policy, int ivalue)
        pd.name = policy;
        pd.ivalue = ivalue;
 
-       std::string insertQuery = definitionTable.insert(&PolicyDefinition::name,
-                                                                                                        &PolicyDefinition::ivalue);
-       database::Statement stmt(*database, insertQuery);
+       std::string query = polDefinitionTable.insert(&PolicyDefinition::name,
+                                                                                                 &PolicyDefinition::ivalue);
+       database::Statement stmt(*database, query);
        stmt.bind(1, pd.name);
        stmt.bind(2, pd.ivalue);
        if (!stmt.exec())
@@ -161,46 +153,38 @@ void PolicyStorage::define(const std::string& policy, int ivalue)
 void PolicyStorage::enroll(const std::string& name)
 {
        INFO(VIST, "Enroll admin: " + name);
-       if (admins.find(name) != admins.end()) {
+       if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
                ERROR(VIST, "Admin is aleady enrolled.: " + name);
                return;
        }
 
-       Admin admin;
-       admin.pkg = name;
-       admin.key = "Not supported";
-       admin.removable = true;
-
-       std::string insertQuery = adminTable.insert(&Admin::pkg,
-                                                                                               &Admin::key,
-                                                                                               &Admin::removable);
-       database::Statement stmt(*database, insertQuery);
-       stmt.bind(1, admin.pkg);
-       stmt.bind(2, admin.key);
-       stmt.bind(3, admin.removable);
+       std::string query = adminTable.insert(&Admin::name);
+       DEBUG(VIST, "Enroll admin query statement: " + query);
+       database::Statement stmt(*database, query);
+       stmt.bind(1, name);
        if (!stmt.exec())
-               throw std::runtime_error("Failed to enroll admin: " + admin.pkg);
+               throw std::runtime_error("Failed to enroll admin: " + name);
 
-       /// Sync admin for getting admin ID.
-       syncAdmin();
-       /// ManagedPolicy is triggered by enrolling admin.
-       syncManagedPolicy();
+       admins.push_back(name);
+       /// PolicyActivated is triggered by enrolling admin.
+       syncPolicyActivated();
 
-       int count = managedPolicies.size() / admins.size();
+       int count = activatedPolicies.size() / admins.size();
        INFO(VIST, "Admin[" + name + "] manages " + std::to_string(count) + "-policies.");
 }
 
 void PolicyStorage::disenroll(const std::string& name)
 {
        INFO(VIST, "Disenroll admin: " + name);
-       if (admins.find(name) == admins.end()) {
+       auto iter = std::find(admins.begin(), admins.end(), name);
+       if (iter == admins.end()) {
                ERROR(VIST, "Not exist admin: " + name);
                return;
        } else {
-               admins.erase(name);
+               admins.erase(iter);
        }
 
-       std::string query = adminTable.remove().where(expr(&Admin::pkg) == name);
+       std::string query = adminTable.remove().where(expr(&Admin::name) == name);
        database::Statement stmt(*database, query);
        stmt.bind(1, name);
        if (!stmt.exec())
@@ -211,29 +195,27 @@ void PolicyStorage::update(const std::string& admin,
                                                   const std::string& policy,
                                                   const PolicyValue& value)
 {
-       if (admins.find(admin) == admins.end())
+       DEBUG(VIST, "Policy-update is called by admin: " + admin + ", about: " + policy +
+                               ", value: " + std::to_string(value));
+
+       if (std::find(admins.begin(), admins.end(), admin) == admins.end())
                throw std::runtime_error("Not exist admin: " + admin);
 
        if (definitions.find(policy) == definitions.end())
                throw std::runtime_error("Not exist policy: " + policy);
 
-       DEBUG(VIST, "Policy-update is called by admin: " + admin + ", about: " + policy +
-                               ", value: " + std::to_string(value));
-
-       int policyId = definitions[policy].id;
        int policyValue = value;
-       int adminId = admins[admin].id;
-       std::string query = managedPolTable.update(&ManagedPolicy::value)
-                                                                          .where(expr(&ManagedPolicy::pid) == policyId &&
-                                                                                         expr(&ManagedPolicy::aid) == adminId);
+       std::string query = polActivatedTable.update(&PolicyActivated::value)
+                                                                          .where(expr(&PolicyActivated::admin) == admin &&
+                                                                                         expr(&PolicyActivated::policy) == policy);
        database::Statement stmt(*database, query);
        stmt.bind(1, policyValue);
-       stmt.bind(2, policyId);
-       stmt.bind(3, adminId);
+       stmt.bind(2, admin);
+       stmt.bind(3, policy);
        if (!stmt.exec())
                throw runtime::Exception("Failed to update policy:" + policy);
 
-       syncManagedPolicy();
+       syncPolicyActivated();
 }
 
 PolicyValue PolicyStorage::strictest(const std::string& policy)
@@ -242,12 +224,11 @@ PolicyValue PolicyStorage::strictest(const std::string& policy)
                throw std::runtime_error("Not exist policy: " + policy);
 
        // There is no enrolled admins.
-       if (managedPolicies.size() == 0)
+       if (activatedPolicies.size() == 0)
                return PolicyValue(definitions[policy].ivalue);
 
        std::shared_ptr<PolicyValue> strictestPtr = nullptr;
-       int policyId = definitions[policy].id;
-       auto range = managedPolicies.equal_range(policyId);
+       auto range = activatedPolicies.equal_range(policy);
        for (auto iter = range.first; iter != range.second; iter++) {
                int value = iter->second.value;
                if (strictestPtr == nullptr)
@@ -278,14 +259,8 @@ std::unordered_map<std::string, PolicyValue> PolicyStorage::strictest()
        return policies;
 }
 
-std::vector<std::string> PolicyStorage::getAdmins()
+const std::vector<std::string>& PolicyStorage::getAdmins() const noexcept
 {
-       std::vector<std::string> admins;
-       for (const auto& pair : this->admins) {
-               std::string name = pair.first;
-               admins.emplace_back(std::move(name));
-       }
-
        return admins;
 }
 
index a725f4136622c2ec07ba7d38af82c35bf393eede..b26df61eb325ad816d1e7cf27adb0616b76d1ff8 100644 (file)
@@ -38,9 +38,9 @@ public:
        /// TODO(Sangwan): Consider to support lazy sync
        void sync();
 
-       void syncPolicyDefinition();
        void syncAdmin();
-       void syncManagedPolicy();
+       void syncPolicyActivated();
+       void syncPolicyDefinition();
 
        inline bool exists(const std::string& policy) const noexcept
        {
@@ -49,7 +49,7 @@ public:
 
        inline bool isActivated() const noexcept
        {
-               return admins.size() > 0 && managedPolicies.size() > 0;
+               return admins.size() > 0 && activatedPolicies.size() > 0;
        }
 
        void enroll(const std::string& admin);
@@ -64,7 +64,7 @@ public:
        /// Return all strictest policy values
        std::unordered_map<std::string, PolicyValue> strictest();
 
-       std::vector<std::string> getAdmins();
+       const std::vector<std::string>& getAdmins() const noexcept;
 
 private:
        std::string getScript(const std::string& name);
@@ -73,9 +73,9 @@ private:
 
        /// DB Cache objects
        /// TODO(Sangwan): add locking mechanism
+       std::vector<std::string> admins;
+       std::unordered_map<std::string, PolicyActivated> activatedPolicies;
        std::unordered_map<std::string, PolicyDefinition> definitions;
-       std::unordered_map<std::string, Admin> admins;
-       std::unordered_map<int, ManagedPolicy> managedPolicies;
 };
 
 } // namespace policy