Merge "Part 2: Adding ACL support for CLI commands and docs"

This commit is contained in:
Jenkins 2015-10-03 09:06:05 +00:00 committed by Gerrit Code Review
commit 68adf0cecf
10 changed files with 840 additions and 49 deletions

View File

@ -8,7 +8,9 @@ Key Management API. There is a Python library for accessing the API
Installation
------------
The client is `pip installable <https://pypi.python.org/pypi/python-barbicanclient>`__ as follows:
The client is
`pip installable <https://pypi.python.org/pypi/python-barbicanclient>`__ as
follows:
.. code:: console
@ -18,7 +20,8 @@ The client is `pip installable <https://pypi.python.org/pypi/python-barbicanclie
barbicanclient - Python Library
-------------------------------
The full api is `documented in the official OpenStack documentation site <http://docs.openstack.org/developer/python-barbicanclient>`__.
The full api is
`documented in the official OpenStack documentation site <http://docs.openstack.org/developer/python-barbicanclient>`__.
Here's an example of storing a secret in barbican using the python library
@ -76,7 +79,8 @@ with keystone authentication:
barbican - Command Line Client
------------------------------
The command line client is self-documenting. Use the --help flag to access the usage options
The command line client is self-documenting. Use the --help flag to access the
usage options
.. code:: console
@ -158,21 +162,26 @@ The command line client is self-documenting. Use the --help flag to access the u
See "barbican help COMMAND" for help on a specific command.
Commands:
complete print bash completion command
acl get Retrieve ACLs for a secret or container by providing its href.
acl delete Delete ACLs for a secret or container as identified by its href.
acl submit Submit ACL on a secret or container as identified by its href.
acl user add Add ACL users to a secret or container as identified by its href.
acl user remove Remove ACL users from a secret or container as identified by its href.
complete print bash completion command
container create Store a container in Barbican.
container delete Delete a container by providing its href.
container get Retrieve a container by providing its URI.
container list List containers.
help print detailed help for another command
order create Create a new order.
order delete Delete an order by providing its href.
order get Retrieve an order by providing its URI.
order list List orders.
secret delete Delete an secret by providing its href.
secret get Retrieve a secret by providing its URI.
secret list List secrets.
secret store Store a secret in Barbican.
secret update Update a secret with no payload in Barbican.
container get Retrieve a container by providing its URI.
container list List containers.
help print detailed help for another command
order create Create a new order.
order delete Delete an order by providing its href.
order get Retrieve an order by providing its URI.
order list List orders.
secret delete Delete an secret by providing its href.
secret get Retrieve a secret by providing its URI.
secret list List secrets.
secret store Store a secret in Barbican
secret update Update a secret with no payload in Barbican.
* License: Apache License, Version 2.0
* Documentation: http://docs.openstack.org/developer/python-barbicanclient

View File

