0

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?

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193

1 Answers1

1

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)
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Hi - as I mentioned in my original post (just before the edits) I also tried that, but it gave the same error. Is the service file not being loaded or something for some reason? – ArtOfWarfare Dec 21 '15 at 19:42
  • So, that just worked on my system. The service file is used by `systemd` to start Firewalld. Is firewalld running on your system? What does `systemctl status firewalld` report? Do you see a `firewalld` process running? – larsks Dec 21 '15 at 19:44
  • It was not running. I have started it now with `systemctl start firewalld.service`. Now the proxy is being created and returning answers properly. What is the best way to start the service from within Python? I was under the impression the `dbus` module would start it at the right time... or at least provide a function for starting it for me. Is my best bet going to be `subprocess.call()` or is there something I'm overlooking in the `dbus` module? – ArtOfWarfare Dec 21 '15 at 19:46
  • 1
    The correct thing to do is `systemctl enable firewalld` so that it is started by systemd when your system boots. – larsks Dec 21 '15 at 20:17
  • If you have a moment, could you take a look at this? I think I may have found a bug in the Python `dbus` module... http://stackoverflow.com/questions/34424037/dbus-to-python-takes-exactly-1-argument – ArtOfWarfare Dec 22 '15 at 20:37