1
#pragma once
2

            
3
#include "envoy/config/core/v3/config_source.pb.h"
4
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
5
#include "envoy/secret/secret_manager.h"
6
#include "envoy/secret/secret_provider.h"
7
#include "envoy/server/transport_socket_config.h"
8
#include "envoy/ssl/certificate_validation_context_config.h"
9
#include "envoy/ssl/tls_certificate_config.h"
10

            
11
#include "source/common/common/logger.h"
12
#include "source/common/secret/sds_api.h"
13

            
14
#include "absl/container/node_hash_map.h"
15

            
16
namespace Envoy {
17
namespace Secret {
18

            
19
class SecretManagerImpl : public SecretManager {
20
public:
21
  SecretManagerImpl(OptRef<Server::ConfigTracker> config_tracker);
22
  absl::Status
23
  addStaticSecret(const envoy::extensions::transport_sockets::tls::v3::Secret& secret) override;
24

            
25
  TlsCertificateConfigProviderSharedPtr
26
  findStaticTlsCertificateProvider(const std::string& name) const override;
27

            
28
  CertificateValidationContextConfigProviderSharedPtr
29
  findStaticCertificateValidationContextProvider(const std::string& name) const override;
30

            
31
  TlsSessionTicketKeysConfigProviderSharedPtr
32
  findStaticTlsSessionTicketKeysContextProvider(const std::string& name) const override;
33

            
34
  GenericSecretConfigProviderSharedPtr
35
  findStaticGenericSecretProvider(const std::string& name) const override;
36

            
37
  TlsCertificateConfigProviderSharedPtr createInlineTlsCertificateProvider(
38
      const envoy::extensions::transport_sockets::tls::v3::TlsCertificate& tls_certificate)
39
      override;
40

            
41
  CertificateValidationContextConfigProviderSharedPtr
42
  createInlineCertificateValidationContextProvider(
43
      const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext&
44
          certificate_validation_context) override;
45

            
46
  TlsSessionTicketKeysConfigProviderSharedPtr createInlineTlsSessionTicketKeysProvider(
47
      const envoy::extensions::transport_sockets::tls::v3::TlsSessionTicketKeys&
48
          tls_session_ticket_keys) override;
49

            
50
  GenericSecretConfigProviderSharedPtr createInlineGenericSecretProvider(
51
      const envoy::extensions::transport_sockets::tls::v3::GenericSecret& generic_secret) override;
52

            
53
  TlsCertificateConfigProviderSharedPtr
54
  findOrCreateTlsCertificateProvider(const envoy::config::core::v3::ConfigSource& config_source,
55
                                     const std::string& config_name,
56
                                     Server::Configuration::ServerFactoryContext& server_context,
57
                                     OptRef<Init::Manager> init_manager, bool warm) override;
58

            
59
  CertificateValidationContextConfigProviderSharedPtr
60
  findOrCreateCertificateValidationContextProvider(
61
      const envoy::config::core::v3::ConfigSource& config_source, const std::string& config_name,
62
      Server::Configuration::ServerFactoryContext& server_context,
63
      Init::Manager& init_manager) override;
64

            
65
  TlsSessionTicketKeysConfigProviderSharedPtr findOrCreateTlsSessionTicketKeysContextProvider(
66
      const envoy::config::core::v3::ConfigSource& config_source, const std::string& config_name,
67
      Server::Configuration::ServerFactoryContext& server_context,
68
      Init::Manager& init_manager) override;
69

            
70
  GenericSecretConfigProviderSharedPtr
71
  findOrCreateGenericSecretProvider(const envoy::config::core::v3::ConfigSource& config_source,
72
                                    const std::string& config_name,
73
                                    Server::Configuration::ServerFactoryContext& server_context,
74
                                    Init::Manager& init_manager) override;
75

            
76
private:
77
  ProtobufTypes::MessagePtr dumpSecretConfigs(const Matchers::StringMatcher& name_matcher);
78

            
79
  template <class SecretType>
80
  class DynamicSecretProviders : public Logger::Loggable<Logger::Id::secret> {
81
  public:
82
    // Finds or creates SdsApi object.
83
    std::shared_ptr<SecretType>
84
    findOrCreate(const envoy::config::core::v3::ConfigSource& sds_config_source,
85
                 const std::string& config_name,
86
                 Server::Configuration::ServerFactoryContext& server_context,
87
261
                 OptRef<Init::Manager> init_manager, bool warm) {
88
261
      const std::string map_key =
89
261
          absl::StrCat(MessageUtil::hash(sds_config_source), ".", config_name);
90

            
91
261
      std::shared_ptr<SecretType> secret_provider = dynamic_secret_providers_[map_key].lock();
92
261
      if (!secret_provider) {
93
        // SdsApi is owned by ListenerImpl and ClusterInfo which are destroyed before
94
        // SecretManagerImpl. It is safe to invoke this callback at the destructor of SdsApi.
95
247
        std::function<void()> unregister_secret_provider = [map_key, this]() {
96
247
          removeDynamicSecretProvider(map_key);
97
247
        };
98
247
        secret_provider = SecretType::create(server_context, sds_config_source, config_name,
99
247
                                             unregister_secret_provider, warm);
100
247
        dynamic_secret_providers_[map_key] = secret_provider;
101
247
      }
102
      // It is important to add the init target to the manager regardless the secret provider is new
103
      // or existing. Different clusters / listeners can share same secret so they have to be marked
104
      // warming correctly.
105

            
106
      // Note that we are not using server_context's init manager because in some cases,
107
      // for example oauth2 filter with sds config, it could be server's init manager. In oauth2
108
      // filter example, if the filter config is dynamic, it could be received from xds server when
109
      // the server's init manager is already in the initialized state. In that situation, adding
110
      // init target to the initialized init manager will lead to assertion failure.
111
      //
112
      // It is expected that correct init manager will be passed to this method by the caller
113
      // separately.
114
261
      if (init_manager) {
115
237
        init_manager->add(*secret_provider->initTarget());
116
254
      } else {
117
24
        secret_provider->start();
118
24
      }
119
261
      return secret_provider;
120
261
    }
121

            
122
252
    std::vector<std::shared_ptr<SecretType>> allSecretProviders() {
123
252
      std::vector<std::shared_ptr<SecretType>> providers;
124
252
      for (const auto& secret_entry : dynamic_secret_providers_) {
125
44
        std::shared_ptr<SecretType> secret_provider = secret_entry.second.lock();
126
44
        if (secret_provider) {
127
44
          providers.push_back(std::move(secret_provider));
128
44
        }
129
44
      }
130
252
      return providers;
131
252
    }
132

            
133
  private:
134
    // Removes dynamic secret provider which has been deleted.
135
247
    void removeDynamicSecretProvider(const std::string& map_key) {
136
247
      ENVOY_LOG(debug, "Unregister secret provider. hash key: {}", map_key);
137

            
138
247
      auto num_deleted = dynamic_secret_providers_.erase(map_key);
139
247
      ASSERT(num_deleted == 1, "");
140
247
    }
141

            
142
    absl::node_hash_map<std::string, std::weak_ptr<SecretType>> dynamic_secret_providers_;
143
  };
144

            
145
  // Manages pairs of secret name and TlsCertificateConfigProviderSharedPtr.
146
  absl::node_hash_map<std::string, TlsCertificateConfigProviderSharedPtr>
147
      static_tls_certificate_providers_;
148

            
149
  // Manages pairs of secret name and CertificateValidationContextConfigProviderSharedPtr.
150
  absl::node_hash_map<std::string, CertificateValidationContextConfigProviderSharedPtr>
151
      static_certificate_validation_context_providers_;
152

            
153
  absl::node_hash_map<std::string, TlsSessionTicketKeysConfigProviderSharedPtr>
154
      static_session_ticket_keys_providers_;
155

            
156
  // Manages pairs of secret name and GenericSecretConfigProviderSharedPtr.
157
  absl::node_hash_map<std::string, GenericSecretConfigProviderSharedPtr>
158
      static_generic_secret_providers_;
159

            
160
  // map hash code of SDS config source and SdsApi object.
161
  DynamicSecretProviders<TlsCertificateSdsApi> certificate_providers_;
162
  DynamicSecretProviders<CertificateValidationContextSdsApi> validation_context_providers_;
163
  DynamicSecretProviders<TlsSessionTicketKeysSdsApi> session_ticket_keys_providers_;
164
  DynamicSecretProviders<GenericSecretSdsApi> generic_secret_providers_;
165

            
166
  Server::ConfigTracker::EntryOwnerPtr config_tracker_entry_;
167
};
168

            
169
} // namespace Secret
170
} // namespace Envoy