1
#include "source/common/ssl/tls_certificate_config_impl.h"
2

            
3
#include "envoy/common/exception.h"
4
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
5
#include "envoy/server/transport_socket_config.h"
6

            
7
#include "source/common/common/empty_string.h"
8
#include "source/common/common/fmt.h"
9
#include "source/common/config/datasource.h"
10

            
11
namespace Envoy {
12
namespace Ssl {
13

            
14
namespace {
15

            
16
// Either return the supplied string, or set error and return an empty string
17
// string.
18
21112
std::string maybeSet(absl::StatusOr<std::string> to_set, absl::Status error) {
19
21112
  if (to_set.status().ok()) {
20
21104
    return std::move(to_set.value());
21
21104
  }
22
8
  error = to_set.status();
23
8
  return "";
24
21112
}
25

            
26
std::vector<uint8_t> maybeReadOcspStaple(const envoy::config::core::v3::DataSource& source,
27
5278
                                         Api::Api& api, absl::Status& creation_status) {
28
5278
  auto staple_or_error = Config::DataSource::read(source, true, api);
29
5278
  if (!staple_or_error.ok()) {
30
    creation_status = staple_or_error.status();
31
    return {};
32
  }
33
5278
  const std::string& staple = staple_or_error.value();
34

            
35
5278
  if (source.specifier_case() ==
36
5278
      envoy::config::core::v3::DataSource::SpecifierCase::kInlineString) {
37
1
    creation_status =
38
1
        absl::InvalidArgumentError("OCSP staple cannot be provided via inline_string");
39
1
    return {};
40
1
  }
41

            
42
5277
  return {staple.begin(), staple.end()};
43
5278
}
44
} // namespace
45

            
46
static const std::string INLINE_STRING = "<inline>";
47

            
48
absl::StatusOr<TlsCertificateConfigImpl> TlsCertificateConfigImpl::create(
49
    const envoy::extensions::transport_sockets::tls::v3::TlsCertificate& config,
50
    Server::Configuration::TransportSocketFactoryContext& factory_context, Api::Api& api,
51
5278
    const std::string& certificate_name) {
52
5278
  absl::Status creation_status = absl::OkStatus();
53
5278
  TlsCertificateConfigImpl ret(config, factory_context, api, creation_status, certificate_name);
54
5278
  RETURN_IF_NOT_OK(creation_status);
55
5257
  return ret;
56
5278
}
57

            
58
TlsCertificateConfigImpl::TlsCertificateConfigImpl(
59
    const envoy::extensions::transport_sockets::tls::v3::TlsCertificate& config,
60
    Server::Configuration::TransportSocketFactoryContext& factory_context, Api::Api& api,
61
    absl::Status& creation_status, const std::string& certificate_name)
62
5278
    : certificate_chain_(maybeSet(Config::DataSource::read(config.certificate_chain(), true, api),
63
5278
                                  creation_status)),
64
      certificate_chain_path_(
65
5278
          Config::DataSource::getPath(config.certificate_chain())
66
5278
              .value_or(certificate_chain_.empty() ? EMPTY_STRING : INLINE_STRING)),
67
5278
      certificate_name_(certificate_name),
68
      private_key_(
69
5278
          maybeSet(Config::DataSource::read(config.private_key(), true, api), creation_status)),
70
5278
      private_key_path_(Config::DataSource::getPath(config.private_key())
71
5278
                            .value_or(private_key_.empty() ? EMPTY_STRING : INLINE_STRING)),
72
5278
      pkcs12_(maybeSet(Config::DataSource::read(config.pkcs12(), true, api), creation_status)),
73
5278
      pkcs12_path_(Config::DataSource::getPath(config.pkcs12())
74
5278
                       .value_or(pkcs12_.empty() ? EMPTY_STRING : INLINE_STRING)),
75
5278
      password_(maybeSet(Config::DataSource::read(config.password(), true, api), creation_status)),
76
5278
      password_path_(Config::DataSource::getPath(config.password())
77
5278
                         .value_or(password_.empty() ? EMPTY_STRING : INLINE_STRING)),
78
5278
      ocsp_staple_(maybeReadOcspStaple(config.ocsp_staple(), api, creation_status)),
79
5278
      ocsp_staple_path_(Config::DataSource::getPath(config.ocsp_staple())
80
5278
                            .value_or(ocsp_staple_.empty() ? EMPTY_STRING : INLINE_STRING)),
81
5278
      private_key_method_(nullptr) {
82
  // If creation_status was invalid as part of the data members init, there's no
83
  // need to continue with the update.
84
5278
  RETURN_ONLY_IF_NOT_OK_REF(creation_status);
85
5277
  if (config.has_pkcs12()) {
86
17
    if (config.has_private_key()) {
87
1
      creation_status = absl::InvalidArgumentError(
88
1
          fmt::format("Certificate configuration can't have both pkcs12 and private_key"));
89
1
    }
90
17
    if (config.has_certificate_chain()) {
91
1
      creation_status = absl::InvalidArgumentError(
92
1
          fmt::format("Certificate configuration can't have both pkcs12 and certificate_chain"));
93
1
    }
94
17
    if (config.has_private_key_provider()) {
95
1
      creation_status = absl::InvalidArgumentError(
96
1
          fmt::format("Certificate configuration can't have both pkcs12 and private_key_provider"));
97
1
    }
98
5260
  } else {
99
5260
    if (config.has_private_key_provider()) {
100
30
      private_key_method_ =
101
30
          factory_context.serverFactoryContext()
102
30
              .sslContextManager()
103
30
              .privateKeyMethodManager()
104
30
              .createPrivateKeyMethodProvider(config.private_key_provider(), factory_context);
105
30
      if (private_key_method_ == nullptr ||
106
30
          (!private_key_method_->isAvailable() && !config.private_key_provider().fallback())) {
107
3
        creation_status =
108
3
            absl::InvalidArgumentError(fmt::format("Failed to load private key provider: {}",
109
3
                                                   config.private_key_provider().provider_name()));
110
3
        return;
111
3
      }
112

            
113
27
      if (!private_key_method_->isAvailable()) {
114
2
        private_key_method_ = nullptr;
115
2
      }
116
27
    }
117
5257
    if (certificate_chain_.empty()) {
118
12
      creation_status = absl::InvalidArgumentError(
119
12
          fmt::format("Failed to load incomplete certificate from {}: certificate chain not set",
120
12
                      certificate_chain_path_));
121
12
    }
122

            
123
5257
    if (private_key_.empty() && private_key_method_ == nullptr) {
124
14
      creation_status = absl::InvalidArgumentError(
125
14
          fmt::format("Failed to load incomplete private key from path: {}", private_key_path_));
126
14
    }
127
5257
  }
128
5277
}
129

            
130
} // namespace Ssl
131
} // namespace Envoy