Nick and Cody celebrate Thanksgiving with a holiday special reviewing some policy related questions Nick recently received.
Get the list of all network interfaces present
default:sys.interfaces only contains configured interfaces, not configured interfaces.
default:sys.interfaces_data at least for Linux systems, this variable contains much more information.
bundle agent __main__
{
vars:
"sys_interfaces_data_keys"
slist => getindices( "sys.interfaces_data" );
reports:
"$(sys_interfaces_data_keys)";
}
cf-agent --no-lock --log-level info --file /tmp/getindices-sys.interfaces_data.cf
R: lo
R: enx0892048803e7
R: enx5cff35c6864b
R: wlp0s20f3
R: virbr0
R: docker0
R: br-a7d465b9949b
R: vboxnet0
R: tun0
cf-promises can be very useful for reviewing the first order variables that are defined using the --show-vars
option.
cf-promises --show-vars=sys\.interfaces
Variable name Variable value Meta tags Comment
default:sys.interfaces {"enx0892048803e7","wlp0s20f3","virbr0","docker0","br-a7d465b9949b","vboxnet0","tun0"} inventory,source=agent,attribute_name=Interfaces
default:sys.interfaces_data {"br-a7d465b9949b":{"device":"br-a7d465b9949b","receive_bytes":"0","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"0","transmit_bytes":"0","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"0"},"docker0":{"device":"docker0","receive_bytes":"0","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"0","transmit_bytes":"0","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"0"},"enx0892048803e7":{"device":"enx0892048803e7","receive_bytes":"6362565862","receive_compressed":"0","receive_drop":"10728","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"8119215","transmit_bytes":"2704360457","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"5210158"},"enx5cff35c6864b":{"device":"enx5cff35c6864b","receive_bytes":"0","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"0","transmit_bytes":"0","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"0"},"lo":{"device":"lo","receive_bytes":"30236494","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"331169","transmit_bytes":"30236494","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"331169"},"tun0":{"device":"tun0","receive_bytes":"1224387","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"6628","transmit_bytes":"1478565","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"8042"},"vboxnet0":{"device":"vboxnet0","receive_bytes":"0","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"0","transmit_bytes":"2473935","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"3790"},"virbr0":{"device":"virbr0","receive_bytes":"0","receive_compressed":"0","receive_drop":"0","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"0","transmit_bytes":"0","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"0"},"wlp0s20f3":{"device":"wlp0s20f3","receive_bytes":"29822471","receive_compressed":"0","receive_drop":"9015","receive_errors":"0","receive_fifo":"0","receive_frame":"0","receive_multicast":"0","receive_packets":"150090","transmit_bytes":"3287961","transmit_compressed":"0","transmit_drop":"0","transmit_errors":"0","transmit_fifo":"0","transmit_frame":"0","transmit_multicast":"0","transmit_packets":"9598"}} networking,/proc,source=agent,procfs
cf-agent can show the state of variables defined at the end of execution using the --show-evaluated-vars
option.
Matching an IP address with a regular expression
Why was the regular expression 172\.16\.1\.*
not matching 172.16.1.10
?
bundle agent __main__
{
vars:
"ipregex" string => "172\.16\.1\.*";
classes:
"found" expression => regcmp("$(ipregex)","172.16.1.10");
reports:
found::
"Found the ip";
!found::
"Did not find the ip";
}
cf-agent --no-lock --log-level info --file /tmp/regex-ip.cf
R: Did not find the ip
Because there was a bug in the regex, a missing .
after the escaped one:
bundle agent __main__
{
vars:
"ipregex" string => "172\.16\.1\..*";
classes:
"found" expression => regcmp("$(ipregex)","172.16.1.10");
reports:
found::
"Found the ip";
!found::
"Did not find the ip";
}
cf-agent --no-lock --log-level info --file /tmp/regex-ip-fixed.cf
R: Found the ip
Use the builtin functions for iprange() and isipinsubnet() for improved readability.
Checking IP validity
Regular expressions can still be useful for validating input from external data sources to avoid application mis-configuration.
For example, every() can be used to validate a whole list of ip addresses. Remember, regular expressions can be multi-line which can improve readability.
bundle agent __main__
{
vars:
"ip_list1" slist => { "192.168.56.2", "1.1.1.1" };
"ip_list2" slist => { "2.1.1.356", "192.168.1.1" };
"ipv4_regex"
# https://watson-wilson.ca/blog/2015/08/20/build-better-regular-expressions-in-cfengine/
string => "(?xms)
# First octet
(?:
25[0-5] # Remember ips go as high as 255.
| # or
2[0-4][0-9] # Between 200 and 249.
| # or
[0-1]?[0-9]{1,2} # Less than 200.
)
[.] # Decimal point
# Second octet
(?:
25[0-5] # Remember ips go as high as 255.
| # or
2[0-4][0-9] # Between 200 and 249.
| # or
[0-1]?[0-9]{1,2} # Less than 200.
)
[.] # Decimal point
# Third octet
(?:
25[0-5] # Remember ips go as high as 255.
| # or
2[0-4][0-9] # Between 200 and 249.
| # or
[0-1]?[0-9]{1,2} # Less than 200.
)
[.] # Decimal point
# Forth octet
(?:
25[0-5] # Remember ips go as high as 255.
| # or
2[0-4][0-9] # Between 200 and 249.
| # or
[0-1]?[0-9]{1,2} # Less than 200.
)
";
classes:
"ip_list1_all_valid_ipv4" expression => every( "$(ipv4_regex)", @(ip_list1) );
"ip_list2_all_valid_ipv4" expression => every( "$(ipv4_regex)", @(ip_list2) );
reports:
ip_list1_all_valid_ipv4::
"All elements of ip_list1 are valid IPv4 addresses";
ip_list2_all_valid_ipv4::
"All elements of ip_list2 are valid IPv4 addresses";
!ip_list1_all_valid_ipv4::
"Not all elements of ip_list1 are valid IPv4 addresses";
!ip_list2_all_valid_ipv4::
"Not all elements of ip_list2 are valid IPv4 addresses";
}
cf-agent --no-lock --log-level info --file /tmp/ipv4-validity.cf
R: All elements of ip_list1 are valid IPv4 addresses
R: Not all elements of ip_list2 are valid IPv4 addresses
Validating IPv4 addresses with isipinsubnet()
You can use isipinsubnet()
to check that an IP address is valid (Nick was trying to use iprange()
incorrectly for this during the recording):
bundle agent __main__
{
vars:
"ip" string => "172.16.1.10";
"range" string => "0.0.0.0/0";
classes:
"valid_ipv4" expression => isipinsubnet( "$(range)", "$(ip)" );
reports:
valid_ipv4::
"The IP $(ip) is part of the range $(range)";
!valid_ipv4::
"The IP $(ip) is NOT part of the range $(range)";
}
cf-agent --no-lock --log-level info --file /tmp/validate-ip-isipinsubnet.cf
: R: The IP 172.16.1.10 is part of the range 0.0.0.0/0
Limiting messages to the system log
system_log_level in body common control control controls the minimum log level for messages to be sent to the system log.
Newly exposed (master/3.25.0) to be configurable via Augments.
{
"variables": {
"default:def.control_common_system_log_level": {
"value": "info",
"comment": "We want syslog to recieve messages tha are level info and above."
}
}
}
Is it possible to increase log verbosity for bundles called via usebundle?
Yes, it’s possible to increase the verbosity of specific promises, but not for all promises in a specific bundle. log_level in action body allows you to increase the verbosity of a specific promise, but it does not apply to all promises of a bundle at once (nor would it be inherited by subsequent methods promises).
Is it possible to change the order of promises
Normal ordering (vars
before classes
, files
before packages
) can not be changed but promise execution can be influenced using classes and/or more weakly with the depends_on
attribute.
bundle agent __main__
{
reports:
"one" handle => "one", depends_on => { "two"};
"two" handle => "two";
}
cf-agent --no-lock --log-level info --file /tmp/depends_on.cf
R: two
R: one
Maybe someday, an option to resolve using written order vs normal order.
Video
The video recording is available on YouTube:
At the end of every webinar, we stop the recording for a nice and relaxed, off-the-record chat with attendees. Join the next webinar to not miss this discussion.
Links
- Connect on LinkedIn w/ Cody, Craig, Herman, or Nick
- All Episodes