Barbican in RDO

Introducing Barbican …

Barbican is an OpenStack project has been recently packaged for RDO.

It provides two services:

  • the Key Management Service (KMS), which provides secure management and storage of secrets (like encryption keys or
    passwords), including the generation of symmetric and asymmetric
  • the Certificate Management Service (CMS) wich provides issuance of x509 certificates.

KMS has been gaining traction in OpenStack over the last few years.  Some of the current use cases include:

  • Generation and storage of volume encryption keys by cinder, and their subsequent retrieval by nova in the hypervisor when an encrypted volume is mounted.
  • Storage and retrieval of certificates and private keys in Neutron Load Balancing as a Service (LBaaS).
  • Storage and retrieval of keys used to sign Glance images. (in progress).
  • Storage and retrieval of Swift objects (for encryption-at-rest) (in progress).
  • Storage of generated and user provided passwords for Sahara (in progress).

CMS has not yet gained a lot of traction, although a lot of projects have expressed some interest.  There is still a bit of work to do there, but there have been some interesting features that have been added (like the ability to create subordinate CAs).

Installing and Starting Barbican

Installing Barbican is super-easy now that its all packaged in RDO.  To be specific, we have packaged the Liberty version of Barbican, so you’ll need to use the Liberty RDO components if you install all the projects together on the same server.

To install Barbican:

sudo yum install -y
sudo yum install -y openstack-barbican-api openstack-barbican

This will install all the python libraries and server classes and configuration for a basic, operational Barbican server.  I’ll explain what that means shortly.

To start the server,

sudo systemctl start openstack-barbican-api.service

This should start up a gunicorn server serving the Barbican WSGI application, serving requests on port 9311::

[root@openstack2 ~]# ps -ef |grep gunicorn
 barbican  3695     1  0 01:00 ?        00:00:07 /usr/bin/python /usr/bin/gunicorn --pid /run/barbican/pid -c /etc/barbican/ --paste /etc/barbican/barbican-api-paste.ini
 barbican  3700  3695  0 01:00 ?        00:00:01 /usr/bin/python /usr/bin/gunicorn --pid /run/barbican/pid -c /etc/barbican/ --paste /etc/barbican/barbican-api-paste.ini
 barbican  3705  3695  0 01:00 ?        00:00:01 /usr/bin/python /usr/bin/gunicorn --pid /run/barbican/pid -c /etc/barbican/ --paste /etc/barbican/barbican-api-paste.ini
 barbican  3710  3695  0 01:00 ?        00:00:00 /usr/bin/python /usr/bin/gunicorn --pid /run/barbican/pid -c /etc/barbican/ --paste /etc/barbican/barbican-api-paste.ini
 barbican  3715  3695  0 01:00 ?        00:00:00 /usr/bin/python /usr/bin/gunicorn --pid /run/barbican/pid -c /etc/barbican/ --paste /etc/barbican/barbican-api-paste.ini

The Barbican WSGI application is basically:

  • A REST front-end, that can be configured to accept authentication through middleware modules.  Barbican currently expects to receive the same headers (X-Project-Id for instance) as would be provided by a keystone token.
  • An application layer which processes requests, routes them to the appropriate backend plugin, and stores metadata in a local database.(sqlite database at /var/lib/barbican/barbican.sqlite, by default).  It is possible to configure other databases like postgres.
  • A backend plugin layer, which consists of plugins that interact with various back-end devices to actually store secrets or issue certificates.

For storing, retrieving and generating keys, for instance, there are
several plugins:

  • a simple storage plugin, which simply encrypts the secret using a static symmetric key stored in a configuration file.  This is great for testing but absolutely NOT for production.
  • a KMIP plugin, used to talk to a KMIP device.
  • a PKCS11 plugin, used to talk to an HSM using PKCS11.
  • a Dogtag plugin, used to talk to a Dogtag Key Recovery Authority (KRA).  I worked on this, and will have a lot more to say about this later.

For issuing certificates, we have:

  • A simple testing plugin that pretty much just pretends to send the
    certificate request somewhere, and sends back “Waiting for CA ..”.
  • Another simple testing plugin (called snakeoil) that processes the certificate request and returns a self signed certificate using OpenSSL.  Snakeoil has also implemented the subCA feature.
  • A Dogtag CA plugin, suitable for contacting Dogtag CA servers. Again, I’ll have much more to say about this later.
  • A Symantec plugin, suitable for contacting Symantec public CAs. (in progress).
  • A Digicert plugin (in progress).

Out of the box, the Barbican server will be configured to not expect authentication (although you still need to provide the X-Project-ID as a request header), will send secret storage/retrieval/generation requests to the simple storage plugin, and will send certificate requests to the simple testing and snakeoil plugins.

It will also serve requests over HTTP (NOT https!) on port 9311.   This is useful to do some basic integration and sanity tests though, as I’ll describe in the section below. In later posts, I’ll describe how  to secure the front-end using haproxy, to enable keystone authentication, and to configure Barbican to use some production-ready back-ends (Dogtag).

