Project

General

Profile

Actions

Bug #27246

closed

IPAddr::InvalidAddressError on valid link-local address on Windows

Added by Martyn Smith almost 5 years ago. Updated over 4 years ago.

Status:
Closed
Priority:
Normal
Category:
Facts
Target version:
-
Fixed in Releases:
Found in Releases:

Description

Hi

There appears to be an issue with parsing valid link-local ipv6 addresses on Azure.

This address (assigned on Windows)

Ethernet adapter Ethernet:

Connection-specific DNS Suffix  . : reddog.microsoft.com
Description . . . . . . . . . . . : Microsoft Hyper-V Network Adapter
Physical Address. . . . . . . . . : 00-22-48-07-F2-71
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Link-local IPv6 Address . . . . . : fe80::302f:51e0:1313:f50d%5(Preferred)
IPv4 Address. . . . . . . . . . . : XXX.XXX.XXX.XXX Preferred)
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Lease Obtained. . . . . . . . . . : Friday, June 28, 2019 10:06:52 AM

is read by factor correctly as:

"ipaddress6": "fe80::302f:51e0:1313:f50d%5",

and then causes an exception

2019-07-08T03:44:22 [I|app|9449499f] Import facts for 'server.domain.tribal-int.com' completed. Added: 0, Updated: 0, Deleted 0 facts
2019-07-08T03:44:22 [W|app|9449499f] Action failed
IPAddr::InvalidAddressError: invalid address
/opt/rh/rh-ruby25/root/usr/share/ruby/ipaddr.rb:649:in `in6_addr'
/opt/rh/rh-ruby25/root/usr/share/ruby/ipaddr.rb:586:in `initialize'
/usr/share/foreman/app/models/subnet.rb:299:in `new'
/usr/share/foreman/app/models/subnet.rb:299:in `subnet_for'
/usr/share/foreman/app/models/host/base.rb:488:in `set_interface'
/usr/share/foreman/app/models/host/base.rb:222:in `block in set_interfaces'
/usr/share/foreman/app/models/host/base.rb:219:in `each'
/usr/share/foreman/app/models/host/base.rb:219:in `set_interfaces'
/usr/share/foreman/app/models/host/base.rb:189:in `populate_fields_from_facts'
/usr/share/foreman/app/models/host/managed.rb:412:in `populate_fields_from_facts'
/usr/share/foreman/app/models/concerns/puppet_host_extensions.rb:3:in `populate_fields_from_facts'
/usr/share/foreman/app/models/host/base.rb:169:in `block in parse_facts'
/usr/share/foreman/app/services/foreman/telemetry_helper.rb:27:in `telemetry_duration_histogram'
/usr/share/foreman/app/models/host/base.rb:168:in `parse_facts'
/usr/share/foreman/app/models/host/base.rb:154:in `import_facts'
/opt/theforeman/tfm/root/usr/share/gems/gems/foreman_default_hostgroup-5.0.0/lib/default_hostgroup_base_host_patch.rb:13:in `import_facts'
/usr/share/foreman/app/models/host/managed.rb:326:in `import_facts'
/opt/theforeman/tfm/root/usr/share/gems/gems/foreman_default_hostgroup-5.0.0/lib/default_hostgroup_base_host_patch.rb:6:in `import_facts'
/usr/share/foreman/app/controllers/api/v2/hosts_controller.rb:306:in `facts'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:194:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/rendering.rb:30:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:109:in `block in run_callbacks'
/usr/share/foreman/app/controllers/api/v2/base_controller.rb:163:in `disable_json_root'
/usr/share/foreman/app/controllers/concerns/foreman/controller/timezone.rb:10:in `set_timezone'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/usr/share/foreman/app/models/concerns/foreman/thread_session.rb:32:in `clear_thread'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/usr/share/foreman/app/controllers/concerns/foreman/controller/topbar_sweeper.rb:12:in `set_topbar_sweeper_controller'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm/root/usr/share/gems/gems/audited-4.7.1/lib/audited/sweeper.rb:14:in `around'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm/root/usr/share/gems/gems/audited-4.7.1/lib/audited/sweeper.rb:14:in `around'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:136:in `run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:41:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/rescue.rb:22:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `block in instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:134:in `process'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionview-5.2.1/lib/action_view/rendering.rb:32:in `process'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal.rb:191:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal.rb:252:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:34:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:18:in `block in <class:Constraints>'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:48:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:52:in `block in serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `each'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:840:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/static_dispatcher.rb:65:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/extractor/recorder.rb:137:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/usr/share/foreman/lib/foreman/middleware/telemetry.rb:10:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/middleware/checksum_in_headers.rb:27:in `call'
/usr/share/foreman/lib/foreman/middleware/catch_json_parse_errors.rb:9:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/tempfile_reaper.rb:15:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/etag.rb:25:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/conditional_get.rb:38:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/head.rb:12:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/http/content_security_policy.rb:18:in `call'
/usr/share/foreman/lib/foreman/middleware/logging_context_session.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:232:in `context'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:226:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:98:in `run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/rack/logger.rb:38:in `call_app'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/rack/logger.rb:28:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/sprockets-rails-3.2.1/lib/sprockets/rails/quiet_assets.rb:13:in `call'
/usr/share/foreman/lib/foreman/middleware/logging_context_request.rb:11:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/method_override.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/runtime.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/executor.rb:14:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/sendfile.rb:111:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/secure_headers-6.0.0/lib/secure_headers/middleware.rb:13:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/engine.rb:524:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/railtie.rb:190:in `public_send'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/railtie.rb:190:in `method_missing'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:68:in `block in call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `each'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `call'
/usr/share/passenger/phusion_passenger/rack/thread_handler_extension.rb:74:in `process_request'
/usr/share/passenger/phusion_passenger/request_handler/thread_handler.rb:141:in `accept_and_process_next_request'
/usr/share/passenger/phusion_passenger/request_handler/thread_handler.rb:109:in `main_loop'
/usr/share/passenger/phusion_passenger/request_handler.rb:455:in `block (3 levels) in start_threads'
/opt/theforeman/tfm/root/usr/share/gems/gems/logging-2.2.2/lib/logging/diagnostic_context.rb:474:in `block in create_with_logging_context'

This appears to be caused by the regex relating to ipv6 addresses not taking into account that a valid format can contain % followed by a number as per the thread below:

https://superuser.com/questions/99746/why-is-there-a-percent-sign-in-the-ipv6-address


Related issues 1 (0 open1 closed)

Related to Foreman - Bug #26060: Fact parse error - IPAddr::InvalidAddressError: invalid addressClosedActions
Actions #1

Updated by Martyn Smith almost 5 years ago

  • Related to Bug #26060: Fact parse error - IPAddr::InvalidAddressError: invalid address added
Actions #2

Updated by Martyn Smith almost 5 years ago

  • Category set to Facts
Actions #3

Updated by Martyn Smith almost 5 years ago

Looks like it relates to the RE_IPV6ADDRLIKE_FULL and RE_IPV6ADDRLIKE_COMPRESSED regexes from upstream Ruby code in ipaddr.rb

Neither of these recognise the link-local address.

Actions #4

Updated by Martyn Smith almost 5 years ago

Ok - I've a hacky workaround that works but it's a change to the upstream ipaddr.rb

Documenting it here for those interested as this breaks default_hostgroup and subnets having the VMs that are provisioned being recognised as being on the subnet when the facts are uploaded into foreman.

Update the ruby/ipaddr.rb with the 2 extra lines in the regex as highlighted below.

RE_IPV6ADDRLIKE_COMPRESSED = %r{
\A
( (?: (?: [\da-f]{1,4} : )* [\da-f]{1,4} )? )
::
( (?:
( (?: [\da-f]{1,4} : )* )
(?:
[\da-f]{1,4} |
(\d+) \. (\d+) \. (\d+) \. (\d+)
+ |
+ [\da-f]{1,4} %[\d]+
)
)? )
\z

Regards
Martyn

Actions #5

Updated by Ewoud Kohl van Wijngaarden almost 5 years ago

That's not really correct because in Linux the device identifiers (which are after the % sign) are the literal device identifier, e.g. eth0, enp0s31f6 or wlp58s0.

Perhaps we should catch it and do some fallback logic. Something like this is untested, but fairly defensive in its parsing.

def parse_ip(address)
  begin
    IPAddr.new(address)
  rescue IPAddr::InvalidAddressError
    # Discard the device identifier for IPv6 link local
    raise unless address.is_a?(String) && address.include?('%')
    result = IPAddr.new(address.split('%').first)
    raise unless result.ipv6? && result.link_local?
    result
  end
end
Actions #6

Updated by Ewoud Kohl van Wijngaarden almost 5 years ago

https://bugs.ruby-lang.org/issues/8464 looks like an upstream bug about this.

Actions #7

Updated by The Foreman Bot almost 5 years ago

  • Status changed from New to Ready For Testing
  • Assignee set to Ewoud Kohl van Wijngaarden
  • Pull request https://github.com/theforeman/foreman/pull/6884 added
Actions #8

Updated by Martyn Smith almost 5 years ago

Thanks Ewoud

I'd definitely suggest we catch it as an exception on fact upload appears to stop other processes, which run after the fact upload,to run. Subnets assignment and default_hostgroup updates are processes I'm aware of but there are possibly others as well.

I'm happy that changing the ipaddr regex is the wrong approach and accept your suggestion.

Martyn

Actions #9

Updated by Timo Goebel almost 5 years ago

  • Fixed in Releases 1.23.0 added
Actions #10

Updated by Ewoud Kohl van Wijngaarden almost 5 years ago

  • Status changed from Ready For Testing to Closed
Actions #11

Updated by The Foreman Bot over 4 years ago

  • Pull request https://github.com/theforeman/foreman/pull/7119 added
Actions

Also available in: Atom PDF