Skip to Main Content

Infrastructure Software

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Secure Remote RESTful Administration with the Remote Administration Daemon

steph-choyer-OracleJul 30 2015 — edited Dec 2 2016

by Gary Pennington and Glynn Foster

Learn how to configure an Oracle Solaris 11.3 system to provide secure administration over the new REST APIs using the Oracle Solaris Remote Administration Daemon (RAD).

Introduction

One of the new enhancements included in Oracle Solaris 11 is the Remote Administration Daemon (also known as RAD). RAD provides a set of programmatic interfaces to allow administrators to manage Oracle Solaris 11 subsystems such as Oracle Solaris Zones, the ZFS file system, the Service Management Facility (SMF), and more. A previous article, "Getting Started with the Remote Administration Daemon on Oracle Solaris 11," covered how to use RAD using C, Python, Java, and REST programmatic interfaces. This article shows administrators how they can configure an Oracle Solaris 11.3 system to enable REST-based calls over HTTPS using the Transport Layer Security (TLS) protocol.

RAD REST Bindings

In Oracle Solaris 11.3, a new REST interface to RAD has been added. REST APIs are an increasingly popular way of interacting with system services across the network over both HTTP and HTTPS using an encoding payload such as JSON or XML. Oracle Solaris 11.3 includes a new SMF service instance, svc:/system/rad:local-http, that is responsible for facilitating RAD communication from HTTP clients. Given that HTTP connections are not encrypted, the default configuration allows only for accepting connections from a local host on a UNIX socket. With a little configuration, administrators can open up a public port and provide secure transport over TLS.

Creating a New RAD Service Instance

The first step we need to do is to configure RAD to accept connections from a remote host over HTTP. In Oracle Solaris 11.3, there are currently three SMF service instances that are responsible for handling RAD connections:

  • The svc:/system/rad:local service instance manages local connections through UNIX sockets.
  • The svc:/system/rad:remote service instance manages secure remote TLS connections over TCP sockets.
  • The svc:/system/rad:local-http service instance provides access for local connections over HTTP.

At the time of this writing, there is no system-provided service instance to manage secure remote connections over HTTP, so we need to create one—it is likely that one will be provided in a future release of Oracle Solaris.

To do this, we need to create an SMF manifest. There are a number of ways to achieve this—either by taking a copy of the existing /lib/svc/manifest/system/rad.xml manifest and modifying it, or by using svcbundle(1M) to generate one and refining it afterwards. The key elements that the service instance needs to expose relate to key and certificate handling (using the PEM format common for most certificate authorities), the port to accept connections from, and the RAD protocol being used.

For convenience, the full SMF manifest is provided below:

# cat rad-remote-http.xml

<?xml version="1.0" ?>

<!DOCTYPE service_bundle

SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>

<service_bundle type="manifest" name="site/rad">

   <service version="1" type="service" name="site/rad">

       <dependency restart_on="none" type="service"

           name="multi_user_dependency" grouping="require_all">

           <service_fmri value="svc:/milestone/multi-user"/>

       </dependency>

       <exec_method name='start' type='method' exec='/usr/lib/rad/rad -sp' timeout_seconds='0'/>

       <exec_method name='stop' type='method' exec=':kill' timeout_seconds='0'/>

       <instance name='remote-http' enabled='false' complete='true'>

         <property_group name='ssl_port' type='xport_tls'>

           <propval name='certificate' type='astring' value='/etc/rad/cert.pem'/>

           <propval name='generate' type='boolean' value='true'/>

           <propval name='localonly' type='boolean' value='false'/>

           <propval name='pam_service' type='astring' value='rad-tls'/>

           <propval name='port' type='integer' value='12303'/>

           <propval name='privatekey' type='astring' value='/etc/rad/key.pem'/>

           <propval name='proto' type='astring' value='rad_http'/>

           <propval name='value_authorization' type='astring' value='solaris.smf.value.rad'/>

         </property_group>

         <property_group name='config' type='application'>

           <property name='moduledir' type='astring'>

             <astring_list>

               <value_node value='/usr/lib/rad/transport'/>

               <value_node value='/usr/lib/rad/protocol'/>

               <value_node value='/usr/lib/rad/module'/>

               <value_node value='/usr/lib/rad/site-modules'/>

             </astring_list>

           </property>

         </property_group>

       </instance>

       <template>

           <common_name>

                 <loctext xml:lang="C">Remote RAD HTTP</loctext>

           </common_name>

           <description>

               <loctext xml:lang="C">RAD connections over REST (HTTP)</loctext>

           </description>

       </template>

   </service>