@ -0,0 +1,261 @@
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Command-line interface sub-commands related to ACLs.
"""
from cliff import command
from cliff import lister
from barbicanclient import acls
class ArgMixin(object):
"Mixin class for CLI arguments and validation"
def add_ref_arg(self, parser):
parser.add_argument('URI',
help='The URI reference for the secret or '
'container.')
def add_per_acl_args(self, parser):
parser.add_argument('--user', '-u',
action='append', default=None, nargs='?',
dest='users',
help='Keystone userid(s) for ACL.')
group = parser.add_mutually_exclusive_group()
group.add_argument('--project-access',
dest='project_access',
action='store_true',
default=None,
help='Flag to enable project access behavior.')
group.add_argument('--no-project-access',
dest='project_access',
action='store_false',
help='Flag to disable project access behavior.')
parser.add_argument('--operation-type', '-o',
default=acls.DEFAULT_OPERATION_TYPE,
dest='operation_type', choices=['read'],
help='Type of Barbican operation ACL is set for')
def create_blank_acl_entity_from_uri(self, acl_manager, args):
"""Validates URI argument and creates blank ACL entity"""
entity = acl_manager.create(args.URI)
entity.validate_input_ref()
return entity
def create_acl_entity_from_args(self, acl_manager, args):
blank_entity = self.create_blank_acl_entity_from_uri(acl_manager, args)
users = args.users
if users is None:
users = []
else:
users = [user for user in users if user is not None]
entity = acl_manager.create(
entity_ref=blank_entity.entity_ref, users=users,
project_access=args.project_access,
operation_type=args.operation_type)
return entity
def get_acls_as_lister(self, acl_entity):
"""Gets per operation ACL data in expected format for lister command"""
map(lambda acl: setattr(acl, 'columns', acl_entity.columns),
acl_entity.operation_acls)
return acls.ACLFormatter._list_objects(acl_entity.operation_acls)
class DeleteACLs(command.Command, ArgMixin):
"""Delete ACLs for a secret or container as identified by its href."""
def get_parser(self, prog_name):
parser = super(DeleteACLs, self).get_parser(prog_name)
self.add_ref_arg(parser)
return parser
def take_action(self, args):
"""Deletes a secret or container ACL settings from Barbican.
This action removes all of defined ACL settings for a secret or
container in Barbican.
"""
blank_entity = self.create_blank_acl_entity_from_uri(
self.app.client_manager.key_manager.acls, args)
blank_entity.remove()
class GetACLs(lister.Lister, ArgMixin):
"""Retrieve ACLs for a secret or container by providing its href."""
def get_parser(self, prog_name):
parser = super(GetACLs, self).get_parser(prog_name)
self.add_ref_arg(parser)
return parser
def take_action(self, args):
"""Retrieves a secret or container ACL settings from Barbican.
This action provides list of all ACL settings for a secret or container
in Barbican.
:returns: List of objects for valid entity_ref
:rtype: :class:`barbicanclient.acls.SecretACL` or
:class:`barbicanclient.acls.ContainerACL`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
blank_entity = self.create_blank_acl_entity_from_uri(
self.app.client_manager.key_manager.acls, args)
acl_entity = self.app.client_manager.key_manager.acls.get(
blank_entity.entity_ref)
return self.get_acls_as_lister(acl_entity)
class SubmitACL(lister.Lister, ArgMixin):
"""Submit ACL on a secret or container as identified by its href."""
def get_parser(self, prog_name):
parser = super(SubmitACL, self).get_parser(prog_name)
self.add_ref_arg(parser)
self.add_per_acl_args(parser)
return parser
def take_action(self, args):
"""Submit complete secret or container ACL settings to Barbican
This action replaces existing ACL setting on server with provided
inputs.
:returns: List of objects for valid entity_ref
:rtype: :class:`barbicanclient.acls.SecretACL` or
:class:`barbicanclient.acls.ContainerACL`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
entity = self.create_acl_entity_from_args(
self.app.client_manager.key_manager.acls, args)
entity.submit()
entity.load_acls_data() # read ACL settings from server
return self.get_acls_as_lister(entity)
class AddACLUsers(lister.Lister, ArgMixin):
"""Add ACL users to a secret or container as identified by its href."""
def get_parser(self, prog_name):
parser = super(AddACLUsers, self).get_parser(prog_name)
self.add_ref_arg(parser)
self.add_per_acl_args(parser)
return parser
def take_action(self, args):
"""Add users to a secret or a container ACL defined in Barbican
Provided users are added to existing ACL users if there. If input users
is None or empty list, no change is made in existing ACL users list.
If input project_access flag is None, then no change is made in
existing project access behavior.
:returns: List of objects for valid entity_ref
:rtype: :class:`barbicanclient.acls.SecretACL` or
:class:`barbicanclient.acls.ContainerACL`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
input_entity = self.create_acl_entity_from_args(
self.app.client_manager.key_manager.acls, args)
server_entity = self.app.client_manager.key_manager.acls.get(
input_entity.entity_ref)
for input_acl in input_entity.operation_acls:
server_acl = server_entity.get(input_acl.operation_type)
if server_acl:
if input_acl.project_access is not None:
server_acl.project_access = input_acl.project_access
# if input data has users, add it to existing users list
if input_acl.users is not None:
server_acl.users.extend(input_acl.users)
# provided input operation_type does not exist in server entity
else:
server_entity.add_operation_acl(
users=input_acl.users,
project_access=input_acl.project_access,
operation_type=input_acl.operation_type)
server_entity.submit() # apply changes to server
server_entity.load_acls_data()
return self.get_acls_as_lister(server_entity)
class RemoveACLUsers(lister.Lister, ArgMixin):
"""Remove ACL users from a secret or container as identified by its href.
"""
def get_parser(self, prog_name):
parser = super(RemoveACLUsers, self).get_parser(prog_name)
self.add_ref_arg(parser)
self.add_per_acl_args(parser)
return parser
def take_action(self, args):
"""Remove users from a secret or a container ACL defined in Barbican
Provided users are removed from existing ACL users if there. If any of
input users are not part of ACL users, they are simply ignored.
If input project_access flag is None, then no change is made in
existing project access behavior.
:returns: List of objects for valid entity_ref
:rtype: :class:`barbicanclient.acls.SecretACL` or
:class:`barbicanclient.acls.ContainerACL`
:raises barbicanclient.exceptions.HTTPAuthError: 401 Responses
:raises barbicanclient.exceptions.HTTPClientError: 4xx Responses
:raises barbicanclient.exceptions.HTTPServerError: 5xx Responses
"""
input_entity = self.create_acl_entity_from_args(
self.app.client_manager.key_manager.acls, args)
server_entity = self.app.client_manager.key_manager.acls.get(
input_entity.entity_ref)
for input_acl in input_entity.operation_acls:
server_acl = server_entity.get(input_acl.operation_type)
if server_acl:
if input_acl.project_access is not None:
server_acl.project_access = input_acl.project_access
# if input data has users, then remove matching one
# from server acl users
if input_acl.users is not None:
acl_users = server_acl.users
acl_users = set(acl_users).difference(input_acl.users)
del server_acl.users[:]
server_acl.users = acl_users
server_entity.submit() # apply changes to server
server_entity.load_acls_data()
return self.get_acls_as_lister(server_entity)

