Advertisement
Guest User

Untitled

a guest
Apr 13th, 2017
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
LDIF 5.85 KB | None | 0 0
  1. diff --git a/plugins/s3_auth/s3_auth.cc b/plugins/s3_auth/s3_auth.cc
  2. index a52b07fa1..7dc92fc03 100644
  3. --- a/plugins/s3_auth/s3_auth.cc
  4. +++ b/plugins/s3_auth/s3_auth.cc
  5. @@ -27,6 +27,10 @@
  6.  #include <stdlib.h>
  7.  #include <limits.h>
  8.  #include <ctype.h>
  9. +#include <sys/time.h>
  10. +
  11. +#include <string>
  12. +#include <unordered_map>
  13.  
  14.  #include <openssl/sha.h>
  15.  #include <openssl/hmac.h>
  16. @@ -42,6 +46,24 @@ static const char PLUGIN_NAME[] = "s3_auth";
  17.  static const char DATE_FMT[]    = "%a, %d %b %Y %H:%M:%S %z";
  18.  
  19.  ///////////////////////////////////////////////////////////////////////////////
  20. +// Cache for the secrets file, to avoid reading / loding them repeatedly on
  21. +// a reload of remap.config. This gets cached for 60s (not configurable).
  22. +//
  23. +class S3Config;
  24. +
  25. +class ConfigCache
  26. +{
  27. +public:
  28. +  S3Config *get(const char *file);
  29. +
  30. +private:
  31. +  std::unordered_map<std::string, std::pair<S3Config *, int>> _cache;
  32. +  static const int _ttl = 60;
  33. +};
  34. +
  35. +ConfigCache gConfCache;
  36. +
  37. +///////////////////////////////////////////////////////////////////////////////
  38.  // One configuration setup
  39.  //
  40.  int event_handler(TSCont, TSEvent, void *); // Forward declaration
  41. @@ -70,6 +92,26 @@ public:
  42.      return _secret && (_secret_len > 0) && _keyid && (_keyid_len > 0) && (2 == _version);
  43.    }
  44.  
  45. +  // Used to copy relevant configurations that can be configured in a config file
  46. +  void
  47. +  copy_from(const S3Config *src)
  48. +  {
  49. +    if (src->_secret) {
  50. +      _secret     = src->_secret;
  51. +      _secret_len = src->_secret_len;
  52. +    }
  53. +
  54. +    if (src->_keyid) {
  55. +      _keyid     = src->_keyid;
  56. +      _keyid_len = src->_keyid_len;
  57. +    }
  58. +
  59. +    // ToDo: this is a little odd, in that we'd overwrite something specified via getop parsing :/. Would
  60. +    // need to know if the configuration file has modified these. But maybe that's an unusual use case...
  61. +    _version   = src->_version;
  62. +    _virt_host = src->_virt_host;
  63. +  }
  64. +
  65.    // Getters
  66.    bool
  67.    virt_host() const
  68. @@ -124,7 +166,7 @@ public:
  69.    }
  70.  
  71.    // Parse configs from an external file
  72. -  bool parse_config(const char *config);
  73. +  bool parse_config(const std::string &filename);
  74.  
  75.    // This should be called from the remap plugin, to setup the TXN hook for
  76.    // SEND_REQUEST_HDR, such that we always attach the appropriate S3 auth.
  77. @@ -145,24 +187,17 @@ private:
  78.  };
  79.  
  80.  bool
  81. -S3Config::parse_config(const char *config)
  82. +S3Config::parse_config(const std::string &filename)
  83.  {
  84. -  if (!config) {
  85. +  if (0 == filename.size()) {
  86.      TSError("[%s] called without a config file, this is broken", PLUGIN_NAME);
  87.      return false;
  88.    } else {
  89. -    char filename[PATH_MAX + 1];
  90. -
  91. -    if (*config != '/') {
  92. -      snprintf(filename, sizeof(filename) - 1, "%s/%s", TSConfigDirGet(), config);
  93. -      config = filename;
  94. -    }
  95. -
  96.      char line[512]; // These are long lines ...
  97. -    FILE *file = fopen(config, "r");
  98. +    FILE *file = fopen(filename.c_str(), "r");
  99.  
  100.      if (nullptr == file) {
  101. -      TSError("[%s] unable to open %s", PLUGIN_NAME, config);
  102. +      TSError("[%s] unable to open %s", PLUGIN_NAME, filename.c_str());
  103.        return false;
  104.      }
  105.  
  106. @@ -209,6 +244,51 @@ S3Config::parse_config(const char *config)
  107.  }
  108.  
  109.  ///////////////////////////////////////////////////////////////////////////////
  110. +// Implementation for the ConfigCache, it has to go here since we have a sort
  111. +// of circular dependency. Note that we always parse / get the configuration
  112. +// for the file, either from cache or by making one. The user of this just
  113. +// has to copy the relevant portions, but should not use the returned object
  114. +// directly (i.e. it must be copied).
  115. +//
  116. +S3Config *
  117. +ConfigCache::get(const char *file)
  118. +{
  119. +  std::string filename;
  120. +  struct timeval tv;
  121. +
  122. +  gettimeofday(&tv, nullptr);
  123. +
  124. +  // Make sure the filename is an absolute path, prepending the config dir if needed
  125. +  if (*file != '/') {
  126. +    filename = TSConfigDirGet();
  127. +    filename += "/";
  128. +  }
  129. +  filename += filename;
  130. +
  131. +  auto it = _cache.find(filename);
  132. +
  133. +  if (it != _cache.end()) {
  134. +    if (tv.tv_sec > (it->second.second + _ttl)) {
  135. +      // Update the cached configuration file.
  136. +      delete it->second.first;
  137. +      it->second.first = new S3Config();
  138. +      it->second.first->parse_config(filename);
  139. +    }
  140. +    return it->second.first;
  141. +  } else {
  142. +    // Create a new cached file.
  143. +    S3Config *s3 = new S3Config();
  144. +
  145. +    s3->parse_config(filename);
  146. +    _cache[filename] = std::make_pair(s3, tv.tv_sec);
  147. +
  148. +    return s3;
  149. +  }
  150. +
  151. +  TSAssert(!"Configuration parsing / caching failed");
  152. +}
  153. +
  154. +///////////////////////////////////////////////////////////////////////////////
  155.  // This class is used to perform the S3 auth generation.
  156.  //
  157.  class S3Request
  158. @@ -541,7 +621,8 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE
  159.      {nullptr, no_argument, nullptr, '\0'},
  160.    };
  161.  
  162. -  S3Config *s3 = new S3Config();
  163. +  S3Config *s3          = new S3Config();
  164. +  S3Config *file_config = nullptr;
  165.  
  166.    // argv contains the "to" and "from" URLs. Skip the first so that the
  167.    // second one poses as the program name.
  168. @@ -553,7 +634,7 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE
  169.  
  170.      switch (opt) {
  171.      case 'c':
  172. -      s3->parse_config(optarg);
  173. +      file_config = gConfCache.get(optarg); // Get cached, or new, config object, from a file
  174.        break;
  175.      case 'a':
  176.        s3->set_keyid(optarg);
  177. @@ -574,6 +655,11 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf ATS_UNUSE
  178.      }
  179.    }
  180.  
  181. +  // Copy the config file secret into our instance of the configuration.
  182. +  if (file_config) {
  183. +    s3->copy_from(file_config);
  184. +  }
  185. +
  186.    // Make sure we got both the shared secret and the AWS secret
  187.    if (!s3->valid()) {
  188.      TSError("[%s] requires both shared and AWS secret configuration", PLUGIN_NAME);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement