Chapter 2. WebYaST Architecture

Contents

2.1. REST-API Interface
2.2. SSL Certificates

WebYaST consists of the following main components:

YaST2 Webservice

The YaST2 Webservice runs on the host system (appliance). It receives requests from YaST2 Webclient, handles user authentication via PAM modules, checks his rights via PolicyKit, and then sends the requests to YaST-DBus.

YaST2 Webclient

The YaST2 Webclient is an web application that provides user interface for authentication, appliance configuration, and monitoring.

YaST2 Webclient and YaST2 Webservice communicate via the standard HTTP(s) protocol.

Figure 2.1. WebYaST Architecture

WebYaST Architecture

2.1. REST-API Interface

The YaST2 Webservice provides an interface to the YaST environment of the host appliance. This service is running on an installed Web server and provides an API which is based on the REST (Representational State Transfer) architecture.

[Note]New Web Server is Used in WebYaST 1.2

WebYaST 1.2 uses a new web server as the back-end technology; lighttpd, which was used in previous releases, has been replaced with nginx. If you upgrade WebYaST from 1.1 to 1.2, you should remove lighttpd from your appliance depending on whether it is needed for other appliacations in your appliance.

With the nginx web server, WebYaST is loaded on demand and unloaded after 5 minutes of inactivity. Thus, memory is saved.

For more information about REST, see http://en.wikipedia.org/wiki/Representational_State_Transfer.

For example, to get or set the systemtime, use the following HTTP URL:

http://hostname/systemtime

The following set of operations is supported by the Web service. You can use these methods for manipulating values:

GET

Retrieving a value. For more information, see Section 2.1.1.1, “The GET Method”.

PUT

Overwriting a value. For more information, see Section 2.1.1.2, “The PUT Method”.

POST

Creating a new value. For more information, see Section 2.1.1.3, “The POST Method”.

DELETE

Deleting a value, for example an user account. For more information, see Section 2.1.1.4, “The DELETE Method”.

2.1.1. General Structure of HTTP Requests

Information can be handled in three different formats (according to the MIME type of the data supported by the Web service):

HTML format

With URL http://hostname/systemtime

XML format

With URL http://hostname/systemtime.xml

JSON format

With URL http://hostname/systemtime.json

2.1.1.1. The GET Method

You can either get information in a block or you can get each entry of the block in an extra HTTP call. GET http://hostname/systemtime.xml returns:

<systemtime> 
<currenttime type="datetime">2008-09-10T17:13:37Z</currenttime>
  <is_utc type="boolean">false</is_utc>
  <timezone>Europe/Berlin</timezone>
  <validtimezones type="array">
     <timezone>
        <id>Africa/Abidjan</id>
     </timezone>
     <timezone>
        <id>Africa/Accra</id>
     </timezone>
     ....
     ..
     .
  </validtimezones>
</systemtime>

GET calls can be generated on the command line with as follows

curl -0 -X GET -b cookie_file http://0.0.0.0:4984/systemtime.xml

where cookie_file is a cookie containing the login information of the current session. The cookie file can be generated by the following command:

 curl -u tux -c cookie.txt http://0.0.0.0:4984/login

2.1.1.2. The PUT Method

PUT requests are used to overwrite existing values. Multiple values can be overwritten at once in a block or each entry of the block can be set explicitly in an extra HTTP call. For example, you can change multiple entries within the following block of XML data

     <?xml version="1.0" encoding="UTF-8"?>
     <language>
     <first_language>de_DE</first_language>
     <second_languages type="array">
     <language>
     <id>en_US</id>
     </language>
     <language>
     <id>en_GB</id>
     </language>
     </second_languages>
     </language>
    

by using the following command:

PUT http://hostname/languages

It is also possible to use data in HTML or JSON formats.

PUT calls can be generated with the following command:

     curl -0 -v -H "Content-Type: application/xml; charset=utf-8"
     -T data-file -b cookie_file http://0.0.0.0:4984/languages.xml
    

2.1.1.3. The POST Method

POST requests are used for creating new entries, for example adding a new user account. They are also used for requests that do not change any data, like starting or stopping services or generating a login session:

 POST http://hostname/login