View File

@ -18,8 +18,10 @@ import six
from oslo_utils.timeutils import parse_isotime
from barbicanclient import acls as acl_manager
from barbicanclient import base
from barbicanclient import formatter
from barbicanclient import secrets as secret_manager
@ -92,6 +94,8 @@ class Container(ContainerFormatter):
self._created = None
self._updated = None
self._status = None
self._acl_manager = acl_manager.ACLManager(api)
self._acls = None
def _initialize_secrets(self, secrets):
try:
@ -138,6 +142,13 @@ class Container(ContainerFormatter):
self._reload()
return self._status
@property
def acls(self):
"""Get ACL settings for this container."""
if self._container_ref and not self._acls:
self._acls = self._acl_manager.get(self.container_ref)
return self._acls
@property
def secret_refs(self):
if self._cached_secrets:

View File

@ -19,6 +19,7 @@ import logging
from oslo_utils.timeutils import parse_isotime
import six
from barbicanclient import acls as acl_manager
from barbicanclient import base
from barbicanclient import exceptions
from barbicanclient import formatter
@ -109,6 +110,8 @@ class Secret(SecretFormatter):
status=status,
creator_id=creator_id
)
self._acl_manager = acl_manager.ACLManager(api)
self._acls = None
@property
def secret_ref(self):
@ -192,6 +195,13 @@ class Secret(SecretFormatter):
return None
return self._payload
@property
def acls(self):
"""Get ACL settings for this secret."""
if self.secret_ref and not self._acls:
self._acls = self._acl_manager.get(self.secret_ref)
return self._acls
@name.setter
@immutable_after_save
def name(self, value):

