Implement --set-policy option in Cyad 84/32184/8
authorAleksander Zdyb <a.zdyb@samsung.com>
Mon, 15 Dec 2014 12:58:31 +0000 (13:58 +0100)
committerPawel Wieczorek <p.wieczorek2@samsung.com>
Tue, 30 Dec 2014 07:37:31 +0000 (08:37 +0100)
Policies can be added or altered one by one or in bulk mode.

Option --bulk accepts file name as an argument.
The "-" value means standard input.

Change-Id: I479a29fd5ff43463f6f78d7865468bd84e1642ee

src/cyad/CommandlineParser/CyadCommandlineParser.cpp
src/cyad/CommandlineParser/CyadCommandlineParser.h
src/cyad/CommandsDispatcher.h
test/cyad/commandline.cpp
test/cyad/commandline_errors.cpp

index 713b506..c72967a 100644 (file)
@@ -47,6 +47,24 @@ namespace CyadCmdlineArgs {
 
     const char METADATA = 'm';
     const char * const METADATA_LONG = "metadata";
+
+    const char BUCKET = 'k';
+    const char * const BUCKET_LONG = "bucket";
+
+    const char SET_POLICY = 's';
+    const char * const SET_POLICY_LONG = "set-policy";
+
+    const char CLIENT = 'c';
+    const char * const CLIENT_LONG = "client";
+
+    const char USER = 'u';
+    const char * const USER_LONG = "user";
+
+    const char PRIVILEGE = 'r';
+    const char * const PRIVILEGE_LONG = "privilege";
+
+    const char BULK = 'f';
+    const char * const BULK_LONG = "bulk";
 }
 
 namespace CyadCmdlineErrors {
@@ -55,9 +73,12 @@ namespace CyadCmdlineErrors {
     const char * const UNKNOWN_OPTION = "Unknown option";
     const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket";
     const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket";
+    const char * const UNKNOWN_OPTION_SET_POLICY = "Unknown option in --set-policy";
     const char * const NO_POLICY = "No --policy specified";
     const char * const NO_BUCKET = "No bucket specified";
     const char * const INVALID_POLICY = "Invalid --policy option";
+    const char * const OPTION_MISSING_SET_POLICY = "One or more option missing in --set-policy";
+    const char * const ARGUMENT_MISSING_SET_POLICY = "One or more argument missing in --set-policy";
 }
 
 CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv)
@@ -72,6 +93,7 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
         { Args::HELP_LONG,          no_argument,       nullptr, Args::HELP },
         { Args::SET_BUCKET_LONG,    required_argument, nullptr, Args::SET_BUCKET },
         { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET },
+        { Args::SET_POLICY_LONG,    no_argument,       nullptr, Args::SET_POLICY },
         { nullptr, 0, nullptr, 0 }
     };
 
@@ -80,7 +102,8 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
     std::stringstream optstr;
     optstr << ":" << Args::HELP
            << Args::SET_BUCKET << ":"
