* Restconf authentication callback (ca_auth) signature changed
* Not backward compatible: All uses of the ca-auth callback in restconf plugins must be changed
* New version is: `int ca_auth(h, req, auth_type, authp, userp)`
* where `auth_type` is the requested authentication-type (none, client-cert or user-defined)
* `authp` is the returned authentication flag
* `userp` is the returned associated authenticated user
* and the return value is three-valued: -1: Error, 0: ignored, 1: OK
* For more info see [clixon-docs](https://clixon-docs.readthedocs.io/en/latest/restconf.html)
* New clixon-restconf@2020-12-30.yang revision
This commit is contained in:
parent
1f0147f996
commit
710fc76887
54 changed files with 1216 additions and 485 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
|
@ -32,6 +32,7 @@ Expected: February 2021
|
|||
### New features
|
||||
|
||||
* NETCONF Call Home Call Home RFC 8071
|
||||
* See [Netconf/ssh callhome](https://clixon-docs.readthedocs.io/en/latest/netconf.html#callhome)
|
||||
* Solution description using openssh and utility functions, no changes to core clixon
|
||||
* Example: test/test_netconf_ssh_callhome.sh
|
||||
* RESTCONF Call home not done
|
||||
|
|
@ -42,6 +43,14 @@ Expected: February 2021
|
|||
|
||||
Developers may need to change their code
|
||||
|
||||
* Restconf authentication callback (ca_auth) signature changed
|
||||
* Not backward compatible: All uses of the ca-auth callback in restconf plugins must be changed
|
||||
* New version is: `int ca_auth(h, req, auth_type, authp, userp)`
|
||||
* where `auth_type` is the requested authentication-type (none, client-cert or user-defined)
|
||||
* `authp` is the returned authentication flag
|
||||
* `userp` is the returned associated authenticated user
|
||||
* and the return value is three-valued: -1: Error, 0: ignored, 1: OK
|
||||
* For more info see [clixon-docs](https://clixon-docs.readthedocs.io/en/latest/restconf.html)
|
||||
* rpc msg C API rearranged to separate socket/connect from connect
|
||||
* Added `cvv_i` output parameter to `api_path_fmt2api_path()` to see how many cvv entries were used.
|
||||
|
||||
|
|
@ -50,6 +59,10 @@ Developers may need to change their code
|
|||
Users may have to change how they access the system
|
||||
|
||||
* Handling empty netconf XML messages "]]>]]>" is changed from being accepted to return an error.
|
||||
* New clixon-restconf@2020-12-30.yang revision
|
||||
* Added: debug field
|
||||
* Added 'none' as default value for auth-type
|
||||
* Changed http-auth-type enum from 'password' to 'user'
|
||||
* New clixon-lib@2020-12-30.yang revision
|
||||
* Changed: RPC process-control output parameter status to pid
|
||||
* New clixon-config@2020-12-30.yang revision
|
||||
|
|
@ -710,7 +723,7 @@ Patch release based on testing by Dave Cornejo, Netgate
|
|||
|
||||
### Summary
|
||||
|
||||
The main improvement in this release concerns security in terms of priveleges and credentials of accessing the clixon backend. There is also stricter multi-namespace checks which primarily effects where augmented models are used.
|
||||
The main improvement in this release concerns security in terms of privileges and credentials of accessing the clixon backend. There is also stricter multi-namespace checks which primarily effects where augmented models are used.
|
||||
|
||||
### Major New features
|
||||
* The backend daemon can drop privileges after initialization to run as non-privileged user
|
||||
|
|
@ -718,7 +731,7 @@ The main improvement in this release concerns security in terms of priveleges an
|
|||
* use `-U <user>` clixon_backend command-line option to drop to `user`
|
||||
* Generic options are the following:
|
||||
* `CLICON_BACKEND_USER` drop of privileges to this user
|
||||
* `CLICON_BACKEND_PRIVELEGES` can have the following values:
|
||||
* `CLICON_BACKEND_PRIVILEGES` can have the following values:
|
||||
* `none` Make no drop/change in privileges. This is currently the default.
|
||||
* `drop_perm` After initialization, drop privileges permanently
|
||||
* `drop_perm` After initialization, drop privileges temporarily (to a euid)
|
||||
|
|
@ -749,8 +762,8 @@ a="urn:example:a" xmlns:b="urn:example:b"/>`
|
|||
* New clixon-config@2019-09-11.yang revision
|
||||
* Added: CLICON_BACKEND_USER: Drop of privileges to this user, owner of backend socket (default: `clicon`)
|
||||
* Therefore new installation should now add a UNIX `clicon` user
|
||||
* Added: CLICON_BACKEND_PRIVELEGES: If and how to drop privileges
|
||||
* Added: CLICON_NACM_CREDENTIALS: If and how to check backend socket priveleges with NACM
|
||||
* Added: CLICON_BACKEND_PRIVILEGES: If and how to drop privileges
|
||||
* Added: CLICON_NACM_CREDENTIALS: If and how to check backend socket privileges with NACM
|
||||
* Added: CLICON_NACM_RECOVERY_USER: Name of NACM recovery user.
|
||||
* Restconf top-level operations GET root resource modified to comply with RFC 8040 Sec 3.1
|
||||
* non-pretty print remove all spaces, eg `{"operations":{"clixon-example:client-rpc":[null]`
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ APPSRC += backend_socket.c
|
|||
APPSRC += backend_client.c
|
||||
APPSRC += backend_commit.c
|
||||
APPSRC += backend_plugin.c
|
||||
APPSRC += backend_plugin_restconf.c # Pseudo plugin for restconf daemon
|
||||
APPSRC += backend_startup.c
|
||||
APPOBJ = $(APPSRC:.c=.o)
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
#include "backend_commit.h"
|
||||
#include "backend_handle.h"
|
||||
#include "backend_startup.h"
|
||||
#include "backend_plugin_restconf.h"
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define BACKEND_OPTS "hD:f:E:l:d:p:b:Fza:u:P:1qs:c:U:g:y:o:"
|
||||
|
|
@ -388,169 +389,6 @@ ret2status(int ret,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* Restconf process pseudo plugin
|
||||
*/
|
||||
|
||||
#define RESTCONF_PROCESS "restconf"
|
||||
|
||||
/*! Process rpc callback function
|
||||
* - if RPC op is start, if enable is true, start the service, if false, error or ignore it
|
||||
* - if RPC op is stop, stop the service
|
||||
* These rules give that if RPC op is start and enable is false -> change op to none
|
||||
*/
|
||||
int
|
||||
restconf_rpc_wrapper(clicon_handle h,
|
||||
process_entry_t *pe,
|
||||
char **operation)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (strcmp(*operation, "stop") == 0){
|
||||
/* if RPC op is stop, stop the service */
|
||||
}
|
||||
else if (strcmp(*operation, "start") == 0){
|
||||
/* RPC op is start & enable is true, then start the service,
|
||||
& enable is false, error or ignore it */
|
||||
if (xmldb_get(h, "running", NULL, "/restconf", &xt) < 0)
|
||||
goto done;
|
||||
if (xt != NULL &&
|
||||
xpath_first(xt, NULL, "/restconf[enable='false']") != NULL) {
|
||||
*operation = "none";
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Enable process-control of restconf daemon, ie start/stop restconf by registering restconf process
|
||||
* @param[in] h Clicon handle
|
||||
* @note Could also look in clixon-restconf and start process if enable is true, but that needs to
|
||||
* be in start callback using a pseudo plugin.
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_control(clicon_handle h)
|
||||
{
|
||||
int retval = -1;
|
||||
char **argv = NULL;
|
||||
int i;
|
||||
int nr;
|
||||
char dbgstr[8];
|
||||
char wwwstr[64];
|
||||
|
||||
nr = 4;
|
||||
if (clicon_debug_get() != 0)
|
||||
nr += 2;
|
||||
if ((argv = calloc(nr, sizeof(char *))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "calloc");
|
||||
goto done;
|
||||
}
|
||||
i = 0;
|
||||
snprintf(wwwstr, sizeof(wwwstr)-1, "%s/clixon_restconf", clicon_option_str(h, "CLICON_WWWDIR"));
|
||||
argv[i++] = wwwstr;
|
||||
argv[i++] = "-f";
|
||||
argv[i++] = clicon_option_str(h, "CLICON_CONFIGFILE");
|
||||
if (clicon_debug_get() != 0){
|
||||
argv[i++] = "-D";
|
||||
snprintf(dbgstr, sizeof(dbgstr)-1, "%d", clicon_debug_get());
|
||||
argv[i++] = dbgstr;
|
||||
}
|
||||
argv[i++] = NULL;
|
||||
assert(i==nr);
|
||||
if (clixon_process_register(h, RESTCONF_PROCESS,
|
||||
NULL /* XXX network namespace */,
|
||||
restconf_rpc_wrapper,
|
||||
argv, nr) < 0)
|
||||
goto done;
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Restconf pseduo-plugin process validate
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_validate(clicon_handle h,
|
||||
transaction_data td)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xtarget;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
xtarget = transaction_target(td);
|
||||
/* If ssl-enable is true and (at least a) socket has ssl,
|
||||
* then server-cert-path and server-key-path must exist */
|
||||
if (xpath_first(xtarget, NULL, "restconf/enable[.='true']") &&
|
||||
xpath_first(xtarget, NULL, "restconf/socket[ssl='true']")){
|
||||
/* Should filepath be checked? One could claim this is a runtime system,... */
|
||||
if (xpath_first(xtarget, 0, "restconf/server-cert-path") == NULL){
|
||||
clicon_err(OE_CFG, 0, "SSL enabled but server-cert-path not set");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
if (xpath_first(xtarget, 0, "restconf/server-key-path") == NULL){
|
||||
clicon_err(OE_CFG, 0, "SSL enabled but server-key-path not set");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Restconf pseduo-plugin process commit
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_commit(clicon_handle h,
|
||||
transaction_data td)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xtarget;
|
||||
cxobj *cx;
|
||||
int enabled = 0;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
xtarget = transaction_target(td);
|
||||
if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
|
||||
enabled++;
|
||||
if ((cx = xpath_first(xtarget, NULL, "/restconf/enable")) != NULL &&
|
||||
xml_flag(cx, XML_FLAG_CHANGE|XML_FLAG_ADD)){
|
||||
if (clixon_process_operation(h, RESTCONF_PROCESS,
|
||||
enabled?"start":"stop", 0, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Register start/stop restconf RPC and create pseudo-plugin to monitor enable flag
|
||||
* @param[in] h Clixon handle
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_reg(clicon_handle h,
|
||||
yang_stmt *yspec)
|
||||
{
|
||||
int retval = -1;
|
||||
clixon_plugin *cp = NULL;
|
||||
|
||||
if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0)
|
||||
goto done;
|
||||
cp->cp_api.ca_trans_commit = restconf_pseudo_process_commit;
|
||||
cp->cp_api.ca_trans_validate = restconf_pseudo_process_validate;
|
||||
|
||||
/* Register generic process-control of restconf daemon, ie start/stop restconf */
|
||||
if (restconf_pseudo_process_control(h) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Debug timer */
|
||||
int
|
||||
|
|
@ -981,7 +819,7 @@ main(int argc,
|
|||
goto done;
|
||||
/* Check restconf start/stop from backend */
|
||||
if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS")){
|
||||
if (restconf_pseudo_process_reg(h, yspec) < 0)
|
||||
if (backend_plugin_restconf_register(h, yspec) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* Here all modules are loaded
|
||||
|
|
|
|||
223
apps/backend/backend_plugin_restconf.c
Normal file
223
apps/backend/backend_plugin_restconf.c
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2017-2019 Olof Hagsand
|
||||
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*
|
||||
* Pseudo backend plugin for starting restconf daemon
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clicon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
#include "clixon_backend_transaction.h"
|
||||
#include "backend_plugin_restconf.h"
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* Restconf process pseudo plugin
|
||||
*/
|
||||
|
||||
#define RESTCONF_PROCESS "restconf"
|
||||
|
||||
/*! Process rpc callback function
|
||||
* - if RPC op is start, if enable is true, start the service, if false, error or ignore it
|
||||
* - if RPC op is stop, stop the service
|
||||
* These rules give that if RPC op is start and enable is false -> change op to none
|
||||
*/
|
||||
int
|
||||
restconf_rpc_wrapper(clicon_handle h,
|
||||
process_entry_t *pe,
|
||||
char **operation)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (strcmp(*operation, "stop") == 0){
|
||||
/* if RPC op is stop, stop the service */
|
||||
}
|
||||
else if (strcmp(*operation, "start") == 0){
|
||||
/* RPC op is start & enable is true, then start the service,
|
||||
& enable is false, error or ignore it */
|
||||
if (xmldb_get(h, "running", NULL, "/restconf", &xt) < 0)
|
||||
goto done;
|
||||
if (xt != NULL &&
|
||||
xpath_first(xt, NULL, "/restconf[enable='false']") != NULL) {
|
||||
*operation = "none";
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Enable process-control of restconf daemon, ie start/stop restconf by registering restconf process
|
||||
* @param[in] h Clicon handle
|
||||
* @note Could also look in clixon-restconf and start process if enable is true, but that needs to
|
||||
* be in start callback using a pseudo plugin.
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_control(clicon_handle h)
|
||||
{
|
||||
int retval = -1;
|
||||
char **argv = NULL;
|
||||
int i;
|
||||
int nr;
|
||||
char dbgstr[8];
|
||||
char wwwstr[64];
|
||||
|
||||
nr = 4;
|
||||
if (clicon_debug_get() != 0)
|
||||
nr += 2;
|
||||
if ((argv = calloc(nr, sizeof(char *))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "calloc");
|
||||
goto done;
|
||||
}
|
||||
i = 0;
|
||||
snprintf(wwwstr, sizeof(wwwstr)-1, "%s/clixon_restconf", clicon_option_str(h, "CLICON_WWWDIR"));
|
||||
argv[i++] = wwwstr;
|
||||
argv[i++] = "-f";
|
||||
argv[i++] = clicon_option_str(h, "CLICON_CONFIGFILE");
|
||||
/* Add debug if backend has debug.
|
||||
* There is also a debug flag in clixon-restconf.yang but it kicks in after it starts
|
||||
*/
|
||||
if (clicon_debug_get() != 0){
|
||||
argv[i++] = "-D";
|
||||
snprintf(dbgstr, sizeof(dbgstr)-1, "%d", clicon_debug_get());
|
||||
argv[i++] = dbgstr;
|
||||
}
|
||||
argv[i++] = NULL;
|
||||
assert(i==nr);
|
||||
if (clixon_process_register(h, RESTCONF_PROCESS,
|
||||
NULL /* XXX network namespace */,
|
||||
restconf_rpc_wrapper,
|
||||
argv, nr) < 0)
|
||||
goto done;
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Restconf pseduo-plugin process validate
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_validate(clicon_handle h,
|
||||
transaction_data td)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xtarget;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
xtarget = transaction_target(td);
|
||||
/* If ssl-enable is true and (at least a) socket has ssl,
|
||||
* then server-cert-path and server-key-path must exist */
|
||||
if (xpath_first(xtarget, NULL, "restconf/enable[.='true']") &&
|
||||
xpath_first(xtarget, NULL, "restconf/socket[ssl='true']")){
|
||||
/* Should filepath be checked? One could claim this is a runtime system,... */
|
||||
if (xpath_first(xtarget, 0, "restconf/server-cert-path") == NULL){
|
||||
clicon_err(OE_CFG, 0, "SSL enabled but server-cert-path not set");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
if (xpath_first(xtarget, 0, "restconf/server-key-path") == NULL){
|
||||
clicon_err(OE_CFG, 0, "SSL enabled but server-key-path not set");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Restconf pseduo-plugin process commit
|
||||
*/
|
||||
static int
|
||||
restconf_pseudo_process_commit(clicon_handle h,
|
||||
transaction_data td)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xtarget;
|
||||
cxobj *cx;
|
||||
int enabled = 0;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
xtarget = transaction_target(td);
|
||||
if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
|
||||
enabled++;
|
||||
if ((cx = xpath_first(xtarget, NULL, "/restconf/enable")) != NULL &&
|
||||
xml_flag(cx, XML_FLAG_CHANGE|XML_FLAG_ADD)){
|
||||
if (clixon_process_operation(h, RESTCONF_PROCESS,
|
||||
enabled?"start":"stop", 0, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Register start/stop restconf RPC and create pseudo-plugin to monitor enable flag
|
||||
* @param[in] h Clixon handle
|
||||
*/
|
||||
int
|
||||
backend_plugin_restconf_register(clicon_handle h,
|
||||
yang_stmt *yspec)
|
||||
{
|
||||
int retval = -1;
|
||||
clixon_plugin *cp = NULL;
|
||||
|
||||
if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0)
|
||||
goto done;
|
||||
cp->cp_api.ca_trans_commit = restconf_pseudo_process_commit;
|
||||
cp->cp_api.ca_trans_validate = restconf_pseudo_process_validate;
|
||||
|
||||
/* Register generic process-control of restconf daemon, ie start/stop restconf */
|
||||
if (restconf_pseudo_process_control(h) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
43
apps/backend/backend_plugin_restconf.h
Normal file
43
apps/backend/backend_plugin_restconf.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2017-2019 Olof Hagsand
|
||||
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*
|
||||
* Pseudo backend plugin for starting restconf daemon
|
||||
*/
|
||||
|
||||
#ifndef _BACKEND_PLUGIN_RESTCONF_H_
|
||||
#define _BACKEND_PLUGIN_RESTCONF_H_
|
||||
|
||||
int backend_plugin_restconf_register(clicon_handle h, yang_stmt *yspec);
|
||||
|
||||
#endif /* _BACKEND_PLUGIN_RESTCONF_H_ */
|
||||
|
|
@ -61,6 +61,7 @@
|
|||
/* clicon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
#include "restconf_lib.h"
|
||||
#include "restconf_handle.h"
|
||||
|
||||
/* header part is copied from struct clicon_handle in lib/src/clixon_handle.c */
|
||||
|
|
@ -90,6 +91,7 @@ struct restconf_handle {
|
|||
|
||||
/* ------ end of common handle ------ */
|
||||
clicon_hash_t *rh_params; /* restconf parameters, including http headers */
|
||||
clixon_auth_type_t rh_auth_type; /* authentication type */
|
||||
};
|
||||
|
||||
/*! Creates and returns a clicon config handle for other CLICON API calls
|
||||
|
|
@ -172,3 +174,33 @@ restconf_param_del_all(clicon_handle h)
|
|||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Get restconf http parameter
|
||||
* @param[in] h Clicon handle
|
||||
* @retval auth_type
|
||||
*/
|
||||
clixon_auth_type_t
|
||||
restconf_auth_type_get(clicon_handle h)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
return rh->rh_auth_type;
|
||||
}
|
||||
|
||||
/*! Set restconf http parameter
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] name Data name
|
||||
* @param[in] val Data value as null-terminated string
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* Currently using clixon runtime data but there is risk for colliding names
|
||||
*/
|
||||
int
|
||||
restconf_auth_type_set(clicon_handle h,
|
||||
clixon_auth_type_t type)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
rh->rh_auth_type = type;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,5 +47,7 @@ int restconf_handle_exit(clicon_handle h);
|
|||
char *restconf_param_get(clicon_handle h, const char *param);
|
||||
int restconf_param_set(clicon_handle h, const char *param, char *val);
|
||||
int restconf_param_del_all(clicon_handle h);
|
||||
clixon_auth_type_t restconf_auth_type_get(clicon_handle h);
|
||||
int restconf_auth_type_set(clicon_handle h, clixon_auth_type_t type);
|
||||
|
||||
#endif /* _RESTCONF_HANDLE_H_ */
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@
|
|||
#include <clixon/clixon.h>
|
||||
|
||||
#include "restconf_api.h"
|
||||
#include "restconf_handle.h"
|
||||
#include "restconf_lib.h"
|
||||
#include "restconf_err.h"
|
||||
#include "restconf_handle.h"
|
||||
|
||||
/* See RFC 8040 Section 7: Mapping from NETCONF<error-tag> to Status Code
|
||||
* and RFC 6241 Appendix A. NETCONF Error list
|
||||
|
|
@ -495,3 +496,123 @@ restconf_drop_privileges(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Generic Www handle (can be part of clixon handle)
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not authenticated
|
||||
* @retval 1 Authenticated
|
||||
*/
|
||||
int
|
||||
restconf_authentication_cb(clicon_handle h,
|
||||
void *req,
|
||||
int pretty,
|
||||
restconf_media media_out)
|
||||
{
|
||||
int retval = -1;
|
||||
clixon_auth_type_t auth_type;
|
||||
int authenticated;
|
||||
int ret;
|
||||
char *username = NULL;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
|
||||
auth_type = restconf_auth_type_get(h);
|
||||
clicon_debug(1, "%s auth-type:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
|
||||
ret = 0;
|
||||
authenticated = 0;
|
||||
if (auth_type != CLIXON_AUTH_NONE)
|
||||
if ((ret = clixon_plugin_auth_all(h, req,
|
||||
auth_type,
|
||||
&authenticated,
|
||||
&username)) < 0)
|
||||
goto done;
|
||||
if (ret == 1){ /* OK, tag username to handle */
|
||||
clicon_username_set(h, username);
|
||||
}
|
||||
else { /* Default behaviour */
|
||||
switch (auth_type){
|
||||
case CLIXON_AUTH_NONE:
|
||||
clicon_username_set(h, "none");
|
||||
authenticated = 1;
|
||||
break;
|
||||
case CLIXON_AUTH_CLIENT_CERTIFICATE: {
|
||||
char *cn;
|
||||
/* Check for cert subject common name (CN) */
|
||||
if ((cn = restconf_param_get(h, "SSL_CN")) != NULL){
|
||||
clicon_username_set(h, cn);
|
||||
authenticated = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLIXON_AUTH_USER:
|
||||
authenticated = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (authenticated == 0){ /* Message is not authenticated (401 returned) */
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
goto done;
|
||||
goto notauth;
|
||||
}
|
||||
retval = 0;
|
||||
goto notauth;
|
||||
}
|
||||
/* If set but no user, set a dummy user */
|
||||
retval = 1;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d authenticated:%d user:%s",
|
||||
__FUNCTION__, retval, authenticated, clicon_username_get(h));
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
notauth:
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Basic config init
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] xrestconf XML config containing clixon-restconf top-level
|
||||
* @retval -1 Error
|
||||
* @retval 0 Restconf is disable
|
||||
* @retval 1 OK
|
||||
*/
|
||||
int
|
||||
restconf_config_init(clicon_handle h,
|
||||
cxobj *xrestconf)
|
||||
{
|
||||
int retval = -1;
|
||||
char *enable;
|
||||
cxobj *x;
|
||||
char *bstr;
|
||||
cvec *nsc = NULL;
|
||||
clixon_auth_type_t auth_type;
|
||||
|
||||
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
|
||||
(enable = xml_body(x)) != NULL){
|
||||
if (strcmp(enable, "false") == 0){
|
||||
clicon_debug(1, "%s restconf disabled", __FUNCTION__);
|
||||
goto disable;
|
||||
}
|
||||
}
|
||||
|
||||
/* get common fields */
|
||||
if ((x = xpath_first(xrestconf, nsc, "auth-type")) != NULL &&
|
||||
(bstr = xml_body(x)) != NULL){
|
||||
if ((auth_type = clixon_auth_type_str2int(bstr)) < 0){
|
||||
clicon_err(OE_CFG, EFAULT, "Invalid restconf auth-type: %s", bstr);
|
||||
goto done;
|
||||
}
|
||||
restconf_auth_type_set(h, auth_type);
|
||||
}
|
||||
retval = 1;
|
||||
done:
|
||||
return retval;
|
||||
disable:
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ int restconf_insert_attributes(cxobj *xdata, cvec *qvec);
|
|||
int restconf_main_extension_cb(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
|
||||
char *restconf_uripath(clicon_handle h);
|
||||
int restconf_drop_privileges(clicon_handle h, char *user);
|
||||
int restconf_authentication_cb(clicon_handle h, void *req, int pretty, restconf_media media_out);
|
||||
int restconf_config_init(clicon_handle h, cxobj *xrestconf);
|
||||
|
||||
#endif /* _RESTCONF_LIB_H_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -83,15 +83,18 @@
|
|||
#include "restconf_err.h"
|
||||
#include "restconf_root.h"
|
||||
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:"
|
||||
|
||||
/* See see listen(5) */
|
||||
#define SOCKET_LISTEN_BACKLOG 16
|
||||
|
||||
/* clixon evhtp handle */
|
||||
/* Clixon evhtp handle
|
||||
* Global data about evhtp lib,
|
||||
* See evhtp_request_t *req for per-message state data
|
||||
*/
|
||||
typedef struct {
|
||||
clicon_handle eh_h;
|
||||
evhtp_t **eh_htpvec; /* One per socket */
|
||||
int eh_htplen; /* Number of sockets */
|
||||
struct event_base *eh_evbase; /* Change to list */
|
||||
|
|
@ -150,7 +153,7 @@ restconf_sig_term(int arg)
|
|||
exit(-1);
|
||||
if (_EVHTP_HANDLE) /* global */
|
||||
evhtp_terminate(_EVHTP_HANDLE);
|
||||
if (_CLICON_HANDLE){
|
||||
if (_CLICON_HANDLE){ /* could be replaced by eh->eh_h */
|
||||
// stream_child_freeall(_CLICON_HANDLE);
|
||||
restconf_terminate(_CLICON_HANDLE);
|
||||
}
|
||||
|
|
@ -448,7 +451,8 @@ static void
|
|||
cx_path_wellknown(evhtp_request_t *req,
|
||||
void *arg)
|
||||
{
|
||||
clicon_handle h = arg;
|
||||
cx_evhtp_handle *eh = (cx_evhtp_handle*)arg;
|
||||
clicon_handle h = eh->eh_h;
|
||||
int ret;
|
||||
|
||||
clicon_debug(1, "------------");
|
||||
|
|
@ -479,7 +483,8 @@ static void
|
|||
cx_path_restconf(evhtp_request_t *req,
|
||||
void *arg)
|
||||
{
|
||||
clicon_handle h = arg;
|
||||
cx_evhtp_handle *eh = (cx_evhtp_handle*)arg;
|
||||
clicon_handle h = eh->eh_h;
|
||||
int ret;
|
||||
cvec *qvec = NULL;
|
||||
|
||||
|
|
@ -488,7 +493,6 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
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){
|
||||
|
|
@ -844,8 +848,7 @@ cx_evhtp_socket(clicon_handle h,
|
|||
cvec *nsc,
|
||||
char *server_cert_path,
|
||||
char *server_key_path,
|
||||
char *server_ca_cert_path,
|
||||
int auth_type_client_certificate)
|
||||
char *server_ca_cert_path)
|
||||
{
|
||||
int retval = -1;
|
||||
char *netns = NULL;
|
||||
|
|
@ -862,7 +865,6 @@ cx_evhtp_socket(clicon_handle h,
|
|||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifndef EVHTP_DISABLE_EVTHR /* threads */
|
||||
evhtp_use_threads_wexit(htp, NULL, NULL, 4, NULL);
|
||||
#endif
|
||||
|
|
@ -871,12 +873,12 @@ cx_evhtp_socket(clicon_handle h,
|
|||
/* Callback right after a connection is accepted. */
|
||||
evhtp_set_post_accept_cb(htp, cx_post_accept, h);
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, "/" RESTCONF_API, cx_path_restconf, h) == NULL){
|
||||
if (evhtp_set_cb(htp, "/" RESTCONF_API, cx_path_restconf, eh) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, h) == NULL){
|
||||
if (evhtp_set_cb(htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, eh) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -934,39 +936,39 @@ cx_evhtp_init(clicon_handle h,
|
|||
cx_evhtp_handle *eh)
|
||||
{
|
||||
int retval = -1;
|
||||
char* enable;
|
||||
int ssl_enable = 0;
|
||||
int dbg = 0;
|
||||
cxobj **vec = NULL;
|
||||
size_t veclen;
|
||||
char *server_cert_path = NULL;
|
||||
char *server_key_path = NULL;
|
||||
char *server_ca_cert_path = NULL;
|
||||
char *auth_type = NULL;
|
||||
int auth_type_client_certificate = 0;
|
||||
cxobj *x;
|
||||
char *bstr;
|
||||
int i;
|
||||
int ret;
|
||||
clixon_auth_type_t auth_type;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
|
||||
(enable = xml_body(x)) != NULL){
|
||||
if (strcmp(enable, "false") == 0){
|
||||
clicon_debug(1, "%s restconf disabled", __FUNCTION__);
|
||||
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto disable;
|
||||
}
|
||||
}
|
||||
auth_type = restconf_auth_type_get(h);
|
||||
/* If at least one socket has ssl then enable global ssl_enable */
|
||||
ssl_enable = xpath_first(xrestconf, nsc, "socket[ssl='true']") != NULL;
|
||||
/* get common fields */
|
||||
if ((x = xpath_first(xrestconf, nsc, "auth-type")) != NULL)
|
||||
auth_type = xml_body(x);
|
||||
if (auth_type && strcmp(auth_type, "client-certificate") == 0)
|
||||
auth_type_client_certificate = 1;
|
||||
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-cert-path")) != NULL)
|
||||
server_cert_path = xml_body(x);
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-key-path")) != NULL)
|
||||
server_key_path = xml_body(x);
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-ca-cert-path")) != NULL)
|
||||
server_ca_cert_path = xml_body(x);
|
||||
if ((x = xpath_first(xrestconf, nsc, "debug")) != NULL &&
|
||||
(bstr = xml_body(x)) != NULL){
|
||||
dbg = atoi(bstr);
|
||||
clicon_debug_init(dbg, NULL);
|
||||
}
|
||||
|
||||
/* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */
|
||||
if (ssl_enable){
|
||||
|
|
@ -982,11 +984,11 @@ cx_evhtp_init(clicon_handle h,
|
|||
if (cx_get_ssl_server_certs(h, server_cert_path, server_key_path, eh->eh_ssl_config) < 0)
|
||||
goto done;
|
||||
/* If client auth get client CA cert */
|
||||
if (auth_type_client_certificate)
|
||||
if (auth_type == CLIXON_AUTH_CLIENT_CERTIFICATE)
|
||||
if (cx_get_ssl_client_ca_certs(h, server_ca_cert_path, eh->eh_ssl_config) < 0)
|
||||
goto done;
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
if (auth_type_client_certificate){
|
||||
if (auth_type == CLIXON_AUTH_CLIENT_CERTIFICATE){
|
||||
eh->eh_ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
eh->eh_ssl_config->verify_depth = 2;
|
||||
|
|
@ -998,8 +1000,7 @@ cx_evhtp_init(clicon_handle h,
|
|||
goto done;
|
||||
for (i=0; i<veclen; i++){
|
||||
if (cx_evhtp_socket(h, eh, ssl_enable, vec[i], nsc,
|
||||
server_cert_path, server_key_path, server_ca_cert_path,
|
||||
auth_type_client_certificate) < 0)
|
||||
server_cert_path, server_key_path, server_ca_cert_path) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 1;
|
||||
|
|
@ -1319,15 +1320,23 @@ main(int argc,
|
|||
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||
clicon_argv_set(h, argv0, argc, argv);
|
||||
|
||||
/* Init restconf auth-type */
|
||||
restconf_auth_type_set(h, CLIXON_AUTH_NONE);
|
||||
|
||||
/* Dump configuration options on debug */
|
||||
if (dbg)
|
||||
clicon_option_dump(h, dbg);
|
||||
|
||||
/* Call start function in all plugins before we go interactive */
|
||||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
if ((eh = malloc(sizeof *eh)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(eh, 0, sizeof *eh);
|
||||
eh->eh_h = h;
|
||||
_EVHTP_HANDLE = eh; /* global */
|
||||
|
||||
/* Read config */
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ usage(clicon_handle h,
|
|||
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
||||
"\t-y <file>\t Load yang spec file (override yang main module)\n"
|
||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||
|
||||
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
||||
"\t-r \t\t Do not drop privileges if run as root\n"
|
||||
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n",
|
||||
|
|
@ -215,7 +216,10 @@ main(int argc,
|
|||
size_t cligen_buflen;
|
||||
size_t cligen_bufthreshold;
|
||||
int dbg = 0;
|
||||
int drop_priveleges = 1;
|
||||
int drop_privileges = 1;
|
||||
cxobj *xconfig = NULL;
|
||||
cxobj *xrestconf = NULL;
|
||||
int ret;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -311,7 +315,7 @@ main(int argc,
|
|||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||
break;
|
||||
case 'r':{ /* Do not drop privileges if run as root */
|
||||
drop_priveleges = 0;
|
||||
drop_privileges = 0;
|
||||
break;
|
||||
}
|
||||
case 'o':{ /* Configuration option */
|
||||
|
|
@ -333,6 +337,9 @@ main(int argc,
|
|||
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||
clicon_argv_set(h, argv0, argc, argv);
|
||||
|
||||
/* Init restconf auth-type */
|
||||
restconf_auth_type_set(h, CLIXON_AUTH_NONE);
|
||||
|
||||
/* Init cligen buffers */
|
||||
cligen_buflen = clicon_option_int(h, "CLICON_CLI_BUF_START");
|
||||
cligen_bufthreshold = clicon_option_int(h, "CLICON_CLI_BUF_THRESHOLD");
|
||||
|
|
@ -418,11 +425,18 @@ main(int argc,
|
|||
if (dbg)
|
||||
clicon_option_dump(h, dbg);
|
||||
|
||||
/* Call start function in all plugins before we go interactive
|
||||
*/
|
||||
/* Call start function in all plugins before we go interactive */
|
||||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
xconfig = clicon_conf_xml(h); /* Get local config */
|
||||
if ((xrestconf = xpath_first(xconfig, NULL, "restconf")) != NULL){
|
||||
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon disabled in config");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
|
||||
goto done;
|
||||
|
|
@ -454,7 +468,7 @@ main(int argc,
|
|||
clicon_err(OE_UNIX, errno, "chmod");
|
||||
goto done;
|
||||
}
|
||||
if (drop_priveleges){
|
||||
if (drop_privileges){
|
||||
/* Drop privileges to WWWUSER if started as root */
|
||||
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -396,9 +396,8 @@ api_root_restconf(clicon_handle h,
|
|||
char *media_str = NULL;
|
||||
restconf_media media_out = YANG_DATA_JSON;
|
||||
char *indata = NULL;
|
||||
int authenticated = 0;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
char *username = NULL;
|
||||
int ret;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (req == NULL){
|
||||
|
|
@ -426,7 +425,6 @@ api_root_restconf(clicon_handle h,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
clicon_debug(1, "%s ACCEPT: %s %s", __FUNCTION__, media_str, restconf_media_int2str(media_out));
|
||||
|
||||
if ((pvec = clicon_strsep(path, "/", &pn)) == NULL)
|
||||
|
|
@ -464,26 +462,10 @@ api_root_restconf(clicon_handle h,
|
|||
/* If present, check credentials. See "plugin_credentials" in plugin
|
||||
* See RFC 8040 section 2.5
|
||||
*/
|
||||
if ((authenticated = clixon_plugin_auth_all(h, req)) < 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s auth:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
|
||||
/* If set but no user, set a dummy user */
|
||||
if (authenticated){
|
||||
if (clicon_username_get(h) == NULL)
|
||||
clicon_username_set(h, "none");
|
||||
}
|
||||
else{
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
if ((ret = restconf_authentication_cb(h, req, pretty, media_out)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto ok;
|
||||
}
|
||||
goto ok;
|
||||
}
|
||||
clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
if (strcmp(api_resource, "yang-library-version")==0){
|
||||
if (api_yang_library_version(h, req, pretty, media_out) < 0)
|
||||
goto done;
|
||||
|
|
@ -538,14 +520,14 @@ api_root_restconf(clicon_handle h,
|
|||
retval = 0;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
if (username)
|
||||
free(username);
|
||||
if (pcvec)
|
||||
cvec_free(pcvec);
|
||||
if (pvec)
|
||||
free(pvec);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,13 +382,11 @@ api_stream(clicon_handle h,
|
|||
cvec *pcvec = NULL; /* for rest api */
|
||||
cbuf *cb = NULL;
|
||||
char *indata;
|
||||
int authenticated = 0;
|
||||
int pretty;
|
||||
restconf_media media_out = YANG_DATA_XML; /* XXX default */
|
||||
cbuf *cbret = NULL;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
int s = -1;
|
||||
int ret;
|
||||
#ifdef STREAM_FORK
|
||||
int pid;
|
||||
struct stream_child *sc;
|
||||
|
|
@ -430,26 +428,10 @@ api_stream(clicon_handle h,
|
|||
/* If present, check credentials. See "plugin_credentials" in plugin
|
||||
* See RFC 8040 section 2.5
|
||||
*/
|
||||
if ((authenticated = clixon_plugin_auth_all(h, req)) < 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s auth:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
|
||||
/* If set but no user, we set a dummy user */
|
||||
if (authenticated){
|
||||
if (clicon_username_get(h) == NULL)
|
||||
clicon_username_set(h, "none");
|
||||
}
|
||||
else{
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
if ((ret = restconf_authentication_cb(h, req, pretty, media_out)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto ok;
|
||||
}
|
||||
goto ok;
|
||||
}
|
||||
clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
if (restconf_stream(h, req, method, qvec, pretty, media_out, &s) < 0)
|
||||
goto done;
|
||||
if (s != -1){
|
||||
|
|
@ -465,8 +447,6 @@ api_stream(clicon_handle h,
|
|||
cbuf_free(cb);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
#endif /* STREAM_FORK */
|
||||
/* Listen to backend socket */
|
||||
if (clixon_event_reg_fd(s,
|
||||
|
|
@ -523,7 +503,5 @@ api_stream(clicon_handle h,
|
|||
cbuf_free(cb);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,22 +55,12 @@
|
|||
* -a basic authentication
|
||||
* -s ssl client certificates
|
||||
*/
|
||||
#define RESTCONF_EXAMPLE_OPTS "as"
|
||||
#define RESTCONF_EXAMPLE_OPTS ""
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* Use http basic auth. Set by starting restonf with:
|
||||
* clixon_restconf ... -- -a
|
||||
*/
|
||||
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.
|
||||
|
|
@ -199,16 +189,21 @@ b64_decode(const char *src,
|
|||
}
|
||||
|
||||
/*! HTTP basic authentication example (note hardwired)
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Per-message request www handle to use with restconf_api.h
|
||||
* @param[out] authp 0: Credentials failed, no user set (401 returned). 1: Credentials OK and user set
|
||||
* @param[out] userp If retval is OK and auth=1, the associated user, malloced by plugin
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Unauth
|
||||
* @retval 1 Auth
|
||||
* @retval 0 OK, see auth parameter on result.
|
||||
* @note user should be malloced
|
||||
* @note: Three hardwired users: andy, wilma, guest w password "bar".
|
||||
* Enabled by passing -- -a to the main function
|
||||
*/
|
||||
static int
|
||||
example_basic_auth(clicon_handle h,
|
||||
void *arg)
|
||||
void *req,
|
||||
int *authp,
|
||||
char **userp)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
|
|
@ -220,6 +215,11 @@ example_basic_auth(clicon_handle h,
|
|||
size_t authlen;
|
||||
int ret;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (authp == NULL || userp == NULL){
|
||||
clicon_err(OE_PLUGIN, EINVAL, "Output parameter is NULL");
|
||||
goto done;
|
||||
}
|
||||
/* At this point in the code we must use HTTP basic authentication */
|
||||
if ((auth = restconf_param_get(h, "HTTP_AUTHORIZATION")) == NULL)
|
||||
goto fail;
|
||||
|
|
@ -252,71 +252,61 @@ example_basic_auth(clicon_handle h,
|
|||
}
|
||||
if (strcmp(passwd, passwd2))
|
||||
goto fail;
|
||||
retval = 1;
|
||||
clicon_debug(1, "%s user:%s", __FUNCTION__, user);
|
||||
if (clicon_username_set(h, user) < 0)
|
||||
goto done;
|
||||
/* authenticated */
|
||||
retval = 1;
|
||||
*userp = user;
|
||||
*authp = 1;
|
||||
retval = 0;
|
||||
done: /* error */
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
if (user)
|
||||
free(user);
|
||||
clicon_debug(1, "%s retval:%d authp:%d userp:%s", __FUNCTION__, retval, *authp, *userp);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
return retval;
|
||||
fail: /* unauthenticated */
|
||||
retval = 0;
|
||||
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 */
|
||||
*authp = 0;
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Authentication callback
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] arg
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Per-message request www handle to use with restconf_api.h
|
||||
* @param[in] auth_type Authentication type: none, user-defined, or client-cert
|
||||
* @param[out] authp 0: Credentials failed, no user set (401 returned). 1: Credentials OK and user set
|
||||
* @param[out] userp The associated user, malloced by plugin. Only if retval is 1/OK and authp=1,
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Unauth
|
||||
* @retval 1 Auth
|
||||
* @retval 0 Ignore, undecided, not handled, same as no callback
|
||||
* @retval 1 OK, see auth parameter on result.
|
||||
* @note user should be malloced
|
||||
*/
|
||||
int
|
||||
example_restconf_credentials(clicon_handle h,
|
||||
void *arg)
|
||||
void *req,
|
||||
clixon_auth_type_t auth_type,
|
||||
int *authp,
|
||||
char **userp)
|
||||
{
|
||||
if (basic_auth)
|
||||
return example_basic_auth(h, arg);
|
||||
else if (ssl_client_certs)
|
||||
return example_client_certs(h, arg);
|
||||
else
|
||||
return 1;
|
||||
int retval = -1;
|
||||
|
||||
clicon_debug(1, "%s auth:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
|
||||
switch (auth_type){
|
||||
case CLIXON_AUTH_NONE:
|
||||
/* Shouldnt happen */
|
||||
retval = 0; /* Ignore, shouldnt happen */
|
||||
break;
|
||||
case CLIXON_AUTH_CLIENT_CERTIFICATE:
|
||||
retval = 0; /* Ignore, use default */
|
||||
break;
|
||||
case CLIXON_AUTH_USER:
|
||||
if (example_basic_auth(h, req, authp, userp) < 0)
|
||||
goto done;
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d auth:%d user:%s", __FUNCTION__, retval, *authp, *userp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Local example restconf rpc callback
|
||||
|
|
@ -394,12 +384,6 @@ clixon_plugin_init(clicon_handle h)
|
|||
optind = 1;
|
||||
while ((c = getopt(argc, argv, RESTCONF_EXAMPLE_OPTS)) != -1)
|
||||
switch (c) {
|
||||
case 'a': /* basic authentication */
|
||||
basic_auth = 1;
|
||||
break;
|
||||
case 's': /* ssl client certs */
|
||||
ssl_client_certs = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
* Types
|
||||
*/
|
||||
|
||||
|
||||
/*! Registered RPC callback function
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] xn Request: <rpc><xn></rpc>
|
||||
|
|
@ -92,9 +93,18 @@ typedef int (*clicon_upgrade_cb)(
|
|||
cbuf *cbret
|
||||
);
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
/* Clixon authentication type
|
||||
* @see http-auth-type in clixon-restconf.yang
|
||||
* For now only used by restconf frontend
|
||||
*/
|
||||
enum clixon_auth_type {
|
||||
CLIXON_AUTH_NONE = 0, /* Message is authenticated automatically, Do not call ca-auth callback */
|
||||
CLIXON_AUTH_CLIENT_CERTIFICATE, /* TLS Client certification authentication */
|
||||
CLIXON_AUTH_USER, /* User-defined authentication according to ca-auth callback.
|
||||
Such as "password" authentication */
|
||||
};
|
||||
typedef enum clixon_auth_type clixon_auth_type_t;
|
||||
|
||||
/* Common plugin function names, function types and signatures.
|
||||
* This plugin code is exytended by backend, cli, netconf, restconf plugins
|
||||
* Cli see cli_plugin.c
|
||||
|
|
@ -135,14 +145,41 @@ typedef int (plgextension_t)(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
|
|||
/*! Called by restconf on each incoming request to check credentials and return username
|
||||
*/
|
||||
|
||||
/* Plugin authorization. Set username option (or not)
|
||||
* @param[in] Clicon handle
|
||||
* @param[in] void*, eg Fastcgihandle request restconf
|
||||
/*! Plugin callback for authenticating messages (for restconf)
|
||||
*
|
||||
* Given a message (its headers) and authentication type, determine if the message
|
||||
* passes authentication.
|
||||
*
|
||||
* If the message is not authenticated, an error message is returned with tag: "access denied" and
|
||||
* HTTP error code 401 Unauthorized - Client is not authenticated
|
||||
*
|
||||
* If the message is authenticated, a user is associated with the message. This user can be derived
|
||||
* from the headers or mapped in an application-dependent way. This user is used internally in Clixon and
|
||||
* sent via the IPC protocol to the backend where it may be used for NACM authorization.
|
||||
*
|
||||
* The auth-type parameter specifies how the authentication is made and what default value is:
|
||||
* none: Message is authenticated. No callback is called, authenticated user is set to special user
|
||||
* "none". Typically assumes NACM is not enabled.
|
||||
* client-cert: Default: Set to authenticated and extract the username from the SSL_CN parameter
|
||||
* A callback can revise this behavior
|
||||
* user: Default: Message is not authenticated (401 returned)
|
||||
* Typically done by basic auth, eg HTTP_AUTHORIZATION header, and verify password
|
||||
*
|
||||
* If there are multiple callbacks, the first result which is not "ignore" is returned. This is to allow for
|
||||
* different callbacks registering different classes, or grouping of authentication.
|
||||
*
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Per-message request www handle to use with restconf_api.h
|
||||
* @param[in] auth_type Authentication type: none, user-defined, or client-cert
|
||||
* @param[out] authp 0: Credentials failed, no user set (401 returned). 1: Credentials OK and user set
|
||||
* @param[out] userp The associated user, malloced by plugin. Only if retval is 1/OK and authp=1,
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Credential not OK
|
||||
* @retval 1 Credential OK
|
||||
* @retval 0 Ignore, undecided, not handled, same as no callback
|
||||
* @retval 1 OK, see auth parameter on result.
|
||||
*
|
||||
* @note user should be freed by caller
|
||||
*/
|
||||
typedef int (plgauth_t)(clicon_handle, void *);
|
||||
typedef int (plgauth_t)(clicon_handle h, void *req, clixon_auth_type_t auth_type, int *authp, char **userp);
|
||||
|
||||
/*! Reset system status
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -305,8 +342,7 @@ int clixon_plugin_start_all(clicon_handle h);
|
|||
int clixon_plugin_exit_one(clixon_plugin *cp, clicon_handle h);
|
||||
int clixon_plugin_exit_all(clicon_handle h);
|
||||
|
||||
int clixon_plugin_auth_one(clixon_plugin *cp, clicon_handle h, void *arg);
|
||||
int clixon_plugin_auth_all(clicon_handle h, void *arg);
|
||||
int clixon_plugin_auth_all(clicon_handle h, void *req, clixon_auth_type_t auth_type, int *authp, char **userp);
|
||||
|
||||
int clixon_plugin_extension_one(clixon_plugin *cp, clicon_handle h, yang_stmt *yext, yang_stmt *ys);
|
||||
int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
|
||||
|
|
@ -324,4 +360,8 @@ int upgrade_callback_reg_fn(clicon_handle h, clicon_upgrade_cb cb, const char *s
|
|||
int upgrade_callback_delete_all(clicon_handle h);
|
||||
int upgrade_callback_call(clicon_handle h, cxobj *xt, char *ns, uint16_t op, uint32_t from, uint32_t to, cbuf *cbret);
|
||||
|
||||
const clixon_auth_type_t clixon_auth_type_str2int(char *auth_type);
|
||||
const char *clixon_auth_type_int2str(clixon_auth_type_t auth_type);
|
||||
|
||||
|
||||
#endif /* _CLIXON_PLUGIN_H_ */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
|
@ -55,6 +56,7 @@
|
|||
|
||||
#include "clixon_err.h"
|
||||
#include "clixon_queue.h"
|
||||
#include "clixon_string.h"
|
||||
#include "clixon_hash.h"
|
||||
#include "clixon_log.h"
|
||||
#include "clixon_file.h"
|
||||
|
|
@ -462,73 +464,91 @@ clixon_plugin_exit_all(clicon_handle h)
|
|||
}
|
||||
|
||||
/*! Run the restconf user-defined credentials callback
|
||||
* @param[in] cp Plugin handle
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] arg Argument, such as fastcgi handler for restconf
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not authenticated
|
||||
* @retval 1 Authenticated
|
||||
* @param[in] req Per-message request www handle to use with restconf_api.h
|
||||
* @param[in] auth_type Authentication type: none, user-defined, or client-cert
|
||||
* @param[out] authp 0: Credentials failed, no user set (401 returned). 1: Credentials OK and user set
|
||||
* @param[out] userp The associated user, malloced by plugin. Only if retval is 1/OK and authp=1,
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Ignore, undecided, not handled, same as no callback
|
||||
* @retval 1 OK, see auth parameter on result.
|
||||
* @note If authenticated either a callback was called and clicon_username_set()
|
||||
* Or no callback was found.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
clixon_plugin_auth_one(clixon_plugin *cp,
|
||||
clicon_handle h,
|
||||
void *arg)
|
||||
void *req,
|
||||
clixon_auth_type_t auth_type,
|
||||
int *authp,
|
||||
char **userp)
|
||||
{
|
||||
int retval = 1; /* Authenticated */
|
||||
int retval = -1;
|
||||
plgauth_t *fn; /* Plugin auth */
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if ((fn = cp->cp_api.ca_auth) != NULL){
|
||||
if ((retval = fn(h, arg)) < 0) {
|
||||
if ((retval = fn(h, req, auth_type, authp, userp)) < 0) {
|
||||
if (clicon_errno < 0)
|
||||
clicon_log(LOG_WARNING, "%s: Internal error: Auth callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||
__FUNCTION__, cp->cp_name);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
retval = 0; /* Ignored / no callback */
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d user:%s", __FUNCTION__, retval, *userp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Run the restconf user-defined credentials callback for all plugins
|
||||
* Find first authentication callback and call that, then return.
|
||||
* The callback is to set the authenticated user
|
||||
* @param[in] cp Plugin handle
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] arg Argument, such as fastcgi handler for restconf
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not authenticated
|
||||
* @retval 1 Authenticated
|
||||
* @note If authenticated either a callback was called and clicon_username_set()
|
||||
* Or no callback was found.
|
||||
* @param[in] req Per-message request www handle to use with restconf_api.h
|
||||
* @param[in] auth_type Authentication type: none, user-defined, or client-cert
|
||||
* @param[out] authp 0: Credentials failed, no user set (401 returned). 1: Credentials OK and user set
|
||||
* @param[out] userp The associated user, malloced by plugin. Only if retval is 1/OK and authp=1,
|
||||
* @retval -1 Fatal error
|
||||
* @retval 0 Ignore, undecided, not handled, same as no callback
|
||||
* @retval 1 OK, see auth parameter on result.
|
||||
*/
|
||||
int
|
||||
clixon_plugin_auth_all(clicon_handle h,
|
||||
void *arg)
|
||||
void *req,
|
||||
clixon_auth_type_t auth_type,
|
||||
int *authp,
|
||||
char **userp)
|
||||
{
|
||||
int retval = -1;
|
||||
clixon_plugin *cp = NULL;
|
||||
int i = 0;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (authp == NULL || userp == NULL){
|
||||
clicon_err(OE_PLUGIN, EINVAL, "Output parameter is NULL");
|
||||
goto done;
|
||||
}
|
||||
*authp = -1;
|
||||
*userp = NULL;
|
||||
ret = 0; /* ignore */
|
||||
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||
i++;
|
||||
if ((ret = clixon_plugin_auth_one(cp, h, arg)) < 0)
|
||||
if ((ret = clixon_plugin_auth_one(cp, h, req, auth_type, authp, userp)) < 0)
|
||||
goto done;
|
||||
if (ret == 1)
|
||||
goto authenticated;
|
||||
break;
|
||||
break; /* result, not ignored */
|
||||
/* ret == 0, ignore try next */
|
||||
}
|
||||
retval = ret;
|
||||
if (retval == 1){
|
||||
assert(*authp != -1);
|
||||
if (*authp == 1)
|
||||
assert(*userp != NULL);
|
||||
}
|
||||
if (i==0)
|
||||
retval = 1;
|
||||
else
|
||||
retval = 0;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
return retval;
|
||||
authenticated:
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Callback for a yang extension (unknown) statement single plugin
|
||||
|
|
@ -931,3 +951,29 @@ upgrade_callback_call(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Authentication type
|
||||
* @see http-auth-type in clixon-restconf.yang
|
||||
* @see restconf_media_str2int
|
||||
*/
|
||||
static const map_str2int clixon_auth_type[] = {
|
||||
{"none", CLIXON_AUTH_NONE},
|
||||
{"client-certificate", CLIXON_AUTH_CLIENT_CERTIFICATE},
|
||||
{"user", CLIXON_AUTH_USER},
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
/*! Translate from string to auth-type
|
||||
*/
|
||||
const clixon_auth_type_t
|
||||
clixon_auth_type_str2int(char *auth_type)
|
||||
{
|
||||
return clicon_str2int(clixon_auth_type, auth_type);
|
||||
}
|
||||
|
||||
/*! Translate from auth-type to string
|
||||
*/
|
||||
const char *
|
||||
clixon_auth_type_int2str(clixon_auth_type_t auth_type)
|
||||
{
|
||||
return clicon_int2str(clixon_auth_type, auth_type);
|
||||
}
|
||||
|
|
|
|||
25
test/lib.sh
25
test/lib.sh
|
|
@ -196,11 +196,16 @@ fi
|
|||
# Default restconf configuration: http IPv4
|
||||
# Can be placed in clixon-config
|
||||
# Note that https clause assumes there exists certs and keys in /etc/ssl,...
|
||||
function restconf_config()
|
||||
{
|
||||
AUTH=$1
|
||||
if [ $RCPROTO = http ]; then
|
||||
RESTCONFIG="<restconf><enable>true</enable><auth-type>password</auth-type><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
||||
RESTCONFIG="<restconf><enable>true</enable><auth-type>$AUTH</auth-type><debug>1</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
||||
else
|
||||
RESTCONFIG="<restconf><enable>true</enable><auth-type>password</auth-type><server-cert-path>/etc/ssl/certs/clixon-server-crt.pem</server-cert-path><server-key-path>/etc/ssl/private/clixon-server-key.pem</server-key-path><server-ca-cert-path>/etc/ssl/certs/clixon-ca-crt.pem</server-ca-cert-path><socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket></restconf>"
|
||||
RESTCONFIG="<restconf><enable>true</enable><auth-type>$AUTH</auth-type><server-cert-path>/etc/ssl/certs/clixon-server-crt.pem</server-cert-path><server-key-path>/etc/ssl/private/clixon-server-key.pem</server-key-path><server-ca-cert-path>/etc/ssl/certs/clixon-ca-crt.pem</server-ca-cert-path><debug>1</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket></restconf>"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Some tests may set owner of testdir to something strange and quit, need
|
||||
# to reset to me
|
||||
|
|
@ -374,7 +379,7 @@ function new(){
|
|||
# Evaluate and return
|
||||
# Example: expectpart $(fn arg) 0 "my return" -- "foo"
|
||||
# - evaluated expression
|
||||
# - expected command return value (0 if OK)
|
||||
# - expected command return value (0 if OK) or list of values, eg "55 56"
|
||||
# - expected stdout outcome*
|
||||
# - the token "--not--"
|
||||
# - not expected stdout outcome*
|
||||
|
|
@ -391,11 +396,25 @@ function expectpart(){
|
|||
# echo "ret:\"$ret\""
|
||||
# echo "retval:$retval"
|
||||
# echo "expect:\"$expect\""
|
||||
if [ "$retval" -eq "$retval" 2> /dev/null ] ; then # single retval
|
||||
if [ $r != $retval ]; then
|
||||
echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:"
|
||||
echo -e "\e[0m:"
|
||||
exit -1
|
||||
fi
|
||||
else # List of retvals
|
||||
found=0
|
||||
for rv in $retval; do
|
||||
if [ $r == $rv ]; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
if [ $found -eq 0 ]; then
|
||||
echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:"
|
||||
echo -e "\e[0m:"
|
||||
exit -1
|
||||
fi
|
||||
fi
|
||||
if [ -z "$ret" -a -z "$expect" ]; then
|
||||
return
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ if [ ! -d $pdir ]; then
|
|||
mkdir $pdir
|
||||
fi
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>/tmp/conf_yang.xml</CLICON_CONFIGFILE>
|
||||
|
|
@ -273,4 +276,7 @@ stop_backend -f $cfg
|
|||
# unset conditional parameters
|
||||
unset format
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ cfg=$dir/conf_yang.xml
|
|||
fyang=$dir/main.yang
|
||||
fyang2=$dir/ietf-interfaces@2019-03-04.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -273,4 +276,7 @@ if [ $BE -ne 0 ]; then
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ APPNAME=example
|
|||
cfg=$dir/choice.xml
|
||||
fyang=$dir/type.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -298,4 +301,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ if [ ! -d $pdir ]; then
|
|||
mkdir $pdir
|
||||
fi
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -171,4 +174,7 @@ stop_backend -f $cfg
|
|||
# unset conditional parameters
|
||||
unset format
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ cfg=$dir/conf_yang.xml
|
|||
|
||||
# Use yang in example
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -188,4 +191,7 @@ if [ $BE -ne 0 ]; then
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/example-my-crypto.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -334,4 +337,7 @@ fi
|
|||
|
||||
endtest
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -132,8 +135,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -202,4 +205,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ cfg=$dir/conf_yang.xml
|
|||
fyang=$dir/nacm-example.yang
|
||||
fyang2=$dir/itf.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -232,8 +235,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -332,4 +335,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -106,8 +109,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -165,4 +168,7 @@ if [ $BE -ne 0 ]; then # Bring your own backend
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ cfg=$dir/conf_yang.xml
|
|||
fyang=$dir/nacm-example.yang
|
||||
fyang2=$dir/nacm-example2.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -237,8 +240,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -297,4 +300,7 @@ if [ $BE -ne 0 ]; then # Bring your own backend
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -233,8 +236,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -295,4 +298,7 @@ if [ $BE -ne 0 ]; then # Bring your own backend
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ fyang=$dir/nacm-example.yang
|
|||
# Which format to use as datastore format internally
|
||||
: ${format:=xml}
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -112,8 +115,8 @@ EOF
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "wait restconf"
|
||||
wait_restconf
|
||||
|
|
@ -234,5 +237,8 @@ endtest
|
|||
|
||||
rm -rf $dir
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
# unset conditional parameters
|
||||
unset format
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ cfg=$dir/conf_yang.xml
|
|||
fyang=$dir/nacm-example.yang
|
||||
nacmfile=$dir/nacmfile
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
# Note filter out example_backend_nacm.so in CLICON_BACKEND_REGEXP below
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -151,8 +154,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable http basic auth)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -227,4 +230,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -134,8 +137,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -270,4 +273,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -153,8 +156,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -272,4 +275,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ APPNAME=example
|
|||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/nacm-example.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -155,8 +158,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -168,7 +171,6 @@ expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><ca
|
|||
new "commit it"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
||||
new "enable nacm"
|
||||
expectpart "$(curl -u andy:bar $CURLOPTS -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"
|
||||
|
||||
|
|
@ -239,4 +241,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ fyang=$dir/nacm-example.yang
|
|||
|
||||
# cred:none, exact, except
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $fyang
|
||||
module nacm-example{
|
||||
yang-version 1.1;
|
||||
|
|
@ -103,8 +106,8 @@ EOF
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -226,4 +229,7 @@ testrun $CRED $REALUSER $PSEUDO $RECOVERY false false
|
|||
|
||||
endtest
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ module scaling{
|
|||
}
|
||||
EOF
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -210,6 +213,9 @@ stop_backend -f $cfg
|
|||
|
||||
rm -rf $dir
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
# unset conditional parameters
|
||||
unset format
|
||||
unset perfnr
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ fyang=$dir/$APPNAME.yang
|
|||
fconfig=$dir/large.xml
|
||||
fstate=$dir/state.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -214,4 +217,6 @@ unset format
|
|||
unset perfnr
|
||||
unset perfreq
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ fyang=$dir/$APPNAME.yang
|
|||
fconfig=$dir/large.xml
|
||||
fstate=$dir/state.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -198,9 +201,12 @@ fi
|
|||
|
||||
rm -rf $dir
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
# unset conditional parameters
|
||||
unset format
|
||||
unset perfnr
|
||||
unset perfreq
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,57 @@ if [ -d ${TOP_SRCDIR}/yang/clixon ]; then
|
|||
else
|
||||
cp /usr/local/share/clixon/$y $dir/
|
||||
fi
|
||||
|
||||
if [ "${WITH_RESTCONF}" = "evhtp" ]; then
|
||||
# Create server certs
|
||||
certdir=$dir/certs
|
||||
srvkey=$certdir/srv_key.pem
|
||||
srvcert=$certdir/srv_cert.pem
|
||||
cakey=$certdir/ca_key.pem # needed?
|
||||
cacert=$certdir/ca_cert.pem
|
||||
test -d $certdir || mkdir $certdir
|
||||
. ./certs.sh
|
||||
else
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
fi
|
||||
|
||||
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
||||
state='{"clixon-example:state":{"op":\["41","42","43"\]}'
|
||||
|
||||
if $IPv6; then
|
||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||
RESTCONFIG1=$(cat <<EOF
|
||||
<restconf xmlns="http://clicon.org/restconf">
|
||||
<enable>true</enable>
|
||||
<auth-type>none</auth-type>
|
||||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cakey</server-ca-cert-path>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>::</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>::</address><port>443</port><ssl>true</ssl></socket>
|
||||
</restconf>
|
||||
EOF
|
||||
)
|
||||
else
|
||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||
RESTCONFIG1=$(cat <<EOF
|
||||
<restconf xmlns="http://clicon.org/restconf">
|
||||
<enable>true</enable>
|
||||
<auth-type>none</auth-type>
|
||||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cakey</server-ca-cert-path>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket>
|
||||
</restconf>
|
||||
EOF
|
||||
)
|
||||
fi
|
||||
|
||||
# Start with common config, then append fcgi/evhtp specific config
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -54,54 +105,10 @@ cat <<EOF > $cfg
|
|||
<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>
|
||||
$RESTCONFIG <!-- only fcgi -->
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
if [ "${WITH_RESTCONF}" = "evhtp" ]; then
|
||||
# Create server certs
|
||||
certdir=$dir/certs
|
||||
srvkey=$certdir/srv_key.pem
|
||||
srvcert=$certdir/srv_cert.pem
|
||||
cakey=$certdir/ca_key.pem # needed?
|
||||
cacert=$certdir/ca_cert.pem
|
||||
test -d $certdir || mkdir $certdir
|
||||
. ./certs.sh
|
||||
fi
|
||||
|
||||
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
||||
state='{"clixon-example:state":{"op":\["41","42","43"\]}'
|
||||
|
||||
if $IPv6; then
|
||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||
RESTCONFIG=$(cat <<EOF
|
||||
<restconf xmlns="http://clicon.org/restconf">
|
||||
<enable>true</enable>
|
||||
<auth-type>password</auth-type>
|
||||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cakey</server-ca-cert-path>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>::</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>::</address><port>443</port><ssl>true</ssl></socket>
|
||||
</restconf>
|
||||
EOF
|
||||
)
|
||||
else
|
||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||
RESTCONFIG=$(cat <<EOF
|
||||
<restconf xmlns="http://clicon.org/restconf">
|
||||
<enable>true</enable>
|
||||
<auth-type>password</auth-type>
|
||||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cakey</server-ca-cert-path>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket>
|
||||
<socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket>
|
||||
</restconf>
|
||||
EOF
|
||||
)
|
||||
fi
|
||||
|
||||
# Restconf test routine with arguments:
|
||||
# 1. proto:http/https
|
||||
|
|
@ -132,7 +139,7 @@ function testrun()
|
|||
wait_backend
|
||||
|
||||
new "netconf edit config"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG1</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf commit"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||
|
|
@ -403,4 +410,8 @@ done
|
|||
# unset conditional parameters
|
||||
unset RCPROTO
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
unset RESTCONFIG1
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ APPNAME=example
|
|||
cfg=$dir/conf.xml
|
||||
fyang=$dir/restconf.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -219,4 +222,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ fyang2=$dir/augment.yang
|
|||
fxml=$dir/initial.xml
|
||||
fstate=$dir/state.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -256,4 +259,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ cat <<EOF > $dir/example-system.yang
|
|||
}
|
||||
EOF
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -267,4 +270,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ APPNAME=example
|
|||
cfg=$dir/conf.xml
|
||||
fyang=$dir/list.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -182,4 +185,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ test -d $certdir || mkdir $certdir
|
|||
RESTCONFIG=$(cat <<EOF
|
||||
<restconf>
|
||||
<enable>true</enable>
|
||||
<auth-type>password</auth-type>
|
||||
<auth-type>none</auth-type>
|
||||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cakey</server-ca-cert-path>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ cfg=$dir/conf.xml
|
|||
fyang=$dir/stream.yang
|
||||
xml=$dir/xml.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -63,6 +66,7 @@ cat <<EOF > $cfg
|
|||
<CLICON_STREAM_PATH>streams</CLICON_STREAM_PATH>
|
||||
<CLICON_STREAM_URL>https://localhost</CLICON_STREAM_URL>
|
||||
<CLICON_STREAM_RETENTION>60</CLICON_STREAM_RETENTION>
|
||||
$RESTCONFIG
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
|
|
@ -285,6 +289,9 @@ fi
|
|||
|
||||
rm -rf $dir
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
# unset conditional parameters
|
||||
unset clixon_util_stream
|
||||
unset nr
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# Use nacm module in example/main/example_restconf.c hardcoded to
|
||||
# andy:bar and wilma:bar
|
||||
|
||||
|
||||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
|
|
@ -12,6 +13,9 @@ cfg=$dir/conf.xml
|
|||
startupdb=$dir/startup_db
|
||||
fjukebox=$dir/example-jukebox.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config user
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -116,8 +120,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting restconf"
|
||||
wait_restconf
|
||||
|
|
@ -173,8 +177,8 @@ if [ $RC -ne 0 ]; then
|
|||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
|
||||
new "start restconf daemon (-a is enable basic authentication)"
|
||||
start_restconf -f $cfg -- -a
|
||||
new "start restconf daemon"
|
||||
start_restconf -f $cfg
|
||||
|
||||
new "waiting"
|
||||
wait_restconf
|
||||
|
|
@ -260,4 +264,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ APPNAME=example
|
|||
cfg=$dir/conf.xml
|
||||
startupdb=$dir/startup_db
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -324,5 +327,8 @@ sleep $DEMWAIT # Lots of processes need to die before next test
|
|||
new "endtest"
|
||||
endtest
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ cacert=$certdir/ca_cert.pem
|
|||
|
||||
users="andy guest" # generate certs for some users in nacm.sh
|
||||
|
||||
xusers="limited" # Set invalid cert
|
||||
|
||||
# Whether to generate new keys or not (only if $dir is not removed)
|
||||
# Here dont generate keys if restconf started stand-alone (RC=0)
|
||||
: ${genkeys:=true}
|
||||
|
|
@ -95,7 +97,7 @@ if $genkeys; then
|
|||
. ./certs.sh
|
||||
|
||||
# create client certs
|
||||
for name in $users; do
|
||||
for name in $users $xusers; do
|
||||
cat<<EOF > $dir/$name.cnf
|
||||
[req]
|
||||
prompt = no
|
||||
|
|
@ -117,6 +119,10 @@ EOF
|
|||
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 # client key
|
||||
|
||||
# invalid
|
||||
for name in $xusers; do
|
||||
openssl x509 -req -extfile $dir/$name.cnf -days 0 -passin "pass:password" -in $certdir/$name.csr -CA $cacert -CAkey $cakey -CAcreateserial -out $certdir/$name.crt
|
||||
done # invalid
|
||||
fi # genkeys
|
||||
|
||||
# Write local config
|
||||
|
|
@ -145,6 +151,7 @@ cat <<EOF > $cfg
|
|||
<server-cert-path>$srvcert</server-cert-path>
|
||||
<server-key-path>$srvkey</server-key-path>
|
||||
<server-ca-cert-path>$cacert</server-ca-cert-path>
|
||||
<!--debug>1</debug-->
|
||||
<socket>
|
||||
<namespace>default</namespace>
|
||||
<address>0.0.0.0</address>
|
||||
|
|
@ -181,8 +188,8 @@ EOF
|
|||
if [ $RC -ne 0 ]; then
|
||||
new "kill old restconf daemon"
|
||||
stop_restconf_pre
|
||||
new "start restconf daemon -s -c -- -s"
|
||||
start_restconf -f $cfg -- -s
|
||||
new "start restconf daemon -s -c"
|
||||
start_restconf -f $cfg
|
||||
fi
|
||||
|
||||
new "wait for restconf"
|
||||
|
|
@ -203,6 +210,18 @@ EOF
|
|||
new "admin get x 42"
|
||||
expectpart "$(curl $CURLOPTS --key $certdir/andy.key --cert $certdir/andy.crt -X GET $RCPROTO://localhost/restconf/data/example:x)" 0 "HTTP/1.1 200 OK" '{"example:x":42}'
|
||||
|
||||
# Negative tests
|
||||
new "Unknown yyy no cert get x 42"
|
||||
echo "dummy" > $certdir/yyy.key
|
||||
echo "dummy" > $certdir/yyy.crt
|
||||
expectpart "$(curl $CURLOPTS --key $certdir/yyy.key --cert $certdir/yyy.crt -X GET $RCPROTO://localhost/restconf/data/example:x 2>&1)" 58 " could not load PEM client certificate"
|
||||
|
||||
new "Certificate required"
|
||||
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/example:x 2>&1)" "55 56"
|
||||
|
||||
new "limited invalid cert"
|
||||
expectpart "$(curl $CURLOPTS --key $certdir/limited.key --cert $certdir/limited.crt -X GET $RCPROTO://localhost/restconf/data/example:x 2>&1)" 56 "certificate expired"
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
new "Kill restconf daemon"
|
||||
stop_restconf
|
||||
|
|
@ -226,3 +245,5 @@ rm -rf $dir
|
|||
|
||||
# unset conditional parameters
|
||||
unset RCPROTO
|
||||
|
||||
endtest
|
||||
|
|
@ -34,6 +34,9 @@ EOF
|
|||
|
||||
# Use yang in example
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -128,4 +131,7 @@ if [ -f $dir/startup_db ]; then
|
|||
err "startup should not exist"
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ APPNAME=example
|
|||
|
||||
cfg=$dir/conf.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
# Use yang in example
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
|
|
@ -199,4 +202,7 @@ fi
|
|||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ fextra=$dir/extra.yang # Referenced from main (with same prefix)
|
|||
fextra1=$dir/extra1.yang # Referenced from sub1
|
||||
fextra2=$dir/extra2.yang # Referenced from sub2
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -238,4 +241,7 @@ fi
|
|||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ fanydata=$dir/yang/anydata.yang
|
|||
funknown=$dir/yang/unknown.yang
|
||||
fstate=$dir/state.xml
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $fanydata
|
||||
module any{
|
||||
yang-version 1.1;
|
||||
|
|
@ -277,4 +280,7 @@ testrun false true
|
|||
new "startup, treat unknown as anydata----"
|
||||
testrun true true
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ cfg=$dir/conf_yang.xml
|
|||
fyang1=$dir/example1.yang
|
||||
fyang2=$dir/example2.yang
|
||||
|
||||
# Define default restconfig config: RESTCONFIG
|
||||
restconf_config none
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -141,4 +144,7 @@ if [ $BE -ne 0 ]; then
|
|||
stop_backend -f $cfg
|
||||
fi
|
||||
|
||||
# Set by restconf_config
|
||||
unset RESTCONFIG
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ YANGSPECS = clixon-config@2020-12-30.yang
|
|||
YANGSPECS += clixon-lib@2020-12-30.yang
|
||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||
YANGSPECS += clixon-restconf@2020-10-30.yang
|
||||
YANGSPECS += clixon-restconf@2020-12-30.yang
|
||||
|
||||
APPNAME = clixon # subdir ehere these files are installed
|
||||
|
||||
|
|
|
|||
160
yang/clixon/clixon-restconf@2020-12-30.yang
Normal file
160
yang/clixon/clixon-restconf@2020-12-30.yang
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
module clixon-restconf {
|
||||
yang-version 1.1;
|
||||
namespace "http://clicon.org/restconf";
|
||||
prefix "clrc";
|
||||
|
||||
import ietf-inet-types {
|
||||
prefix inet;
|
||||
}
|
||||
|
||||
organization
|
||||
"Clixon";
|
||||
|
||||
contact
|
||||
"Olof Hagsand <olof@hagsand.se>";
|
||||
|
||||
description
|
||||
"This YANG module provides a data-model for the Clixon RESTCONF daemon.
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||
|
||||
This file is part of CLIXON
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an \"AS IS\" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the \"GPL\"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****";
|
||||
|
||||
revision 2020-12-30 {
|
||||
description
|
||||
"Added: debug field
|
||||
Added 'none' as default value for auth-type
|
||||
Changed http-auth-type enum from 'password' to 'user'";
|
||||
}
|
||||
revision 2020-10-30 {
|
||||
description
|
||||
"Initial release";
|
||||
}
|
||||
typedef http-auth-type {
|
||||
type enumeration {
|
||||
enum none {
|
||||
description
|
||||
"Incoming message are set to authenticated by default. No ca-auth callback is called,
|
||||
Authenticated user is set to special user 'none'.
|
||||
Typically assumes NACM is not enabled.";
|
||||
}
|
||||
enum client-certificate {
|
||||
description
|
||||
"TLS client certificate validation is made on each incoming message. If it passes
|
||||
the authenticated user is extracted from the SSL_CN parameter
|
||||
The ca-auth callback can be used to revise this behavior.";
|
||||
}
|
||||
enum user {
|
||||
description
|
||||
"User-defined authentication as defined by the ca-auth callback.
|
||||
One example is some form of password authentication, such as basic auth.";
|
||||
}
|
||||
}
|
||||
description
|
||||
"Enumeration of HTTP authorization types.";
|
||||
}
|
||||
grouping clixon-restconf{
|
||||
description
|
||||
"HTTP RESTCONF configuration.";
|
||||
leaf enable {
|
||||
type boolean;
|
||||
default "false";
|
||||
description
|
||||
"Enables RESTCONF functionality.
|
||||
Note that starting/stopping of a restconf daemon is different from it being
|
||||
enabled or not.
|
||||
For example, if the restconf daemon is under systemd management, the restconf
|
||||
daemon will only start if enable=true.";
|
||||
}
|
||||
leaf auth-type {
|
||||
type http-auth-type;
|
||||
description
|
||||
"The authentication type.
|
||||
Note client-certificate applies only if ssl-enable is true and socket has ssl";
|
||||
default none;
|
||||
}
|
||||
leaf server-cert-path {
|
||||
type string;
|
||||
description
|
||||
"Path to server certificate file.
|
||||
Note only applies if socket has ssl enabled";
|
||||
}
|
||||
leaf server-key-path {
|
||||
type string;
|
||||
description
|
||||
"Path to server key file
|
||||
Note only applies if socket has ssl enabled";
|
||||
}
|
||||
leaf server-ca-cert-path {
|
||||
type string;
|
||||
description
|
||||
"Path to server CA cert file
|
||||
Note only applies if socket has ssl enabled";
|
||||
}
|
||||
leaf debug {
|
||||
description
|
||||
"Set debug level of restconf daemon.
|
||||
0 is no debug, 1 is debugging, more is detailed debug.
|
||||
Debug logs will be directed to syslog with
|
||||
ident: clixon_restconf and PID
|
||||
facility: LOG_USER
|
||||
level: LOG_DEBUG";
|
||||
type uint32;
|
||||
default 0;
|
||||
}
|
||||
list socket {
|
||||
key "namespace address port";
|
||||
leaf namespace {
|
||||
type string;
|
||||
description "indicates a namespace for instance. On platforms where namespaces are not suppported, always 'default'";
|
||||
}
|
||||
leaf address {
|
||||
type inet:ip-address;
|
||||
description "IP address to bind to";
|
||||
}
|
||||
leaf port {
|
||||
type inet:port-number;
|
||||
description "IP port to bind to";
|
||||
}
|
||||
leaf ssl {
|
||||
type boolean;
|
||||
default true;
|
||||
description "Enable for HTTPS otherwise HTTP protocol";
|
||||
}
|
||||
}
|
||||
}
|
||||
container restconf {
|
||||
description
|
||||
"This presence is strictly not necessary since the enable flag
|
||||
in clixon-restconf is the flag bearing the actual semantics.
|
||||
However, removing the presence leads to default config in all
|
||||
clixon installations, even those which do not use backend-started restconf.
|
||||
One could see this as mostly cosmetically annoying.
|
||||
Alternative would be to make the inclusion of this yang conditional.";
|
||||
presence "Enables RESTCONF";
|
||||
uses clixon-restconf;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue