LCOV - code coverage report
Current view: top level - source/extensions/common/dynamic_forward_proxy - dns_cache.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 3 20 15.0 %
Date: 2024-01-05 06:35:25 Functions: 3 10 30.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "envoy/common/random_generator.h"
       4             : #include "envoy/event/dispatcher.h"
       5             : #include "envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.pb.h"
       6             : #include "envoy/singleton/manager.h"
       7             : #include "envoy/thread_local/thread_local.h"
       8             : #include "envoy/upstream/resource_manager.h"
       9             : 
      10             : #include "source/common/http/header_utility.h"
      11             : #include "source/common/runtime/runtime_features.h"
      12             : 
      13             : namespace Envoy {
      14             : namespace Extensions {
      15             : namespace Common {
      16             : namespace DynamicForwardProxy {
      17             : 
      18             : /**
      19             :  * A cached DNS host.
      20             :  */
      21             : class DnsHostInfo {
      22             : public:
      23             :   // DFP hosts are created after a DNS lookup for a domain name (e.g. foo.com) but are created
      24             :   // with an IP address and port to resolve to. To prevent bugs where we insert say foo.com
      25             :   // (default port 80) then later look up foo.com (default port 443) and get IP addresses with
      26             :   // port 80, we "fully qualify" hostnames with the port.
      27             :   //
      28             :   // This normalizes hostnames, respecting the port if it exists, and adding the default port
      29             :   // if there is no port.
      30           0 :   static std::string normalizeHostForDfp(absl::string_view host, uint16_t default_port) {
      31           0 :     if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.dfp_mixed_scheme")) {
      32           0 :       return std::string(host);
      33           0 :     }
      34           0 :     if (Http::HeaderUtility::hostHasPort(host)) {
      35           0 :       return std::string(host);
      36           0 :     }
      37           0 :     return absl::StrCat(host, ":", default_port);
      38           0 :   }
      39             : 
      40           0 :   virtual ~DnsHostInfo() = default;
      41             : 
      42             :   /**
      43             :    * Returns the host's currently resolved address. This address may change periodically due to
      44             :    * async re-resolution. This address may be null in the case of failed resolution.
      45             :    */
      46             :   virtual Network::Address::InstanceConstSharedPtr address() const PURE;
      47             : 
      48             :   /**
      49             :    * Returns whether the first DNS resolving attempt is completed or not.
      50             :    */
      51             :   virtual bool firstResolveComplete() const PURE;
      52             : 
      53             :   /**
      54             :    * Returns the host's currently resolved address. These addresses may change periodically due to
      55             :    * async re-resolution.
      56             :    */
      57             :   virtual std::vector<Network::Address::InstanceConstSharedPtr> addressList() const PURE;
      58             : 
      59             :   /**
      60             :    * Returns the host that was actually resolved via DNS. If port was originally specified it will
      61             :    * be stripped from this return value.
      62             :    */
      63             :   virtual const std::string& resolvedHost() const PURE;
      64             : 
      65             :   /**
      66             :    * Returns whether the original host is an IP address.
      67             :    */
      68             :   virtual bool isIpAddress() const PURE;
      69             : 
      70             :   /**
      71             :    * Indicates that the host has been used and should not be purged depending on any configured
      72             :    * TTL policy
      73             :    */
      74             :   virtual void touch() PURE;
      75             : };
      76             : 
      77             : using DnsHostInfoSharedPtr = std::shared_ptr<DnsHostInfo>;
      78             : 
      79             : #define ALL_DNS_CACHE_CIRCUIT_BREAKERS_STATS(OPEN_GAUGE, REMAINING_GAUGE)                          \
      80           0 :   OPEN_GAUGE(rq_pending_open, Accumulate)                                                          \
      81           0 :   REMAINING_GAUGE(rq_pending_remaining, Accumulate)
      82             : 
      83             : struct DnsCacheCircuitBreakersStats {
      84             :   ALL_DNS_CACHE_CIRCUIT_BREAKERS_STATS(GENERATE_GAUGE_STRUCT, GENERATE_GAUGE_STRUCT)
      85             : };
      86             : 
      87             : /**
      88             :  * A resource manager of DNS Cache.
      89             :  */
      90             : class DnsCacheResourceManager {
      91             : public:
      92           0 :   virtual ~DnsCacheResourceManager() = default;
      93             : 
      94             :   /**
      95             :    * Returns the resource limit of pending requests to DNS.
      96             :    */
      97             :   virtual ResourceLimit& pendingRequests() PURE;
      98             : 
      99             :   /**
     100             :    * Returns the reference of stats for dns cache circuit breakers.
     101             :    */
     102             :   virtual DnsCacheCircuitBreakersStats& stats() PURE;
     103             : };
     104             : 
     105             : /**
     106             :  * A cache of DNS hosts. Hosts will re-resolve their addresses or be automatically purged
     107             :  * depending on configured policy.
     108             :  */
     109             : class DnsCache {
     110             : public:
     111             :   /**
     112             :    * Callbacks used in the loadDnsCacheEntry() method.
     113             :    */
     114             :   class LoadDnsCacheEntryCallbacks {
     115             :   public:
     116           0 :     virtual ~LoadDnsCacheEntryCallbacks() = default;
     117             : 
     118             :     /**
     119             :      * Called when the DNS cache load is complete (or failed).
     120             :      *
     121             :      * @param host_info the DnsHostInfo for the resolved host.
     122             :      */
     123             :     virtual void onLoadDnsCacheComplete(const DnsHostInfoSharedPtr& host_info) PURE;
     124             :   };
     125             : 
     126             :   /**
     127             :    * Handle returned from loadDnsCacheEntry(). Destruction of the handle will cancel any future
     128             :    * callback.
     129             :    */
     130             :   class LoadDnsCacheEntryHandle {
     131             :   public:
     132           0 :     virtual ~LoadDnsCacheEntryHandle() = default;
     133             :   };
     134             : 
     135             :   using LoadDnsCacheEntryHandlePtr = std::unique_ptr<LoadDnsCacheEntryHandle>;
     136             : 
     137             :   /**
     138             :    * Update callbacks that can be registered in the addUpdateCallbacks() method.
     139             :    */
     140             :   class UpdateCallbacks {
     141             :   public:
     142           0 :     virtual ~UpdateCallbacks() = default;
     143             : 
     144             :     /**
     145             :      * Called when a host has been added or has had its address updated.
     146             :      * @param host supplies the added/updated host.
     147             :      * @param host_info supplies the associated host info.
     148             :      */
     149             :     virtual void onDnsHostAddOrUpdate(const std::string& host,
     150             :                                       const DnsHostInfoSharedPtr& host_info) PURE;
     151             : 
     152             :     /**
     153             :      * Called when a host has been removed.
     154             :      * @param host supplies the removed host.
     155             :      */
     156             :     virtual void onDnsHostRemove(const std::string& host) PURE;
     157             : 
     158             :     /**
     159             :      * Called when any resolution for a host completes.
     160             :      * @param host supplies the added/updated host.
     161             :      * @param host_info supplies the associated host info.
     162             :      * @param status supplies the resolution status.
     163             :      */
     164             :     virtual void onDnsResolutionComplete(const std::string& host,
     165             :                                          const DnsHostInfoSharedPtr& host_info,
     166             :                                          Network::DnsResolver::ResolutionStatus status) PURE;
     167             :   };
     168             : 
     169             :   /**
     170             :    * Handle returned from addUpdateCallbacks(). Destruction of the handle will remove the
     171             :    * registered callbacks.
     172             :    */
     173             :   class AddUpdateCallbacksHandle {
     174             :   public:
     175           0 :     virtual ~AddUpdateCallbacksHandle() = default;
     176             :   };
     177             : 
     178             :   using AddUpdateCallbacksHandlePtr = std::unique_ptr<AddUpdateCallbacksHandle>;
     179             : 
     180           5 :   virtual ~DnsCache() = default;
     181             : 
     182             :   /**
     183             :    * Initiate a DNS cache load.
     184             :    * @param host supplies the host to load. Hosts are cached inclusive of port, even though the
     185             :    *             port will be stripped during resolution. This means that 'a.b.c' and 'a.b.c:9001'
     186             :    *             will both resolve 'a.b.c' but will generate different host entries with different
     187             :    *             target ports.
     188             :    * @param default_port supplies the port to use if the host does not have a port embedded in it.
     189             :    * @param callbacks supplies the cache load callbacks to invoke if async processing is needed.
     190             :    * @return a cache load result which includes both a status and handle. If the handle is non-null
     191             :    *         the callbacks will be invoked at a later time, otherwise consult the status for the
     192             :    *         reason the cache is not loading. In this case, callbacks will never be called.
     193             :    */
     194             :   enum class LoadDnsCacheEntryStatus {
     195             :     // The cache entry is already loaded. Callbacks will not be called.
     196             :     InCache,
     197             :     // The cache entry is loading. Callbacks will be called at a later time unless cancelled.
     198             :     Loading,
     199             :     // The cache is full and the requested host is not in cache. Callbacks will not be called.
     200             :     Overflow
     201             :   };
     202             : 
     203             :   struct LoadDnsCacheEntryResult {
     204             :     LoadDnsCacheEntryStatus status_;
     205             :     LoadDnsCacheEntryHandlePtr handle_;
     206             :     absl::optional<DnsHostInfoSharedPtr> host_info_;
     207             :   };
     208             : 
     209             :   /**
     210             :    * Attempt to load a DNS cache entry.
     211             :    * @param host the hostname to lookup
     212             :    * @param default_port the port to use
     213             :    * @param is_proxy_lookup indicates if the request is safe to fast-fail. The Dynamic Forward Proxy
     214             :    * filter sets this to true if no address is necessary due to an upstream proxy being configured.
     215             :    * @return a handle that on destruction will de-register the callbacks.
     216             :    */
     217             :   virtual LoadDnsCacheEntryResult loadDnsCacheEntry(absl::string_view host, uint16_t default_port,
     218             :                                                     bool is_proxy_lookup,
     219             :                                                     LoadDnsCacheEntryCallbacks& callbacks) PURE;
     220             : 
     221             :   /**
     222             :    * Add update callbacks to the cache.
     223             :    * @param callbacks supplies the callbacks to add.
     224             :    * @return a handle that on destruction will de-register the callbacks.
     225             :    */
     226             :   virtual AddUpdateCallbacksHandlePtr addUpdateCallbacks(UpdateCallbacks& callbacks) PURE;
     227             : 
     228             :   using IterateHostMapCb = std::function<void(absl::string_view, const DnsHostInfoSharedPtr&)>;
     229             : 
     230             :   /**
     231             :    * Iterates over all entries in the cache, calling a callback for each entry
     232             :    *
     233             :    * @param iterate_callback the callback to invoke for each entry in the cache
     234             :    */
     235             :   virtual void iterateHostMap(IterateHostMapCb iterate_callback) PURE;
     236             : 
     237             :   /**
     238             :    * Retrieve the DNS host info of a given host currently stored in the cache.
     239             :    * @param host_name supplies the host name.
     240             :    * @return the DNS host info associated with the given host name if the host's address is cached,
     241             :    * otherwise `absl::nullopt`.
     242             :    */
     243             :   virtual absl::optional<const DnsHostInfoSharedPtr> getHost(absl::string_view host_name) PURE;
     244             : 
     245             :   /**
     246             :    * Check if a DNS request is allowed given resource limits.
     247             :    * @return RAII handle for pending request circuit breaker if the request was allowed.
     248             :    */
     249             :   virtual Upstream::ResourceAutoIncDecPtr canCreateDnsRequest() PURE;
     250             : 
     251             :   /**
     252             :    * Force a DNS refresh of all known hosts, ignoring any ongoing failure or success timers. This
     253             :    * can be used in response to network changes which might alter DNS responses, for example.
     254             :    */
     255             :   virtual void forceRefreshHosts() PURE;
     256             : };
     257             : 
     258             : using DnsCacheSharedPtr = std::shared_ptr<DnsCache>;
     259             : 
     260             : /**
     261             :  * A manager for multiple DNS caches.
     262             :  */
     263             : class DnsCacheManager {
     264             : public:
     265           5 :   virtual ~DnsCacheManager() = default;
     266             : 
     267             :   /**
     268             :    * Get a DNS cache.
     269             :    * @param config supplies the cache parameters. If a cache exists with the same parameters it
     270             :    *               will be returned, otherwise a new one will be created.
     271             :    */
     272             :   virtual absl::StatusOr<DnsCacheSharedPtr>
     273             :   getCache(const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config) PURE;
     274             : 
     275             :   /**
     276             :    * Look up an existing DNS cache by name.
     277             :    * @param name supplies the cache name to look up. If a cache exists with the same name it
     278             :    *             will be returned.
     279             :    * @return pointer to the cache if it exists, nullptr otherwise.
     280             :    */
     281             :   virtual DnsCacheSharedPtr lookUpCacheByName(absl::string_view cache_name) PURE;
     282             : };
     283             : 
     284             : using DnsCacheManagerSharedPtr = std::shared_ptr<DnsCacheManager>;
     285             : 
     286             : /**
     287             :  * Factory for getting a DNS cache manager.
     288             :  */
     289             : class DnsCacheManagerFactory {
     290             : public:
     291           5 :   virtual ~DnsCacheManagerFactory() = default;
     292             : 
     293             :   /**
     294             :    * Get a DNS cache manager.
     295             :    */
     296             :   virtual DnsCacheManagerSharedPtr get() PURE;
     297             : };
     298             : 
     299             : } // namespace DynamicForwardProxy
     300             : } // namespace Common
     301             : } // namespace Extensions
     302             : } // namespace Envoy

Generated by: LCOV version 1.15