There is a puppet module in progress that I will be helping to shepherd through (with a lot of help from Emilien) over the next few weeks.  This puppet module will install Barbican as an apache module, rather than a standalone app.  The repo for this project is here.

Testing Barbican

Testing Secret Storage/Generation/Retrieval

To store a secret, we’ll invoke the REST API directly:

 curl -X POST \
      -H 'content-type:application/json' \ 
      -H 'X-Project-Id:12345'
      -d '{\
           "payload": "my-secret-here", 
           "payload_content_type": "text/plain"}' \ 
{"secret_ref": "http://localhost:9311/v1/secrets/886c7e43-19c7-460b-b695-c71ea1dcf1df"}

To retrieve metadata about the secret::

curl -X GET \
    -H 'content-type:application/json' \
    -H 'X-Project-Id:12345' \ 
{"status": "ACTIVE", 
 "secret_type": "opaque", 
 "updated": "2015-11-21T14:09:52.498425", 
 "name": null, 
 "algorithm": null, 
 "created": "2015-11-21T14:09:52.495135", 
 "secret_ref": "http://localhost:9311/v1/secrets/886c7e43-19c7-460b-b695-c71ea1dcf1df", 
 "content_types": {"default": "text/plain"}, 
 "creator_id": null, "mode": null, 
 "bit_length": null, "expiration": null

And to retrieve the secret itself::

curl -X GET -H 'accept:text/plain' -H 'X-Project-Id:12345' \ 

To generate a secret::

curl -X POST \
  -H 'content-type:application/json' \
  -H 'X-Project-Id:12345' 
  -d '{"payload": "my-secret-here", 
       "payload_content_type": "text/plain"}' \ 
{"secret_ref": "http://localhost:9311/v1/secrets/886c7e43-19c7-460b-b695-c71ea1dcf1df"}

and to retrieve it::

curl -X GET \
  -H 'accept:application/octet-string' \
  -H 'X-Project-Id:12345' \ 
<<binary data>>

Testing Certificate Generation

First, we need to determine which Certificate Authorities (CAs) are available.  A certificate plugin can provide access to many CAs. In this case, we expect to see at least two CAs (for the simple and snake oil plugins).::