The following call checks the system account and creates a session with given values and generates a session cookie valid for a period of 1 day:

<hash>
  <login>tux</login>
  <password>password_tux</password>
  <remember_me type="boolean">true</remember_me>
</hash>

If the login is successful, the following data are returned:

<hash>
  <login>granted</login>
</hash>

If the login is not successful, the following data are returned:

<hash>
  <login>denied</login>
</hash>

If curl is used for testing, you can generate a session cookie with the login data specified in login_xml_file with the following command:

 curl -0 -X POST -v -H "Content-Type: application/xml; charset=utf-8"
 -T login_xml_file -c cookie_file http://0.0.0.0:4984/login.xml

2.1.1.4. The DELETE Method

DELETE requests are used for deleting entries, for example a user account:

  DELETE http://0.0.0.0:4984/yast/v1/users/tux 
 

DELETE calls can be generated with the following command:

  curl -0 -X DELETE -b cookie_file http://0.0.0.0:4984/users/tux
 

2.1.2. YaST2 Webservice API

The YaST2 Webservice API has two kinds of interfaces:

Fixed Interfaces

Exist on every YaST2 Webservice. They are used for session handling or checking permissions. For more information, refer to Section 2.1.2.1, “Fixed Interfaces”.

Variable Interfaces

Depends on the particular module (user, patches, systemtime) installed on the respective YaST2 Webservice. For more information, refer to Section 2.1.2.2, “Variable Interface”.

2.1.2.1. Fixed Interfaces

The following interfaces are present in every YaST2 Webservice:

2.1.2.1.1. hostname/login

This interface handles login and creation of a session. An additional login cookie is generated if required. The existence of the given system user account is checked via PAM.

<hash>
  <login>tux</login>
  <password>password_tux</password>
  <remember_me type="boolean">true</remember_me>
</hash>

If the login is successful, the following data are returned:

<hash>
  <login>granted</login>
</hash>

If the login is not successful, the following data are returned:

<hash>
  <login>denied</login>
</hash>

If curl is used for testing, you can generate a session cookie with the login data specified in login_xml_file with the following command:

 curl -0 -X POST -v -H "Content-Type: application/xml; charset=utf-8"
 -T login_xml_file -c cookie_file http://0.0.0.0:4984/login.xml
2.1.2.1.2. hostname/logout

This interface destroys the current session and invalidates the respective cookie (if the cookie exists).

 POST hostname/logout

It returns:

<hash>
  <logout>Goodbye!</logout>
</hash>
2.1.2.1.3. hostname/permissions

This interface is useful when it is necessary to check user permissions in advance, for example, before a menu entry is generated. Two arguments are used:

user_id

The ID of the user whose permissions should be checked.

filter

Filter for the permissions.

The following call

GET /permissions?user_id=user_id
GET /permissions?user_id=user_id&filter=filter

returns:

<permissions type="array">
  <permission>
    <name>org.opensuse.yast.system.time.read</name>
    <grant type="boolean">true</grant>
  </permission>
  <permission>
    <name>org.opensuse.yast.systemtime.write-timezone</name>
    <grant type="boolean">true</grant>
  </permission>
  <permission>
    <name>org.opensuse.yast.systemtime.read-isutc</name>
    <grant type="boolean">true</grant>
  </permission>
  <permission>
    <name>org.opensuse.yast.systemtime.write</name>
    <grant type="boolean">true</grant>
  </permission>
  ...
  ..
  .
</permissions> 

2.1.2.2. Variable Interface

WebYaST contains several plug-ins. Every plug-in is designed for a special task and has its own REST-API. Because of this, the YaST2 Webservice API depends on which plug-ins (defined in packages) are installed.

An useful feature of any REST interface is that you can ask the interface for its API format via the following call:

 GET hostname/resources.xml

It returns:

<resources type="array">
   <resource>
     <interface>org.opensuse.yast.system.patches</interface>
     <singular type="boolean">false</singular>
     <href>/patches</href>
     </resource>

     ...
   
   <resource>
     <interface>org.opensuse.yast.commandlines</interface>
     <singular type="boolean">false</singular>
     <href>/yast/commandlines</href>
   </resource>
</resources>

2.1.3. Security Handling

