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
24052
    : factory_context_(factory_context) {}
22

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

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

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

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

            
73
22365
absl::optional<uint64_t> ContextManagerImpl::secondsUntilFirstOcspResponseExpires() const {
74
22365
  absl::optional<uint64_t> ret;
75
22590
  for (const auto& context : contexts_) {
76
6170
    if (context) {
77
6170
      auto next_expiration = context->secondsUntilFirstOcspResponseExpires();
78
6170
      if (next_expiration) {
79
2397
        ret = std::min<uint64_t>(next_expiration.value(),
80
2397
                                 ret.value_or(std::numeric_limits<uint64_t>::max()));
81
2397
      }
82
6170
    }
83
6170
  }
84
22365
  return ret;
85
22365
}
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
7056
void ContextManagerImpl::removeContext(const Envoy::Ssl::ContextSharedPtr& old_context) {
96
7056
  if (old_context != nullptr) {
97
6938
    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
6938
    ASSERT(erased == 1);
101
6938
  }
102
7056
}
103

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