View File

@ -18,6 +18,7 @@ import json
import mock
from oslo_utils import timeutils
from barbicanclient import acls
from barbicanclient.tests import test_client
from barbicanclient import base, containers, secrets
@ -520,3 +521,28 @@ class WhenTestingContainers(test_client.BaseEntityResource):
self.responses.get(self.entity_base, json={'total': 1})
total = self.manager.total()
self.assertEqual(total, 1)
def test_should_get_acls_lazy(self):
data = self.container.get_dict(self.entity_href,
consumers=[self.container.consumer])
m = self.responses.get(self.entity_href, json=data)
acl_data = {'read': {'project-access': True, 'users': ['u2']}}
acl_ref = self.entity_href + '/acl'
n = self.responses.get(acl_ref, json=acl_data)
container = self.manager.get(container_ref=self.entity_href)
self.assertIsNotNone(container)
self.assertEqual(self.container.name, container.name)
# Verify GET was called for secret but for acl it was not called
self.assertTrue(m.called)
self.assertFalse(n.called)
# Check an attribute to trigger lazy-load
self.assertEqual(['u2'], container.acls.read.users)
self.assertTrue(container.acls.read.project_access)
self.assertIsInstance(container.acls, acls.ContainerACL)
# Verify the correct URL was used to make the GET call
self.assertEqual(acl_ref, n.last_request.url)

View File

