YaST/Research/YaaS/Team 3

From openSUSE

Contents

REST API implementation

Python/Django: REST interface already exists: http://code.google.com/p/django-rest-interface/

Defining a class for system time:

 class SystemTime(Resource):
     def read(self, request):
         return HttpResponse(getSystemTime())
     def update(self, request):
         return HttpResponse(request.PUT) #does not really set, just returns data it gets

Similar classes are to be defined for time zone and time as a whole

Defining URL rewrite:

 urlpatterns = patterns(,
    (r'^time/systemtime', SystemTime(permitted_methods = ('GET', 'PUT'))),
    (r'^time/timezone', TimeZone(permitted_methods = ('GET', 'PUT'))),
    (r'^time/?$', Time(permitted_methods = ('GET', 'POST'))) # does not work if only one method is allowed, don't know why
 )

Connection to DBUS

Reading information about network interfaces:

 def getInterfaces():
   bus = dbus.SystemBus()
   NMC = 'org.freedesktop.NetworkManager'
   NMI = NMC
   nmo = bus.get_object(NMC, '/org/freedesktop/NetworkManager')
   nmi = dbus.Interface(nmo, NMI)
   ret = 'State: ' + str(nmi.state()) + '<br>'
   devices = nmi.GetDevices()
   ret = ret + 'Devices:<br>'
   for device in devices:
       ret = ret + device + '<br>'
   return ret

Creating a class for REST is a piece of cake then :-)

 class Network(Resource):
   def read(self, request):
     return HttpResponse(getInterfaces())
 [...]
   (r'^network/?', Network(permitted_methods = ('GET', 'POST')))

Authentication

There was needed to patch the django-rest-interface, there was a bug in creating structure requesting authentication. Following patch applies to both Digest and Basic authentication:

--- authentication.py   2008-06-30 16:09:10.000000000 +0200
+++ /usr/lib64/python2.5/django_restapi/authentication.py       2008-07-02 12:31:46.000000000 +0200
@@ -49,7 +49,7 @@
         Returns the http headers that ask for appropriate
         authorization.
         """
-        return {'WWW-Authenticate' : 'Basic realm="%s"' % self.realm}
+        return {'www-authenticate' : ('WWW-Authenticate' , 'Basic realm="%s"' % self.realm) }

     def is_authenticated(self, request):
         """
@@ -158,7 +158,7 @@
         if stale:
             parts['stale'] = 'true'
         head = ", ".join(['%s="%s"' % (k, v) for (k, v) in parts.items()])
-        return {'WWW-Authenticate':'Digest %s' % head}
+        return {'www-authenticate' : ('WWW-Authenticate','Digest %s' % head)}

     def is_authenticated(self, request):
         """

All code which is dealing with authentication as well as authorization against PolicyKit (currently with 1:1 mapping between system users and web users) is in authentication.py in the subversion repo.

All passwords are currently hardcoded; users of the same name need to be created and PolicyKit needs to be configured appropriately (according to actions, which are defined in mapping the URLs)

The WSAuthentication class

The WSAuthentication class is intended to wrap real authentication class and its data. The main benefit is that when changing the authentication mechanism, only this class needs to be changed.

Authentication is most likely to need to be changed, depending on mapping between WS users and local users on the system. Proper authentication methods are available by the HTTP protocol and the right one should be evaluated. Hardcoded database of users and passwords is only a temporary solution.

The PolkitResource class

The PolkitResource clas is a parent class of all resources. It handles authentication as well as authorization of the access to individual resources. When using it, all permission checking is pretty simple:

   def read(self, request):
       permission_check = self.PolkitCheck ("read", self.AuthenticatedUser(request))
       if (permission_check != 0):
           return self.ReturnAutorizationError(permission_check)
       return HttpResponse(getTimeZone())

To use this class, its child class needs to have defined the authentication class and policy kit actions for each method of the access to the class. If action for a access method is not defined, it is allowed for each authenticated user.

  (r'^system/time/timezone$', TimeZone(authentication = WSAuthentication(), permitted_methods = ('GET', 'PUT'), polkit_actions = { 'read': 'org.freedesktop.hal.storage.mount-fixed' , 'update': 'org.freedesktop.hal.storage.mount-fixed' })),

Communication with the Backend

Communication with the backend is done vie D-Bus, via functions, which had been provided by Jozef Uhliarik and which map on SCR. This means, that the service layer needs to contain whole business logic which YaST does have.

PolicyKit is not informed about user who performs an action - it is always user with whose permissions the web service is running. The user access is checked via PolicyKit from the web service.

Problems where we are in stuck

Surprisingly none at this moment :-)

TODO

Handle mime-types (XML vs. other outputs)

We need to provide output and input in multiple mime types. HTTP protocol has sufficient support in the headers. See YaST/Research/YaaS/Team_2#MIME_Type.

Use exactly interface agreed with Team 2

The interface was changed several times. In order to move forward, we did not adapt to each change; once it gets stabilized, we should do it. See YaST/Research/YaaS/Team_2#Data_Exchange

Adapt to interface which will be provided by DBus team (Team 4)

The 4th team has worked on multiple variants where to provide interface. We will need to think it over together with the team and find interface which we use. The interface will need to be well defined by team 4.

Decide whether to use D-Bus or other channel to communicate with the back-end

Currenty, we use D-Bus. We need to analyze especially the security impact of this decision and eventually introduce different communication channel. The advantage of D-Bus is that the backend will support it anyway.

Document the web service architecture, review it security-wise

Especially authentication, authorization and communication protocol between the web service and YaST (which is running with root permissions) needs to be documented and reviewed.

Code