theforeman/smart_proxy_dhcp_dnsmasq

request agains /dhcp/... result in `Invalid IP Address`

cmeissner opened this issue · 2 comments

We use dnsmasq as DHCP server and want to configure it via foreman smart-proxy. We configured the dhcp feature with the following dhcpopts.conf file which we places in /etc/dnsmasq.d directory.

# define a different lease file
dhcp-leasefile=/var/lib/dnsmasq/dhcp.leases

# ip range served by dhcp server
dhcp-range=10.2.1.1,10.2.1.99,12h  ## 12h ist die Lease-Time

# dhcp-options
dhcp-option=3,10.2.1.1 # default gw
dhcp-option=6,10.2.1.1 # nameserver1

The dhcp_dnsmasq smart proxy configuration looks as followed.

:config: /etc/dnsmasq.conf
:target_dir: /var/lib/foreman-proxy/dhcp/
:lease_file: /var/lib/dnsmasq/dhcp.leases
:reload_cmd: systemctl reload dnsmasq

I we now try to get a list of subnets from smart proxy we this output.

[root@centos8 ~]# curl http://localhost:8000/dhcp
Invalid IP Address

And in proxy.log we see the following trace.

2020-07-15T23:33:26 2db6cf98 [I] Started GET /dhcp
2020-07-15T23:33:26 2db6cf98 [E] Invalid IP Address
2020-07-15T23:33:26 2db6cf98 [W] Error details for Invalid IP Address : <Proxy::Validations::Error>: Invalid IP Address
/usr/share/foreman-proxy/lib/proxy/validations.rb:16:in `validate_ip'
/usr/share/foreman-proxy/modules/dhcp_common/subnet.rb:17:in `initialize'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:146:in `new'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:146:in `parse_config_for_subnet'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:33:in `load!'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_main.rb:20:in `initialize'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/plugin_configuration.rb:25:in `new'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/plugin_configuration.rb:25:in `block in load_dependency_injection_wirings'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:8:in `instance'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:57:in `get_dependency'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:74:in `block in inject_attr'
/usr/share/foreman-proxy/modules/dhcp/dhcp_api.rb:13:in `block in <class:DhcpApi>'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1635:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1635:in `block in compile!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:992:in `block (3 levels) in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1011:in `route_eval'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:992:in `block (2 levels) in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1040:in `block in process_route'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1038:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1038:in `process_route'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:990:in `block in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:989:in `each'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:989:in `route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1097:in `block in dispatch!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `block in invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1094:in `dispatch!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:924:in `block in call!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `block in invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:924:in `call!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:913:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/method_override.rb:24:in `call'
/usr/share/foreman-proxy/lib/proxy/log.rb:103:in `call'
/usr/share/foreman-proxy/lib/proxy/request_id_middleware.rb:11:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/xss_header.rb:18:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/path_traversal.rb:16:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/json_csrf.rb:26:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/base.rb:50:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/base.rb:50:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/frame_options.rb:31:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/null_logger.rb:11:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/head.rb:12:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/show_exceptions.rb:22:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:194:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1958:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1502:in `block in call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1729:in `synchronize'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1502:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:74:in `block in call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in `each'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/builder.rb:244:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/handler/webrick.rb:95:in `service'
/usr/share/ruby/webrick/httpserver.rb:140:in `service'
/usr/share/ruby/webrick/httpserver.rb:96:in `run'
/usr/share/ruby/webrick/server.rb:307:in `block in start_thread'
/usr/share/gems/gems/logging-2.2.2/lib/logging/diagnostic_context.rb:474:in `block in create_with_logging_context'
2020-07-15T23:33:26 2db6cf98 [W] Invalid IP Address : <Proxy::Validations::Error>: Invalid IP Address
/usr/share/foreman-proxy/lib/proxy/validations.rb:16:in `validate_ip'
/usr/share/foreman-proxy/modules/dhcp_common/subnet.rb:17:in `initialize'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:146:in `new'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:146:in `parse_config_for_subnet'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_subnet_service.rb:33:in `load!'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/dhcp_dnsmasq_main.rb:20:in `initialize'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/plugin_configuration.rb:25:in `new'
/usr/local/share/gems/gems/smart_proxy_dhcp_dnsmasq-1.0/lib/smart_proxy_dhcp_dnsmasq/plugin_configuration.rb:25:in `block in load_dependency_injection_wirings'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:8:in `instance'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:57:in `get_dependency'
/usr/share/foreman-proxy/lib/proxy/dependency_injection.rb:74:in `block in inject_attr'
/usr/share/foreman-proxy/modules/dhcp/dhcp_api.rb:13:in `block in <class:DhcpApi>'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1635:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1635:in `block in compile!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:992:in `block (3 levels) in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1011:in `route_eval'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:992:in `block (2 levels) in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1040:in `block in process_route'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1038:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1038:in `process_route'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:990:in `block in route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:989:in `each'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:989:in `route!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1097:in `block in dispatch!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `block in invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1094:in `dispatch!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:924:in `block in call!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `block in invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `catch'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1076:in `invoke'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:924:in `call!'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:913:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/method_override.rb:24:in `call'
/usr/share/foreman-proxy/lib/proxy/log.rb:103:in `call'
/usr/share/foreman-proxy/lib/proxy/request_id_middleware.rb:11:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/xss_header.rb:18:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/path_traversal.rb:16:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/json_csrf.rb:26:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/base.rb:50:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/base.rb:50:in `call'
/usr/share/gems/gems/rack-protection-2.0.3/lib/rack/protection/frame_options.rb:31:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/null_logger.rb:11:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/head.rb:12:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/show_exceptions.rb:22:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:194:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1958:in `call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1502:in `block in call'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1729:in `synchronize'
/usr/share/gems/gems/sinatra-2.0.3/lib/sinatra/base.rb:1502:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:74:in `block in call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in `each'
/usr/share/gems/gems/rack-2.2.2/lib/rack/urlmap.rb:58:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/builder.rb:244:in `call'
/usr/share/gems/gems/rack-2.2.2/lib/rack/handler/webrick.rb:95:in `service'
/usr/share/ruby/webrick/httpserver.rb:140:in `service'
/usr/share/ruby/webrick/httpserver.rb:96:in `run'
/usr/share/ruby/webrick/server.rb:307:in `block in start_thread'
/usr/share/gems/gems/logging-2.2.2/lib/logging/diagnostic_context.rb:474:in `block in create_with_logging_context'
2020-07-15T23:33:26 2db6cf98 [I] Finished GET /dhcp with 400 (2.08 ms)

