Enable to enroll policy admin
authorSangwan Kwon <sangwan.kwon@samsung.com>
Fri, 27 Sep 2019 07:54:58 +0000 (16:54 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Thu, 10 Oct 2019 06:26:21 +0000 (15:26 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/policyd/core/db-schema.h
src/policyd/core/policy-storage.cpp
src/policyd/core/policy-storage.h
src/policyd/core/tests/storage-tests.cpp

index 19bccf9a9962fc36a3fffbe8e7d10f5e9e2b0f99..98f7a3b0d5bd978122660c718cfb519fa5becd6e 100644 (file)
@@ -21,25 +21,25 @@ namespace policyd {
 namespace schema {
 
 struct Admin {
-       int id;
+       int id = -1;
        std::string pkg;
-       int uid;
+       int uid = -1;
        std::string key;
-       int removable;
+       int removable = -1;
 };
 
 struct ManagedPolicy {
-       int id;
-       int aid;
-       int pid;
-       int value;
+       int id = -1;
+       int aid = -1;
+       int pid = -1;
+       int value = -1;
 };
 
 struct PolicyDefinition {
-       int id;
-       int scope;
+       int id = -1;
+       int scope = -1;
        std::string name;
-       int ivalue;
+       int ivalue = -1;
 };
 
 } // namespace schema
index 3e86b157f10f3ce71564fa741e1a7f93ce574741..05abc3c63963edae303b11ea595f434cb5abcdfb 100644 (file)
@@ -27,27 +27,24 @@ using namespace policyd::schema;
 
 namespace {
 
-auto _admin = make_table("admin",
-                                                make_column("id", &Admin::id),
-                                                make_column("pkg", &Admin::pkg),
-                                                make_column("uid", &Admin::uid),
-                                                make_column("key", &Admin::key),
-                                                make_column("removable", &Admin::removable));
-
-auto _managedPolicy = 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 _policyDefinition = make_table("policy_definition",
-                                                                       make_column("id", &PolicyDefinition::id),
-                                                                       make_column("scope", &PolicyDefinition::scope),
-                                                                       make_column("name", &PolicyDefinition::name),
-                                                                       make_column("ivalue", &PolicyDefinition::ivalue));
-
-auto _dpm = make_database("dpm", _admin, _managedPolicy, _policyDefinition);
-
+auto adminTable = make_table("admin",
+                                                        make_column("id", &Admin::id),
+                                                        make_column("pkg", &Admin::pkg),
+                                                        make_column("uid", &Admin::uid),
+                                                        make_column("key", &Admin::key),
+                                                        make_column("removable", &Admin::removable));
+
+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 definitionTable = make_table("policy_definition",
+                                                                 make_column("id", &PolicyDefinition::id),
+                                                                 make_column("scope", &PolicyDefinition::scope),
+                                                                 make_column("name", &PolicyDefinition::name),
+                                                                 make_column("ivalue", &PolicyDefinition::ivalue));
 } // anonymous namespace
 
 namespace policyd {
@@ -70,7 +67,8 @@ void PolicyStorage::sync()
 
 void PolicyStorage::syncPolicyDefinition()
 {
-       std::string query = _policyDefinition.selectAll();
+       this->definitions.clear();
+       std::string query = definitionTable.selectAll();
        database::Statement stmt(*database, query);
 
        while (stmt.step()) {
@@ -79,14 +77,15 @@ void PolicyStorage::syncPolicyDefinition()
                pd.scope = stmt.getColumn(1);
                pd.name = std::string(stmt.getColumn(2));
                pd.ivalue = stmt.getColumn(3);
-               DEBUG(DPM, "Sync policy:" + pd.name);
+               DEBUG(DPM, "Defined policy:" + pd.name);
                this->definitions.emplace(pd.name, std::move(pd));
        }
 }
 
 void PolicyStorage::syncAdmin()
 {
-       std::string query = _admin.selectAll();
+       this->admins.clear();
+       std::string query = adminTable.selectAll();
        database::Statement stmt(*database, query);
 
        while (stmt.step()) {
@@ -96,13 +95,14 @@ void PolicyStorage::syncAdmin()
                admin.uid = stmt.getColumn(2);
                admin.key = std::string(stmt.getColumn(3));
                admin.removable = stmt.getColumn(4);
-               this->admins.emplace_back(std::move(admin));
+               this->admins.emplace(admin.pkg, std::move(admin));
        }
 }
 
 void PolicyStorage::syncManagedPolicy()
 {
-       std::string query = _managedPolicy.selectAll();
+       this->managedPolicies.clear();
+       std::string query = managedPolTable.selectAll();
        database::Statement stmt(*database, query);
 
        while (stmt.step()) {
@@ -115,4 +115,64 @@ void PolicyStorage::syncManagedPolicy()
        }
 }
 
+void PolicyStorage::enroll(const std::string& name, uid_t domain)
+{
+       int uid = static_cast<int>(domain);
+       std::string alias = getAlias(name, uid);
+       INFO(DPM, "Enroll admin: " + alias);
+       if (admins.find(alias) != admins.end()) {
+               ERROR(DPM, "Admin is aleady enrolled.: " + alias);
+               return;
+       } 
+
+       Admin admin;
+       admin.pkg = name;
+       admin.uid = uid;
+       admin.key = "Not supported";
+       admin.removable = true;
+
+       std::string insertQuery = adminTable.insert(&Admin::pkg, &Admin::uid,
+                                                                                               &Admin::key, &Admin::removable);
+       database::Statement stmt(*database, insertQuery);
+       stmt.bind(1, admin.pkg);
+       stmt.bind(2, admin.uid);
+       stmt.bind(3, admin.key);
+       stmt.bind(4, admin.removable);
+       if (!stmt.exec())
+               throw std::runtime_error("Failed to enroll admin.: " + admin.pkg);
+
+       this->admins.emplace(alias, std::move(admin));
+
+       syncManagedPolicy();
+       int count = managedPolicies.size() / admins.size();
+       INFO(DPM, "Admin[" + alias + "] manages " + std::to_string(count) + "policies.");
+}
+
+void PolicyStorage::disenroll(const std::string& name, uid_t domain)
+{
+       int uid = static_cast<int>(domain);
+       std::string alias = getAlias(name, uid);
+       INFO(DPM, "Disenroll admin: " + alias);
+       if (admins.find(alias) == admins.end()) {
+               ERROR(DPM, "Not exist admin.: " + alias);
+               return;
+       } else {
+               admins.erase(alias);
+       }
+
+       std::string query = adminTable.remove().where(expr(&Admin::pkg) == name &&
+                                                                                                 expr(&Admin::uid) == uid);
+       database::Statement stmt(*database, query);
+       stmt.bind(1, name);
+       stmt.bind(2, uid);
+       if (!stmt.exec())
+               throw std::runtime_error("Failed to disenroll admin.: " + name);
+}
+
+std::string PolicyStorage::getAlias(const std::string& name, uid_t uid) const noexcept
+{
+       return name + std::to_string(uid);
+}
+
+
 } // namespace policyd
index 62690612c970bad4461ca6f8130ba9cd6490b7da..49e4a377fd5359d6529c31e40d9f2fc1be07aa0d 100644 (file)
@@ -32,22 +32,32 @@ class PolicyStorage final {
 public:
        explicit PolicyStorage(const std::string& path);
 
+       /// TODO(Sangwan): Consider to support lazy sync
        void sync();
 
-       inline bool exists(const std::string& policy) noexcept {
+       inline bool exists(const std::string& policy) const noexcept {
                return definitions.find(policy) != definitions.end();
        }
 
+       inline bool isActivated() const noexcept {
+               return admins.size() > 0 && managedPolicies.size() > 0;
+       }
+
+       void enroll(const std::string& admin, uid_t uid);
+       void disenroll(const std::string& name, uid_t uid);
+
 private:
        void syncPolicyDefinition();
        void syncAdmin();
        void syncManagedPolicy();
 
+       std::string getAlias(const std::string& name, uid_t uid) const noexcept;
+
        std::shared_ptr<klay::database::Connection> database;
 
        /// DB Cache objects
        std::unordered_map<std::string, PolicyDefinition> definitions;
-       std::vector<Admin> admins;
+       std::unordered_map<std::string, Admin> admins;
        std::vector<ManagedPolicy> managedPolicies;
 };
 
index 6cf74a37a180ac3d20d77a7baf11270f0b062a42..72d2f66f7a790057a832fa8c7dc638b4a6ad2acd 100644 (file)
@@ -22,16 +22,17 @@ using namespace policyd;
 
 class PolicyStorageTests : public testing::Test {};
 
-TEST_F(PolicyStorageTests, policy_storage) {
+TEST_F(PolicyStorageTests, initialize) {
        bool isRaised = false;
 
        try {
+               /// TODO(Sangwan KWon): Change to test db
                PolicyStorage storage(DB_PATH);
        } catch (const std::exception&) {
                isRaised = true;
        }
 
-       EXPECT_TRUE(!isRaised);
+       EXPECT_FALSE(isRaised);
 
        isRaised = false;
        try {
@@ -42,3 +43,18 @@ TEST_F(PolicyStorageTests, policy_storage) {
 
        EXPECT_TRUE(isRaised);
 }
+
+TEST_F(PolicyStorageTests, enrollment) {
+       PolicyStorage storage(DB_PATH);
+       EXPECT_FALSE(storage.isActivated());
+
+       storage.enroll("testAdmin", 0);
+       storage.enroll("testAdmin", 1);
+       EXPECT_TRUE(storage.isActivated());
+
+       storage.disenroll("testAdmin", 0);
+       EXPECT_TRUE(storage.isActivated());
+
+       storage.disenroll("testAdmin", 1);
+       EXPECT_FALSE(storage.isActivated());
+}