// If password is not specified an empty
// password is used.
- "password": "1234"
+ "password": "1234",
+ "password-file": "",
+ "user-file": ""
},
// This specifies a hidden client.
// The user id is the content of the
// file /usr/local/share/kea/kea-creds/hiddenu.
"user-file": "hiddenu",
+ "user": "",
// The password is the content of the
// file /usr/local/share/kea/kea-creds/hiddenp.
- "password-file": "hiddenp"
+ "password-file": "hiddenp",
+ "password": ""
},
// This specifies a hidden client using a
// The secret is the content of the file
// /usr/local/share/kea/kea-creds/hiddens which must be in
// the <user-id>:<password> format.
- "password-file": "hiddens"
+ "password-file": "hiddens",
+ "user-file": "",
+ "user": "",
+ "password": ""
}
]
}
// If password is not specified an empty
// password is used.
- "password": "1234"
+ "password": "1234",
+ "password-file": "",
+ "user-file": ""
},
// This specifies a hidden client.
// The user id is the content of the
// file /usr/local/share/kea/kea-creds/hiddenu.
"user-file": "hiddenu",
+ "user": "",
// The password is the content of the
// file /usr/local/share/kea/kea-creds/hiddenp.
- "password-file": "hiddenp"
+ "password-file": "hiddenp",
+ "password": ""
},
// This specifies a hidden client using a
// The secret is the content of the file
// /usr/local/share/kea/kea-creds/hiddens which must be in
// the <user-id>:<password> format.
- "password-file": "hiddens"
+ "password-file": "hiddens",
+ "user-file": "",
+ "user": "",
+ "password": ""
}
]
}
-// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2025 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
-// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2025 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
ElementPtr database = Element::createMap();
database->set("type", Element::create("memfile"));
database->set("lfc-interval", Element::create(3600));
- ASSERT_NO_THROW_LOG(translator_->setDatabase(xpath, database));
+ ASSERT_NO_THROW_LOG(translator_->setDatabase(xpath, database, /* has_mandatory_key = */ false));
// Get it back.
ConstElementPtr got;
sess_->applyChanges();
// Reset to empty.
- ASSERT_NO_THROW_LOG(translator_->setDatabase(xpath, ConstElementPtr()));
+ ASSERT_NO_THROW_LOG(translator_->setDatabase(xpath, ConstElementPtr(), /* has_mandatory_key = */ false));
// Get it back.
ConstElementPtr database;
sess_->applyChanges();
// Reset to empty.
- EXPECT_NO_THROW_LOG(translator_->setDatabase(xdatabase, ConstElementPtr()));
+ EXPECT_NO_THROW_LOG(translator_->setDatabase(xdatabase, ConstElementPtr(), /* has_mandatory_key = */ true));
// Get empty.
ConstElementPtr databases;
sess_->applyChanges();
// Reset to empty.
- EXPECT_NO_THROW_LOG(translator_->setDatabases(xdatabase, ConstElementPtr()));
+ EXPECT_NO_THROW_LOG(translator_->setDatabase(xdatabase, ConstElementPtr(), /* has_mandatory_key = */ true));
// Get empty.
ConstElementPtr databases;
ConstElementPtr database = elem->get("lease-database");
if (database && !database->empty()) {
- setDatabase(xpath + "/lease-database", database);
+ setDatabase(xpath + "/lease-database", database, /* has_mandatory_key = */ false);
}
ConstElementPtr loggers = elem->get("loggers");
ElementPtr
TranslatorControlSocket::getControlSocketKea(DataNode const& data_node) {
ElementPtr result(Element::createMap());
- getMandatoryLeaf(result, data_node, "socket-type");
checkAndGetLeaf(result, data_node, "socket-name");
+ checkAndGetLeaf(result, data_node, "socket-type");
if (model_ != KEA_CTRL_AGENT) {
checkAndGetLeaf(result, data_node, "socket-address");
checkAndGetLeaf(result, data_node, "socket-port");
authentication = Element::createMap();
}
- getMandatoryDivergingLeaf(authentication, node, "type", "auth-type");
+ checkAndGetDivergingLeaf(authentication, node, "type", "auth-type");
checkAndGetLeaf(authentication, node, "realm");
checkAndGetLeaf(authentication, node, "directory");
ConstElementPtr clients = getControlSocketAuthenticationClients(node);
(model_ == KEA_DHCP_DDNS)) {
setControlSocketsKea(xpath, elem);
} else if (model_ == KEA_CTRL_AGENT) {
- setControlSocketKea(xpath, elem);
+ setControlSocketKea(xpath, elem, /* has_mandatory_key = */ true);
} else {
isc_throw(NotImplemented,
"setControlSocket not implemented for the model: "
(model_ == KEA_DHCP6_SERVER) ||
(model_ == KEA_DHCP_DDNS) ||
(model_ == KEA_CTRL_AGENT)) {
- setControlSocketKea(xpath, elem);
+ setControlSocketKea(xpath, elem, /* has_mandatory_key = */ false);
} else {
isc_throw(NotImplemented,
"setControlSocket not implemented for the model: "
string type = control_socket->get("socket-type")->stringValue();
ostringstream key;
key << xpath << "[socket-type='" << type << "']";
- setControlSocketKea(key.str(), control_socket);
+ setControlSocketKea(key.str(), control_socket, /* has_mandatory_key = */ true);
}
}
void
-TranslatorControlSocket::setControlSocketKea(string const& xpath, ConstElementPtr elem) {
+TranslatorControlSocket::setControlSocketKea(string const& xpath,
+ ConstElementPtr elem,
+ bool has_mandatory_key) {
if (!elem) {
deleteItem(xpath);
return;
}
+ if (has_mandatory_key) {
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+ } else {
+ checkAndSetLeaf(elem, xpath, "socket-type", LeafBaseType::String);
+ }
+
checkAndSetLeaf(elem, xpath, "socket-name", LeafBaseType::String);
if (model_ != KEA_CTRL_AGENT) {
checkAndSetLeaf(elem, xpath, "socket-address", LeafBaseType::String);
- checkAndSetLeaf(elem, xpath, "socket-port", LeafBaseType::Uint32);
+ checkAndSetLeaf(elem, xpath, "socket-port", LeafBaseType::Uint16);
checkAndSetLeaf(elem, xpath, "trust-anchor", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "cert-file", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "key-file", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "cert-required", LeafBaseType::Bool);
ConstElementPtr authentication = elem->get("authentication");
if (authentication && !authentication->empty()) {
- setMandatoryDivergingLeaf(authentication, xpath , "type", "auth-type", LeafBaseType::String);
+ setMandatoryDivergingLeaf(authentication, xpath +"/authentication" , "type", "auth-type", LeafBaseType::String);
checkAndSetLeaf(authentication, xpath + "/authentication", "realm", LeafBaseType::String);
checkAndSetLeaf(authentication, xpath + "/authentication", "directory", LeafBaseType::String);
ConstElementPtr clients = authentication->get("clients");
}
ConstElementPtr http_headers = elem->get("http-headers");
if (http_headers && !http_headers->empty()) {
- for (size_t i = 0; i < http_headers->size(); ++i) {
- ElementPtr header = elem->getNonConst(i);
- // setHeader
- }
+ setControlSocketHttpHeaders(xpath + "/http-headers", http_headers);
}
}
- setMandatoryLeaf(elem, xpath, "socket-type", LeafBaseType::Enum);
checkAndSetUserContext(elem, xpath);
}
if (password_file) {
password_file_str = password_file->stringValue();
}
- key << xpath << "[user='" << user_str << "'][password=']" << password_str
+ key << xpath << "[user='" << user_str << "'][password='" << password_str
<< "'][user-file='" << user_file_str << "'][password-file='"
<< password_file_str << "']";
setControlSocketAuthenticationClient(key.str(), client);
deleteItem(xpath);
return;
}
- for (size_t i = 0; i < elem->size(); ++i) {
- ElementPtr header = elem->getNonConst(i);
- ostringstream key;
- if (!header->contains("name")) {
+ for (ConstElementPtr header : elem->listValue()) {
+ ConstElementPtr name(header->get("name"));
+ if (!name) {
isc_throw(BadValue, "http header without name: " << header->str());
}
- key << xpath << "[name='" << header->stringValue() << "']";
+ ostringstream key;
+ key << xpath << "[name='" << name->stringValue() << "']";
setControlSocketHttpHeader(key.str(), header);
}
}
checkAndSetLeaf(elem, xpath, "value", LeafBaseType::String);
checkAndSetUserContext(elem, xpath);
- setMandatoryLeaf(elem, xpath, "name", LeafBaseType::Enum);
}
} // namespace yang
///
/// @param xpath The xpath of the control socket.
/// @param elem The JSON element.
+ /// @param has_mandatory_key Whether this specific database instance has a mandatory key.
/// @throw BadValue on control socket without socket type or name.
- void setControlSocketKea(const std::string& xpath, isc::data::ConstElementPtr elem);
+ void setControlSocketKea(const std::string& xpath, isc::data::ConstElementPtr elem, bool has_mandatory_key);
/// @brief setControlSocketAuthenticationClients for kea models.
///
TranslatorDatabase::getDatabaseKea(DataNode const& data_node) {
ElementPtr result = Element::createMap();
+ checkAndGetDivergingLeaf(result, data_node, "type", "database-type");
checkAndGetLeaf(result, data_node, "cert-file");
checkAndGetLeaf(result, data_node, "cipher-list");
checkAndGetLeaf(result, data_node, "connect-timeout");
}
void
-TranslatorDatabase::setDatabase(string const& xpath, ConstElementPtr elem) {
+TranslatorDatabase::setDatabase(string const& xpath, ConstElementPtr elem, bool has_mandatory_key) {
try {
if ((model_ == KEA_DHCP4_SERVER) ||
(model_ == KEA_DHCP6_SERVER)) {
- setDatabaseKea(xpath, elem);
+ setDatabaseKea(xpath, elem, has_mandatory_key);
} else {
isc_throw(NotImplemented,
"setDatabase not implemented for the model: " << model_);
}
void
-TranslatorDatabase::setDatabaseKea(string const& xpath, ConstElementPtr elem) {
- setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+TranslatorDatabase::setDatabaseKea(string const& xpath, ConstElementPtr elem, bool has_mandatory_key) {
+ if (!elem) {
+ deleteItem(xpath);
+ return;
+ }
+
+ if (has_mandatory_key) {
+ // Set the list element. This is important in case we have no other elements except the key.
+ setItem(xpath, ElementPtr(), LeafBaseType::Unknown);
+ } else {
+ checkAndSetDivergingLeaf(elem, xpath, "type", "database-type", LeafBaseType::String);
+ }
checkAndSetLeaf(elem, xpath, "connect-timeout", LeafBaseType::Uint32);
checkAndSetLeaf(elem, xpath, "cert-file", LeafBaseType::String);
string type = database->get("type")->stringValue();
ostringstream key;
key << xpath << "[database-type='" << type << "']";
- setDatabase(key.str(), database);
+ setDatabase(key.str(), database, /* has_mandatory_key = */ true);
}
}
///
/// @param xpath The xpath of the database access.
/// @param elem The JSON element.
- void setDatabase(const std::string& xpath, isc::data::ConstElementPtr elem);
+ /// @param has_mandatory_key Whether this specific database instance has a mandatory key.
+ void setDatabase(const std::string& xpath,
+ isc::data::ConstElementPtr elem,
+ bool has_mandatory_key);
protected:
/// @brief getDatabase JSON for kea-dhcp[46]-server models.
///
/// @param xpath The xpath of the database access.
/// @param elem The JSON element.
+ /// @param has_mandatory_key Whether this specific database instance has a mandatory key.
/// @throw BadValue on database without type,
- void setDatabaseKea(const std::string& xpath, isc::data::ConstElementPtr elem);
+ void setDatabaseKea(const std::string& xpath,
+ isc::data::ConstElementPtr elem,
+ bool has_mandatory_key);
}; // TranslatorDatabase
/// @brief A translator class for converting a database access list between
-68739faa231a48c837adb3b306858b5656a1439b39b675f601d21515278d8747
+160eb58d10c1c29ab40763f69b9d905644ee767badfdceee6bdd730e9a6071f6
description "HTTP/HTTPS socket address.";
}
leaf socket-port {
- type string;
+ type uint16;
description "HTTP/HTTPS socket port.";
}
uses control-socket-tls;
grouping authentication {
description "HTTP authentication.";
container authentication {
- grouping auth-type {
- leaf auth-type {
- type enumeration {
- enum "basic" {
- description "Basic HTTP authentication";
- }
+ presence "";
+ leaf auth-type {
+ type enumeration {
+ enum "basic" {
+ description "Basic HTTP authentication";
}
- description "HTTP authentication type.";
- mandatory true;
}
+ description "HTTP authentication type.";
+ mandatory true;
}
leaf realm {
type string;
type string;
description "HTTP authentication directory.";
}
+ uses clients;
}
- uses clients;
}
grouping hooks-libraries {