From 28864311d38eb28c4dcf6a2dc5e6f70108f94ffa Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Wed, 30 Nov 2022 18:22:30 -0500 Subject: [PATCH] rgw: added rgw-policy-check rgw-policy-check - a program to do syntax checking on bucket policy. This program just reads the policy into memory, so it is not checking anything except syntax. Signed-off-by: Marcus Watts rgw: Fix return value of `rgw-policy-check` Signed-off-by: Adam C. Emerson rgw: Use ceph initialization in `rgw-policy-check` Specifically so we can pull in the options from `ceph.conf` and similar. Signed-off-by: Adam C. Emerson --- ceph.spec.in | 2 + debian/ceph-common.install | 1 + doc/man/8/CMakeLists.txt | 1 + doc/man/8/rgw-policy-check.rst | 55 +++++++++++++++++ doc/man_index.rst | 1 + src/rgw/CMakeLists.txt | 6 ++ src/rgw/rgw_polparser.cc | 105 +++++++++++++++++++++++++++++++++ 7 files changed, 171 insertions(+) create mode 100644 doc/man/8/rgw-policy-check.rst create mode 100644 src/rgw/rgw_polparser.cc diff --git a/ceph.spec.in b/ceph.spec.in index 4f362aec006df..0ace470f5786f 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -2129,7 +2129,9 @@ fi %{_bindir}/rgw-gap-list %{_bindir}/rgw-gap-list-comparator %{_bindir}/rgw-orphan-list +%{_bindir}/rgw-policy-check %{_mandir}/man8/radosgw.8* +%{_mandir}/man8/rgw-policy-check.8* %dir %{_localstatedir}/lib/ceph/radosgw %{_unitdir}/ceph-radosgw@.service %{_unitdir}/ceph-radosgw.target diff --git a/debian/ceph-common.install b/debian/ceph-common.install index c3bc9dbaa4ee7..1c787b05f5920 100755 --- a/debian/ceph-common.install +++ b/debian/ceph-common.install @@ -37,6 +37,7 @@ usr/share/man/man8/crushdiff.8 usr/share/man/man8/mount.ceph.8 usr/share/man/man8/rados.8 usr/share/man/man8/radosgw-admin.8 +usr/share/man/man8/rgw-policy-check.8 usr/share/man/man8/rbd.8 usr/share/man/man8/rbdmap.8 usr/share/man/man8/rbd-replay*.8 diff --git a/doc/man/8/CMakeLists.txt b/doc/man/8/CMakeLists.txt index 4675cc11dd232..f1df5b4b448ee 100644 --- a/doc/man/8/CMakeLists.txt +++ b/doc/man/8/CMakeLists.txt @@ -59,6 +59,7 @@ if(WITH_RADOSGW) radosgw.rst radosgw-admin.rst rgw-orphan-list.rst + rgw-policy-check.rst ceph-diff-sorted.rst) endif() diff --git a/doc/man/8/rgw-policy-check.rst b/doc/man/8/rgw-policy-check.rst new file mode 100644 index 0000000000000..3f055711fc4e9 --- /dev/null +++ b/doc/man/8/rgw-policy-check.rst @@ -0,0 +1,55 @@ +:orphan: + +=================================================== +rgw-policy-check -- verify syntax of bucket policy +=================================================== + +.. program:: rgw-policy-check + +Synopsis +======== + +| **rgw-policy-check** + -t *tenant* [ *filename* ... ] + + +Description +=========== + +This program reads one or more files containing bucket policy +and determines if it is syntactically correct. +It does not check to see if the policy makes sense; +it only checks to see if the file would be accepted +by the policy parsing logic inside +:program:`radsogw`. + +More than one filename may be specified. If no files are +given, the program will read from stdin. + +On success, the program will say nothing. On failure, +the program will emit a error message indicating the +problem. The program will terminate with non-zero exit +status if one or more policies could not be read or parsed. + +Options +======= + +.. option: -t *tenant* + + Specify *tenant* as the tenant. This is required by the + policy parsing logic and is used to construct the internal + state representation of the policy. + +Availability +============ + +**rgw-policy-check** is part of Ceph, a massively scalable, open-source, +distributed storage system. Please refer to the Ceph documentation at +http://ceph.com/docs for more information. + +See also +======== + +:doc:`radosgw `\(8) + +.. _Bucket Policies: ../../radosgw/bucketpolicy.rst diff --git a/doc/man_index.rst b/doc/man_index.rst index 1f786ac8a7431..989ed7e229a05 100644 --- a/doc/man_index.rst +++ b/doc/man_index.rst @@ -47,3 +47,4 @@ man/8/rgw-orphan-list man/8/ceph-immutable-object-cache man/8/ceph-diff-sorted + man/8/rgw-policy-check diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index e082de9d09a89..50d8cb32c18db 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -459,6 +459,12 @@ target_link_libraries(radosgw-object-expirer ${rgw_libs} librados ${CURL_LIBRARIES} ${EXPAT_LIBRARIES}) install(TARGETS radosgw-object-expirer DESTINATION bin) +set(radosgw_polparser_srcs + rgw_polparser.cc) +add_executable(rgw-policy-check ${radosgw_polparser_srcs}) +target_link_libraries(rgw-policy-check ${rgw_libs}) +install(TARGETS rgw-policy-check DESTINATION bin) + set(librgw_srcs librgw.cc) add_library(rgw SHARED ${librgw_srcs}) diff --git a/src/rgw/rgw_polparser.cc b/src/rgw/rgw_polparser.cc new file mode 100644 index 0000000000000..eca5066b3ce3c --- /dev/null +++ b/src/rgw/rgw_polparser.cc @@ -0,0 +1,105 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include +#include +#include +#include +#include +#include + +#include "include/buffer.h" + +#include "common/ceph_argparse.h" +#include "common/common_init.h" + +#include "global/global_init.h" + +#include "rgw/rgw_iam_policy.h" + +// Returns true on success +bool parse(CephContext* cct, const std::string& tenant, + const std::string& fname, std::istream& in) noexcept +{ + bufferlist bl; + bl.append(in); + try { + auto p = rgw::IAM::Policy( + cct, tenant, bl, + cct->_conf.get_val("rgw_policy_reject_invalid_principals")); + } catch (const rgw::IAM::PolicyParseException& e) { + std::cerr << fname << ": " << e.what() << std::endl; + return false; + } catch (const std::exception& e) { + std::cerr << fname << ": caught exception: " << e.what() << std::endl;; + return false; + } + return true; +} + +void helpful_exit(std::string_view cmdname) +{ + std::cerr << cmdname << "-h for usage" << std::endl; + exit(1); +} + +void usage(std::string_view cmdname) +{ + std::cout << "usage: " << cmdname << " -t [filename]" + << std::endl; +} + +int main(int argc, const char** argv) +{ + std::string_view cmdname = argv[0]; + std::string tenant; + + auto args = argv_to_vec(argc, argv); + if (ceph_argparse_need_usage(args)) { + usage(cmdname); + exit(0); + } + + auto cct = global_init(nullptr, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DAEMON_ACTIONS | + CINIT_FLAG_NO_MON_CONFIG); + common_init_finish(cct.get()); + std::string val; + for (std::vector::iterator i = args.begin(); i != args.end(); ) { + if (ceph_argparse_double_dash(args, i)) { + break; + } else if (ceph_argparse_witharg(args, i, &val, "--tenant", "-t", + (char*)nullptr)) { + tenant = std::move(val); + } else { + ++i; + } + } + + if (tenant.empty()) { + std::cerr << cmdname << ": must specify tenant name" << std::endl; + helpful_exit(cmdname); + } + + bool success = true; + + if (args.empty()) { + success = parse(cct.get(), tenant, "(stdin)", std::cin); + } else { + for (const auto& file : args) { + std::ifstream in; + in.open(file, std::ifstream::in); + if (!in.is_open()) { + std::cerr << "Can't read " << file << std::endl; + success = false; + } + if (!parse(cct.get(), tenant, file, in)) { + success = false; + } + } + } + + return success ? 0 : 1; +} -- 2.39.5