return ::cynara_admin_erase(p_cynara_admin, start_bucket, recursive, client, user, privilege);
}
+int AdminApiWrapper::cynara_admin_list_policies(struct cynara_admin *p_cynara_admin,
+ const char *bucket, const char *client,
+ const char *user, const char *privilege,
+ struct cynara_admin_policy ***policies) {
+ return ::cynara_admin_list_policies(p_cynara_admin, bucket, client, user, privilege, policies);
+}
+
} /* namespace Cynara */
const char *start_bucket, const int recursive,
const char *client, const char *user, const char *privilege,
int *result, char **result_extra);
+ virtual int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket,
+ const char *client, const char *user,
+ const char *privilege,
+ struct cynara_admin_policy ***policies);
virtual int cynara_admin_erase(struct cynara_admin *p_cynara_admin, const char *start_bucket,
int recursive, const char *client, const char *user,
const char *privilege);
const char *start_bucket, const int recursive,
const char *client, const char *user, const char *privilege,
int *result, char **result_extra) = 0;
+ virtual int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket,
+ const char *client, const char *user,
+ const char *privilege,
+ struct cynara_admin_policy ***policies) = 0;
virtual int cynara_admin_erase(struct cynara_admin *p_cynara_admin, const char *start_bucket,
int recursive, const char *client, const char *user,
const char *privilege) = 0;
{ CmdlineOpt::Check,
{ "check", CmdlineOpt::Check, "check",
"", OptHasArg::NoArgument } },
+ { CmdlineOpt::ListPolicies,
+ { "list-policies", CmdlineOpt::ListPolicies, "list-policies=<bucket>",
+ "name of bucket to erase policies from", OptHasArg::RequiredArgument } },
{ CmdlineOpt::Type,
{ "type", CmdlineOpt::Type, "type=<type>",
helpStr << opt(CmdlineOpt::Privilege) << std::endl;
helpStr << std::endl;
+ helpStr << head("Policies list options", CmdlineOpt::ListPolicies) << std::endl;
+ helpStr << opt(CmdlineOpt::ListPolicies) << std::endl;
+ helpStr << opt(CmdlineOpt::Client) << std::endl;
+ helpStr << opt(CmdlineOpt::User) << std::endl;
+ helpStr << opt(CmdlineOpt::Privilege) << std::endl;
+ helpStr << std::endl;
+
helpStr << head("Help options", CmdlineOpt::Help) << std::endl;
helpStr << opt(CmdlineOpt::Help);
SetPolicy = 's',
Erase = 'e',
Check = 'a',
+ ListPolicies = 'l',
Type = 't',
Metadata = 'm',
return dispatcher.execute(*this);
}
+int ListPoliciesCyadCommand::run(CommandsDispatcher &dispatcher) {
+ return dispatcher.execute(*this);
+}
+
} /* namespace Cynara */
PolicyKey m_policyKey;
};
+class ListPoliciesCyadCommand : public CyadCommand {
+public:
+ ListPoliciesCyadCommand(const PolicyBucketId &bucketId, const PolicyKey &policyKey)
+ : m_bucketId(bucketId), m_policyKey(policyKey) {}
+
+ virtual ~ListPoliciesCyadCommand() {}
+
+ virtual int run(CommandsDispatcher &dispatcher);
+
+ const PolicyBucketId &bucketId(void) const {
+ return m_bucketId;
+ }
+
+ const PolicyKey &policyKey(void) const {
+ return m_policyKey;
+ }
+
+private:
+ PolicyBucketId m_bucketId;
+ PolicyKey m_policyKey;
+};
+
} /* namespace Cynara */
#endif /* SRC_CYAD_COMMANDLINEPARSER_CYADCOMMAND_H_ */
CmdlineOpt::DeleteBucket,
CmdlineOpt::SetPolicy,
CmdlineOpt::Erase,
- CmdlineOpt::Check
+ CmdlineOpt::Check,
+ CmdlineOpt::ListPolicies
};
const auto longOpts = Opts::makeLongOptions(opts);
case CmdlineOpt::Check:
return parseCheck();
+ case CmdlineOpt::ListPolicies:
+ return parseListPolicies(optarg);
+
case '?': // Unknown option
return sharedError(Err::unknownOption());
case CmdlineOpt::SetBucket:
case CmdlineOpt::DeleteBucket:
case CmdlineOpt::Erase:
+ case CmdlineOpt::ListPolicies:
return sharedError(Err::noBucket());
}
// Shall never happen, but let's just make compiler happy.
values[CmdlineOpt::Privilege]));
}
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseListPolicies(const std::string &bucketId) {
+ namespace Opts = CmdlineOpts;
+ namespace Err = CmdlineErrors;
+ using CmdlineOpts::CmdlineOpt;
+
+ std::vector<CmdlineOpt> opts = {
+ CmdlineOpt::Client,
+ CmdlineOpt::User,
+ CmdlineOpt::Privilege
+ };
+
+ const auto longOpts = Opts::makeLongOptions(opts);
+ const auto shortOpts = Opts::makeShortOptions(opts);
+
+ typedef std::unordered_map<char, std::string> OptionsValues;
+ OptionsValues values = { { CmdlineOpt::Client, std::string() },
+ { CmdlineOpt::User, std::string() },
+ { CmdlineOpt::Privilege, std::string() } };
+
+ int opt;
+ while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
+ switch (opt) {
+ case CmdlineOpt::Client:
+ case CmdlineOpt::User:
+ case CmdlineOpt::Privilege:
+ values[opt] = optarg;
+ break;
+ case ':': // Missing argument
+ return sharedError(Err::argumentMissing(CmdlineOpt::ListPolicies));
+ default:
+ return sharedError(Err::unknownOption(CmdlineOpt::ListPolicies));
+ }
+ }
+
+ for (const auto &val : values) {
+ if (val.second.empty()) {
+ // TODO: Identify actual option
+ return sharedError(Err::optionMissing(CmdlineOpt::ListPolicies));
+ }
+ }
+
+ return std::make_shared<ListPoliciesCyadCommand>(bucketId,
+ PolicyKey(values[CmdlineOpt::Client],
+ values[CmdlineOpt::User],
+ values[CmdlineOpt::Privilege]));
+}
+
} /* namespace Cynara */
std::shared_ptr<CyadCommand> parseSetPolicy(void);
std::shared_ptr<CyadCommand> parseErase(const std::string &bucketId);
std::shared_ptr<CyadCommand> parseCheck(void);
+ std::shared_ptr<CyadCommand> parseListPolicies(const std::string &bucketId);
private:
int m_argc;
* @brief CommandsDispatcher class (implementation)
*/
+#include <cynara-admin-types.h>
#include <cynara-error.h>
#include <cynara-policy-types.h>
return ret;
}
+int CommandsDispatcher::execute(ListPoliciesCyadCommand &command) {
+ const auto &key = command.policyKey();
+ auto client = key.client().toString().c_str();
+ auto user = key.user().toString().c_str();
+ auto privilege = key.privilege().toString().c_str();
+
+ // Initialization is needed to make compiler happy (-Werror=maybe-uninitialized, FTW)
+ cynara_admin_policy **policies = nullptr;
+
+ auto ret = m_adminApiWrapper.cynara_admin_list_policies(m_cynaraAdmin,
+ command.bucketId().c_str(),
+ client, user, privilege,
+ &policies);
+
+ auto printPolicy = [this] (cynara_admin_policy *p) {
+ m_io.cout() << p->bucket << ";"
+ << p->client << ";"
+ << p->user << ";"
+ << p->privilege << ";"
+ << p->result << ";";
+ if (p->result_extra != nullptr) {
+ m_io.cout() << p->result_extra;
+ }
+ m_io.cout() << std::endl;
+ };
+
+ auto freePolicy = [] (cynara_admin_policy *p) {
+ free(p->bucket);
+ free(p->client);
+ free(p->user);
+ free(p->privilege);
+ free(p->result_extra);
+ free(p);
+ };
+
+ if (ret == CYNARA_API_SUCCESS) {
+ for (int i = 0; policies[i]; ++i) {
+ auto p = policies[i];
+ printPolicy(p);
+ freePolicy(p);
+ }
+ free(policies);
+ }
+
+ return ret;
+}
+
} /* namespace Cynara */
virtual int execute(SetPolicyBulkCyadCommand &);
virtual int execute(EraseCyadCommand &);
virtual int execute(CheckCyadCommand &);
+ virtual int execute(ListPoliciesCyadCommand &);
private:
BaseDispatcherIO &m_io;
#include <algorithm>
#include <cstring>
+#include <functional>
+#include <memory>
#include <new>
#include <stdexcept>
#include <string>
return m_policies.data();
}
+cynara_admin_policy **CynaraAdminPolicies::duplicate(void) const {
+ if (sealed() == false) {
+ throw std::logic_error("Collection is not sealed");
+ }
+
+ auto freePolicies = [this] (cynara_admin_policy **policies) {
+ for (auto i = 0u; i < m_policies.size() - 1; ++i) {
+ auto p = policies[i];
+ ::free(p->bucket);
+ ::free(p->client);
+ ::free(p->user);
+ ::free(p->privilege);
+ ::free(p->result_extra);
+ ::free(p);
+ }
+ free(policies);
+ };
+
+ auto dup = static_cast<cynara_admin_policy **>(calloc(m_policies.size(),
+ sizeof(cynara_admin_policy *)));
+
+ if (dup == nullptr)
+ throw std::bad_alloc();
+
+ std::unique_ptr<cynara_admin_policy *, decltype(freePolicies)> dupPtr(dup, freePolicies);
+
+ for (auto i = 0u; i < m_policies.size() - 1; ++i) {
+ dup[i] = static_cast<cynara_admin_policy *>(calloc(1, sizeof(cynara_admin_policy)));
+
+ if (dup[i] == nullptr)
+ throw std::bad_alloc();
+
+ dup[i]->bucket = strdup(m_policies.at(i)->bucket);
+ if (dup[i]->bucket == nullptr)
+ throw std::bad_alloc();
+
+ dup[i]->client = strdup(m_policies.at(i)->client);
+ if (dup[i]->client == nullptr)
+ throw std::bad_alloc();
+
+ dup[i]->user = strdup(m_policies.at(i)->user);
+ if (dup[i]->user == nullptr)
+ throw std::bad_alloc();
+
+ dup[i]->privilege = strdup(m_policies.at(i)->privilege);
+ if (dup[i]->privilege == nullptr)
+ throw std::bad_alloc();
+
+ dup[i]->result = m_policies.at(i)->result;
+
+ if (m_policies.at(i)->result_extra) {
+ dup[i]->result_extra = strdup(m_policies.at(i)->result_extra);
+ if (dup[i]->result_extra == nullptr)
+ throw std::bad_alloc();
+ } else
+ dup[i]->result_extra = nullptr;
+ }
+
+ dup[m_policies.size() - 1] = nullptr;
+ return dupPtr.release();
+}
+
} /* namespace Cynara */
void seal(void);
cynara_admin_policy* const *data(void) const;
+ cynara_admin_policy **duplicate(void) const;
bool sealed(void) const {
return m_sealed;
int(struct cynara_admin *p_cynara_admin, const char *start_bucket,
const int recursive, const char *client, const char *user,
const char *privilege, int *result, char **result_extra));
+ MOCK_METHOD6(cynara_admin_list_policies,
+ int(struct cynara_admin *p_cynara_admin, const char *bucket, const char *client,
+ const char *user, const char *privilege,
+ struct cynara_admin_policy ***policies));
MOCK_METHOD6(cynara_admin_erase,
int(struct cynara_admin *p_cynara_admin, const char *start_bucket, int recursive,
const char *client, const char *user, const char *privilege));
ASSERT_FALSE(result->recursive());
ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
}
+
+TEST_F(CyadCommandlineTest, listPoliciesDefault) {
+ prepare_argv({ "./cyad", "--list-policies=",
+ "--client=client", "--user=user", "--privilege=privilege" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+ auto result = std::dynamic_pointer_cast<Cynara::ListPoliciesCyadCommand>(parser.parseMain());
+ ASSERT_NE(nullptr, result);
+ ASSERT_EQ(CYNARA_ADMIN_DEFAULT_BUCKET, result->bucketId());
+ ASSERT_EQ(Cynara::PolicyKey("client", "user", "privilege"), result->policyKey());
+}
+
+TEST_F(CyadCommandlineTest, listPoliciesOtherBucket) {
+ prepare_argv({ "./cyad", "--list-policies=some-bucket",
+ "--client=c", "--user=u", "--privilege=p" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+ auto result = std::dynamic_pointer_cast<Cynara::ListPoliciesCyadCommand>(parser.parseMain());
+ ASSERT_NE(nullptr, result);
+ ASSERT_EQ("some-bucket", result->bucketId());
+ ASSERT_EQ(Cynara::PolicyKey("c", "u", "p"), result->policyKey());
+}
Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
ASSERT_ERROR_MSG(Errors::optionMissing(CmdlineOpt::Erase), parser.parseMain());
}
+
+// Error should be argument missing, but getopt acts weird
+TEST_F(CyadCommandlineTest, listPoliciesNoBucket) {
+ prepare_argv({ "./cyad", "--list-policies",
+ "--client=client", "--user=user", "--privilege=privilege" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Errors::optionMissing(CmdlineOpt::ListPolicies), parser.parseMain());
+}
using Cynara::CmdlineOpts::commandlineOptions;
// A cheap trick to make sure this test is updated, when new options are added
- ASSERT_EQ(14, commandlineOptions.size());
+ ASSERT_EQ(15, commandlineOptions.size());
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::SetBucket));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::DeleteBucket));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::SetPolicy));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::Erase));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::Check));
+ ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::ListPolicies));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::Type));
ASSERT_NO_THROW(commandlineOptions.at(CmdlineOpt::Metadata));
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <cynara-admin-types.h>
#include <cynara-error.h>
#include <cynara-policy-types.h>
ASSERT_TRUE(m_io.coutRaw().str().empty());
}
+
+TEST_F(CyadCommandlineDispatcherTest, listPoliciesNone) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::NotNull;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+ using ::testing::StrEq;
+
+ FakeAdminApiWrapper adminApi;
+
+ EXPECT_CALL(adminApi, cynara_admin_initialize(_)).WillOnce(Return(CYNARA_API_SUCCESS));
+ EXPECT_CALL(adminApi, cynara_admin_finish(_)).WillOnce(Return(CYNARA_API_SUCCESS));
+
+ Cynara::CommandsDispatcher dispatcher(m_io, adminApi);
+
+ Cynara::ListPoliciesCyadCommand command("", { "client", "user", "privilege" });
+
+ Cynara::CynaraAdminPolicies resultPolicies;
+ resultPolicies.seal();
+ auto policies = resultPolicies.duplicate();
+
+ EXPECT_CALL(adminApi, cynara_admin_list_policies(_, StrEq(""), StrEq("client"), StrEq("user"),
+ StrEq("privilege"), NotNull()))
+ .WillOnce(DoAll(SetArgPointee<5>(policies), Return(CYNARA_API_SUCCESS)));
+
+ dispatcher.execute(command);
+
+ ASSERT_EQ("", m_io.coutRaw().str());
+}
+
+TEST_F(CyadCommandlineDispatcherTest, listPoliciesTwo) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::NotNull;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+ using ::testing::StrEq;
+
+ FakeAdminApiWrapper adminApi;
+
+ EXPECT_CALL(adminApi, cynara_admin_initialize(_)).WillOnce(Return(CYNARA_API_SUCCESS));
+ EXPECT_CALL(adminApi, cynara_admin_finish(_)).WillOnce(Return(CYNARA_API_SUCCESS));
+
+ Cynara::CommandsDispatcher dispatcher(m_io, adminApi);
+
+ Cynara::ListPoliciesCyadCommand command("", { "client", "user", "privilege" });
+
+ Cynara::CynaraAdminPolicies resultPolicies;
+ resultPolicies.add("bucket", { CYNARA_ADMIN_DENY, "metadata" }, {"cli", "usr", "privilege"} );
+ resultPolicies.add("bucket-2", { CYNARA_ADMIN_ALLOW, "" }, {"cli", "usr", "privilege"} );
+ resultPolicies.seal();
+ auto policies = resultPolicies.duplicate();
+
+ EXPECT_CALL(adminApi, cynara_admin_list_policies(_, StrEq(""), StrEq("client"), StrEq("user"),
+ StrEq("privilege"), NotNull()))
+ .WillOnce(DoAll(SetArgPointee<5>(policies), Return(CYNARA_API_SUCCESS)));
+
+ dispatcher.execute(command);
+
+ ASSERT_EQ("bucket;cli;usr;privilege;0;metadata\nbucket-2;cli;usr;privilege;65535;\n",
+ m_io.coutRaw().str());
+}