-           << Args::DELETE_BUCKET << ":";
+           << Args::DELETE_BUCKET << ":"
+           << Args::SET_POLICY;
 
     while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
         switch (opt) {
@@ -93,6 +116,9 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
             case Args::DELETE_BUCKET:
                 return parseDeleteBucket(optarg);
 
+            case Args::SET_POLICY:
+                return parseSetPolicy();
+
             case '?': // Unknown option
                 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
 
@@ -171,6 +197,85 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseDeleteBucket(const std:
     }
 }
 
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetPolicy(void) {
+    namespace Args = CyadCmdlineArgs;
+    namespace Errors = CyadCmdlineErrors;
+
+    const struct option long_options[] = {
+        { Args::CLIENT_LONG,    required_argument, nullptr, Args::CLIENT },
+        { Args::USER_LONG,      required_argument, nullptr, Args::USER },
+        { Args::PRIVILEGE_LONG, required_argument, nullptr, Args::PRIVILEGE },
+        { Args::BUCKET_LONG,    required_argument, nullptr, Args::BUCKET },
+        { Args::POLICY_LONG,    required_argument, nullptr, Args::POLICY },
+        { Args::METADATA_LONG,  required_argument, nullptr, Args::METADATA },
+        { Args::BULK_LONG,      required_argument, nullptr, Args::BULK },
+        { nullptr, 0, nullptr, 0 }
+    };
+
+    typedef std::map<char, std::string> OptionsValues;
+    OptionsValues values = { { Args::CLIENT,    std::string() },
+                             { Args::USER,      std::string() },
+                             { Args::PRIVILEGE, std::string() },
+                             { Args::POLICY,    std::string() } };
+
+    std::string metadata;
+    std::string bucket;
+
+    int opt;
+    std::stringstream optstr;
+    optstr << ":"
+           << Args::CLIENT << ":"
+           << Args::USER << ":"
+           << Args::PRIVILEGE << ":"
+           << Args::BUCKET << ":"
+           << Args::POLICY << ":"
+           << Args::METADATA << ":"
+           << Args::BULK << ":";
+
+    while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
+        switch(opt) {
+        case Args::CLIENT:
+        case Args::USER:
+        case Args::PRIVILEGE:
+        case Args::POLICY:
+            values[opt] = optarg;
+            break;
+        case Args::BUCKET:
+            bucket = optarg;
+            break;
+        case Args::METADATA:
+            metadata = optarg;
+            break;
+        case Args::BULK:
+            return std::make_shared<SetPolicyBulkCyadCommand>(optarg);
+        case ':': // Missing argument
+            return std::make_shared<ErrorCyadCommand>(Errors::ARGUMENT_MISSING_SET_POLICY);
+        default:
+            return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_SET_POLICY);
+        }
+    }
+
+    for (const auto &val : values) {
+        if (val.second.empty()) {
+            // TODO: Identify actual option
+            return std::make_shared<ErrorCyadCommand>(Errors::OPTION_MISSING_SET_POLICY);
+        }
+    }
+
+    try {
+        auto policyType = parsePolicyType(values[Args::POLICY]);
+        auto policyResult = PolicyResult(policyType, metadata);
+        return std::make_shared<SetPolicyCyadCommand>(bucket, policyResult,
+                                                      PolicyKey(values[Args::CLIENT],
+                                                                values[Args::USER],
+                                                                values[Args::PRIVILEGE]));
+    } catch (const PolicyParsingException &) {
+        return std::make_shared<ErrorCyadCommand>(Errors::INVALID_POLICY);
+    }
+
+    return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_ERROR);
+}
+
 PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) {
     if (rawPolicy == "DENY")
         return CYNARA_ADMIN_DENY;
index 4b629c4..891751e 100644 (file)
@@ -44,6 +44,21 @@ namespace CyadCmdlineArgs {
 
     extern const char METADATA;
     extern const char * const METADATA_LONG;
+
+    extern const char BUCKET;
+    extern const char * const BUCKET_LONG;
+
+    extern const char CLIENT;
+    extern const char * const CLIENT_LONG;
+
+    extern const char USER;
+    extern const char * const USER_LONG;
+
+    extern const char PRIVILEGE;
+    extern const char * const PRIVILEGE_LONG;
+
+    extern const char BULK;
+    extern const char * const BULK_LONG;
 }
 
 namespace CyadCmdlineErrors {
@@ -52,9 +67,12 @@ namespace CyadCmdlineErrors {
     extern const char * const UNKNOWN_OPTION;
     extern const char * const UNKNOWN_OPTION_SET_BUCKET;
     extern const char * const UNKNOWN_OPTION_DELETE_BUCKET;
+    extern const char * const UNKNOWN_OPTION_SET_POLICY;
     extern const char * const NO_POLICY;
     extern const char * const NO_BUCKET;
     extern const char * const INVALID_POLICY;
+    extern const char * const OPTION_MISSING_SET_POLICY;
+    extern const char * const ARGUMENT_MISSING_SET_POLICY;
 }
 
 class CyadCommandlineParser {
@@ -68,6 +86,7 @@ public:
 protected:
     std::shared_ptr<CyadCommand> parseSetBucket(const std::string &bucketId);
     std::shared_ptr<CyadCommand> parseDeleteBucket(const std::string &bucketId);
+    std::shared_ptr<CyadCommand> parseSetPolicy(void);
 
 private:
     int m_argc;
index 4193a95..5193e1d 100644 (file)
@@ -57,7 +57,7 @@ private:
                                     "  -d, --delete-bucket=<name>     name of bucket to delete\n"
                                     "\n"
                                     "Policy set options (with -s or --set-policy)\n"
-                                    "  -l, --client=<client>          client value\n"
+                                    "  -c, --client=<client>          client value\n"
                                     "  -u, --user=<user>              user value\n"
                                     "  -r, --privilege=<privilege>    privilege value\n"
                                     "  -p, --policy=<policy>          policy\n"
index 31b0771..60bb69a 100644 (file)
@@ -73,6 +73,64 @@ TEST_F(CyadCommandlineTest, setBucketWithMetadata) {
     ASSERT_EQ(ultimateAnswer, result->policyResult().metadata());
 }
 
+TEST_F(CyadCommandlineTest, setPolicy) {
+    prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket",
+                   "--client=client", "--user=user", "--privilege=privilege",
+                   "--policy=42" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("some-bucket", result->bucketId());
+
+    ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
+    ASSERT_EQ(42, result->policyResult().policyType());
+    ASSERT_TRUE(result->policyResult().metadata().empty());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyWithMetadata) {
+    prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket",
+                   "--client=client", "--user=user", "--privilege=privilege",
+                   "--policy=42", "--metadata=some-metadata" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("some-bucket", result->bucketId());
+
+    ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
+    ASSERT_EQ(42, result->policyResult().policyType());
+    ASSERT_EQ("some-metadata", result->policyResult().metadata());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyInDefaultBucket) {
+    prepare_argv({ "./cyad", "--set-policy", "--bucket=",
+                   "--client=client", "--user=user", "--privilege=privilege",
+                   "--policy=ALLOW", "--metadata=some-metadata" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("", result->bucketId());
+    ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
+    ASSERT_EQ(CYNARA_ADMIN_ALLOW, result->policyResult().policyType());
+    ASSERT_EQ("some-metadata", result->policyResult().metadata());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyInDefaultBucketNoOption) {
+    prepare_argv({ "./cyad", "--set-policy",
+                   "--client=client", "--user=user", "--privilege=privilege",
+                   "--policy=ALLOW", "--metadata=some-metadata" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("", result->bucketId());
+    ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
+    ASSERT_EQ(CYNARA_ADMIN_ALLOW, result->policyResult().policyType());
+    ASSERT_EQ("some-metadata", result->policyResult().metadata());
+}
+
 TEST_F(CyadCommandlineTest, parsePolicyTypeBase10) {
     auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
         return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
@@ -105,3 +163,21 @@ TEST_F(CyadCommandlineTest, parsePolicyTypeHuman) {
     ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("BUCKET"));
     ASSERT_EQ(CYNARA_ADMIN_ALLOW,  parsePolicyType("ALLOW"));
 }
+
+TEST_F(CyadCommandlineTest, setPoliciesBulkFilename) {
+    prepare_argv({ "./cyad", "--set-policy", "--bulk=/tmp/input_file" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyBulkCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("/tmp/input_file", result->filename());
+}
+
+TEST_F(CyadCommandlineTest, setPoliciesBulkStdin) {
+    prepare_argv({ "./cyad", "--set-policy", "--bulk=-" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetPolicyBulkCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("-", result->filename());
+}
index 5aa358f..fb2fa30 100644 (file)
@@ -90,3 +90,29 @@ TEST_F(CyadCommandlineTest, setBucketMetadataNoPolicy) {
     Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
     ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain());
 }
+
+TEST_F(CyadCommandlineTest, setPolicyNoOption) {
+    prepare_argv({ "./cyad", "--set-policy" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::OPTION_MISSING_SET_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyUnknownOption) {
+    prepare_argv({ "./cyad", "--set-policy", "--unknown-option" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_SET_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyArgumentMissing) {
+    prepare_argv({ "./cyad", "--set-policy", "--bucket" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::ARGUMENT_MISSING_SET_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setPolicyNoPolicy) {
+    // TODO: In the future, we can identify actual options being missed
+    prepare_argv({ "./cyad", "--set-policy", "--bucket=some-bucket",
+                   "--client=client", "--user=user", "--privilege=privilege" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::OPTION_MISSING_SET_POLICY, parser.parseMain());
+}