remove ceph code
[stor4nfv.git] / src / ceph / src / rgw / rgw_keystone.cc
diff --git a/src/ceph/src/rgw/rgw_keystone.cc b/src/ceph/src/rgw/rgw_keystone.cc
deleted file mode 100644 (file)
index 3294380..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include <errno.h>
-#include <fnmatch.h>
-
-#include <boost/algorithm/string/predicate.hpp>
-
-#include "common/errno.h"
-#include "common/ceph_json.h"
-#include "include/types.h"
-#include "include/str_list.h"
-
-#include "rgw_common.h"
-#include "rgw_keystone.h"
-#include "common/ceph_crypto_cms.h"
-#include "common/armor.h"
-#include "common/Cond.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rgw
-
-int rgw_open_cms_envelope(CephContext * const cct,
-                          const std::string& src,
-                          std::string& dst)             /* out */
-{
-#define BEGIN_CMS "-----BEGIN CMS-----"
-#define END_CMS "-----END CMS-----"
-
-  int start = src.find(BEGIN_CMS);
-  if (start < 0) {
-    ldout(cct, 0) << "failed to find " << BEGIN_CMS << " in response" << dendl;
-    return -EINVAL;
-  }
-  start += sizeof(BEGIN_CMS) - 1;
-
-  int end = src.find(END_CMS);
-  if (end < 0) {
-    ldout(cct, 0) << "failed to find " << END_CMS << " in response" << dendl;
-    return -EINVAL;
-  }
-
-  string s = src.substr(start, end - start);
-
-  int pos = 0;
-
-  do {
-    int next = s.find('\n', pos);
-    if (next < 0) {
-      dst.append(s.substr(pos));
-      break;
-    } else {
-      dst.append(s.substr(pos, next - pos));
-    }
-    pos = next + 1;
-  } while (pos < (int)s.size());
-
-  return 0;
-}
-
-int rgw_decode_b64_cms(CephContext * const cct,
-                       const string& signed_b64,
-                       bufferlist& bl)
-{
-  bufferptr signed_ber(signed_b64.size() * 2);
-  char *dest = signed_ber.c_str();
-  const char *src = signed_b64.c_str();
-  size_t len = signed_b64.size();
-  char buf[len + 1];
-  buf[len] = '\0';
-
-  for (size_t i = 0; i < len; i++, src++) {
-    if (*src != '-') {
-      buf[i] = *src;
-    } else {
-      buf[i] = '/';
-    }
-  }
-
-  int ret = ceph_unarmor(dest, dest + signed_ber.length(), buf,
-                         buf + signed_b64.size());
-  if (ret < 0) {
-    ldout(cct, 0) << "ceph_unarmor() failed, ret=" << ret << dendl;
-    return ret;
-  }
-
-  bufferlist signed_ber_bl;
-  signed_ber_bl.append(signed_ber);
-
-  ret = ceph_decode_cms(cct, signed_ber_bl, bl);
-  if (ret < 0) {
-    ldout(cct, 0) << "ceph_decode_cms returned " << ret << dendl;
-    return ret;
-  }
-
-  return 0;
-}
-
-#define PKI_ANS1_PREFIX "MII"
-
-bool rgw_is_pki_token(const string& token)
-{
-  return token.compare(0, sizeof(PKI_ANS1_PREFIX) - 1, PKI_ANS1_PREFIX) == 0;
-}
-
-void rgw_get_token_id(const string& token, string& token_id)
-{
-  if (!rgw_is_pki_token(token)) {
-    token_id = token;
-    return;
-  }
-
-  unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE];
-
-  MD5 hash;
-  hash.Update((const byte *)token.c_str(), token.size());
-  hash.Final(m);
-
-  char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
-  buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5);
-  token_id = calc_md5;
-}
-
-bool rgw_decode_pki_token(CephContext * const cct,
-                          const string& token,
-                          bufferlist& bl)
-{
-  if (!rgw_is_pki_token(token)) {
-    return false;
-  }
-
-  int ret = rgw_decode_b64_cms(cct, token, bl);
-  if (ret < 0) {
-    return false;
-  }
-
-  ldout(cct, 20) << "successfully decoded pki token" << dendl;
-
-  return true;
-}
-
-
-namespace rgw {
-namespace keystone {
-
-ApiVersion CephCtxConfig::get_api_version() const noexcept
-{
-  switch (g_ceph_context->_conf->rgw_keystone_api_version) {
-  case 3:
-    return ApiVersion::VER_3;
-  case 2:
-    return ApiVersion::VER_2;
-  default:
-    dout(0) << "ERROR: wrong Keystone API version: "
-            << g_ceph_context->_conf->rgw_keystone_api_version
-            << "; falling back to v2" <<  dendl;
-    return ApiVersion::VER_2;
-  }
-}
-
-std::string CephCtxConfig::get_endpoint_url() const noexcept
-{
-  static const std::string url = g_ceph_context->_conf->rgw_keystone_url;
-
-  if (url.empty() || boost::algorithm::ends_with(url, "/")) {
-    return url;
-  } else {
-    static const std::string url_normalised = url + '/';
-    return url_normalised;
-  }
-}
-
-int Service::get_admin_token(CephContext* const cct,
-                             TokenCache& token_cache,
-                             const Config& config,
-                             std::string& token)
-{
-  /* Let's check whether someone uses the deprecated "admin token" feauture
-   * based on a shared secret from keystone.conf file. */
-  const auto& admin_token = config.get_admin_token();
-  if (! admin_token.empty()) {
-    token = std::string(admin_token.data(), admin_token.length());
-    return 0;
-  }
-
-  TokenEnvelope t;
-
-  /* Try cache first before calling Keystone for a new admin token. */
-  if (token_cache.find_admin(t)) {
-    ldout(cct, 20) << "found cached admin token" << dendl;
-    token = t.token.id;
-    return 0;
-  }
-
-  /* Call Keystone now. */
-  const auto ret = issue_admin_token_request(cct, config, t);
-  if (! ret) {
-    token_cache.add_admin(t);
-    token = t.token.id;
-  }
-
-  return ret;
-}
-
-int Service::issue_admin_token_request(CephContext* const cct,
-                                       const Config& config,
-                                       TokenEnvelope& t)
-{
-  std::string token_url = config.get_endpoint_url();
-  if (token_url.empty()) {
-    return -EINVAL;
-  }
-
-  bufferlist token_bl;
-  RGWGetKeystoneAdminToken token_req(cct, &token_bl);
-  token_req.append_header("Content-Type", "application/json");
-  JSONFormatter jf;
-
-  const auto keystone_version = config.get_api_version();
-  if (keystone_version == ApiVersion::VER_2) {
-    AdminTokenRequestVer2 req_serializer(config);
-    req_serializer.dump(&jf);
-
-    std::stringstream ss;
-    jf.flush(ss);
-    token_req.set_post_data(ss.str());
-    token_req.set_send_length(ss.str().length());
-    token_url.append("v2.0/tokens");
-
-  } else if (keystone_version == ApiVersion::VER_3) {
-    AdminTokenRequestVer3 req_serializer(config);
-    req_serializer.dump(&jf);
-
-    std::stringstream ss;
-    jf.flush(ss);
-    token_req.set_post_data(ss.str());
-    token_req.set_send_length(ss.str().length());
-    token_url.append("v3/auth/tokens");
-  } else {
-    return -ENOTSUP;
-  }
-
-  const int ret = token_req.process("POST", token_url.c_str());
-  if (ret < 0) {
-    return ret;
-  }
-
-  /* Detect rejection earlier than during the token parsing step. */
-  if (token_req.get_http_status() ==
-          RGWGetKeystoneAdminToken::HTTP_STATUS_UNAUTHORIZED) {
-    return -EACCES;
-  }
-
-  if (t.parse(cct, token_req.get_subject_token(), token_bl,
-              keystone_version) != 0) {
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-int Service::get_keystone_barbican_token(CephContext * const cct,
-                                         std::string& token)
-{
-  using keystone_config_t = rgw::keystone::CephCtxConfig;
-  using keystone_cache_t = rgw::keystone::TokenCache;
-
-  auto& config = keystone_config_t::get_instance();
-  auto& token_cache = keystone_cache_t::get_instance<keystone_config_t>();
-
-  std::string token_url = config.get_endpoint_url();
-  if (token_url.empty()) {
-    return -EINVAL;
-  }
-
-  rgw::keystone::TokenEnvelope t;
-
-  /* Try cache first. */
-  if (token_cache.find_barbican(t)) {
-    ldout(cct, 20) << "found cached barbican token" << dendl;
-    token = t.token.id;
-    return 0;
-  }
-
-  bufferlist token_bl;
-  RGWKeystoneHTTPTransceiver token_req(cct, &token_bl);
-  token_req.append_header("Content-Type", "application/json");
-  JSONFormatter jf;
-
-  const auto keystone_version = config.get_api_version();
-  if (keystone_version == ApiVersion::VER_2) {
-    rgw::keystone::BarbicanTokenRequestVer2 req_serializer(cct);
-    req_serializer.dump(&jf);
-
-    std::stringstream ss;
-    jf.flush(ss);
-    token_req.set_post_data(ss.str());
-    token_req.set_send_length(ss.str().length());
-    token_url.append("v2.0/tokens");
-
-  } else if (keystone_version == ApiVersion::VER_3) {
-    BarbicanTokenRequestVer3 req_serializer(cct);
-    req_serializer.dump(&jf);
-
-    std::stringstream ss;
-    jf.flush(ss);
-    token_req.set_post_data(ss.str());
-    token_req.set_send_length(ss.str().length());
-    token_url.append("v3/auth/tokens");
-  } else {
-    return -ENOTSUP;
-  }
-
-  ldout(cct, 20) << "Requesting secret from barbican url=" << token_url << dendl;
-  const int ret = token_req.process("POST", token_url.c_str());
-  if (ret < 0) {
-    ldout(cct, 20) << "Barbican process error:" << token_bl.c_str() << dendl;
-    return ret;
-  }
-
-  /* Detect rejection earlier than during the token parsing step. */
-  if (token_req.get_http_status() ==
-      RGWKeystoneHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
-    return -EACCES;
-  }
-
-  if (t.parse(cct, token_req.get_subject_token(), token_bl,
-              keystone_version) != 0) {
-    return -EINVAL;
-  }
-
-  token_cache.add_barbican(t);
-  token = t.token.id;
-  return 0;
-}
-
-
-bool TokenEnvelope::has_role(const std::string& r) const
-{
-  list<Role>::const_iterator iter;
-  for (iter = roles.cbegin(); iter != roles.cend(); ++iter) {
-      if (fnmatch(r.c_str(), ((*iter).name.c_str()), 0) == 0) {
-        return true;
-      }
-  }
-  return false;
-}
-
-int TokenEnvelope::parse(CephContext* const cct,
-                         const std::string& token_str,
-                         ceph::bufferlist& bl,
-                         const ApiVersion version)
-{
-  JSONParser parser;
-  if (! parser.parse(bl.c_str(), bl.length())) {
-    ldout(cct, 0) << "Keystone token parse error: malformed json" << dendl;
-    return -EINVAL;
-  }
-
-  JSONObjIter token_iter = parser.find_first("token");
-  JSONObjIter access_iter = parser.find_first("access");
-
-  try {
-    if (version == rgw::keystone::ApiVersion::VER_2) {
-      if (! access_iter.end()) {
-        decode_v2(*access_iter);
-      } else if (! token_iter.end()) {
-        /* TokenEnvelope structure doesn't follow Identity API v2, so let's
-         * fallback to v3. Otherwise we can assume it's wrongly formatted.
-         * The whole mechanism is a workaround for s3_token middleware that
-         * speaks in v2 disregarding the promise to go with v3. */
-        decode_v3(*token_iter);
-
-        /* Identity v3 conveys the token inforamtion not as a part of JSON but
-         * in the X-Subject-Token HTTP header we're getting from caller. */
-        token.id = token_str;
-      } else {
-        return -EINVAL;
-      }
-    } else if (version == rgw::keystone::ApiVersion::VER_3) {
-      if (! token_iter.end()) {
-        decode_v3(*token_iter);
-        /* v3 suceeded. We have to fill token.id from external input as it
-         * isn't a part of the JSON response anymore. It has been moved
-         * to X-Subject-Token HTTP header instead. */
-        token.id = token_str;
-      } else if (! access_iter.end()) {
-        /* If the token cannot be parsed according to V3, try V2. */
-        decode_v2(*access_iter);
-      } else {
-        return -EINVAL;
-      }
-    } else {
-      return -ENOTSUP;
-    }
-  } catch (JSONDecoder::err& err) {
-    ldout(cct, 0) << "Keystone token parse error: " << err.message << dendl;
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-bool TokenCache::find(const std::string& token_id,
-                      rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-  return find_locked(token_id, token);
-}
-
-bool TokenCache::find_locked(const std::string& token_id,
-                             rgw::keystone::TokenEnvelope& token)
-{
-  assert(lock.is_locked_by_me());
-  map<string, token_entry>::iterator iter = tokens.find(token_id);
-  if (iter == tokens.end()) {
-    if (perfcounter) perfcounter->inc(l_rgw_keystone_token_cache_miss);
-    return false;
-  }
-
-  token_entry& entry = iter->second;
-  tokens_lru.erase(entry.lru_iter);
-
-  if (entry.token.expired()) {
-    tokens.erase(iter);
-    if (perfcounter) perfcounter->inc(l_rgw_keystone_token_cache_hit);
-    return false;
-  }
-  token = entry.token;
-
-  tokens_lru.push_front(token_id);
-  entry.lru_iter = tokens_lru.begin();
-
-  if (perfcounter) perfcounter->inc(l_rgw_keystone_token_cache_hit);
-
-  return true;
-}
-
-bool TokenCache::find_admin(rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-
-  return find_locked(admin_token_id, token);
-}
-
-bool TokenCache::find_barbican(rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-
-  return find_locked(barbican_token_id, token);
-}
-
-void TokenCache::add(const std::string& token_id,
-                     const rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-  add_locked(token_id, token);
-}
-
-void TokenCache::add_locked(const std::string& token_id,
-                            const rgw::keystone::TokenEnvelope& token)
-{
-  assert(lock.is_locked_by_me());
-  map<string, token_entry>::iterator iter = tokens.find(token_id);
-  if (iter != tokens.end()) {
-    token_entry& e = iter->second;
-    tokens_lru.erase(e.lru_iter);
-  }
-
-  tokens_lru.push_front(token_id);
-  token_entry& entry = tokens[token_id];
-  entry.token = token;
-  entry.lru_iter = tokens_lru.begin();
-
-  while (tokens_lru.size() > max) {
-    list<string>::reverse_iterator riter = tokens_lru.rbegin();
-    iter = tokens.find(*riter);
-    assert(iter != tokens.end());
-    tokens.erase(iter);
-    tokens_lru.pop_back();
-  }
-}
-
-void TokenCache::add_admin(const rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-
-  rgw_get_token_id(token.token.id, admin_token_id);
-  add_locked(admin_token_id, token);
-}
-
-void TokenCache::add_barbican(const rgw::keystone::TokenEnvelope& token)
-{
-  Mutex::Locker l(lock);
-
-  rgw_get_token_id(token.token.id, barbican_token_id);
-  add_locked(barbican_token_id, token);
-}
-
-void TokenCache::invalidate(const std::string& token_id)
-{
-  Mutex::Locker l(lock);
-  map<string, token_entry>::iterator iter = tokens.find(token_id);
-  if (iter == tokens.end())
-    return;
-
-  ldout(cct, 20) << "invalidating revoked token id=" << token_id << dendl;
-  token_entry& e = iter->second;
-  tokens_lru.erase(e.lru_iter);
-  tokens.erase(iter);
-}
-
-int TokenCache::RevokeThread::check_revoked()
-{
-  std::string url;
-  std::string token;
-
-  bufferlist bl;
-  RGWGetRevokedTokens req(cct, &bl);
-
-  if (rgw::keystone::Service::get_admin_token(cct, *cache, config, token) < 0) {
-    return -EINVAL;
-  }
-
-  url = config.get_endpoint_url();
-  if (url.empty()) {
-    return -EINVAL;
-  }
-
-  req.append_header("X-Auth-Token", token);
-
-  const auto keystone_version = config.get_api_version();
-  if (keystone_version == rgw::keystone::ApiVersion::VER_2) {
-    url.append("v2.0/tokens/revoked");
-  } else if (keystone_version == rgw::keystone::ApiVersion::VER_3) {
-    url.append("v3/auth/tokens/OS-PKI/revoked");
-  }
-
-  req.set_send_length(0);
-  int ret = req.process(url.c_str());
-  if (ret < 0) {
-    return ret;
-  }
-
-  bl.append((char)0); // NULL terminate for debug output
-
-  ldout(cct, 10) << "request returned " << bl.c_str() << dendl;
-
-  JSONParser parser;
-
-  if (!parser.parse(bl.c_str(), bl.length())) {
-    ldout(cct, 0) << "malformed json" << dendl;
-    return -EINVAL;
-  }
-
-  JSONObjIter iter = parser.find_first("signed");
-  if (iter.end()) {
-    ldout(cct, 0) << "revoked tokens response is missing signed section" << dendl;
-    return -EINVAL;
-  }
-
-  JSONObj *signed_obj = *iter;
-  const std::string signed_str = signed_obj->get_data();
-
-  ldout(cct, 10) << "signed=" << signed_str << dendl;
-
-  std::string signed_b64;
-  ret = rgw_open_cms_envelope(cct, signed_str, signed_b64);
-  if (ret < 0) {
-    return ret;
-  }
-
-  ldout(cct, 10) << "content=" << signed_b64 << dendl;
-  
-  bufferlist json;
-  ret = rgw_decode_b64_cms(cct, signed_b64, json);
-  if (ret < 0) {
-    return ret;
-  }
-
-  ldout(cct, 10) << "ceph_decode_cms: decoded: " << json.c_str() << dendl;
-
-  JSONParser list_parser;
-  if (!list_parser.parse(json.c_str(), json.length())) {
-    ldout(cct, 0) << "malformed json" << dendl;
-    return -EINVAL;
-  }
-
-  JSONObjIter revoked_iter = list_parser.find_first("revoked");
-  if (revoked_iter.end()) {
-    ldout(cct, 0) << "no revoked section in json" << dendl;
-    return -EINVAL;
-  }
-
-  JSONObj *revoked_obj = *revoked_iter;
-
-  JSONObjIter tokens_iter = revoked_obj->find_first();
-  for (; !tokens_iter.end(); ++tokens_iter) {
-    JSONObj *o = *tokens_iter;
-
-    JSONObj *token = o->find_obj("id");
-    if (!token) {
-      ldout(cct, 0) << "bad token in array, missing id" << dendl;
-      continue;
-    }
-
-    const std::string token_id = token->get_data();
-    cache->invalidate(token_id);
-  }
-  
-  return 0;
-}
-
-bool TokenCache::going_down() const
-{
-  return down_flag;
-}
-
-void* TokenCache::RevokeThread::entry()
-{
-  do {
-    ldout(cct, 2) << "keystone revoke thread: start" << dendl;
-    int r = check_revoked();
-    if (r < 0) {
-      ldout(cct, 0) << "ERROR: keystone revocation processing returned error r="
-                    << r << dendl;
-    }
-
-    if (cache->going_down()) {
-      break;
-    }
-
-    lock.Lock();
-    cond.WaitInterval(lock,
-                     utime_t(cct->_conf->rgw_keystone_revocation_interval, 0));
-    lock.Unlock();
-  } while (!cache->going_down());
-
-  return nullptr;
-}
-
-void TokenCache::RevokeThread::stop()
-{
-  Mutex::Locker l(lock);
-  cond.Signal();
-}
-
-}; /* namespace keystone */
-}; /* namespace rgw */