@ -18,6 +18,7 @@ import json
from oslo_utils import timeutils
from barbicanclient.tests import test_client
from barbicanclient import acls
from barbicanclient import secrets, base, exceptions
@ -235,6 +236,30 @@ class WhenTestingSecrets(test_client.BaseEntityResource):
# Verify the correct URL was used to make the GET call
self.assertEqual(self.entity_href, m.last_request.url)
def test_should_get_acls_lazy(self):
data = self.secret.get_dict(self.entity_href)
m = self.responses.get(self.entity_href, json=data)
acl_data = {'read': {'project-access': True, 'users': ['u1']}}
acl_ref = self.entity_href + '/acl'
n = self.responses.get(acl_ref, json=acl_data)
secret = self.manager.get(secret_ref=self.entity_href)
self.assertIsNotNone(secret)
self.assertEqual(self.secret.name, secret.name)
# Verify GET was called for secret but for acl it was not called
self.assertTrue(m.called)
self.assertFalse(n.called)
# Check an attribute to trigger lazy-load
self.assertEqual(['u1'], secret.acls.read.users)
self.assertTrue(secret.acls.read.project_access)
self.assertIsInstance(secret.acls, acls.SecretACL)
# Verify the correct URL was used to make the GET call
self.assertEqual(acl_ref, n.last_request.url)
def test_should_get_payload_only_when_content_type_is_set(self):
"""
DEPRECATION WARNING:

View File

@ -26,8 +26,8 @@ If you don't have variables saved to your environment or you wish to use
different credentials than those defined, any of the optional arguments listed
above may be passed to Barbican.
Barbican takes a positional argument <entity>, which specifies whether you
wish to operate on a secret or an order.
Barbican takes a positional argument <entity>, which specifies whether you wish
to operate on a secret or an order.
Secrets
-------
@ -36,9 +36,9 @@ Secrets
$ barbican secret <action>
A subcommand describing the action to be performed should follow.
The subcommands are mostly the same for secrets and orders, although some
optional arguments only apply to one or the other.
A subcommand describing the action to be performed should follow. The
subcommands are mostly the same for secrets and orders, although some optional
arguments only apply to one or the other.
Subcommand actions that a user can take for secrets are:
@ -179,3 +179,265 @@ Secret List
+-----------------------------------------------------------------------+------+----------------------------------+--------+-------------------------------------------+-----------+------------+------+------------+
| http://localhost:9311/v1/secrets/bb3d8c20-8ea5-4bfc-9645-c8da79c8b371 | None | 2015-04-15 20:37:37.501475+00:00 | ACTIVE | {u'default': u'application/octet-stream'} | aes | 256 | cbc | None |
+-----------------------------------------------------------------------+------+----------------------------------+--------+-------------------------------------------+-----------+------------+------+------------+
ACLS
----
.. code-block:: bash
$ barbican acl <action>
A subcommand describing the action to be performed should follow. The
subcommands are mostly the same for secret and container ACLs.
Subcommand actions that a user can take for ACLs are:
.. code-block:: bash
acl delete Delete ACLs for a secret or container as identified by its href.
acl get Retrieve ACLs for a secret or container by providing its href.
acl submit Submit ACL on a secret or container as identified by its href.
acl user add Add ACL users to a secret or container as identified by its href.
acl user remove Remove ACL users from a secret or container as identified by its href.
ACL **get** or **delete** subcommand, only takes secret or container href. All
other ACL commands take additional arguments to specify ACL settings data.
Please see help message for both cases of argument. Either secret ref or
container ref is required for all of acl actions.
.. code-block:: bash
$ barbican help acl get
usage: barbican acl get [-h] [-f {csv,table,value}] [-c COLUMN]
[--max-width <integer>]
[--quote {all,minimal,none,nonnumeric}]
URI
Retrieve ACLs for a secret or container by providing its href.
positional arguments:
URI The URI reference for the secret or container.
optional arguments:
-h, --help show this help message and exit
output formatters:
output formatter options
-f {csv,table,value}, --format {csv,table,value}
the output format, defaults to table
-c COLUMN, --column COLUMN
specify the column(s) to include, can be repeated
table formatter:
--max-width <integer>
Maximum display width, 0 to disable
CSV Formatter:
--quote {all,minimal,none,nonnumeric}
when to include quotes, defaults to nonnumeric
Following is snippet of related command line options for an ACL modify action
e.g. submit, add or remove.
.. code-block:: bash
$ barbican help acl submit/user add/user remove
usage: barbican acl submit [-h] [-f {csv,table,value}] [-c COLUMN]
[--max-width <integer>]
[--quote {all,minimal,none,nonnumeric}]
[--user [USER]]
[--project-access | --no-project-access]
[--operation-type {read}]
URI
....
....
positional arguments:
URI The URI reference for the secret or container.
optional arguments:
-h, --help show this help message and exit
--user [USER], -u [USER]
Keystone userid(s) for ACL.
--project-access Flag to enable project access behavior.
--no-project-access Flag to disable project access behavior.
--operation-type {read}, -o {read}
Type of Barbican operation ACL is set for
....
....
.. note::
Default for ``operation-type`` argument is 'read' as that's the only operation
currently supported by Barbican ACL API. So this argument can be skipped in
CLI call.
ACLs Get
~~~~~~~~
To get complete ACL setting for a secret or container, use this ACL action.
.. code-block:: bash
$ barbican acl get http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| read | False | [u'721e27b8505b499e8ab3b38154705b9e', u'2d0ee7c681cc4549b6d76769c320d91f'] | 2015-07-21 17:52:01.729370+00:00 | 2015-07-28 02:08:02.455276+00:00 | http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213/acl |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
$ barbican acl get http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Container ACL Ref |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| read | False | [u'2d0ee7c681cc4549b6d76769c320d91f'] | 2015-07-28 01:36:55.791381+00:00 | 2015-07-28 02:05:41.175386+00:00 | http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19/acl |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
Secret or container ref is required. If missing, it will result in error.
.. code-block:: bash
$ barbican acl get
usage: barbican acl get [-h] [-f {csv,table,value}] [-c COLUMN]
[--max-width <integer>]
[--quote {all,minimal,none,nonnumeric}]
URI
barbican acl get: error: too few arguments
ACLs Submit
~~~~~~~~~~~
To submit complete ACL setting for a secret or container, use this ACL action.
.. code-block:: bash
$ barbican acl submit --user 2d0ee7c681cc4549b6d76769c320d91f --user 721e27b8505b499e8ab3b38154705b9e http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| read | True | [u'721e27b8505b499e8ab3b38154705b9e', u'2d0ee7c681cc4549b6d76769c320d91f'] | 2015-07-21 17:52:01.729370+00:00 | 2015-08-12 09:53:20.225971+00:00 | http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213/acl |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
If ``user`` argument is missing or has no value, then empty list is passed for
users and this approach can be used to remove existing ACL users. If project
access argument is not provided, then by default project access is enabled. To
disable project access behavior, just pass ``no-project-access`` argument
without any value.
.. code-block:: bash
$ barbican acl submit --user --no-project-access http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213
+----------------+----------------+-------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+-------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| read | False | [] | 2015-07-21 17:52:01.729370+00:00 | 2015-08-12 09:55:23.043433+00:00 | http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213/acl |
+----------------+----------------+-------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
$ barbican acl submit --user 2d0ee7c681cc4549b6d76769c320d91f --no-project-access http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Container ACL Ref |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| read | False | [u'2d0ee7c681cc4549b6d76769c320d91f'] | 2015-07-29 22:01:00.878270+00:00 | 2015-08-19 05:56:09.930302+00:00 | http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19/acl |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
Following error is returned when both mutually exclusive flags are passed.
.. code-block:: bash
$ barbican acl submit --project-access --no-project-access http://localhost:9311/v1/secrets/7776adb8-e865-413c-8ccc-4f09c3fe0213
usage: barbican acl submit [-h] [-f {csv,table,value}] [-c COLUMN]
[--max-width <integer>]
[--quote {all,minimal,none,nonnumeric}]
[--user [USER]]
[--project-access | --no-project-access]
[--operation-type {read}]
URI
barbican acl submit: error: argument --no-project-access: not allowed with argument --project-access
ACL Add User(s)
~~~~~~~~~~~~~~~
To add ACL users for a secret or container, use this ACL action.
If ``user`` argument is missing or has no value, then no change is made in ACL
users. If project access argument is not provided, then no change is made in
existing project access behavior flag.
.. code-block:: bash
$ barbican acl user add --user c1d20e4b7e7d4917aee6f0832152269b http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Container ACL Ref |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
| read | False | [u'2d0ee7c681cc4549b6d76769c320d91f', u'c1d20e4b7e7d4917aee6f0832152269b'] | 2015-07-29 22:01:00.878270+00:00 | 2015-08-12 10:08:19.129370+00:00 | http://localhost:9311/v1/containers/83c302c7-86fe-4f07-a277-c4962f121f19/acl |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+------------------------------------------------------------------------------+
.. code-block:: bash
# Added 2 users for secret (084c2098-66db-4401-8348-d969be0eddaa) earlier via set action.
$ barbican acl user add --user --no-project-access http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| read | False | [u'721e27b8505b499e8ab3b38154705b9e', u'2d0ee7c681cc4549b6d76769c320d91f'] | 2015-08-12 10:09:27.564371+00:00 | 2015-08-12 10:11:09.749980+00:00 | http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa/acl |
+----------------+----------------+----------------------------------------------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
ACL Remove User(s)
~~~~~~~~~~~~~~~~~~
To remove ACL users for a secret or container, use this ACL action.
If ``user`` argument is missing or has no value, then no change is made in ACL
users. If project access argument is not provided, then no change is made in
existing project access behavior flag.
If provided userid(s) does not exist in ACL, it is simply ignored and only
existing userid(s) are removed from ACL.
.. code-block:: bash
$ barbican acl user remove --user 2d0ee7c681cc4549b6d76769c320d91f --user invalid_user_id http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
| read | False | [u'721e27b8505b499e8ab3b38154705b9e'] | 2015-08-12 10:09:27.564371+00:00 | 2015-08-12 10:12:21.842888+00:00 | http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa/acl |
+----------------+----------------+---------------------------------------+----------------------------------+----------------------------------+---------------------------------------------------------------------------+
ACLs Delete
~~~~~~~~~~~
To delete existing ACL setting for a secret or container, use this ACL action.
.. code-block:: bash
$ barbican acl delete http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa
$ barbican acl get http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa
+----------------+----------------+-------+---------+---------+---------------------------------------------------------------------------+
| Operation Type | Project Access | Users | Created | Updated | Secret ACL Ref |
+----------------+----------------+-------+---------+---------+---------------------------------------------------------------------------+
| read | True | [] | None | None | http://localhost:9311/v1/secrets/084c2098-66db-4401-8348-d969be0eddaa/acl |
+----------------+----------------+-------+---------+---------+---------------------------------------------------------------------------+

View File

@ -56,6 +56,20 @@ Certificate Authorities
.. autoclass:: barbicanclient.cas.CA
:members:
ACLs
====
.. autoclass:: barbicanclient.acls.ACLManager
:members:
.. autoclass:: barbicanclient.acls.SecretACL
:members:
:inherited-members:
.. autoclass:: barbicanclient.acls.ContainerACL
:members:
:inherited-members:
Exceptions
==========

View File

@ -6,9 +6,9 @@ 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.
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.
@ -25,10 +25,11 @@ 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.
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::
@ -52,8 +53,9 @@ Example::
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.
The secret reference returned by
:meth:`barbicanclient.secrets.SecretManager.store` can later be used to
retrieve the secret data from barbican.
Example::
@ -65,17 +67,17 @@ Example::
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
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 Type | Python 2 Type | Python 3 Type | Barbican Content Type |
+=================+===============+===============+==========================+
| six.binary_type | str | bytes | application/octet-stream |
| six.binary_type | str | bytes | application/octet-stream |
+-----------------+---------------+---------------+--------------------------+
| six.text_type | unicode | str | text/plain |
| six.text_type | unicode | str | text/plain |
+-----------------+---------------+---------------+--------------------------+
.. WARNING::
@ -94,8 +96,8 @@ 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`.
:class:`barbicanclient.orders.OrderManager` instance in the `orders` attribute
of the `Client`.
Example::
@ -112,8 +114,8 @@ Example::
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.
The order reference returned by :meth:`barbicanclient.orders.Order.submit` can
later be used to retrieve the order from Barbican.
Example::
@ -121,8 +123,8 @@ Example::
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
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::
@ -133,17 +135,19 @@ Example::
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.
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 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`
Containers should be managed using the
:class:`barbicanclient.containers.ContainerManager` instance in the
`containers` attribute of the `Client`
Example::
@ -156,8 +160,9 @@ Example::
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.
The container reference returned by
:meth:`barbicanclient.containers.Container.store` can later be used to
retrieve the container from Barbican.
Example::
@ -165,3 +170,165 @@ Example::
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::
# 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::
# 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::
# 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::
# 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::
# 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::
# 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()

View File

@ -51,6 +51,12 @@ openstack.key_manager.v1 =
ca_get = barbicanclient.barbican_cli.cas:GetCA
ca_list = barbicanclient.barbican_cli.cas:ListCA
acl_delete = barbicanclient.barbican_cli.acls:DeleteACLs
acl_get = barbicanclient.barbican_cli.acls:GetACLs
acl_submit = barbicanclient.barbican_cli.acls:SubmitACL
acl_user_add = barbicanclient.barbican_cli.acls:AddACLUsers
acl_user_remove = barbicanclient.barbican_cli.acls:RemoveACLUsers
[build_sphinx]
source-dir = doc/source
build-dir = doc/build