From 154cf13765d001e07fec6706205b3fccf3143ff8 Mon Sep 17 00:00:00 2001 From: Pino de Candia <32303022+pinodeca@users.noreply.github.com> Date: Mon, 29 Jan 2018 23:47:44 +0200 Subject: [PATCH] Added commands to print user/host certificate data. --- .zuul.yaml | 1 + setup.cfg | 6 +++++- tatuclient/client.py | 1 + tatuclient/utils.py | 28 ++++++++++++++++------------ tatuclient/v1/cli/ca.py | 23 +++++++++++++++++++++-- tatuclient/v1/cli/hostcert.py | 19 +++++++++++++++---- tatuclient/v1/cli/usercert.py | 23 +++++++++++++++++------ 7 files changed, 76 insertions(+), 25 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 0ab2597..29b375a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,3 +1,4 @@ - project: + name: openstack/python-tatuclient templates: - tatu-devstack-jobs diff --git a/setup.cfg b/setup.cfg index c9ba355..24b0f01 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ packages = [entry_points] tatuclient.versions = - 2 = tatuclient.v1.client:Client + 1 = tatuclient.v1.client:Client openstack.cli.extension = ssh = tatuclient.osc.plugin @@ -39,14 +39,18 @@ openstack.ssh.v1 = usercert_create = tatuclient.v1.cli.usercert:CreateUserCertCommand usercert_list = tatuclient.v1.cli.usercert:ListUserCertCommand usercert_show = tatuclient.v1.cli.usercert:ShowUserCertCommand + usercert_cert_show = tatuclient.v1.cli.usercert:ShowUserCertCertCommand usercert_revoke = tatuclient.v1.cli.usercert:RevokeUserCertCommand hostcert_list = tatuclient.v1.cli.hostcert:ListHostCertCommand hostcert_show = tatuclient.v1.cli.hostcert:ShowHostCertCommand + hostcert_cert_show = tatuclient.v1.cli.hostcert:ShowHostCertCertCommand sshca_create = tatuclient.v1.cli.ca:CreateCACommand sshca_list = tatuclient.v1.cli.ca:ListCACommand sshca_show = tatuclient.v1.cli.ca:ShowCACommand + sshca_user_key_show = tatuclient.v1.cli.ca:ShowCAUserKeyCommand + sshca_host_key_show = tatuclient.v1.cli.ca:ShowCAHostKeyCommand [build_sphinx] builders = html,man diff --git a/tatuclient/client.py b/tatuclient/client.py index 300afb5..e30e288 100644 --- a/tatuclient/client.py +++ b/tatuclient/client.py @@ -92,6 +92,7 @@ def get_versions(): return dict([(ep.name, ep.plugin) for ep in mgr.extensions]) +#TODO(pino): can this be removed? Is it used anywhere? def Client(version, *args, **kwargs): # noqa versions = get_versions() if version not in versions: diff --git a/tatuclient/utils.py b/tatuclient/utils.py index 7e177ec..0aba1d5 100644 --- a/tatuclient/utils.py +++ b/tatuclient/utils.py @@ -69,21 +69,25 @@ def get_item_properties(item, fields, mixed_case_fields=[], formatters={}): if field in formatters: row.append(formatters[field](item)) else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - if not hasattr(item, field_name) and \ - (isinstance(item, dict) and field_name in item): - data = item[field_name] - else: - data = getattr(item, field_name, '') - if data is None: - data = '' - row.append(data) + row.append(get_property(item, field, mixed_case_fields)) return tuple(row) +def get_item_property(item, field, mixed_case_fields=[]): + if field in mixed_case_fields: + field_name = field.replace(' ', '_') + else: + field_name = field.lower().replace(' ', '_') + if not hasattr(item, field_name) and \ + (isinstance(item, dict) and field_name in item): + data = item[field_name] + else: + data = getattr(item, field_name, '') + if data is None: + data = '' + return data + + def get_columns(data): """ Some row's might have variable count of columns, ensure that we have the diff --git a/tatuclient/v1/cli/ca.py b/tatuclient/v1/cli/ca.py index c22f507..9ef14d2 100644 --- a/tatuclient/v1/cli/ca.py +++ b/tatuclient/v1/cli/ca.py @@ -53,13 +53,32 @@ class ShowCACommand(command.ShowOne): common.add_all_common_options(parser) return parser - def take_action(self, parsed_args): + def _get_data(self, parsed_args): client = self.app.client_manager.ssh common.set_all_common_headers(client, parsed_args) - data = client.ca.get(parsed_args.auth_id) + return client.ca.get(parsed_args.auth_id) + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) return _names, utils.get_item_properties(data, _columns) +class ShowCAUserKeyCommand(ShowCACommand): + """Print the CA's unformatted public key for user certificates.""" + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) + self.app.stdout.write(utils.get_item_property(data, 'user_pub_key')) + + +class ShowCAHostKeyCommand(ShowCACommand): + """Print the CA's unformatted public key for user certificates.""" + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) + self.app.stdout.write(utils.get_item_property(data, 'host_pub_key')) + + class CreateCACommand(command.ShowOne): """Create new CA""" diff --git a/tatuclient/v1/cli/hostcert.py b/tatuclient/v1/cli/hostcert.py index 9cfff76..b62028c 100644 --- a/tatuclient/v1/cli/hostcert.py +++ b/tatuclient/v1/cli/hostcert.py @@ -24,8 +24,8 @@ from tatuclient.v1.utils import get_all LOG = logging.getLogger(__name__) -_columns = ['host_id', 'srv_url', 'pat_bastions', 'fingerprint', 'cert'] -_names = ['Instance ID', 'SRV URL', 'PAT Bastions', 'Fingerprint', 'SSH Certificate'] +_columns = ['host_id', 'srv_url', 'pat_bastions', 'fingerprint'] +_names = ['Instance ID', 'SRV URL', 'PAT Bastions', 'Fingerprint'] class ListHostCertCommand(command.Lister): @@ -53,8 +53,19 @@ class ShowHostCertCommand(command.ShowOne): common.add_all_common_options(parser) return parser - def take_action(self, parsed_args): + def _get_data(self, parsed_args): client = self.app.client_manager.ssh common.set_all_common_headers(client, parsed_args) - data = client.hostcert.get(parsed_args.host_id, parsed_args.fingerprint) + return client.hostcert.get(parsed_args.host_id, parsed_args.fingerprint) + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) return _names, utils.get_item_properties(data, _columns) + + +class ShowUserCertCertCommand(ShowUserCertCommand): + """Print the HostCert's unformatted certificate data.""" + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) + self.app.stdout.write(utils.get_item_property(data, 'cert')) diff --git a/tatuclient/v1/cli/usercert.py b/tatuclient/v1/cli/usercert.py index 892065a..676899e 100644 --- a/tatuclient/v1/cli/usercert.py +++ b/tatuclient/v1/cli/usercert.py @@ -24,8 +24,8 @@ from tatuclient.v1.utils import get_all LOG = logging.getLogger(__name__) -_columns = ['serial', 'revoked', 'user_id', 'auth_id', 'fingerprint', 'cert'] -_names = ['Serial Number', 'Revoked', 'User ID', 'Project/CA ID', 'Fingerprint', 'SSH Certificate'] +_columns = ['serial', 'revoked', 'user_id', 'auth_id', 'fingerprint'] +_names = ['Serial Number', 'Revoked', 'User ID', 'Project/CA ID', 'Fingerprint'] class ListUserCertCommand(command.Lister): @@ -52,26 +52,37 @@ class ShowUserCertCommand(command.ShowOne): common.add_all_common_options(parser) return parser - def take_action(self, parsed_args): + def _get_data(self, parsed_args): client = self.app.client_manager.ssh common.set_all_common_headers(client, parsed_args) - data = client.usercert.get(parsed_args.serial) + return client.usercert.get(parsed_args.serial) + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) return _names, utils.get_item_properties(data, _columns) +class ShowUserCertCertCommand(ShowUserCertCommand): + """Print the UserCert's unformatted certificate data.""" + + def take_action(self, parsed_args): + data = self._get_data(parsed_args) + self.app.stdout.write(utils.get_item_property(data, 'cert')) + + class CreateUserCertCommand(command.ShowOne): """Create new UserCert""" def get_parser(self, prog_name): parser = super(CreateUserCertCommand, self).get_parser(prog_name) - parser.add_argument('user_id', help="User ID") - parser.add_argument('auth_id', help="Project/CA ID") parser.add_argument('pub_key', help="Public Key") common.add_all_common_options(parser) return parser def take_action(self, parsed_args): client = self.app.client_manager.ssh + parsed_args.user_id = client.session.get_user_id() + parsed_args.auth_id = client.session.get_project_id() common.set_all_common_headers(client, parsed_args) data = client.usercert.create(parsed_args) return _names, utils.get_item_properties(data, _columns)