The communication between YaST2 Webclient and YaST2 Webservice is secured by authentication via Pluggable Authentication Modules (PAM) and user permission checks via PolicyKit. The process flow is as follows:

  1. The user starts a login request with username and password. This is sent from his YaST2 Webclient to the YaST2 Webservice via HTTP(S)/REST. The request is checked with PAM and the access is granted or denied accordingly. If the access is granted, a session is created and a cookie is send to the YaST2 Webclient (on demand).

  2. The authenticated user sends a HTTP(S) request with his YaST2 Webclient, for example: GET http://hostname/yast/protocol_version/systemtime.xml.

  3. The YaST2 Webservice checks the authentication by executing the following steps:

    1. Checking the user and password in the HTTP header via PAM (basic authentication).

    2. Checking the password field for a session ID (from a former login request) which is compared with the current session.

    3. If the request includes a cookie with the session information (can be generated while the login request) this cookie is compared with the current session.

    If all these checks fail an HTTP error 401 is returned.

  4. The YaST2 Webservice checks whether the authenticated user has the right for reading these settings:

    policyKit_check ("username",
          "read.systemtime")

    If a call needs to be performed with root privileges, the request is sent using the YaST-DBus interface.

Each YaST2 Webservice call needs specific access permissions that can be defined for each user. These permissions are handled by PolicyKit in the following files: /usr/share/PolicyKit/policy/org.opensuse.yast.*.

If you encounter a permission error while using the API, the return code 503 is generated and the details are provided in XML:

<error>
        <type>NO_PERM</type>
        <description>
          Permission to allow org.opensuse.yast.system.patches.read is not available 
          for user tux
        </description>
        <permission>org.opensuse.yast.system.patches.read</permission>
        <user>tux</user>
        <bug>false</bug>
</error>

where type contains an internal error identifier, description contains a human-readable description, permission contains the missing permission, user contains the affected user, and bug indicates if the problem is a software bug or just a problem in the configuration.

2.1.3.1. Setting Individual Permissions

Permissions can be set with the command polkit-auth:

polkit-auth --user tux --grant org.opensuse.yast.system.users.delete

Or they can be revoked with the following command:

polkit-auth --user tux --revoke org.opensuse.yast.system.users.read

To grant or revoke all permissions, use the script /usr/sbin/grantwebyastrights delivered with the package webyast-base-ws:

Usage: grantwebyastrights --user <user> --action (show|grant|revoke) 
NOTE: This program should be run by user root 
This call grant/revoke ALL permissions for YaST the Webservice. 
In order to grant/revoke single rights use: 
polkit-auth --user <user> (--grant|revoke) <policyname> 
In order to show all possible permissions use: 
polkit-action 

Each YaST2 Webservice plug-in provides its own policy description file in /usr/share/PolicyKit/policy/. The following conventions apply to the filenames: The filename is the plug-in interface name with .policy as suffix.

For example, the plug-in status has the interface name org.opensuse.yast.system.status (defined in config/resources/status.yml). The policy file in /usr/share/PolicyKit/policy/ has the name org.opensuse.yast.system.status.policy.

2.2. SSL Certificates

An SSL certificate is needed to encrypt the connection between the users browser and the YaST2 Webclient. This SSL certificate is created automatically on the first YaST2 Webservice startup (if it does not already exist).

You may want to use your own certificate or a certificate signed by your company. If the certificate files already exist, they are not changed in any way. Custom certificates can be either placed manually, or can be put into the appliance when it is created (with SUSE Studio, SUSE Studio Onsite or Kiwi).

The certificate files are located in the /etc/lighttpd/certs/ directory. The name of the certificate file is webyast.pem. The name of the certificate's key file is webyast.key.

The file permissions should be set to 0600 for the webyast.key file. For the webyast.pem file, the permissions should be set to 0644. The user and user group for both of these files should be set to nginx.

To change the certificate, you can either place your own certificate files in the /etc/lighttpd/certs/ directory, or configure WebYaST to use a different certificate directory.

To configure a different certificate directory, edit the ssl_certificate and ssl_certificate_key options in the /etc/yastwc/nginx.conf configuration file and restart the WebYaST server with the rcyastwc restart command.


WebYaST WebYaST Vendor Guide 11