summaryrefslogtreecommitdiff
path: root/doc/source/cli/usage.rst
blob: 418f78b3fdd6a8646223e562f2c5c709ab6d3430 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
============
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:

  .. code-block:: python

    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:

  .. code-block:: python

    # 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:

  .. code-block:: python

    # 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:

  .. code-block:: python

    # Submit an order to generate a random encryption key

    from barbicanclient import client

    barbican = client.Client(...)

    my_order = barbican.orders.create_key()
    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:

  .. code-block:: python

    # 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:

  .. code-block:: python

    # 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:

  .. code-block:: python

    # 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:

  .. code-block:: python

    # Retrieve container from Barbican

    retrieved_container = barbican.containers.get(my_container_ref)


ACLs
====

Access Control List (ACL) feature in Barbican provides user level access
control for secrets and containers. By default Barbican manages access to its
resources (secrets, containers) on a per project level and authorization is
granted based on the roles a user has in that project.

ACLs should be managed using the :class:`barbicanclient.acls.ACLManager`
instance in the `acls` attribute of the `Client`.

Example:

  .. code-block:: python

    # Submits ACLs on an existing Secret with URI as 'secret_ref'

    # create ACL entity object with needed settings
    acl_entity = barbican.acls.create(entity_ref=secret_ref, users=[u1, u2],
                                      project_access=False)

    acl_ref = acl_entity.submit()  # submits ACL setting to server at this point.

The secret or container URI can be used to read all of its ACL setting.
Returned value is instance of either :class:`barbicanclient.acls.SecretACL` or
:class:`barbicanclient.acls.ContainerACL`. Refer to respective class for its
available APIs.

Example:

  .. code-block:: python

    # Get ACL entity for a Secret
    # Returned entity will be either SecretACL or ContainerACL.
    # This entity has ACL settings per operation type (e.g. 'read')

    secret_acl = barbican.acls.get(secret_ref)

    # To retrieve (load) ACL using existing ACL entity e.g. container_acl
    container_acl.load_acls_data()

ACLs setting can also be retrieved directly from secret or container entity.
Its data is lazy loaded i.e. related ACL settings are not read till `acls`
attribute is accessed on secret or container entity.

Example:

  .. code-block:: python

    # Get secret entity for a given ref
    secret = barbican.secrets.get(secret_ref)

    # To get project access flag or users for 'read' operation
    project_access_flag = secret.acls.read.project_access
    read_acl_users = secret.acls.read.users


    # Get container entity for a given ref
    container = barbican.containers.get(container_ref)

    # To get project access flag or users for 'read' operation
    project_access_flag = container.acls.read.project_access
    read_acl_users = container.acls.read.users


If need to add users to existing 'read' ACL settings on a secret or container,
above mentioned get and submit methods can be used.

Example:

  .. code-block:: python

    # Every Barbican secret and container has default ACL setting which
    # reflects default project access behavior.

    # ACL settings is modified via submit operation on ACL entity.

    # provide users to be added as list.
    add_users = ['user1', 'user2', 'users3']

    # Case 1 - Add users to 'read' operation ACL setting
    # --------------------------------------------------

    # Get ACL entity from server
    acl_entity = barbican.acls.get(entity_ref=secret_ref)

    # add new users to existing users for 'read' operation
    acl_entity.read.users.extend(add_users)
    # OR
    # acl_entity.get('read').users.extend(add_users)

    acl_ref = acl_entity.submit() # here submits ACL changes to server.

    # Case 2 - Add same users to ACL settings for each operation type
    # ---------------------------------------------------------------

    # Get ACL entity from server
    acl_entity = barbican.acls.get(entity_ref=secret_ref)

    # Go through each operation ACL setting and add users to existing list
    for op_acl in acl_entity.operation_acls
        op_acl.users.extend(add_users)

    acl_ref = acl_entity.submit() # here submits ACL changes to server.

If need to remove some users from existing ACL settings on a secret or
container, similar approach can be used as mentioned above for `add` example.

Example:

  .. code-block:: python

    # provide users to be removed as list.
    remove_users = ['user1', 'user2', 'users3']

    # Case 1 - Remove users from 'read' operation ACL setting
    # -------------------------------------------------------

    # Get ACL entity from server
    acl_entity = barbican.acls.get(entity_ref=container_ref)

    existing_users = acl_entity.read.users
    # OR
    # existing users = acl_entity.get('read').users

    # remove matching users from existing users list
    updated_users = set(existing_users).difference(remove_users)

    # set back updated users to operation specific acl setting
    acl_entity.read.users = updated_users
    # OR
    # acl_entity.get('read').users = updated_users

    acl_ref = acl_entity.submit() # here submits ACL changes to server.

    # Case 2 - Remove same users from ACL settings for each operation type
    # --------------------------------------------------------------------

    # Get ACL entity from server
    acl_entity = barbican.acls.get(secret_ref)

    # Go through each operation ACL setting and remove users from existing list
    for op_acl in acl_entity.operation_acls
        existing_users = op_acl.users

        # remove matching users from existing users list
        updated_users = set(existing_users).difference(remove_users)

        # set back updated users to operation specific acl setting
        op_acl.users = updated_users

    acl_ref = acl_entity.submit() # here submits ACL changes to server.


If need to unset or delete ACL settings on a secret or container,
:meth:`barbicanclient.acls.SecretACL.remove` or
:meth:`barbicanclient.acls.ContainerACL.remove` can be used.

Example:

  .. code-block:: python

    # create ACL entity object with secret or container ref
    blank_acl_entity = barbican.acls.create(entity_ref=secret_ref)

    # removes all ACL settings for the secret on server
    blank_acl_entity.remove()

    # To remove 'read' operation specific ACL setting
    acl_entity = barbican.acls.get(entity_ref=secret_ref)
    acl_entity.read.remove()
    # OR
    # acl_entity.get('read').remove()