curl -X GET \
  -H 'accept:application/json' \
  -H 'X-Project-Id:12345' \ 
{"cas": [
 "http://localhost:9311/v1/cas/c88c0178-1c48-4b40-abb7-5ffd9ac44110", .. 
 "total": 3

You can get more details about each CA – including the plugin name, signing  certificate and PKCS#7 certificate chain by doing a GET on each CA.:

curl -X GET \
  -H 'accept:application/json' \
  -H 'X-Project-Id:12345' \ 
{"status": "ACTIVE", 
 "updated": "2015-11-21T14:08:34.289206", 
 "created": "2015-11-20T06:01:02.853237", 
 "plugin_name": "barbican.plugin.snakeoil_ca.SnakeoilCACertificatePlugin", 
 "meta": [ 
   {"ca_signing_certificate": "-----BEGIN CERTIFICATE-----\nMIIC+zCC..."}, 
   {"intermediates": "-----BEGIN PKCS7-----\nMIIDLAYJKoZIhvcNAQcCoII..."}, 
   {"name": "Snakeoil CA"} 
 "ca_id": "72b53eb0-1d36-48f9-a26a-13449929003b", 
 "plugin_ca_id": "Snakeoil CA", 
 "expiration": "2015-11-22T14:08:34.282407"}

The UUID of the certificate  authority (the ca_id) can be used to specify the CA to which certificate orders should be directed. When the expiration time occurs, the server will query the certificate plugin to determine if the CA data is still valid. This is to allow Barbican to remain in sync with changes in the CA back-ends.

To generate a certificate, we will generate a certificate request, and order a certificate from the snake oil backend. This back-end always returns a self signed certificate. To avoid having to construct all the HTTP requests explicitly, we’ll use the Barbican client. By adding the verbose (-v) option, you can see the exact request sent to the server and the responses.

Note: As of now, the version of python-barbicanclient on Fedora 23 is too old to work with Liberty. Install version 3.3.0-1 from koji instead (package)

sudo yum install python-barbicanclient
openssl genrsa -out rsa.key 2048 
openssl req -new -sha256 -key rsa.key \
  -subj "/CN=server1/" -out csr.txt 
cat csr.txt |base64 > csr.b64  
barbican --os-project-id 12345 --no-auth \
  --endpoint http://localhost:9311 \ 
  order create --type certificate 
  --ca-id 72b53eb0-1d36-48f9-a26a-13449929003b \ 
 --request-file csr.b64
| Field          | Value                                   | 
| Order href     | http://localhost:9311/v1/orders/73f69   |
|                | 01c-ffee-4e11-adfd-f7c6ce8ebe88         | 
| Type           | Certificate                             | 
| Container href | None                                    | 
| Secret href    | N/A                                     | 
| Created        | None                                    | 
| Status         | None                                    | 
| Error code     | None                                    | 
| Error message  | None                                    | 
barbican --os-project-id 12345 --no-auth --endpoint http://localhost:9311 \ 
 order get http://localhost:9311/v1/orders/73f6901c-ffee-4e11-adfd-f7c6ce8ebe88
| Field          | Value                                   | 
| Order href     | http://localhost:9311/v1/orders/73f6901 |
|                |   c-ffee-4e11-adfd-f7c6ce8ebe88         | 
| Type           | Certificate                             | 
| Container href | http://localhost:9311/v1/containers/31  |
|                |   d9166c-14b8-461c-b09c-b207bdd877a9    | 
| Secret href    | N/A                                     | 
| Created        | 2015-11-25 21:52:57.945367+00:00        | 
| Status         | ACTIVE                                  | 
| Error code     | None                                    | 
| Error message  | None                                    | 
barbican --os-project-id 12345 --no-auth --endpoint http://localhost:9311 \ 
 container get http://localhost:9311/v1/containers/31d9166c-14b8-461c-b09c-b207bdd877a9
| Field          | Value                                      | 
| Container href | http://localhost:9311/v1/containers/31d9   |
|                |    166c-14b8-461c-b09c-b207bdd877a9        | 
| Name           | None                                       | 
| Created        | 2015-11-25 21:52:58.038753+00:00           | 
| Status         | ACTIVE                                     | 
| Type           | certificate                                | 
| Certificate    | http://localhost:9311/v1/secrets/7dc81be5  |
|                |   -a513-4371-91be-6a6cfcc059af             | 
| Intermediates  | http://localhost:9311/v1/secrets/ab844561  |
|                |    -84cd-437a-b12f-c38b2cbc4b62            | 
| Private Key    | None                                       | 
| PK Passphrase  | None                                       | 
| Consumers      | None                                       | 
curl -X GET -H 'accept:application/pkix-cert' -H 'X-Project-Id:12345' \ 

In a later post, I will describe how to request a certificate using

Testing subordinate CAs

One exciting new feature that was added in Liberty was the ability to create
subordinate CAs.  These are CAs that have their signing certificate signed by the designated parent CA.  This opens up the possibility of having project specific CAs, and tightly controlled security domains where only a certificate chain is installed and accepted.

This is currently used in Magnum to ensure TLS security and authorization for containers belonging to a specific bay.  It can also be used to tightly
control puppet domains.

At this point, only the snakeoil CA supports this feature.  The latest
master branch of Dogtag (Dogtag 10.3) does support subCA creation, but this support has not yet been extended to the Barbican Dogtag plugin.  I expect to add this support early in the Mitaka cycle.

To create a new subordinate CA, do a POST on the /cas interface, specifying
a snake oil CA as the parent CA.::

curl -X POST \
  -H 'content-type:application/json' \
  -H 'X-Project-Id:12345' \  
  -d '{"name": "Subordinate CA", 
       "description": "Test Subordinate CA", \ 
       "parent_ca_ref": "http://localhost:9311/v1/cas/72b53eb0-1d36-48f9-a26a-13449929003b", \  
       "subject_dn": "CN=Subordinate CA,"}' \ 
{"ca_ref": "http://localhost:9311/v1/cas/78ee20b6-4330-46c1-b747-8be9c1dd60e6"} 

This returns a new subordinate CA.  You can then get the signing certificate, and PKCS#7 certificate chain from the CA metadata, and use the ca_id to request certificates.


5 thoughts on “Barbican in RDO

  1. Many thanks for the great guide .
    While testing this on FC 23 openstack-barbican-api.service failed to start due to wrong /var/lib/barbican permissions – users barbican doesn’t have write permission to this folder .


    1. There are actually a couple of problems which I’ve discovered.
      1. the ownership problem on /var/lib/barbican
      2. the directory /run/barbican not existing after reboot.

      (2) is the result of us delivering /run/barbican instead of /var/run/barbican., which gets linked to run/barbican.
      (1) results because the /var/lib/barbican belongs to the wrong subpackage. The barbican user does not exist when it is installed.

      I’ve put in a patch to fix both these issues, but we decided to restructure the packages slightly as well too. I plan to have the new patch out and reviewed tomorrow morning, so stay tuned.



  2. First of all thanks again for the excellent guide . I tested 90% of the things and almost everything ( with small fixes on the way ) worked fine .Now I have the following in my setup

    FC23 all-in-one
    IPA on RH7.2 as VM
    Barbican added to Keystone
    Secure barbican is behind haproxy with TLS/SSL
    Volumes encryption with ones registered in Barbican
    Barbican is integrated into IPA


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s