Configuration of dnsmasq seems to be ok.

[root@centos8 ~]# dnsmasq -dd -C /etc/dnsmasq.conf
dnsmasq: started, version 2.79 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt DBus no-i18n IDN2 DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth DNSSEC loop-detect inotify
dnsmasq-dhcp: DHCP, IP range 10.2.1.1 -- 10.2.1.99, lease time 12h
dnsmasq: using nameserver 8.8.4.4#53
dnsmasq: using nameserver 8.8.8.8#53
dnsmasq: cleared cache

Hi, I would like to try and fix this and some other issues when parsing the dhcp-range lines in dnsmasq.conf (e.g. multiple subnets, static subnets, etc.).
I already have a small patch for static subnets, but I would like to also add support for multiple subnets (I see it's marked 'TODO' in the code).
@ananace could you point me to the proper foreman-proxy API documentation?

P.S. sorry, I see that you already started to work on these issues in a separate branch.

I don't know if there's any proper API documentation available for the development case, the only documentation I'm aware of is focused more on the use of the smart-proxy. (https://projects.theforeman.org/projects/smart-proxy/wiki)

I unfortunately never really got my own work in the regard finished either, as I could only find very minimal synthetic configuration to base off of, which meant a whole lot of assumptions having to be made.
You're definitely more than welcome to take my code and continue with that if you want to base your development on something, especially if you have some actual configuration which you can use as development/testing data.