Create Openstack CLI plugin for Barbican
This is the first implementation of the barbicanclient plugin for the OpenStack CLI. Since we chose to use cliff in for the client, the integration with the OCC is quite seamless. Only change that needed to be done was that, since the OCC uses a ClientManager class to fetch the specific libraries for the components, we needed to simulate that in the barbicanclient. Currently, the plugin can be used if the barbican server is configured with keystone authentication. This is because currently there is no way for us to set the X-Project-Id header manually from the client (if the plugin is being used) but that functionality is out of the scope of this first implementation. Change-Id: I37fd158af24e785bc0b7125c6b4c1a9795927a10
This commit is contained in:
committed by
Juan Antonio Osorio Robles
parent
d154ad90a8
commit
85f5ec262c
@@ -18,6 +18,7 @@ Command-line interface to the Barbican API.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from cliff import app
|
||||
from cliff import command
|
||||
@@ -52,7 +53,8 @@ class Barbican(app.App):
|
||||
super(Barbican, self).__init__(
|
||||
description=__doc__.strip(),
|
||||
version=version.__version__,
|
||||
command_manager=commandmanager.CommandManager('barbican.client'),
|
||||
command_manager=commandmanager.CommandManager(
|
||||
'openstack.key_manager.v1'),
|
||||
deferred_help=True,
|
||||
**kwargs
|
||||
)
|
||||
@@ -309,8 +311,9 @@ class Barbican(app.App):
|
||||
client interface.
|
||||
This is inherited from the framework.
|
||||
"""
|
||||
self.client_manager = namedtuple('ClientManager', 'key_manager')
|
||||
if cmd.auth_required:
|
||||
self.client = self.create_client(self.options)
|
||||
self.client_manager.key_manager = self.create_client(self.options)
|
||||
|
||||
def run(self, argv):
|
||||
# If no arguments are provided, usage is displayed
|
||||
|
||||
@@ -28,7 +28,7 @@ class GetCA(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
entity = self.app.client.cas.get(ca_ref=args.URI)
|
||||
entity = self.app.client_manager.key_manager.cas.get(ca_ref=args.URI)
|
||||
return entity._get_formatted_entity()
|
||||
|
||||
|
||||
@@ -52,5 +52,6 @@ class ListCA(lister.Lister):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
obj_list = self.app.client.cas.list(args.limit, args.offset, args.name)
|
||||
obj_list = self.app.client_manager.key_manager.cas.list(
|
||||
args.limit, args.offset, args.name)
|
||||
return cas.CA._list_objects(obj_list)
|
||||
|
||||
@@ -31,7 +31,7 @@ class DeleteContainer(command.Command):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
self.app.client.containers.delete(args.URI)
|
||||
self.app.client_manager.key_manager.containers.delete(args.URI)
|
||||
|
||||
|
||||
class GetContainer(show.ShowOne):
|
||||
@@ -43,7 +43,8 @@ class GetContainer(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
entity = self.app.client.containers.get(args.URI)
|
||||
entity = self.app.client_manager.key_manager.containers.get(
|
||||
args.URI)
|
||||
return entity._get_formatted_entity()
|
||||
|
||||
|
||||
@@ -70,8 +71,8 @@ class ListContainer(lister.Lister):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
obj_list = self.app.client.containers.list(args.limit, args.offset,
|
||||
args.name, args.type)
|
||||
obj_list = self.app.client_manager.key_manager.containers.list(
|
||||
args.limit, args.offset, args.name, args.type)
|
||||
return Container._list_objects(obj_list)
|
||||
|
||||
|
||||
@@ -93,8 +94,8 @@ class CreateContainer(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
container_type = self.app.client.containers._container_map.get(
|
||||
args.type)
|
||||
client = self.app.client_manager.key_manager
|
||||
container_type = client.containers._container_map.get(args.type)
|
||||
if not container_type:
|
||||
raise ValueError('Invalid container type specified.')
|
||||
secret_refs = CreateContainer._parse_secrets(args.secret)
|
||||
@@ -103,7 +104,7 @@ class CreateContainer(show.ShowOne):
|
||||
private_key_ref = secret_refs.get('private_key')
|
||||
private_key_pass_ref = secret_refs.get('private_key_passphrase')
|
||||
entity = RSAContainer(
|
||||
api=self.app.client.containers._api,
|
||||
api=client.containers._api,
|
||||
name=args.name,
|
||||
public_key_ref=public_key_ref,
|
||||
private_key_ref=private_key_ref,
|
||||
@@ -115,7 +116,7 @@ class CreateContainer(show.ShowOne):
|
||||
private_key_ref = secret_refs.get('private_key')
|
||||
private_key_pass_ref = secret_refs.get('private_key_passphrase')
|
||||
entity = CertificateContainer(
|
||||
api=self.app.client.containers._api,
|
||||
api=client.containers._api,
|
||||
name=args.name,
|
||||
certificate_ref=certificate_ref,
|
||||
intermediates_ref=intermediates_ref,
|
||||
@@ -123,7 +124,7 @@ class CreateContainer(show.ShowOne):
|
||||
private_key_passphrase_ref=private_key_pass_ref,
|
||||
)
|
||||
else:
|
||||
entity = container_type(api=self.app.client.containers._api,
|
||||
entity = container_type(api=client.containers._api,
|
||||
name=args.name, secret_refs=secret_refs)
|
||||
entity.store()
|
||||
return entity._get_formatted_entity()
|
||||
|
||||
@@ -73,14 +73,14 @@ class CreateOrder(show.ShowOne):
|
||||
raise ValueError(
|
||||
'Couldn\'t read request file %s.' % args.request_file)
|
||||
|
||||
entity = self.app.client.orders.create(
|
||||
entity = self.app.client_manager.key_manager.orders.create(
|
||||
name=args.name, type=args.type, subject_dn=args.subject_dn,
|
||||
request_type=args.request_type,
|
||||
source_container_ref=args.source_container_ref,
|
||||
ca_id=args.ca_id, profile=args.profile,
|
||||
request_data=request_data)
|
||||
else:
|
||||
entity = self.app.client.orders.create(
|
||||
entity = self.app.client_manager.key_manager.orders.create(
|
||||
name=args.name, type=args.type,
|
||||
payload_content_type=args.payload_content_type,
|
||||
algorithm=args.algorithm, bit_length=args.bit_length,
|
||||
@@ -98,7 +98,7 @@ class DeleteOrder(command.Command):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
self.app.client.orders.delete(args.URI)
|
||||
self.app.client_manager.key_manager.orders.delete(args.URI)
|
||||
|
||||
|
||||
class GetOrder(show.ShowOne):
|
||||
@@ -110,7 +110,8 @@ class GetOrder(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
entity = self.app.client.orders.get(order_ref=args.URI)
|
||||
entity = self.app.client_manager.key_manager.orders.get(
|
||||
order_ref=args.URI)
|
||||
return entity._get_formatted_entity()
|
||||
|
||||
|
||||
@@ -131,7 +132,8 @@ class ListOrder(lister.Lister):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
obj_list = self.app.client.orders.list(args.limit, args.offset)
|
||||
obj_list = self.app.client_manager.key_manager.orders.list(
|
||||
args.limit, args.offset)
|
||||
if not obj_list:
|
||||
return [], []
|
||||
columns = obj_list[0]._get_generic_columns()
|
||||
|
||||
@@ -29,7 +29,7 @@ class DeleteSecret(command.Command):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
self.app.client.secrets.delete(args.URI)
|
||||
self.app.client_manager.key_manager.secrets.delete(args.URI)
|
||||
|
||||
|
||||
class GetSecret(show.ShowOne):
|
||||
@@ -62,12 +62,13 @@ class GetSecret(show.ShowOne):
|
||||
|
||||
def take_action(self, args):
|
||||
if args.decrypt or args.payload:
|
||||
entity = self.app.client.secrets.get(args.URI,
|
||||
args.payload_content_type)
|
||||
entity = self.app.client_manager.key_manager.secrets.get(
|
||||
args.URI, args.payload_content_type)
|
||||
return (('Payload',),
|
||||
(entity.payload,))
|
||||
else:
|
||||
entity = self.app.client.secrets.get(secret_ref=args.URI)
|
||||
entity = self.app.client_manager.key_manager.secrets.get(
|
||||
secret_ref=args.URI)
|
||||
return entity._get_formatted_entity()
|
||||
|
||||
|
||||
@@ -82,8 +83,8 @@ class UpdateSecret(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
self.app.client.secrets.update(args.URI,
|
||||
args.payload)
|
||||
self.app.client_manager.key_manager.secrets.update(args.URI,
|
||||
args.payload)
|
||||
|
||||
|
||||
class ListSecret(lister.Lister):
|
||||
@@ -116,10 +117,9 @@ class ListSecret(lister.Lister):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
obj_list = self.app.client.secrets.list(args.limit, args.offset,
|
||||
args.name, args.mode,
|
||||
args.algorithm,
|
||||
args.bit_length)
|
||||
obj_list = self.app.client_manager.key_manager.secrets.list(
|
||||
args.limit, args.offset, args.name, args.mode, args.algorithm,
|
||||
args.bit_length)
|
||||
return secrets.Secret._list_objects(obj_list)
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ class StoreSecret(show.ShowOne):
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
entity = self.app.client.secrets.create(
|
||||
entity = self.app.client_manager.key_manager.secrets.create(
|
||||
name=args.name, payload=args.payload,
|
||||
payload_content_type=args.payload_content_type,
|
||||
payload_content_encoding=args.payload_content_encoding,
|
||||
|
||||
43
barbicanclient/osc_plugin.py
Normal file
43
barbicanclient/osc_plugin.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# 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.
|
||||
|
||||
import logging
|
||||
|
||||
from barbicanclient import client
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_API_VERSION = '1'
|
||||
API_VERSION_OPTION = 'os_key_manager_api_version'
|
||||
API_NAME = 'key_manager'
|
||||
API_VERSIONS = {
|
||||
'1': 'barbicanclient.client.Client',
|
||||
}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns a Barbican service client."""
|
||||
return client.Client(session=instance.session,
|
||||
region_name=instance._region_name)
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
"""Hook to add global options."""
|
||||
parser.add_argument('--os-key-manager-api-version',
|
||||
metavar='<key-manager-api-version>',
|
||||
default=client.env(
|
||||
'OS_KEY_MANAGER_API_VERSION',
|
||||
default=DEFAULT_API_VERSION),
|
||||
help=('Barbican API version, default=' +
|
||||
DEFAULT_API_VERSION +
|
||||
' (Env: OS_KEY_MANAGER_API_VERSION)'))
|
||||
return parser
|
||||
@@ -30,7 +30,7 @@ class ContainerBehaviors(base_behaviors.BaseBehaviors):
|
||||
|
||||
:param container_href the href to the container to delete
|
||||
"""
|
||||
argv = ['container', 'delete']
|
||||
argv = ['secret', 'container', 'delete']
|
||||
self.add_auth_and_endpoint(argv)
|
||||
argv.extend([container_href])
|
||||
|
||||
@@ -44,7 +44,7 @@ class ContainerBehaviors(base_behaviors.BaseBehaviors):
|
||||
|
||||
:return: the href to the newly created container
|
||||
"""
|
||||
argv = ['container', 'create']
|
||||
argv = ['secret', 'container', 'create']
|
||||
self.add_auth_and_endpoint(argv)
|
||||
for secret_href in secret_hrefs:
|
||||
argv.extend(['--secret', secret_href])
|
||||
@@ -64,7 +64,7 @@ class ContainerBehaviors(base_behaviors.BaseBehaviors):
|
||||
:return dict of container values, or an empty dict if the container
|
||||
is not found.
|
||||
"""
|
||||
argv = ['container', 'get']
|
||||
argv = ['secret', 'container', 'get']
|
||||
self.add_auth_and_endpoint(argv)
|
||||
argv.extend([container_href])
|
||||
|
||||
@@ -81,7 +81,7 @@ class ContainerBehaviors(base_behaviors.BaseBehaviors):
|
||||
|
||||
:return: a list of containers
|
||||
"""
|
||||
argv = ['container', 'list']
|
||||
argv = ['secret', 'container', 'list']
|
||||
|
||||
self.add_auth_and_endpoint(argv)
|
||||
stdout, stderr = self.issue_barbican_command(argv)
|
||||
|
||||
21
setup.cfg
21
setup.cfg
@@ -27,12 +27,15 @@ packages =
|
||||
console_scripts =
|
||||
barbican = barbicanclient.barbican:main
|
||||
|
||||
barbican.client =
|
||||
openstack.cli.extension =
|
||||
key_manager = barbicanclient.osc_plugin
|
||||
|
||||
order_create = barbicanclient.barbican_cli.orders:CreateOrder
|
||||
order_delete = barbicanclient.barbican_cli.orders:DeleteOrder
|
||||
order_get = barbicanclient.barbican_cli.orders:GetOrder
|
||||
order_list = barbicanclient.barbican_cli.orders:ListOrder
|
||||
openstack.key_manager.v1 =
|
||||
|
||||
secret_order_create = barbicanclient.barbican_cli.orders:CreateOrder
|
||||
secret_order_delete = barbicanclient.barbican_cli.orders:DeleteOrder
|
||||
secret_order_get = barbicanclient.barbican_cli.orders:GetOrder
|
||||
secret_order_list = barbicanclient.barbican_cli.orders:ListOrder
|
||||
|
||||
secret_delete = barbicanclient.barbican_cli.secrets:DeleteSecret
|
||||
secret_get = barbicanclient.barbican_cli.secrets:GetSecret
|
||||
@@ -40,10 +43,10 @@ barbican.client =
|
||||
secret_store = barbicanclient.barbican_cli.secrets:StoreSecret
|
||||
secret_update = barbicanclient.barbican_cli.secrets:UpdateSecret
|
||||
|
||||
container_delete = barbicanclient.barbican_cli.containers:DeleteContainer
|
||||
container_get = barbicanclient.barbican_cli.containers:GetContainer
|
||||
container_list = barbicanclient.barbican_cli.containers:ListContainer
|
||||
container_create = barbicanclient.barbican_cli.containers:CreateContainer
|
||||
secret_container_delete = barbicanclient.barbican_cli.containers:DeleteContainer
|
||||
secret_container_get = barbicanclient.barbican_cli.containers:GetContainer
|
||||
secret_container_list = barbicanclient.barbican_cli.containers:ListContainer
|
||||
secret_container_create = barbicanclient.barbican_cli.containers:CreateContainer
|
||||
|
||||
ca_get = barbicanclient.barbican_cli.cas:GetCA
|
||||
ca_list = barbicanclient.barbican_cli.cas:ListCA
|
||||
|
||||
@@ -11,6 +11,7 @@ testrepository>=0.0.18
|
||||
testtools>=1.4.0
|
||||
oslotest>=1.10.0 # Apache-2.0
|
||||
nose
|
||||
python-openstackclient>=1.5.0
|
||||
|
||||
# Documentation build requirements
|
||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
|
||||
|
||||
Reference in New Issue
Block a user