Last modified 22 months ago Last modified on 29.06.2015 10:53:09

XML-RPC daemon

Version 1.0.1: bugfixes

This version contains several bugfixes for Debian 7+ and RHEL/CentOS 7+.

Version 1.0 is out

This is the first release considered to have stable set of features.

Description

Daemon and shell client utility, both using XML-RPC protocol wrapped in SSL and provided with HTTP authentication.

Daemon is just a trivial HTTP server, that passes XML-RPC calls to appropriate Perl scripts. It's just simpler to configure such a small daemon than Apache, lighttpd or nginx.

Rationale

Sometimes you just need to have a way of executing some command on remote machine, or maybe on the same machine, but under diffrent UID.

The former case is resolved by using SSH and public/private key pair.

The latter case is quite often used to enable PHP web script to restart service or reload netfilter; an admin grants sudo access to the user www-data.

Both ideas are not the best ones I've ever seen, both are hard to maintain in the long run, both are quite fragile (easy to break) and both can be easily replaced by robust RPC call. The only thing is needed on the client side (like said PHP script that reloads firewall) is to connect to remote machine and tell it to execute already-supplied function. No need to enhance client's privileges.

How to download

git clone http://dozzie.jarowit.net/code/xmlrpcd.git

How to install

NOTE: Installation process is tested for building packages. If you want to make mess in your system by omitting package system, you are on your own.

You need casual package building tools for your distribution, either rpm-build (RPMs) or dpkg-dev with fakeroot (DEBs).

Red Hat

NOTE: You need few Perl modules that are not part of official Red Hat Enterprise Linux distribution. You probably want to look at Repoforge project.

  1. Prepare source RPM (non-root privileges are fine here)
    make srpm
    
  2. Build binary RPM (unless you've taken care of building as non-root, you need to be root here)
    rpmbuild --rebuild xmlrpcd-*.src.rpm
    
  3. Install package with its dependencies (exact path should be printed by previous step); most probably it will be located in /usr/src/redhat/RPMS/noarch/xmlrpcd-*.rpm

Debian

  1. Build binary package
    dpkg-buildpackage -b -uc
    
  2. Install package (../xmlrpcd*.deb) with its dependencies

How to use

There are two parts of xmlrpcd: daemon itself and xmlrpcaller, command line XML-RPC client. The client is not necessary at all, as you can use any XML-RPC library, but it's handy to have a ready-to-use client to test your setup.

xmlrpcd, the daemon, starts with configuration file (YAML format). It should look similar to this:

ssl_cert_file: /etc/xmlrpcd/ssl/server.cert.pem
ssl_key_file:  /etc/xmlrpcd/ssl/server.key.pem
listen_port: 3033
#listen_addr: localhost

# authentication subsystem (use Authen::Simple-compatible modules)
auth_method: Authen::Simple::Passwd
auth_params:
  path: /var/lib/xmlrpcd/passwords.htpasswd

methods:
  auth:
    - /var/lib/xmlrpcd/methods/auth/*/*.pm
  public:
    - /var/lib/xmlrpcd/methods/public/*/*.pm

You need to provide X.509 certificate, as all communication with xmlrpcd is done using HTTPs with basic HTTP authentication.

Next thing is authentication subsystem. In the case above plain file (created with htpasswd utility from Apache distribution) is used. Because of underlying module used for authentication, you can use pretty much anything, including LDAP or Kerberos.

The last and most interesting part is what methods are available. There are two types of methods: public ones and the ones requiring successful authentication. You need to be careful while creating public methods, as anyone who can connect to your server is able to call them!

Method is a simple Perl module that contains a single function called entry_point(), and the function can get parameters:

# UID/GID under which function will be executed (defaults to xmlrpcd:xmlrpcd)
#our $RPC_UID = "nobody";
#our $RPC_GID = "nogroup";
# additional parameters to be passed, in appearance order
# my ($user, $ip, $uri, @args) = @_)
#our $RPC_PARAMS = [qw[user address uri]];

# file .../public/maths/add.pm
sub entry_point {
  my ($a, $b) = @_;

  return $a + $b;
}

1; # Perl module needs to end with this!

Let's say the file is saved as /var/lib/xmlrpcd/methods/public/maths/add.pm.

Now it's time to call just defined method:

xmlrpcaller --host localhost --port 3033 --skip-ca maths.add 2 3

By default, xmlrpcaller heavily verifies server certificate, but for now it's OK to ignore any warnings, hence --skip-ca option.

And two Python examples:

# Python 2.6
import xmlrpclib
server = xmlrpclib.ServerProxy('https://localhost:3033/')
resp = server.maths.add(2, 3)
# Python 2.5 with broken HTTPs support
import xmlrpclib
import httplib
req_body = xmlrpclib.dumps(
  methodname = 'maths.add',
  params = (2, 3),
)
req_headers = { "Content-Type": "text/xml" }

server = httplib.HTTPSConnection('localhost', 3033)
server.request("POST", "/", req_body, req_headers)
http_response = server.getresponse()
resp = xmlrpclib.loads(http_response.read())[0][0]

Note the method name. It's composed of the bare file name with last directory name prepended. Use this to group related methods. And remember to avoid using characters from outside of set a-zA-Z0-9_ for file or last directory name.

Python 2.5 has broken HTTPs support (I'm not sure if it is xmlrpclib or httplib fault). The longer example is a workaround.

NOTE: by default, xmlrpcd runs RPC procedures as xmlrpcd user. If you need it to run some procedure with other (e.g. root) privileges, change the procedure header.