1
#include "source/common/tls/context_manager_impl.h"
2

            
3
#include <algorithm>
4
#include <cstddef>
5
#include <functional>
6
#include <limits>
7

            
8
#include "envoy/stats/scope.h"
9

            
10
#include "source/common/common/assert.h"
11
#include "source/common/config/utility.h"
12
#include "source/common/tls/client_context_impl.h"
13
#include "source/common/tls/context_impl.h"
14

            
15
namespace Envoy {
16
namespace Extensions {
17
namespace TransportSockets {
18
namespace Tls {
19

            
20
ContextManagerImpl::ContextManagerImpl(Server::Configuration::CommonFactoryContext& factory_context)
21
24016
    : factory_context_(factory_context) {}
22

            
23
absl::StatusOr<Envoy::Ssl::ClientContextSharedPtr>
24
ContextManagerImpl::createSslClientContext(Stats::Scope& scope,
25
3543
                                           const Envoy::Ssl::ClientContextConfig& config) {
26
3543
  ASSERT_IS_MAIN_OR_TEST_THREAD();
27
3543
  if (!config.isReady()) {
28
62
    return nullptr;
29
62
  }
30
3481
  auto context_or_error = ClientContextImpl::create(scope, config, factory_context_);
31
3481
  RETURN_IF_NOT_OK(context_or_error.status());
32
3461
  Envoy::Ssl::ClientContextSharedPtr context = std::move(context_or_error.value());
33
3461
  contexts_.insert(context);
34
3461
  return context;
35
3481
}
36

            
37
absl::StatusOr<Envoy::Ssl::ServerContextSharedPtr>
38
ContextManagerImpl::createSslServerContext(Stats::Scope& scope,
39
                                           const Envoy::Ssl::ServerContextConfig& config,
40
3527
                                           Ssl::ContextAdditionalInitFunc additional_init) {
41
3527
  ASSERT_IS_MAIN_OR_TEST_THREAD();
42
3527
  if (!config.isReady()) {
43
42
    return nullptr;
44
42
  }
45

            
46
3485
  auto factory = Envoy::Config::Utility::getFactoryByName<ServerContextFactory>(
47
3485
      "envoy.ssl.server_context_factory.default");
48
3485
  if (!factory) {
49
    IS_ENVOY_BUG("No envoy.ssl.server_context_factory registered");
50
    return nullptr;
51
  }
52
3485
  absl::StatusOr<Envoy::Ssl::ServerContextSharedPtr> context_or_error =
53
3485
      factory->createServerContext(scope, config, factory_context_, std::move(additional_init));
54
3485
  RETURN_IF_NOT_OK(context_or_error.status());
55
3462
  contexts_.insert(*context_or_error);
56
3462
  return *context_or_error;
57
3485
}
58

            
59
22360
absl::optional<uint32_t> ContextManagerImpl::daysUntilFirstCertExpires() const {
60
22360
  absl::optional<uint32_t> ret = absl::make_optional(std::numeric_limits<uint32_t>::max());
61
22581
  for (const auto& context : contexts_) {
62
6165
    if (context) {
63
6165
      const absl::optional<uint32_t> tmp = context->daysUntilFirstCertExpires();
64
6165
      if (!tmp.has_value()) {
65
4
        return absl::nullopt;
66
4
      }
67
6161
      ret = std::min<uint32_t>(tmp.value(), ret.value());
68
6161
    }
69
6165
  }
70
22356
  return ret;
71
22360
}
72

            
73
22357
absl::optional<uint64_t> ContextManagerImpl::secondsUntilFirstOcspResponseExpires() const {
74
22357
  absl::optional<uint64_t> ret;
75
22578
  for (const auto& context : contexts_) {
76
6162
    if (context) {
77
6162
      auto next_expiration = context->secondsUntilFirstOcspResponseExpires();
78
6162
      if (next_expiration) {
79
2398
        ret = std::min<uint64_t>(next_expiration.value(),
80
2398
                                 ret.value_or(std::numeric_limits<uint64_t>::max()));
81
2398
      }
82
6162
    }
83
6162
  }
84
22357
  return ret;
85
22357
}
86

            
87
5
void ContextManagerImpl::iterateContexts(std::function<void(const Envoy::Ssl::Context&)> callback) {
88
5
  for (const auto& context : contexts_) {
89
2
    if (context) {
90
2
      callback(*context);
91
2
    }
92
2
  }
93
5
}
94

            
95
7040
void ContextManagerImpl::removeContext(const Envoy::Ssl::ContextSharedPtr& old_context) {
96
7040
  if (old_context != nullptr) {
97
6922
    auto erased = contexts_.erase(old_context);
98
    // The contexts is expected to be added before is removed.
99
    // And the prod ssl factory implementation guarantees any context is removed exactly once.
100
6922
    ASSERT(erased == 1);
101
6922
  }
102
7040
}
103

            
104
} // namespace Tls
105
} // namespace TransportSockets
106
} // namespace Extensions
107
} // namespace Envoy