Fixed ssl client certs for evhtp.
* Added SSL cert info as options: CLICON_SSL_SERVER_CERT, CLICON_SSL_SERVER_KEY, CLICON_SSL_CA_CERT Added config.sh for testing for autotools
This commit is contained in:
parent
9c82e97072
commit
c049a397b0
22 changed files with 515 additions and 80 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -58,6 +58,7 @@ util/clixon_util_xml
|
|||
util/clixon_util_xpath
|
||||
util/clixon_util_yang
|
||||
|
||||
test/config.sh
|
||||
test/site.sh
|
||||
test/vagrant/site.mk
|
||||
test/cicd/site.mk
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Expected: July 2020
|
|||
* Added a prefix for cli_show_config/cli_show_auto so that it can produce parseable output
|
||||
* Thanks dcornejo@netgate.com for trying it out and suggestions
|
||||
* Embedding restconf into the existing [libevhtp](https://github.com/criticalstack/libevhtp) embedded web server. (Experimental).
|
||||
* The existing FCGI restconf solution will continue to be supported for NGINX and other reverese proxies with an fast CGI API.
|
||||
* The existing FCGI restconf solution will continue to be supported for NGINX and other reverse proxies with a FCGI API.
|
||||
* The restconf code has been refactored to support both modes. Hopefully, it should be straightforward to add another embedded server, such as GNU microhttpd.
|
||||
* The new restconf module is selected using a compile-time autotools configure as follows:
|
||||
* `--with-restconf=fcgi FCGI interface for stand-alone web rev-proxy eg nginx (default)`
|
||||
|
|
@ -45,6 +45,11 @@ Expected: July 2020
|
|||
* New clixon-config@2020-06-17.yang revision
|
||||
* Added CLICON_CLI_LINES_DEFAULT for setting window row size of raw terminals
|
||||
* Added enum HIDE to CLICON_CLI_GENMODEL for auto-cli
|
||||
* Added SSL cert info for evhtp restconf https:
|
||||
* CLICON_SSL_SERVER_CERT
|
||||
* CLICON_SSL_SERVER_KEY
|
||||
* CLICON_SSL_CA_CERT
|
||||
|
||||
* Restconf FCGI (eg via nginx) have changed reply message syntax slightly as follows (due to refactoring and common code with evhtp):
|
||||
* Bodies in error reyruns including html code have been removed
|
||||
* Some (extra) CRLF:s have been removed
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
* libevhtp code
|
||||
*/
|
||||
|
||||
/* XXX temp constant should go away, */
|
||||
#undef _EVHTP_NYI
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
|
@ -82,7 +79,7 @@
|
|||
#include "restconf_root.h"
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:o:P:s"
|
||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:o:P:sc"
|
||||
|
||||
/* Need global variable to for signal handler XXX */
|
||||
static clicon_handle _CLICON_HANDLE = NULL;
|
||||
|
|
@ -100,9 +97,7 @@ restconf_sig_term(int arg)
|
|||
else
|
||||
exit(-1);
|
||||
if (_CLICON_HANDLE){
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_child_freeall(_CLICON_HANDLE);
|
||||
#endif
|
||||
// stream_child_freeall(_CLICON_HANDLE);
|
||||
restconf_terminate(_CLICON_HANDLE);
|
||||
}
|
||||
clicon_exit_set(); /* checked in clixon_event_loop() */
|
||||
|
|
@ -116,9 +111,6 @@ restconf_sig_child(int arg)
|
|||
int pid;
|
||||
|
||||
if ((pid = waitpid(-1, &status, 0)) != -1 && WIFEXITED(status)){
|
||||
#ifdef _EVHTP_NYI
|
||||
;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,11 +259,16 @@ evhtp_params_set(clicon_handle h,
|
|||
evhtp_request_t *req,
|
||||
cvec *qvec)
|
||||
{
|
||||
int retval = -1;
|
||||
htp_method meth;
|
||||
evhtp_uri_t *uri;
|
||||
evhtp_path_t *path;
|
||||
int retval = -1;
|
||||
htp_method meth;
|
||||
evhtp_uri_t *uri;
|
||||
evhtp_path_t *path;
|
||||
evhtp_ssl_t *ssl = NULL;
|
||||
char *subject;
|
||||
cvec *cvv = NULL;
|
||||
char *cn;
|
||||
|
||||
|
||||
if ((uri = req->uri) == NULL){
|
||||
clicon_err(OE_DAEMON, EFAULT, "No uri");
|
||||
goto done;
|
||||
|
|
@ -303,9 +300,18 @@ evhtp_params_set(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
clicon_debug(1, "%s conn->ssl:%d", __FUNCTION__, req->conn->ssl?1:0);
|
||||
if (req->conn->ssl != NULL){
|
||||
if ((ssl = req->conn->ssl) != NULL){
|
||||
if (restconf_param_set(h, "HTTPS", "https") < 0) /* some string or NULL */
|
||||
goto done;
|
||||
/* SSL subject fields, eg CN (Common Name) , can add more here? */
|
||||
if ((subject = (char*)htp_sslutil_subject_tostr(req->conn->ssl)) != NULL){
|
||||
if (str2cvec(subject, '/', '=', &cvv) < 0)
|
||||
goto done;
|
||||
if ((cn = cvec_find_str(cvv, "CN")) != NULL){
|
||||
if (restconf_param_set(h, "SSL_CN", cn) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Translate all http headers by capitalizing, prepend w HTTP_ and - -> _
|
||||
|
|
@ -315,6 +321,8 @@ evhtp_params_set(clicon_handle h,
|
|||
goto done;
|
||||
retval = 1;
|
||||
done:
|
||||
if (cvv)
|
||||
cvec_free(cvv);
|
||||
return retval;
|
||||
fail:
|
||||
retval = 0;
|
||||
|
|
@ -423,6 +431,8 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
/* input debug */
|
||||
if (clicon_debug_get())
|
||||
evhtp_headers_for_each(req->headers_in, print_header, h);
|
||||
|
||||
|
||||
/* get accepted connection */
|
||||
/* Query vector, ie the ?a=x&b=y stuff */
|
||||
if ((qvec = cvec_new(0)) ==NULL){
|
||||
|
|
@ -446,51 +456,93 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
}
|
||||
|
||||
/*! Get Server cert info
|
||||
* @param[out] ssl_config
|
||||
* @param[in] h Clicon handle
|
||||
* @param[out] ssl_config evhtp ssl config struct
|
||||
*/
|
||||
static int
|
||||
get_servercerts(evhtp_ssl_cfg_t *ssl_config,
|
||||
const char *pki_dir,
|
||||
const char *ssl_server_cert)
|
||||
cx_get_certs(clicon_handle h,
|
||||
int ssl_verify_clients,
|
||||
evhtp_ssl_cfg_t *ssl_config)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb = NULL;
|
||||
struct stat f_stat;
|
||||
char *filename;
|
||||
|
||||
if (ssl_config == NULL){
|
||||
clicon_err(OE_CFG, EINVAL, "ssl_config is NULL");
|
||||
clicon_err(OE_CFG, EINVAL, "Input parameter is NULL");
|
||||
goto done;
|
||||
}
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_SERVER_CERT")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_SERVER_CERT option missing");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "%s/%s-crt.pem", pki_dir, ssl_server_cert);
|
||||
if ((ssl_config->pemfile = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
if ((ssl_config->pemfile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->pemfile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL cert '%s'", ssl_config->pemfile);
|
||||
goto done;
|
||||
}
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "%s/%s-key.pem", pki_dir, ssl_server_cert);
|
||||
if ((ssl_config->privfile = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_SERVER_KEY")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_SERVER_KEY option missing");
|
||||
goto done;
|
||||
}
|
||||
if ((ssl_config->privfile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->privfile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||
goto done;
|
||||
}
|
||||
if (ssl_verify_clients){
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_CA_CERT")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_CA_CERT option missing");
|
||||
goto done;
|
||||
}
|
||||
if ((ssl_config->cafile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->cafile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
cx_verify_certs(int pre_verify,
|
||||
evhtp_x509_store_ctx_t *store)
|
||||
{
|
||||
#ifdef NOTYET
|
||||
char buf[256];
|
||||
X509 * err_cert;
|
||||
int err;
|
||||
int depth;
|
||||
SSL * ssl;
|
||||
evhtp_connection_t * connection;
|
||||
evhtp_ssl_cfg_t * ssl_cfg;
|
||||
|
||||
fprintf(stderr, "%s %d\n", __FUNCTION__, pre_verify);
|
||||
|
||||
err_cert = X509_STORE_CTX_get_current_cert(store);
|
||||
err = X509_STORE_CTX_get_error(store);
|
||||
depth = X509_STORE_CTX_get_error_depth(store);
|
||||
ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
|
||||
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
|
||||
|
||||
connection = SSL_get_app_data(ssl);
|
||||
ssl_cfg = connection->htp->ssl_cfg;
|
||||
#endif
|
||||
return pre_verify;
|
||||
}
|
||||
|
||||
/*! Usage help routine
|
||||
* @param[in] argv0 command line
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -513,6 +565,7 @@ usage(clicon_handle h,
|
|||
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
||||
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n"
|
||||
"\t-s\t SSL server, https\n"
|
||||
"\t-c\t SSL verify client certs\n"
|
||||
"\t-P <port>\t HTTP port (default 80, or 443 if -s is given)\n"
|
||||
,
|
||||
argv0,
|
||||
|
|
@ -521,6 +574,8 @@ usage(clicon_handle h,
|
|||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! Main routine for libevhtp restconf
|
||||
*/
|
||||
int
|
||||
|
|
@ -541,15 +596,12 @@ main(int argc,
|
|||
size_t cligen_bufthreshold;
|
||||
uint16_t defaultport = 80;
|
||||
uint16_t port = 0;
|
||||
#ifdef _EVHTP_NYI
|
||||
char *stream_path;
|
||||
#endif
|
||||
evhtp_t *htp = NULL;
|
||||
struct event_base *evbase = NULL;
|
||||
evhtp_ssl_cfg_t *ssl_config = NULL;
|
||||
int dbg = 0;
|
||||
char *ssl_server = NULL; /* SSL server name, default "server", base for srv certs */
|
||||
char *pki_dir = CLIXON_PKI_DIR;
|
||||
int use_ssl = 0;
|
||||
int ssl_verify_clients = 0;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -607,9 +659,7 @@ main(int argc,
|
|||
/* Find and read configfile */
|
||||
if (clicon_options_main(h) < 0)
|
||||
goto done;
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
||||
#endif
|
||||
// stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
||||
|
||||
/* Now rest of options, some overwrite option file */
|
||||
optind = 1;
|
||||
|
|
@ -651,9 +701,12 @@ main(int argc,
|
|||
break;
|
||||
}
|
||||
case 's': /* ssl: use https */
|
||||
ssl_server = CLIXON_SERVER_CERT;
|
||||
use_ssl = 1;
|
||||
defaultport = 443; /* unless explicit -P ? */
|
||||
break;
|
||||
case 'c': /* ssl: verify clients */
|
||||
ssl_verify_clients = 1;
|
||||
break;
|
||||
case 'P': /* http port */
|
||||
if (!strlen(optarg))
|
||||
usage(h, argv0);
|
||||
|
|
@ -669,7 +722,7 @@ main(int argc,
|
|||
if (port == 0)
|
||||
port = defaultport;
|
||||
/* Check server ssl certs */
|
||||
if (ssl_server){
|
||||
if (use_ssl){
|
||||
/* Init evhtp ssl config struct */
|
||||
if ((ssl_config = malloc(sizeof(evhtp_ssl_cfg_t))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
|
|
@ -678,8 +731,14 @@ main(int argc,
|
|||
memset(ssl_config, 0, sizeof(evhtp_ssl_cfg_t));
|
||||
ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
|
||||
|
||||
if (get_servercerts(ssl_config, pki_dir, ssl_server) < 0)
|
||||
if (cx_get_certs(h, ssl_verify_clients, ssl_config) < 0)
|
||||
goto done;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
if (ssl_verify_clients){
|
||||
ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
ssl_config->verify_depth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// ssl_verify_mode = htp_sslutil_verify2opts(optarg);
|
||||
|
|
@ -697,7 +756,7 @@ main(int argc,
|
|||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
if (ssl_server){
|
||||
if (use_ssl){
|
||||
if (evhtp_ssl_init(htp, ssl_config) < 0){
|
||||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
|
|
@ -835,9 +894,7 @@ main(int argc,
|
|||
|
||||
retval = 0;
|
||||
done:
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_child_freeall(h);
|
||||
#endif
|
||||
// stream_child_freeall(h);
|
||||
restconf_terminate(h);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
3
configure
vendored
3
configure
vendored
|
|
@ -5326,7 +5326,7 @@ _ACEOF
|
|||
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile extras/rpm/Makefile docker/Makefile docker/main/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/mandatory/Makefile yang/optional/Makefile doc/Makefile test/Makefile test/cicd/Makefile test/vagrant/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile extras/rpm/Makefile docker/Makefile docker/main/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/mandatory/Makefile yang/optional/Makefile doc/Makefile test/Makefile test/config.sh test/cicd/Makefile test/vagrant/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
|
|
@ -6045,6 +6045,7 @@ do
|
|||
"yang/optional/Makefile") CONFIG_FILES="$CONFIG_FILES yang/optional/Makefile" ;;
|
||||
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
|
||||
"test/config.sh") CONFIG_FILES="$CONFIG_FILES test/config.sh" ;;
|
||||
"test/cicd/Makefile") CONFIG_FILES="$CONFIG_FILES test/cicd/Makefile" ;;
|
||||
"test/vagrant/Makefile") CONFIG_FILES="$CONFIG_FILES test/vagrant/Makefile" ;;
|
||||
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ AC_OUTPUT(Makefile
|
|||
yang/optional/Makefile
|
||||
doc/Makefile
|
||||
test/Makefile
|
||||
test/config.sh
|
||||
test/cicd/Makefile
|
||||
test/vagrant/Makefile
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
* [Thanks](#thanks)
|
||||
* [References](#references)
|
||||
|
||||
NOTE: Outdated docs, see: https://clixon-docs.readthedocs.io for updated docs
|
||||
|
||||
## Background
|
||||
|
||||
This document describes the configuration startup mechanism of the Clixon backend. It describes the mechanism of Clixon version 3.10 which supports the following features:
|
||||
|
|
@ -334,7 +336,7 @@ where changes to the Yang model are documented and loaded into
|
|||
Clixon. The implementation is not complete.
|
||||
|
||||
When upgrading, the system parses the changelog and tries to upgrade
|
||||
the datastore automatically. This featire is experimental and has
|
||||
the datastore automatically. This feature is experimental and has
|
||||
several limitations.
|
||||
|
||||
You enable the automatic upgrading by registering the changelog upgrade method in `clixon_plugin_ini()` using wildcards:
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@
|
|||
/* These include signatures for plugin and transaction callbacks. */
|
||||
#include <clixon/clixon_backend.h>
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define BACKEND_EXAMPLE_OPTS "rsS:iuUt"
|
||||
|
||||
/*! Variable to control if reset code is run.
|
||||
* The reset code inserts "extra XML" which assumes ietf-interfaces is
|
||||
* loaded, and this is not always the case.
|
||||
|
|
@ -1015,7 +1018,7 @@ clixon_plugin_init(clicon_handle h)
|
|||
goto done;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, "rsS:iuUt")) != -1)
|
||||
while ((c = getopt(argc, argv, BACKEND_EXAMPLE_OPTS)) != -1)
|
||||
switch (c) {
|
||||
case 'r':
|
||||
_reset = 1;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@
|
|||
#include <clixon/clixon.h>
|
||||
#include <clixon/clixon_restconf.h> /* minor use */
|
||||
|
||||
/* Command line options to be passed to getopt(3)
|
||||
* -a basic authentication
|
||||
* -s ssl client certificates
|
||||
*/
|
||||
#define RESTCONF_EXAMPLE_OPTS "as"
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
|
@ -60,6 +66,11 @@ static const char Pad64 = '=';
|
|||
*/
|
||||
static int basic_auth = 0;
|
||||
|
||||
/* Use https ssl client certs, map subject CN to user. Set by starting restonf with:
|
||||
* clixon_restconf ... -- -s
|
||||
*/
|
||||
static int ssl_client_certs = 0;
|
||||
|
||||
/* skips all whitespace anywhere.
|
||||
converts characters, four at a time, starting at (or after)
|
||||
src from base - 64 numbers into three 8 bit bytes in the target area.
|
||||
|
|
@ -187,18 +198,17 @@ b64_decode(const char *src,
|
|||
return (tarindex);
|
||||
}
|
||||
|
||||
/*! Process a rest request that requires (cookie) "authentication"
|
||||
/*! HTTP basic authentication example (note hardwired)
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] arg Argument. Here: Fastcgi request handle
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Unauth
|
||||
* @retval 1 Auth
|
||||
* @note: Three hardwired users: andy, wilma, guest w password "bar".
|
||||
* Enabled by passing -- -a to the main function
|
||||
*/
|
||||
int
|
||||
example_restconf_credentials(clicon_handle h,
|
||||
void *arg)
|
||||
static int
|
||||
example_basic_auth(clicon_handle h,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
|
|
@ -210,9 +220,6 @@ example_restconf_credentials(clicon_handle h,
|
|||
size_t authlen;
|
||||
int ret;
|
||||
|
||||
/* HTTP basic authentication not enabled, pass with user "none" */
|
||||
if (basic_auth==0)
|
||||
goto ok;
|
||||
/* At this point in the code we must use HTTP basic authentication */
|
||||
if ((auth = restconf_param_get(h, "HTTP_AUTHORIZATION")) == NULL)
|
||||
goto fail;
|
||||
|
|
@ -249,7 +256,7 @@ example_restconf_credentials(clicon_handle h,
|
|||
clicon_debug(1, "%s user:%s", __FUNCTION__, user);
|
||||
if (clicon_username_set(h, user) < 0)
|
||||
goto done;
|
||||
ok: /* authenticated */
|
||||
/* authenticated */
|
||||
retval = 1;
|
||||
done: /* error */
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
|
|
@ -265,6 +272,53 @@ example_restconf_credentials(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/*! SSL client cert authentication.
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] arg
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Unauth
|
||||
* @retval 1 Auth
|
||||
*/
|
||||
static int
|
||||
example_client_certs(clicon_handle h,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
char *cn;
|
||||
|
||||
/* Check for cert subject common name (CN) */
|
||||
if ((cn = restconf_param_get(h, "SSL_CN")) == NULL)
|
||||
goto fail;
|
||||
if (clicon_username_set(h, cn) < 0)
|
||||
goto done;
|
||||
/* authenticated */
|
||||
retval = 1;
|
||||
done: /* error */
|
||||
return retval;
|
||||
fail: /* unauthenticated */
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Authentication callback
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] arg
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Unauth
|
||||
* @retval 1 Auth
|
||||
*/
|
||||
int
|
||||
example_restconf_credentials(clicon_handle h,
|
||||
void *arg)
|
||||
{
|
||||
if (basic_auth)
|
||||
return example_basic_auth(h, arg);
|
||||
else if (ssl_client_certs)
|
||||
return example_client_certs(h, arg);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*! Local example restconf rpc callback
|
||||
*/
|
||||
int
|
||||
|
|
@ -338,11 +392,14 @@ clixon_plugin_init(clicon_handle h)
|
|||
return NULL;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, "a")) != -1)
|
||||
while ((c = getopt(argc, argv, RESTCONF_EXAMPLE_OPTS)) != -1)
|
||||
switch (c) {
|
||||
case 'a':
|
||||
case 'a': /* basic authentication */
|
||||
basic_auth = 1;
|
||||
break;
|
||||
case 's': /* ssl client certs */
|
||||
ssl_client_certs = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,8 +100,3 @@
|
|||
* clixon-4.4
|
||||
*/
|
||||
#define STATE_ORDERED_BY_SYSTEM
|
||||
|
||||
/*! Dir for Public Key Infrastructure (PKI) X.509 certificates
|
||||
*/
|
||||
#define CLIXON_SERVER_CERT "server"
|
||||
#define CLIXON_PKI_DIR "/etc/pki/clixon"
|
||||
|
|
|
|||
|
|
@ -97,3 +97,17 @@ For example, in FreeBSD, add:
|
|||
make=gmake
|
||||
```
|
||||
|
||||
## https
|
||||
|
||||
If you use evhtp with `configure --with-restconf=evhtp`, you can prepend the tests with RCPROTO=https which will run all restconf tests with SSL https and server certs.
|
||||
|
||||
Ensure the server keys are in order, as follows.
|
||||
|
||||
If you already have server certs, ensure CLICON_SSL_SERVER_CERT and CLICON_SSL_SERVER_KEY points to them.
|
||||
|
||||
If you do not have them, generate self-signed certs, eg as follows:
|
||||
```
|
||||
openssl req -x509 -nodes -newkey rsa:4096 -keyout /etc/ssl/private/clixon-server-key.pem -out /etc/ssl/certs/clixon-server-crt.pem -days 365
|
||||
```
|
||||
|
||||
There are also client-cert tests, eg test_ssl*.sh
|
||||
|
|
|
|||
4
test/config.sh.in
Executable file
4
test/config.sh.in
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
# Generated from autotools
|
||||
|
||||
WITH_RESTCONF=@with_restconf@
|
||||
17
test/lib.sh
17
test/lib.sh
|
|
@ -26,6 +26,14 @@ version=4
|
|||
|
||||
>&2 echo "Running $testfile"
|
||||
|
||||
# Generated config file from autotools / configure
|
||||
if [ -f ./config.sh ]; then
|
||||
. ./config.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
return -1 # error
|
||||
fi
|
||||
fi
|
||||
|
||||
# Site file, an example of this file in README.md
|
||||
if [ -f ./site.sh ]; then
|
||||
. ./site.sh
|
||||
|
|
@ -139,10 +147,11 @@ if [ ! -G $dir ]; then
|
|||
sudo chgrp $u $dir
|
||||
fi
|
||||
|
||||
# If you bring your own backend BE=0 (it is already started),the backend may
|
||||
# If you bring your own backend BE=0 (it is already started), the backend may
|
||||
# have created some files (eg unix socket) in $dir and therefore cannot
|
||||
# be deleted
|
||||
if [ $BE -ne 0 ]; then
|
||||
# be deleted.
|
||||
# Same with RC=0
|
||||
if [ $BE -ne 0 -a $RC -ne 0 ]; then
|
||||
rm -rf $dir/*
|
||||
fi
|
||||
|
||||
|
|
@ -232,7 +241,7 @@ wait_backend(){
|
|||
start_restconf(){
|
||||
# Start in background
|
||||
if [ $RCPROTO = https ]; then
|
||||
EXTRA="-s"
|
||||
EXTRA="-s" # server certs
|
||||
else
|
||||
EXTRA=
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
<CLICON_XMLDB_FORMAT>$format</CLICON_XMLDB_FORMAT>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ cat <<EOF > $cfg
|
|||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
|
|||
263
test/test_ssl_certs.sh
Executable file
263
test/test_ssl_certs.sh
Executable file
|
|
@ -0,0 +1,263 @@
|
|||
#!/usr/bin/env bash
|
||||
# Restconf+NACM openssl functionality using server and client certs
|
||||
# The test creates certs and keys:
|
||||
# A CA, server key/cert, user key/cert for two users
|
||||
# Can we try illegal certs?
|
||||
|
||||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
# Only works with evhtp and https
|
||||
if [ "${WITH_RESTCONF}" != "evhtp" -o "$RCPROTO" = http ]; then
|
||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip
|
||||
fi
|
||||
|
||||
APPNAME=example
|
||||
|
||||
# Common NACM scripts
|
||||
. ./nacm.sh
|
||||
|
||||
# force it (or check it?)
|
||||
RCPROTO=https
|
||||
|
||||
fyang=$dir/example.yang
|
||||
|
||||
cfg=$dir/conf.xml
|
||||
certdir=$dir/certs
|
||||
|
||||
srvkey=$certdir/srv_key.pem
|
||||
srvcert=$certdir/srv_cert.pem
|
||||
cakey=$certdir/ca_key.pem # needed?
|
||||
cacert=$certdir/ca_cert.pem
|
||||
users="andy guest" # generate certs for some users in nacm.sh
|
||||
|
||||
# Whether to generate new keys or not (only if $dir is not removed)
|
||||
# Here dont generate keys if restconf started stand-alone
|
||||
genkeys=true
|
||||
if [ $RC -eq 0 ]; then
|
||||
genkeys=false
|
||||
fi
|
||||
|
||||
test -d $certdir || mkdir $certdir
|
||||
|
||||
# Use yang in example
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||
<CLICON_SSL_SERVER_CERT>$srvcert</CLICON_SSL_SERVER_CERT>
|
||||
<CLICON_SSL_SERVER_KEY>$srvkey</CLICON_SSL_SERVER_KEY>
|
||||
<CLICON_SSL_CA_CERT>$cacert</CLICON_SSL_CA_CERT>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
cat <<EOF > $fyang
|
||||
module example{
|
||||
yang-version 1.1;
|
||||
namespace "urn:example:example";
|
||||
prefix ex;
|
||||
import ietf-netconf-acm {
|
||||
prefix nacm;
|
||||
}
|
||||
leaf x{
|
||||
type int32;
|
||||
description "something to edit";
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Two groups: admin allow all, guest allow nothing
|
||||
RULES=$(cat <<EOF
|
||||
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
|
||||
<enable-nacm>false</enable-nacm>
|
||||
<read-default>permit</read-default>
|
||||
<write-default>deny</write-default>
|
||||
<exec-default>deny</exec-default>
|
||||
|
||||
$NGROUPS
|
||||
|
||||
<rule-list>
|
||||
<name>guest-acl</name>
|
||||
<group>guest</group>
|
||||
<rule>
|
||||
<name>deny-ncm</name>
|
||||
<module-name>*</module-name>
|
||||
<access-operations>*</access-operations>
|
||||
<action>deny</action>
|
||||
<comment>
|
||||
Do not allow guests any access to the NETCONF
|
||||
</comment>
|
||||
</rule>
|
||||
</rule-list>
|
||||
|
||||
$NADMIN
|
||||
|
||||
</nacm>
|
||||
<x xmlns="urn:example:example">0</x>
|
||||
EOF
|
||||
)
|
||||
|
||||
if $genkeys; then
|
||||
# Create certs
|
||||
# 1. CA
|
||||
cat<<EOF > $dir/ca.cnf
|
||||
[ ca ]
|
||||
default_ca = CA_default
|
||||
|
||||
[ CA_default ]
|
||||
serial = ca-serial
|
||||
crl = ca-crl.pem
|
||||
database = ca-database.txt
|
||||
name_opt = CA_default
|
||||
cert_opt = CA_default
|
||||
default_crl_days = 9999
|
||||
default_md = md5
|
||||
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
days = 1
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
prompt = no
|
||||
output_password = password
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = SE
|
||||
L = Stockholm
|
||||
O = Clixon
|
||||
OU = clixon
|
||||
CN = ca
|
||||
emailAddress = olof@hagsand.se
|
||||
|
||||
[ req_attributes ]
|
||||
challengePassword = test
|
||||
|
||||
EOF
|
||||
|
||||
# Generate CA cert
|
||||
openssl req -x509 -days 1 -config $dir/ca.cnf -keyout $cakey -out $cacert
|
||||
|
||||
cat<<EOF > $dir/srv.cnf
|
||||
[req]
|
||||
prompt = no
|
||||
distinguished_name = dn
|
||||
req_extensions = ext
|
||||
[dn]
|
||||
CN = www.clicon.org # localhost
|
||||
emailAddress = olof@hagsand.se
|
||||
O = Clixon
|
||||
L = Stockholm
|
||||
C = SE
|
||||
[ext]
|
||||
subjectAltName = DNS:clicon.org
|
||||
EOF
|
||||
|
||||
# Generate server key
|
||||
openssl genrsa -out $srvkey 2048
|
||||
|
||||
# Generate CSR (signing request)
|
||||
openssl req -new -config $dir/srv.cnf -key $srvkey -out $certdir/srv_csr.pem
|
||||
|
||||
# Sign server cert by CA
|
||||
openssl x509 -req -extfile $dir/srv.cnf -days 1 -passin "pass:password" -in $certdir/srv_csr.pem -CA $cacert -CAkey $cakey -CAcreateserial -out $srvcert
|
||||
|
||||
# create client certs
|
||||
for name in $users; do
|
||||
cat<<EOF > $dir/$name.cnf
|
||||
[req]
|
||||
prompt = no
|
||||
distinguished_name = dn
|
||||
[dn]
|
||||
CN = $name
|
||||
emailAddress = $name@foo.bar
|
||||
O = Clixon
|
||||
L = Stockholm
|
||||
C = SE
|
||||
EOF
|
||||
# Create client key
|
||||
openssl genrsa -out "$certdir/$name.key" 2048
|
||||
|
||||
# Generate CSR (signing request)
|
||||
openssl req -new -config $dir/$name.cnf -key $certdir/$name.key -out $certdir/$name.csr
|
||||
|
||||
# Sign by CA
|
||||
openssl x509 -req -extfile $dir/$name.cnf -days 1 -passin "pass:password" -in $certdir/$name.csr -CA $cacert -CAkey $cakey -CAcreateserial -out $certdir/$name.crt
|
||||
done
|
||||
|
||||
fi # genkeys
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "kill old backend"
|
||||
sudo clixon_backend -zf $cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
sudo pkill -f clixon_backend # to be sure
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
fi
|
||||
|
||||
new "wait for backend"
|
||||
wait_backend
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon -c means client certs, -- -s means ssl client cert authentication in example"
|
||||
start_restconf -f $cfg -c -- -s
|
||||
|
||||
fi
|
||||
#new "wait for restconf"
|
||||
#wait_restconf XXX
|
||||
|
||||
new "auth set authentication config"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "commit it"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "enable nacm"
|
||||
expectpart "$(curl -sSik --key $certdir/andy.key --cert $certdir/andy.crt -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-netconf-acm:enable-nacm": true}' $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/enable-nacm)" 0 "HTTP/1.1 204 No Content"
|
||||
|
||||
new "admin get x"
|
||||
expectpart "$(curl -sSik --key $certdir/andy.key --cert $certdir/andy.crt -X GET $RCPROTO://localhost/restconf/data/example:x)" 0 "HTTP/1.1 200 OK" '{"example:x":0}'
|
||||
|
||||
new "guest get x"
|
||||
expectpart "$(curl -sSik --key $certdir/guest.key --cert $certdir/guest.crt -X GET $RCPROTO://localhost/restconf/data/example:x)" 0 "HTTP/1.1 403 Forbidden" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"access denied"}}}'
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
new "Kill restconf daemon"
|
||||
stop_restconf
|
||||
fi
|
||||
|
||||
if [ $BE -eq 0 ]; then
|
||||
exit # BE
|
||||
fi
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=$(pgrep -u root -f clixon_backend)
|
||||
if [ -z "$pid" ]; then
|
||||
err "backend already dead"
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
rm -rf $dir
|
||||
|
|
@ -23,6 +23,11 @@
|
|||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
# Only works with fcgi and http
|
||||
if [ "${WITH_RESTCONF}" != "fcgi" -o "$RCPROTO" = https ]; then
|
||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip
|
||||
fi
|
||||
|
||||
APPNAME=example
|
||||
: ${clixon_util_stream:=clixon_util_stream}
|
||||
NCWAIT=10 # Wait (netconf valgrind may need more time)
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ if [ $BE -ne 0 ]; then
|
|||
start_backend -s init -f $cfg
|
||||
fi
|
||||
|
||||
new "waiting"
|
||||
new "wait backend"
|
||||
wait_backend
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
|
|
@ -168,7 +168,7 @@ if [ $RC -ne 0 ]; then
|
|||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
new "wait restconf"
|
||||
wait_restconf
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,10 @@ module clixon-config {
|
|||
revision 2020-06-17 {
|
||||
description
|
||||
"Added: CLICON_CLI_LINES_DEFAULT
|
||||
Added enum HIDE to CLICON_CLI_GENMODEL";
|
||||
Added enum HIDE to CLICON_CLI_GENMODEL
|
||||
Added CLICON_SSL_SERVER_CERT
|
||||
Added CLICON_SSL_SERVER_KEY
|
||||
Added CLICON_SSL_CA_CERT";
|
||||
}
|
||||
revision 2020-04-23 {
|
||||
description
|
||||
|
|
@ -377,6 +380,27 @@ module clixon-config {
|
|||
Setting this value to false makes restconf return not pretty-printed
|
||||
which may be desirable for performance or tests";
|
||||
}
|
||||
leaf CLICON_SSL_SERVER_CERT {
|
||||
type string;
|
||||
default "/etc/ssl/certs/clixon-server-crt.pem";
|
||||
description
|
||||
"SSL server cert for restconf https. This is not required if you use
|
||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
||||
}
|
||||
leaf CLICON_SSL_SERVER_KEY {
|
||||
type string;
|
||||
default "/etc/ssl/private/clixon-server-key.pem";
|
||||
description
|
||||
"SSL server private key for restconf https. This is not required if you use
|
||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
||||
}
|
||||
leaf CLICON_SSL_CA_CERT {
|
||||
type string;
|
||||
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
||||
description
|
||||
"SSL CA cert for client authentication. This is not required if you use
|
||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
||||
}
|
||||
leaf CLICON_CLI_DIR {
|
||||
type string;
|
||||
description
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue