Use cidr_match for dependencies in director

Since Icinga has put a stronger focus on dependencies with the release of ‘Dependency Views’, I decided to revisit the topic. I actually wanted to implement a relatively simple example with a router. If the internal interface of the router is not accessible, the dependency should take effect for the entire network.

Router: 192.168.0.1
Network: 192.168.0.0/24

Since I don’t want to specify every single IP address, I need a solution that covers IP ranges or entire networks. In the Icinga 2 Library Reference I found the function cidr_match.

object Dependency "example-dependency" {
 parent_host_name = "192.168.0.1.router"
 dependent_host_name = host.name

  assign where cidr_match("192.168.0.0/24", host.address)
}

However, I have not found a way to define it in the director

Give as much information as you can, e.g.

  • Director version (System - About): 1.11.4
  • Icinga Web 2 version and modules (System - About): 2.12.4
  • Icinga 2 version (icinga2 --version): r2.15.0-1
  • Operating System and version: RHEL 8
  • Webserver, PHP versions: 8.3.19

The use of the DSL is very limited in the director - only command arguments AFIK.

If you’re subnets align with the 8bit boundaries, you could use the equal operator and a wildcard match.
image

There is no matching of “is an ip in 192.168.0.0/24?”
Only option would be something like wildcard operators. Or something like vars.subnet = nuremberg_production

Correction, you could also use the < and > operators to limit to more exotic subnets but be weary of how these operators work with at string.

Thank you for your reply.

Using a placeholder is a simple solution for my example, but unfortunately it’s much more complicated in reality. Using a string comparison with > < sounds like an interesting solution – but could also go terribly wrong.

Thought so.
Well, you could use a regex:

As an example, i built an assign rule matching for hosts with an address in the 192.168.56.0/22 subnet. This would also match for invalid adresses like 192.168.56.999, but i guess you shouldnt configure any addresses like this anyways.

assign where regex("^192\.168\.(5[6-9])\.\d{1,3}$", host.address)

Here is a .conf file to try it out by yourselfes.

object Host "regex1" {
  address = "192.168.56.111"
  check_command = "dummy"
}
object Host "regex2" {
  address = "192.168.60.111"
  check_command = "dummy"
}

object HostGroup "regex-matches" {
  assign where regex("^192\\.168\\.(5[6-9])\\.\\d{1,3}$", host.address)
}

Building on @bberg’s wonderful regex examples, I would suggest the following.

apply Dependency "example-dependeny" to Host {
  parent_host_name = "192.168.0.1.router"

  assign where regex("^192\\.168\\.0\\.(\\d{1,2}|1\\d{2}|2([0-4]\\d|5[0-5]))$", host.address)
}

The regex I built might be a bit overkill and a simple ^192\\.168\\.0\\..*$ should do the trick as well. By the way, you can try out the regular expressions in the icinga2 console.

$ icinga2 console
Icinga 2 (version: r2.15.0-1)
Type $help to view available commands.
<1> => regex("^192\\.168\\.0\\.(\\d{1,2}|1\\d{2}|2([0-4]\\d|5[0-5]))$", "192.168.0.23")
true
<2> => regex("^192\\.168\\.0\\.(\\d{1,2}|1\\d{2}|2([0-4]\\d|5[0-5]))$", "192.168.0.200")
true

However, there is no need to use a regex if you can ust use the cidr_match function.

$ icinga2 console
Icinga 2 (version: r2.15.0-1)
Type $help to view available commands.
<1> => cidr_match("192.168.0.0/24", "192.168.0.200")
true

Resulting in the following dependency:

apply Dependency "example-dependeny" to Host {
  parent_host_name = "192.168.0.1.router"

  assign where cidr_match("192.168.0.0/24", host.address)
}

Edit: Sorry, I have skipped the relevant part of the question: it should work in the director. It’s still early in the morning, or so. Thus, @moreamazingnick’s answer should be perfect.

actually you could do something stupid…
here is an example with a host group apply rule:

cidr_match(“192.168.0.0/24”, host.address)

which is url encoded:

cidr_match%28%22192.168.0.0%2F24%22%2C%20host.address%29

but after you safe it it will look like that:

you can not save it again without url encoding

but it passes every check and deploys.

image

tested with icingaweb2 2.12.5 / director 1.11.5

but the best way would be a feature request on github for like plain query, with the notice that this can break your config.

and another workaround would be assigning hostgroups via plain icinga config files for the subnets and assigning dependecies based on the group.

or you use a custom var and assign the subnet to the host as textfield as well than you can do a equals match on for example host.vars.subnet

Best Regards
Nicolas

Thank you very much, Nicolas.
I have created a host group, and your trick also allows me to store the cidr_match filter in the director. I will now start building/testing the dependencies.

As this represents a DSL injection vulnerability, I wouldn’t build a production configuration with it.

@apenning maybe adding a filter to inhibit if any DSL command is found while saving and a corresponding director/​dsl_in/​apply to control the behavior via role, would allow this to become an official and documented feature?

Also, why would the regex be better then the task specific and better readable cidr_match?

I would prefer cidr_match (or even better imho: matching customvars, because thats a bit more efficient during config rendering). Honestly, during writing my answer i simply didn’t know about cidr_match… should have known better.


and there is a catch:
if I want to store a host Icinga director stores correctly but throws an error on re-evaluation.
this can be caused by the fact that hostgroups are evaluated during save because of permission options.

and this might be the issue with custom apply rules since every possible icingadsl variation needs to be evaluated in php to work with the groupapply rules and the permissions/restriction feature

I agree with @rivad that dsl injection is not a good idea and also added more stable alternatives:

To be honest, I can’t reproduce this problem. I only get the error when changing the host group, as you described earlier. Or does your screenshot already show the behaviour when a dependency is set up? Setting up dependencies once and then not being able to adjust them (easily) would be okay for me – but not being able to adjust hosts is a no-go.

I would also like to see the Director become more flexible so that you don’t feel limited by it.

I think it is only a problem with the hostgroup but icinga can patch this anytime, so the other 2 approaches would be more stable for future updates:

also keep in mind that not every icinga2 concept can and should be used in icinga director.