Search code examples
pythoncentosdbuscentos7firewalld

Control firewalld in CentOS via Python's dbus module?


My goal is to automate configuring firewalls on CentOS 7 machines using Python.

The OS comes with firewalld, so that's what I'm using. I looked into it and found that it uses dbus (I've never heard of or dealt with any of this - please correct me if anything I say is incorrect.)

I found this documentation for how to control dbus processes using Python: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.txt

I checked and the version of Python that comes with the OS includes the dbus module, so it seems like a promising start.

That document suggests that I needed to learn more about what firewalld exposes via the dbus interface. So I did some more research and found this: https://www.mankier.com/5/firewalld.dbus

The first document says I need to start out with a "well-known name". Their example for such a thing was org.freedesktop.NetworkManager. The second document is titled firewalld.dbus, so I figured that was as good a name as any to try since the document doesn't explicitly give a name anywhere else.

The first document also says I need a name for an object path. Their example is /org/freedesktop/NetworkManager. The second document has an object path of /org/fedoraproject/FirewallD1.

I put those together and tried using the first method the first document suggested, SystemBus's get_object():

>>> from dbus import SystemBus
>>> bus = SystemBus()
>>> proxy = bus.get_object('firewalld.dbus', '/org/fedoraproject/FirewallD1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/bus.py", line 241, in get_object
    follow_name_owner_changes=follow_name_owner_changes)
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 248, in __init__
    self._named_service = conn.activate_name_owner(bus_name)
  File "/usr/lib64/python2.7/site-packages/dbus/bus.py", line 180, in activate_name_owner
    self.start_service_by_name(bus_name)
  File "/usr/lib64/python2.7/site-packages/dbus/bus.py", line 278, in start_service_by_name
    'su', (bus_name, flags)))
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException:
    org.freedesktop.DBus.Error.ServiceUnknown:
        The name firewalld.dbus was not provided by any .service files

I also gave org.fedoraproject.FirewallD1 a try as the first parameter but ended up with a similar error message.

Why are these not working? Is there some way I can discover what the proper names are? It mentions ".service files" at the end of the error message... where would such a file be located?


Edit: Found several ".service files" by using find / -name *.service. One of them is at /usr/lib/systemd/system/firewalld.service... seems pretty promising so I'll check it out.

Edit 2: It's a rather short file... only about 10 lines. One of them says BusName=org.fedoraproject.FirewallD1. So I'm not sure why it said the name was not provided by any .service files... unless it's not using this file for some reason?


Solution

  • If the unit file says:

    BusName=org.fedoraproject.FirewallD1
    

    Then maybe you should try using that as your bus name:

    >>> import dbus
    >>> bus = dbus.SystemBus()
    >>> p = bus.get_object('org.fedoraproject.FirewallD1', '/org/fedoraproject/FirewallD1')
    >>> p.getDefaultZone()
    dbus.String(u'FedoraWorkstation')
    

    I figured this out based on the fact that this:

    >>> help(bus.get_object)
    

    Says that the get_object call looks like:

    get_object(self, bus_name, object_path, introspect=True, follow_name_owner_changes=False, **kwargs)