#include "core/framework.h"
#include "core/xpath.h"
-#define NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\",\"odl-netconf-callhome-server:ssh-host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf!\"]}}]}"
+#define NETCONF_SSH_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\", \"odl-netconf-callhome-server:ssh-client-params\": {\"odl-netconf-callhome-server:host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf!\"]}}}]}"
+#define NETCONF_TLS_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\", \"odl-netconf-callhome-server:tls-client-params\": {\"odl-netconf-callhome-server:certificate-id\":\"%s\",\"odl-netconf-callhome-server:key-id\":\"%s\"}}]}"
+#define NETCONF_TRUSTED_CERTIFICATE_CURL_SEND_PAYLOAD_FORMAT "{\"input\":{\"trusted-certificate\":[{\"name\":\"%s\",\"certificate\":\"%s\"}]}}"
static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
-static int send_odl_callhome_configuration(sr_session_ctx_t *current_session);
+static int send_odl_add_trusted_certificate(sr_session_ctx_t *current_session);
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session, bool is_tls);
static int netconf_call_home_status = 0;
return NTS_ERR_FAILED;
}
- rc = create_ssh_callhome_endpoint(current_session, netconf_node);
- if(rc != NTS_ERR_OK) {
- log_error("could not create SSH CallHome endpoint on the NETCONF Server\n");
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
return NTS_ERR_FAILED;
}
- rc = create_tls_callhome_endpoint(current_session, netconf_node);
- if(rc != NTS_ERR_OK) {
- log_error("could not create TLS CallHome endpoint on the NETCONF Server\n");
- return NTS_ERR_FAILED;
+ if (controller->nc_callhome_port == 4335) {
+ // port is CallHome via TLS
+ rc = create_tls_callhome_endpoint(current_session, netconf_node);
+ if(rc != NTS_ERR_OK) {
+ log_error("could not create TLS CallHome endpoint on the NETCONF Server\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
+ }
+ else {
+ // port is CallHome via SSH
+ rc = create_ssh_callhome_endpoint(current_session, netconf_node);
+ if(rc != NTS_ERR_OK) {
+ log_error("could not create SSH CallHome endpoint on the NETCONF Server\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
}
+ controller_details_free(controller);
rc = sr_edit_batch(current_session, netconf_node, "merge");
if(rc != SR_ERR_OK) {
return NTS_ERR_FAILED;
}
-
struct lyd_node *rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_SSH_TCP_CLIENT_SCHEMA_XPATH"/keepalives/idle-time", "1", 0, LYD_PATH_OPT_NOPARENTRET);
if(rcl == 0) {
log_error("could not created yang path\n");
return NTS_ERR_FAILED;
}
- int rc = send_odl_callhome_configuration(current_session);
+ int rc = send_odl_callhome_configuration(current_session, false);
if(rc != NTS_ERR_OK) {
log_add_verbose(2, "could not send ODL Call Home configuration.\n");
}
assert(current_session);
assert(netconf_node);
- // checkAS future usage, TLS endpoint yet supported in ODL
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ char *controller_ip = strdup(controller->ip);
+ uint16_t controller_callhome_port = controller->nc_callhome_port;
+ controller_details_free(controller);
+
+ if(controller_ip == 0) {
+ log_error("strdup failed\n");
+ return NTS_ERR_FAILED;
+ }
+ struct lyd_node *rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/idle-time", "1", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/max-probes", "10", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/probe-interval", "5", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/remote-address", controller_ip, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+ free(controller_ip);
+
+ char port[20];
+ sprintf(port, "%d", controller_callhome_port);
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/remote-port", port, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/server-identity/keystore-reference/asymmetric-key", KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/server-identity/keystore-reference/certificate", KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/required", "", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/ca-certs", "cacerts", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/client-certs", "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, session_context, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/map-type", "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/name", "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_CONN_PERSISTENT_SCHEMA_XPATH, "", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ int rc = send_odl_callhome_configuration(current_session, true);
+ if(rc != NTS_ERR_OK) {
+ log_add_verbose(2, "could not send ODL Call Home configuration.\n");
+ }
+
return NTS_ERR_OK;
}
-static int send_odl_callhome_configuration(sr_session_ctx_t *current_session) {
+static int send_odl_add_trusted_certificate(sr_session_ctx_t *current_session) {
assert(current_session);
- char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
- if(public_ssh_key == 0) {
- log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
+ char *server_cert = read_key(SERVER_CERT_PATH);
+ if(server_cert == 0) {
+ log_error("could not read the serevr certificate from file %s\n", SERVER_CERT_PATH);
return NTS_ERR_FAILED;
}
- char *ssh_key_string;
- ssh_key_string = strtok(public_ssh_key, " ");
- ssh_key_string = strtok(NULL, " ");
- ssh_key_string[strlen(ssh_key_string) - 1] = 0; // trim the newline character
+ char *odl_trusted_certificate_payload = 0;
+ asprintf(&odl_trusted_certificate_payload, NETCONF_TRUSTED_CERTIFICATE_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, server_cert);
+ if(odl_trusted_certificate_payload == 0) {
+ log_error("bad asprintf\n");
+ return NTS_ERR_FAILED;
+ }
+ free(server_cert);
+
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ char *url = 0;
+ asprintf(&url, "%s/rests/operations/netconf-keystore:add-trusted-certificate", controller->base_url);
+ if(url == 0) {
+ log_error("bad asprintf\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
+
+ int rc = http_request(url, controller->username, controller->password, "POST", odl_trusted_certificate_payload, 0, 0);
+ if(rc != NTS_ERR_OK) {
+ log_error("http_request failed\n");
+ }
+
+ free(url);
+ controller_details_free(controller);
+ free(odl_trusted_certificate_payload);
+
+ return rc;
+}
+
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session, bool is_tls) {
+ assert(current_session);
- // checkAS we have hardcoded here the username and password of the NETCONF Server
char *odl_callhome_payload = 0;
- asprintf(&odl_callhome_payload, NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, ssh_key_string);
- free(public_ssh_key);
+ if (!is_tls) {
+ char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
+ if(public_ssh_key == 0) {
+ log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
+ return NTS_ERR_FAILED;
+ }
+
+ char *ssh_key_string;
+ ssh_key_string = strtok(public_ssh_key, " ");
+ ssh_key_string = strtok(NULL, " ");
+ ssh_key_string[strlen(ssh_key_string) - 1] = 0; // trim the newline character
+
+ // checkAS we have hardcoded here the username and password of the NETCONF Server
+ asprintf(&odl_callhome_payload, NETCONF_SSH_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, ssh_key_string);
+ free(public_ssh_key);
+ }
+ else {
+ int ret = send_odl_add_trusted_certificate(current_session);
+ if (ret != NTS_ERR_OK) {
+ log_error("Could not send trusted certificate to ODL.");
+ return NTS_ERR_FAILED;
+ }
+ // checkAS we have hardcoded here the private key of ODL
+ asprintf(&odl_callhome_payload, NETCONF_TLS_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, framework_environment.settings.hostname, "ODL_private_key_0");
+ }
+
if(odl_callhome_payload == 0) {
log_error("bad asprintf\n");
return NTS_ERR_FAILED;