confd: Add YANG pattern constraints for string leaves

Add input validation patterns to string-type leaves in container,
firewall, DHCP, and interface YANG models.  Also use mkdtemp() for
temporary key files in keystore.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
This commit is contained in:
Mattias Walström
2026-02-27 08:35:17 +01:00
committed by Joachim Wiberg
parent d7812c2ea5
commit ed4fe58fda
8 changed files with 68 additions and 26 deletions
+1 -1
View File
@@ -2,6 +2,7 @@
.claude
.gdb_history
.claude
AGENTS.md
/.backup
/.ccache
/dl
@@ -11,4 +12,3 @@
/test/.log
/local.mk
/test/spec/Readme.adoc
+16 -9
View File
@@ -12,8 +12,6 @@
#define XPATH_KEYSTORE_ASYM "/ietf-keystore:keystore/asymmetric-keys"
#define XPATH_KEYSTORE_SYM "/ietf-keystore:keystore/symmetric-keys"
#define SSH_PRIVATE_KEY "/tmp/ssh.key"
#define SSH_PUBLIC_KEY "/tmp/ssh.pub"
/* return file size */
static size_t filesz(const char *fn)
@@ -91,6 +89,9 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s
}
for (size_t i = 0; i < count; i++) {
char tmpdir[] = "/tmp/keystore.XXXXXX";
char priv_path[sizeof(tmpdir) + 16];
char pub_path[sizeof(tmpdir) + 16];
char *name = srx_get_str(session, "%s/name", list[i].xpath);
char *public_key_format, *private_key_format;
char *pub_key = NULL, *priv_key = NULL;
@@ -115,16 +116,24 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s
continue;
NOTE("SSH key (%s) does not exist, generating...", name);
if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) {
if (!mkdtemp(tmpdir)) {
ERRNO("Failed creating temp dir for SSH key generation");
goto next;
}
snprintf(priv_path, sizeof(priv_path), "%s/ssh.key", tmpdir);
snprintf(pub_path, sizeof(pub_path), "%s/ssh.pub", tmpdir);
if (systemf("/usr/libexec/infix/mkkeys %s %s", priv_path, pub_path)) {
ERROR("Failed generating SSH keys for %s", name);
goto next;
}
priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY));
priv_key = filerd(priv_path, filesz(priv_path));
if (!priv_key)
goto next;
pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY));
pub_key = filerd(pub_path, filesz(pub_path));
if (!pub_key)
goto next;
@@ -140,10 +149,8 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s
goto next;
}
next:
if (erase(SSH_PRIVATE_KEY))
ERRNO("Failed removing SSH server private key");
if (erase(SSH_PUBLIC_KEY))
ERRNO("Failed removing SSH server public key");
if (rmrf(tmpdir))
ERRNO("Failed removing temp dir %s", tmpdir);
if (priv_key)
free(priv_key);
+31 -9
View File
@@ -22,6 +22,11 @@ module infix-containers {
prefix infix-sys;
}
revision 2026-02-23 {
description "Input validation improvements";
reference "internal";
}
revision 2025-12-09 {
description "Add resource management:
- Add resource-limit container with memory and cpu configuration.
@@ -84,6 +89,17 @@ module infix-containers {
}
}
typedef image-reference {
description "OCI image reference or transport URI.
Allows registry references (e.g., quay.io/user/image:tag),
transport prefixes (docker://, oci-archive:, dir:), and
download URLs (ftp://, http://, https://).";
type string {
pattern '[a-zA-Z0-9][a-zA-Z0-9_./:@=+%~-]*';
}
}
typedef mount-type {
type enumeration {
enum bind {
@@ -181,7 +197,7 @@ module infix-containers {
container will be put on a queue that retries pull every time
there is a route change in the host's system.";
mandatory true;
type string;
type image-reference;
}
container checksum {
@@ -240,7 +256,9 @@ module infix-containers {
leaf command {
description "Override ENTRYPOINT from image and run command + args.";
type string;
type string {
pattern '[a-zA-Z0-9_./ :=@%^,+-]+';
}
}
leaf hostname {
@@ -298,7 +316,9 @@ module infix-containers {
NOTE: Some (*) options only work with masquerading container bridges,
which automatically create VETH pairs with one end in the host
bridge and the other in the container.";
type string;
type string {
pattern '[a-zA-Z_][a-zA-Z0-9_]*=[a-zA-Z0-9.:_/-]+';
}
}
}
@@ -310,7 +330,9 @@ module infix-containers {
Sample: 8080:80 -- forward tcp port 8080 to container port 80
69:69/udp -- forward udp port 69 to container port 69
127.0.0.1:8080:80 -- forward only from loopback interface";
type string;
type string {
pattern '[0-9.:\[\]]+(/[a-zA-Z]+)?';
}
}
leaf-list dns {
@@ -464,7 +486,7 @@ module infix-containers {
When mounting files, directories (and globs) from the host,
the source must be an absolute path.";
type string {
pattern '/.*';
pattern '/[a-zA-Z0-9_./*?-]+([ ]?[a-zA-Z0-9_./*?-]+)*';
}
}
}
@@ -493,7 +515,7 @@ module infix-containers {
or import the text file using the 'content' node.";
mandatory true;
type string {
pattern '/.*';
pattern '/[a-zA-Z0-9_./-]+(/[a-zA-Z0-9_./-]+)*';
}
}
@@ -545,7 +567,7 @@ module infix-containers {
description "Absolute path to target destination directory inside the container.";
mandatory true;
type string {
pattern '/.*';
pattern '/[a-zA-Z0-9_./-]+(/[a-zA-Z0-9_./-]+)*';
}
}
}
@@ -593,12 +615,12 @@ module infix-containers {
input {
leaf uri {
description "The URL or local file path, e.g., /lib/oci/archive.tar.gz";
type string;
type image-reference;
mandatory true;
}
leaf name {
description "Image name[:tag], default: basename of archive dir + :latest";
type string;
type image-reference;
}
}
}
+9 -3
View File
@@ -113,7 +113,9 @@ module infix-dhcp-server {
case default-opt {
leaf string {
description "Generic string value.";
type string;
type string {
pattern '[^\p{Cc}]*';
}
}
}
}
@@ -150,7 +152,9 @@ module infix-dhcp-server {
leaf description {
description "Additional information about this subnet (e.g., purpose, location, or notes).";
type string;
type string {
pattern '[^\p{Cc}]*';
}
}
leaf enabled {
@@ -206,7 +210,9 @@ module infix-dhcp-server {
leaf description {
description "Additional information about this entry, e.g., owner's name, equipment details, or location.";
type string;
type string {
pattern '[^\p{Cc}]*';
}
}
container match {
+9 -3
View File
@@ -201,7 +201,9 @@ module infix-firewall {
leaf description {
description "Free-form description of the zone.";
type string;
type string {
pattern '[^\p{Cc}<>&]*';
}
}
leaf-list interface {
@@ -304,7 +306,9 @@ module infix-firewall {
leaf description {
description "Free-form description of this policy's purpose and scope.";
type string;
type string {
pattern '[^\p{Cc}<>&]*';
}
}
leaf-list ingress {
@@ -421,7 +425,9 @@ module infix-firewall {
leaf description {
description "Free-form description of the service.";
type string;
type string {
pattern '[^\p{Cc}<>&]*';
}
}
list port {
@@ -204,6 +204,7 @@ module infix-interfaces {
deviate replace {
type string {
length "0..64";
pattern '[^\p{Cc}]*';
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- sh -*-
MODULES=(
"infix-interfaces -e containers"
"infix-containers@2025-12-09.yang"
"infix-containers@2026-02-23.yang"
)