</service_bundle>

From the SMF manifest above, we have created a new SMF instance at svc:/site/rad:remote-http. We can see that the start method will call the /usr/lib/rad/rad daemon. We also include a number of properties within the ssl_port property group: certificate and privatekey provide credentials we need to make a secure connection over HTTPS (RAD will automatically generate these using self-signed certificates), port defines the port number on which to accept connections and is set to 12303, and proto defines that the RAD protocol to use is HTTP (as indicated by rad-http).

The next step is to copy the manifest to our site-wide SMF manifest location, /lib/svc/manifest/site, and restart the svc:/system/manifest-import:default service instance:

root@solaris:~# cp rad-remote-http.xml /lib/svc/manifest/site

root@solaris:~# svcadm restart manifest-import

root@solaris:~# svcadm enable rad:remote-http

root@solaris:~# svcs rad:remote-http

STATE          STIME    FMRI

online         17:46:59 svc:/site/rad:remote-http

If we now try to make a simple request to [https://](/)<hostname>:12303 using a web browser, we will get back the following snippet of JSON:

{

        "status": "illegal access",

        "payload": {

                "Message": "Response content type 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' requested

                yet only 'application/json' is supported by the origin server.",

                "HTTP Method": "GET",

                "URI": "/",

                "RAD Operation": null

        }

}

From the output above, we can see that we're connecting to a valid port with a RAD server on the back end, and it accepts only application/json as input.

Setting up a RAD Connection

As detailed in "Getting Started with the Remote Administration Daemon on Oracle Solaris 11," we need to set up the RAD connection. As before, we'll send a POST request to the /api/com.oracle.solaris.rad.authentication/1.0/Session API, and we'll also provide some credentials included in a JSON file called body.json, as follows:

{

      "username": "root",

      "password": "solaris11",

      "scheme": "pam",

      "preserve": true,

      "timeout": -1

}

We can now use curl(1) with a slightly different set of command-line options that point to our SSL key and certificate pair (which we have copied over to the system from where we are making the RAD queries), saving the authentication token to a file called cookie.txt:

# curl -H "Content-type: application/json" -X POST \

--data-binary @body.json \

--cert solaris-cert.pem --key solaris-key.pem -k \

https://solaris.us.oracle.com:12303/api/com.oracle.solaris.rad.authentication/1.0/Session \

-v -c cookie.txt -b cookie.txt

*   Trying 10.134.79.148...

* Failed to set TCP_KEEPALIVE on fd 4

* Connected to solaris.us.oracle.com (10.134.79.148) port 12303 (#0)

* successfully set certificate verify locations:

*   CAfile: none

  CApath: /etc/openssl/certs

* TLSv1.2, TLS handshake, Client hello (1):

* TLSv1.2, TLS handshake, Server hello (2):

* TLSv1.2, TLS handshake, CERT (11):

* TLSv1.2, TLS handshake, Server finished (14):

* TLSv1.2, TLS handshake, Client key exchange (16):

* TLSv1.2, TLS change cipher, Client hello (1):

* TLSv1.2, TLS handshake, Finished (20):

* TLSv1.2, TLS change cipher, Client hello (1):

* TLSv1.2, TLS handshake, Finished (20):

* SSL connection using TLSv1.2 / AES256-GCM-SHA384

* Server certificate:

*        subject: CN=Remote Administration Daemon @ dcsw-79-148

*        start date: 2015-07-26 23:35:37 GMT

*        expire date: 2025-07-23 23:35:37 GMT

*        issuer: CN=Remote Administration Daemon @ dcsw-79-148

*        SSL certificate verify result: self signed certificate (18), continuing anyway.

> POST /api/com.oracle.solaris.rad.authentication/1.0/Session HTTP/1.1

> User-Agent: curl/7.40.0

> Host: solaris.us.oracle.com:12303

> Accept: */*

> Content-type: application/json

> Content-Length: 128

>

* upload completely sent off: 128 out of 128 bytes

< HTTP/1.1 201 Created

< Connection: Keep-Alive

< Content-Length: 164

< Expires: 0

< Pragma: no-cache

< Cache-Control: no-cache, no-store, must-revalidate

< Location: /api/com.oracle.solaris.rad.authentication/1.0/Session/_rad_reference/3328

* Added cookie _rad_instance="3328" for domain solaris.us.oracle.com, path /api, expire 1437962830

< Set-Cookie: _rad_instance=3328; Path=/api; Max-Age=3600; HttpOnly

* Added cookie _rad_token="613891db-9cd8-44fe-90a2-d6d8d94c2fb3" for

domain solaris.us.oracle.com, path /api, expire 1437962830

< Set-Cookie: _rad_token=613891db-9cd8-44fe-90a2-d6d8d94c2fb3;

Path=/api; Max-Age=3600; HttpOnly

< Date: Mon, 27 Jul 2015 00:59:48 GMT

<

{

        "status": "success",

        "payload": {

                "href": "/api/com.oracle.solaris.rad.authentication/1.0/Session/_rad_reference/3328"

        }

* Connection #0 to host solaris.us.oracle.com left intact

}

We can examine the cookie that has been created:

# cat cookie.txt

# Netscape HTTP Cookie File

# http://curl.haxx.se/docs/http-cookies.html

# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_solaris.us.oracle.com  FALSE  /api  FALSE  1437962830  _rad_instance  3328

#HttpOnly_solaris.us.oracle.com  FALSE  /api  FALSE  1437962830  _rad_token     613891db-9cd8-44fe-90a2-d6d8d94c2fb3

Querying Oracle Solaris Zones

Now that we have our connection token, we can query the system. For example, we will use the /api/com.oracle.solaris.rad.zonemgr/1.0/Zone API to query the zones that have been configured on our host:

# curl -H "Content-type: application/json" -X GET \

--cert solaris-cert.pem --key solaris.pem -k \

https://solaris.us.oracle.com:12303/api/com.oracle.solaris.rad.zonemgr/1.0/Zone -b cookie.txt

{

        "status": "success",

        "payload": [

                {

                        "href": "api/com.oracle.solaris.rad.zonemgr/1.2/Zone/zone1"

                }

        ]

}

From the output above, we can see that we have a single zone called zone1. This is confirmed by running zoneadm(1M) from the host directly:

root@solaris:~# zoneadm list -cv

  ID NAME             STATUS      PATH                         BRAND      IP   

   0 global           running     /                            solaris    shared

   - zone1            configured  /system/zones/zone1          solaris    excl

Summary

The Oracle Solaris Remote Administration Daemon (RAD) provides a powerful set of administrative interfaces to allow local and remote configuration of a mix of technologies, including Oracle Solaris Zones, ZFS, SMF, and others. These programmatic interfaces provide a central point for exposing the capabilities of Oracle Solaris to consumers using common development runtimes, including C, Java, Python, and REST APIs. This capability allows secure remote administration at scale, which is critical for a typical cloud environment.

See Also

Also see these additional resources:

About the Authors

Gary Pennington is a principal software engineer for the Oracle Solaris Core Technologies/System Management Group. He has worked on many parts of Oracle Solaris over the last 15 years, including resource management, virtualization, and RAD. Currently he is the technical lead for RAD.

Glynn Foster is a principal product manager for Oracle Solaris. He is responsible for a number of technology areas including OpenStack, the Oracle Solaris Image Packaging System, installation, and configuration management.

| Revision 1.0, 07/29/2015 |

Follow us:
Blog | Facebook | Twitter | YouTube

Comments

Hello, I've been testing this. Do you know if it's possible to enable CORS support for the rad-http service?

1 - 1

Post Details

Added on Jul 30 2015
1 comment
4,526 views