============
Client Usage
============

To use barbicanclient, you must first create an instance of the
:class:`barbicanclient.client.Client` class.

The client uses Keystone Sessions for both authentication and for handling HTTP
requests.  You can provide authentication credentials to the client by creating
a Keystone Session with the appropriate auth plugin and then passing that
session to the new Client.

See :doc:`authentication` for more details.

Example::

    from barbicanclient import client

    barbican = client.Client(...)

The client object has different attributes that can be used to interact with
the Barbican service.  Each attribute represents an entity in the Barbican
service:  Secrets, Orders and Containers.

Secrets
=======

Secrets represent keys, credentials, and other sensitive data that is stored
by the Barbican service.  To store or retrieve a secret in the Barbican
service you should use the different methods of the :class:`barbicanclient.secrets.SecretManager`
class that is exposed as the `secrets` attribute of the Client.

Example::

    # Store a random text password in Barbican

    from barbicanclient import client
    import random
    import string

    def random_password(length):
        sys_random = random.SystemRandom()
        return u''.join(
            sys_random.choice(string.ascii_letters + string.digits) for _ in range(length)
        )

    barbican = client.Client(...)

    my_secret = barbican.secrets.create()
    my_secret.name = u'Random plain text password'
    my_secret.payload = random_password(24)

    my_secret_ref = my_secret.store()

The secret reference returned by :meth:`barbicanclient.secrets.SecretManager.store`
can later be used to retrieve the secret data from barbican.

Example::

    # Retrieve Secret from secret reference

    retrieved_secret = barbican.secrets.get(my_secret_ref)
    my_password = retrieved_secret.payload

Secret Content Types
--------------------

The Barbican service defines a Secret Content Type.  The client will choose
the correct Content Type based on the type of the data that is set on the
`Secret.payload` property.  The following table summarizes the mapping of
Python types to Barbican Secret Content Types:

+-----------------+---------------+---------------+--------------------------+
|    six Type     | Python 2 Type | Python 3 Type |  Barbican Content Type   |
+=================+===============+===============+==========================+
| six.binary_type |      str      |     bytes     | application/octet-stream |
+-----------------+---------------+---------------+--------------------------+
| six.text_type   |    unicode    |      str      |        text/plain        |
+-----------------+---------------+---------------+--------------------------+

.. WARNING::
   Previous versions of python-barbicanclient allowed the user to set the
   `payload_content_type` and `payload_content_encoding` properties for any
   secret.  This can lead to unexpected behavior such as changing a unicode
   string back to a byte string in Python 2, and dropping the base64 encoding
   of a binary secret as in Launchpad Bug #1419166.
   Because of this, manually setting the `payload_content_type` and the
   `payload_content_encoding` has been deprecated.

Orders
======

Orders are used to request secret material to be created by the Barbican
service.  Submitting an order will result in a Secret being created on your
behalf.  The Secret can then be used like any Secret you may have uploaded
yourself.  Orders should be created using the factory methods in the
:class:`barbicanclient.orders.OrderManager` instance in the `orders`
attribute of the `Client`.

Example::

    # Submit an order to generate a random encryption key

    from barbicanclient import client

    barbican = client.Client(...)

    my_order = barbican.orders.key_order()
    my_order.algorithm = 'AES'
    my_order.mode = 'CBC'
    my_order.bit_length = 256

    my_order_ref = my_order.submit()

The order reference returned by :meth:`barbicanclient.orders.Order.submit`
can later be used to retrieve the order from Barbican.

Example::

    # Retrieve Order from order reference

    retrieved_order = barbican.orders.get(my_order_ref)

Once your order has been processed by Barbican, the order status will be set
to `'ACTIVE'`.  An active order will contain the reference to the requested
secret (or container).

Example::

    # Retrieve Encryption Key generated by the above KeyOrder

    generated_secret = barbican.secrets.get(retrieved_order.secret_ref)
    key = generated_secret.payload

Currently the client can submit :class:`barbicanclient.orders.KeyOrder` orders
for Keys suitable for symmetric encryption, and :class:`barbicanclient.orders.AsymmetricOrder`
for Asymmetric keys such as RSA keys.

Containers
==========

Containers can be either arbitrary groupings of `Secrets` or a strict
grouping of Secrets, such as the Public and Private keys of an RSA keypair.

Containers should be managed using the :class:`barbicanclient.containers.ContainerManager`
instance in the `containers` attribute of the `Client`

Example::

    # Add the Secrets created above to a container

    my_container = barbican.containers.create()

    my_container.add('Retrieved Secret', retrieved_secret)
    my_container.add('Generated Secret', generated_secret)

    my_container_ref = my_container.store()

The container reference returned by :meth:`barbicanclient.containers.Container.store`
can later be used to retrieve the container from Barbican.

Example::

    # Retrieve container from Barbican

    retrieved_container = barbican.containers.get(my_container_ref)

