2323
2424#include " config/ssl_multicert.h"
2525
26+ #include < cerrno>
2627#include < cctype>
2728#include < exception>
2829#include < set>
3233
3334#include " swoc/swoc_file.h"
3435#include " swoc/TextView.h"
36+ #include " tsutil/ts_diag_levels.h"
3537
3638namespace
3739{
3840
41+ constexpr swoc::Errata::Severity ERRATA_NOTE_SEV{static_cast <swoc::Errata::severity_type>(DL_Note)};
42+ constexpr swoc::Errata::Severity ERRATA_WARN_SEV{static_cast <swoc::Errata::severity_type>(DL_Warning)};
43+ constexpr swoc::Errata::Severity ERRATA_ERROR_SEV{static_cast <swoc::Errata::severity_type>(DL_Error)};
44+
3945// YAML key names.
4046constexpr char KEY_SSL_CERT_NAME[] = " ssl_cert_name" ;
4147constexpr char KEY_DEST_IP[] = " dest_ip" ;
@@ -141,13 +147,6 @@ template <> struct convert<config::SSLMultiCertEntry> {
141147 static bool
142148 decode (Node const &node, config::SSLMultiCertEntry &entry)
143149 {
144- for (auto const &elem : node) {
145- std::string key = elem.first .as <std::string>();
146- if (valid_keys.find (key) == valid_keys.end ()) {
147- // Unknown key - we could warn here, but for now we skip silently.
148- }
149- }
150-
151150 if (node[KEY_SSL_CERT_NAME]) {
152151 entry.ssl_cert_name = node[KEY_SSL_CERT_NAME].as <std::string>();
153152 }
@@ -202,7 +201,11 @@ SSLMultiCertParser::parse(std::string const &filename)
202201 std::error_code ec;
203202 std::string content = swoc::file::load (filename, ec);
204203 if (ec) {
205- return {{}, swoc::Errata (" failed to load file: {}" , filename)};
204+ // Missing ssl_multicert.* is an acceptable runtime state.
205+ if (ec.value () == ENOENT) {
206+ return {{}, swoc::Errata (ERRATA_WARN_SEV, " Cannot open SSL certificate configuration \" {}\" - {}" , filename, ec)};
207+ }
208+ return {{}, swoc::Errata (ERRATA_ERROR_SEV, " Failed to read SSL certificate configuration from \" {}\" - {}" , filename, ec)};
206209 }
207210
208211 if (content.empty ()) {
@@ -246,12 +249,14 @@ SSLMultiCertParser::detect_format(std::string_view content, std::string const &f
246249ConfigResult<SSLMultiCertConfig>
247250SSLMultiCertParser::parse_yaml (std::string_view content)
248251{
249- SSLMultiCertConfig result;
252+ SSLMultiCertConfig result;
253+ swoc::Errata errata;
254+ std::set<std::string> unknown_keys;
250255
251256 try {
252257 YAML::Node config = YAML::Load (std::string (content));
253258 if (config.IsNull ()) {
254- return {result, {} };
259+ return {result, std::move (errata) };
255260 }
256261
257262 if (!config[KEY_SSL_MULTICERT]) {
@@ -264,20 +269,37 @@ SSLMultiCertParser::parse_yaml(std::string_view content)
264269 }
265270
266271 for (auto it = entries.begin (); it != entries.end (); ++it) {
267- result.push_back (it->as <SSLMultiCertEntry>());
272+ YAML::Node entry_node = *it;
273+ auto const mark = entry_node.Mark ();
274+ if (!entry_node.IsMap ()) {
275+ return {result, swoc::Errata (ERRATA_ERROR_SEV, " Expected ssl_multicert entries to be maps at line {}, column {}" , mark.line ,
276+ mark.column )};
277+ }
278+
279+ for (auto const &field : entry_node) {
280+ std::string key = field.first .as <std::string>();
281+ if (valid_keys.find (key) == valid_keys.end () && unknown_keys.insert (key).second ) {
282+ errata.note (ERRATA_NOTE_SEV, " Ignoring unknown ssl_multicert key '{}' at line {}, column {}" , key, mark.line ,
283+ mark.column );
284+ }
285+ }
286+
287+ result.push_back (entry_node.as <SSLMultiCertEntry>());
268288 }
269289 } catch (std::exception const &ex) {
270290 return {result, swoc::Errata (" YAML parse error: {}" , ex.what ())};
271291 }
272292
273- return {result, {} };
293+ return {result, std::move (errata) };
274294}
275295
276296ConfigResult<SSLMultiCertConfig>
277297SSLMultiCertParser::parse_legacy (std::string_view content)
278298{
279- SSLMultiCertConfig result;
280- swoc::TextView src{content};
299+ SSLMultiCertConfig result;
300+ swoc::Errata errata;
301+ std::set<std::string> unknown_keys;
302+ swoc::TextView src{content};
281303
282304 while (!src.empty ()) {
283305 swoc::TextView line = src.take_prefix_at (' \n ' );
@@ -316,13 +338,15 @@ SSLMultiCertParser::parse_legacy(std::string_view content)
316338 entry.ssl_ticket_enabled = swoc::svtoi (value);
317339 } else if (key == KEY_SSL_TICKET_NUMBER) {
318340 entry.ssl_ticket_number = swoc::svtoi (value);
341+ } else if (unknown_keys.insert (key).second ) {
342+ errata.note (ERRATA_NOTE_SEV, " Ignoring unknown ssl_multicert key '{}' in legacy format" , key);
319343 }
320344 }
321345
322346 result.push_back (std::move (entry));
323347 }
324348
325- return {result, {} };
349+ return {result, std::move (errata) };
326350}
327351
328352std::string
0 commit comments