%defattr(-,root,root,-)
%{_bindir}/radosgw
%{_bindir}/radosgw-admin
+%{_bindir}/radosgw-token
%{_bindir}/radosgw-object-expirer
%{_mandir}/man8/radosgw.8*
%{_mandir}/man8/radosgw-admin.8*
etc/bash_completion.d/radosgw-admin
usr/bin/radosgw
usr/bin/radosgw-admin
+usr/bin/radosgw-token
usr/bin/radosgw-object-expirer
usr/share/man/man8/radosgw-admin.8
usr/share/man/man8/radosgw.8
/rados
/radosgw
/radosgw-admin
+/radosgw-token
/radosgw-object-expirer
/rbd
/rbd-mirror
rgw/rgw_admin.cc
rgw/rgw_orphan.cc)
+ set(radosgw_token_srcs
+ rgw/rgw_token.cc)
+
set(radosgw_object_expirer_srcs
rgw/rgw_object_expirer.cc)
install(TARGETS radosgw-admin DESTINATION bin)
+ add_executable(radosgw-token ${radosgw_token_srcs})
+ target_link_libraries(radosgw-token librados
+ global ${ALLOC_LIBS})
+ install(TARGETS radosgw-token DESTINATION bin)
+
add_executable(radosgw-object-expirer ${radosgw_object_expirer_srcs})
target_link_libraries(radosgw-object-expirer rgw_a librados
cls_rgw_client cls_lock_client cls_refcount_client
radosgw_admin_LDADD = $(LIBRGW) $(LIBRGW_DEPS) $(CEPH_GLOBAL)
bin_PROGRAMS += radosgw-admin
+radosgw_token_SOURCES = rgw/rgw_token.cc
+radosgw_token_LDADD = $(LIBRGW) $(LIBRGW_DEPS) $(CEPH_GLOBAL)
+bin_PROGRAMS += radosgw-token
+
radosgw_object_expirer_SOURCES = rgw/rgw_object_expirer.cc
radosgw_object_expirer_LDADD = $(LIBRGW) $(LIBRGW_DEPS) $(CEPH_GLOBAL)
bin_PROGRAMS += radosgw-object-expirer
rgw/rgw_cr_rest.h \
rgw/rgw_fcgi.h \
rgw/rgw_xml.h \
+ rgw/rgw_token.h \
rgw/rgw_basic_types.h \
rgw/rgw_cache.h \
rgw/rgw_common.h \
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <errno.h>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "common/config.h"
+#include "common/ceph_argparse.h"
+#include "common/debug.h"
+#include "global/global_init.h"
+#include "include/assert.h"
+#include "include/str_list.h"
+
+#include "rgw_token.h"
+#include "rgw_b64.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+namespace {
+
+ using namespace rgw;
+ using std::get;
+ using std::string;
+
+ RGWToken::token_type type{RGWToken::TOKEN_NONE};
+ string access_key{""};
+ string secret_key{""};
+
+ Formatter* formatter{nullptr};
+
+ bool verbose {false};
+ bool do_encode {false};
+ bool do_decode {false};
+
+}
+
+void usage()
+{
+ cout << "usage: radosgw-token [options...]" << std::endl;
+ cout << "\t(maybe exporting RGW_ACCESS_KEY_ID and RGW_SECRET_ACCESS_KEY)"
+ << std::endl;
+ cout << "\n";
+ generic_client_usage();
+}
+
+int main(int argc, char **argv)
+{
+ std::string val;
+ vector<const char*> args;
+ argv_to_vec(argc, (const char **)argv, args);
+ env_to_vec(args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(g_ceph_context);
+
+ char *v{nullptr};
+ v = getenv("RGW_ACCESS_KEY_ID");
+ if (v) {
+ access_key = v;
+ }
+
+ v = getenv("RGW_SECRET_ACCESS_KEY");
+ if (v) {
+ secret_key = v;
+ }
+
+ for (auto arg_iter = args.begin(); arg_iter != args.end();) {
+ if (ceph_argparse_witharg(args, arg_iter, &val, "--access",
+ (char*) nullptr)) {
+ access_key = val;
+ } else if (ceph_argparse_witharg(args, arg_iter, &val, "--secret",
+ (char*) nullptr)) {
+ secret_key = val;
+ } else if (ceph_argparse_witharg(args, arg_iter, &val, "--ttype",
+ (char*) nullptr)) {
+ for (const auto& ttype : {"ad", "ldap"}) {
+ if (boost::iequals(val, ttype)) {
+ type = RGWToken::to_type(val);
+ break;
+ }
+ }
+ } else if (ceph_argparse_flag(args, arg_iter, "--encode",
+ (char*) nullptr)) {
+ do_encode = true;
+ } else if (ceph_argparse_flag(args, arg_iter, "--decode",
+ (char*) nullptr)) {
+ do_decode = true;
+ } else if (ceph_argparse_flag(args, arg_iter, "--verbose",
+ (char*) nullptr)) {
+ verbose = true;
+ } else {
+ ++arg_iter;
+ }
+ }
+
+ if ((! do_encode) ||
+ (type == RGWToken::TOKEN_NONE)) {
+ usage();
+ return -EINVAL;
+ }
+
+ formatter = new JSONFormatter(true /* pretty */);
+
+ RGWToken token(type, access_key, secret_key);
+ if (do_encode) {
+ token.encode_json(formatter);
+ std::ostringstream os;
+ formatter->flush(os);
+ string token_str = os.str();
+ if (verbose) {
+ std::cout << "expanded token: " << token_str << std::endl;
+ if (do_decode) {
+ RGWToken token2(token_str);
+ std::cout << "decoded expanded token: " << token2 << std::endl;
+ }
+ }
+ std::cout << to_base64(token_str) << std::endl;
+ }
+
+ return 0;
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2016 Red Hat, Inc
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef RGW_TOKEN_H
+#define RGW_TOKEN_H
+
+#include <stdint.h>
+#include <boost/algorithm/string.hpp>
+#include <sstream>
+
+#include "common/ceph_json.h"
+#include "common/Formatter.h"
+#include "rgw/rgw_b64.h"
+
+namespace rgw {
+
+ using std::string;
+
+ class RGWToken {
+ public:
+ static constexpr auto type_name = "RGW_TOKEN";
+
+ enum token_type : uint32_t {
+ TOKEN_NONE,
+ TOKEN_AD,
+ TOKEN_KEYSTONE,
+ TOKEN_LDAP,
+ };
+
+ static enum token_type to_type(const string& s) {
+ if (boost::iequals(s, "ad"))
+ return TOKEN_AD;
+ if (boost::iequals(s, "ldap"))
+ return TOKEN_LDAP;
+ if (boost::iequals(s, "keystone"))
+ return TOKEN_KEYSTONE;
+ return TOKEN_NONE;
+ }
+
+ static const char* from_type(enum token_type type) {
+ switch (type) {
+ case TOKEN_AD:
+ return "ad";
+ break;
+ case TOKEN_LDAP:
+ return "ldap";
+ break;
+ case TOKEN_KEYSTONE:
+ return "keystone";
+ break;
+ default:
+ return "none";
+ };
+ return "none";
+ }
+
+ token_type type;
+ string id;
+ string key;
+
+ virtual uint32_t version() const { return 1; };
+
+ bool valid() {
+ return ((type != TOKEN_NONE) &&
+ (! id.empty()) &&
+ (! key.empty()));
+ }
+
+ RGWToken()
+ : type(TOKEN_NONE) {};
+
+ RGWToken(enum token_type _type, const std::string& _id,
+ const std::string& _key)
+ : type(_type), id(_id), key(_key) {};
+
+ RGWToken(const string& json) {
+ JSONParser p;
+ p.parse(json.c_str(), json.length());
+ JSONDecoder::decode_json(RGWToken::type_name, *this, &p);
+ }
+
+ void encode(bufferlist& bl) const {
+ uint32_t ver = version();
+ string typestr{from_type(type)};
+ ::encode(type_name, bl);
+ ::encode(ver, bl);
+ ::encode(typestr, bl);
+ ::encode(id, bl);
+ ::encode(key, bl);
+ }
+
+ void decode(bufferlist::iterator& bl) {
+ string name;
+ string typestr;
+ uint32_t version;
+ ::decode(name, bl);
+ ::decode(version, bl);
+ ::decode(typestr, bl);
+ type = to_type(typestr.c_str());
+ ::decode(id, bl);
+ ::decode(key, bl);
+ }
+
+ void dump(Formatter* f) const {
+ ::encode_json("version", uint32_t(version()), f);
+ ::encode_json("type", from_type(type), f);
+ ::encode_json("id", id, f);
+ ::encode_json("key", key, f);
+ }
+
+ void encode_json(Formatter* f) {
+ RGWToken& token = *this;
+ f->open_object_section(type_name);
+ ::encode_json(type_name, token, f);
+ f->close_section();
+ }
+
+ void decode_json(JSONObj* obj) {
+ uint32_t version;
+ string type_name;
+ string typestr;
+ JSONDecoder::decode_json("version", version, obj);
+ JSONDecoder::decode_json("type", typestr, obj);
+ type = to_type(typestr.c_str());
+ JSONDecoder::decode_json("id", id, obj);
+ JSONDecoder::decode_json("key", key, obj);
+ }
+
+ std::string encode_json_base64(Formatter* f) {
+ encode_json(f);
+ std::ostringstream os;
+ f->flush(os);
+ return std::move(to_base64(std::move(os.str())));
+ }
+
+ friend inline ostream& operator<<(ostream& os, const RGWToken& token);
+
+ virtual ~RGWToken() {};
+ };
+ WRITE_CLASS_ENCODER(RGWToken)
+
+ inline ostream& operator<<(ostream& os, const RGWToken& token)
+ {
+ os << "<<RGWToken"
+ << " type=" << RGWToken::from_type(token.type)
+ << " id=" << token.id
+ << " key=" << token.key
+ << ">>";
+ return os;
+ }
+
+} /* namespace rgw */
+
+#endif /* RGW_TOKEN_H */
${CMAKE_DL_LIBS}
)
+add_executable(test_rgw_token
+ test_rgw_token.cc
+ $<TARGET_OBJECTS:heap_profiler_objs>
+ )
+set_target_properties(test_rgw_token PROPERTIES COMPILE_FLAGS
+ ${UNITTEST_CXX_FLAGS})
+target_link_libraries(test_rgw_token
+ rgw
+ os
+ global
+ ${UNITTEST_LIBS}
+ ${EXTRALIBS}
+ ${ALLOC_LIBS}
+ ${CMAKE_DL_LIBS}
+ )
+
if(${HAVE_LIBFUSE})
add_executable(test_cfuse_cache_invalidate
test_cfuse_cache_invalidate.cc
librgw.la librados.la $(PTHREAD_LIBS) $(CEPH_GLOBAL) $(EXTRALIBS)
bin_DEBUGPROGRAMS += librgw_file_nfsns
+test_rgw_token_SOURCES = test/test_rgw_token.cc
+test_rgw_token_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+test_rgw_token_LDADD = $(UNITTEST_LDADD) \
+ librgw.la $(PTHREAD_LIBS) $(LIBOS) $(CEPH_GLOBAL) $(EXTRALIBS)
+bin_DEBUGPROGRAMS += test_rgw_token
+
endif # WITH_RADOSGW
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <errno.h>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "common/config.h"
+#include "common/ceph_argparse.h"
+#include "common/debug.h"
+#include "global/global_init.h"
+#include "include/assert.h"
+#include "gtest/gtest.h"
+#include "rgw/rgw_token.h"
+#include "rgw/rgw_b64.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+namespace {
+
+ using namespace rgw;
+ using std::get;
+ using std::string;
+
+ string access_key{"Smonny"};
+ string secret_key{"Turjan of Miir"};
+
+ std::vector<RGWToken> tokens;
+
+ std::string enc_ad{"ewogICAgIlJHV19UT0tFTiI6IHsKICAgICAgICAidmVyc2lvbiI6IDEsCiAgICAgICAgInR5cGUiOiAiYWQiLAogICAgICAgICJpZCI6ICJTbW9ubnkiLAogICAgICAgICJrZXkiOiAiVHVyamFuIG9mIE1paXIiCiAgICB9Cn0K"};
+
+ std::string enc_ldap{"ewogICAgIlJHV19UT0tFTiI6IHsKICAgICAgICAidmVyc2lvbiI6IDEsCiAgICAgICAgInR5cGUiOiAibGRhcCIsCiAgICAgICAgImlkIjogIlNtb25ueSIsCiAgICAgICAgImtleSI6ICJUdXJqYW4gb2YgTWlpciIKICAgIH0KfQo="};
+
+ Formatter* formatter{nullptr};
+ bool verbose {false};
+}
+
+TEST(TOKEN, INIT) {
+ formatter = new JSONFormatter(true /* pretty */);
+ ASSERT_NE(formatter, nullptr);
+}
+
+TEST(TOKEN, ENCODE) {
+ // encode the two supported types
+ RGWToken token_ad(RGWToken::TOKEN_AD, access_key, secret_key);
+ ASSERT_EQ(token_ad.encode_json_base64(formatter), enc_ad);
+ tokens.push_back(token_ad); // provies copiable
+
+ RGWToken token_ldap(RGWToken::TOKEN_LDAP, access_key, secret_key);
+ ASSERT_EQ(token_ldap.encode_json_base64(formatter), enc_ldap);
+ tokens.push_back(token_ldap);
+}
+
+TEST(TOKEN, DECODE) {
+ for (const auto& enc_tok : {enc_ad, enc_ldap}) {
+ RGWToken token{from_base64(enc_tok)}; // decode ctor
+ ASSERT_EQ(token.id, access_key);
+ ASSERT_EQ(token.key, secret_key);
+ }
+}
+
+TEST(TOKEN, SHUTDOWN) {
+ delete formatter;
+}
+
+int main(int argc, char *argv[])
+{
+ string val;
+ vector<const char*> args;
+
+ argv_to_vec(argc, const_cast<const char**>(argv), args);
+ env_to_vec(args);
+
+ for (auto arg_iter = args.begin(); arg_iter != args.end();) {
+ if (ceph_argparse_flag(args, arg_iter, "--verbose",
+ (char*) nullptr)) {
+ verbose = true;
+ } else {
+ ++arg_iter;
+ }
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}