1# Licensed under the Apache License, Version 2.0 (the "License"); you may 2# not use this file except in compliance with the License. You may obtain 3# a copy of the License at 4# 5# http://www.apache.org/licenses/LICENSE-2.0 6# 7# Unless required by applicable law or agreed to in writing, software 8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10# License for the specific language governing permissions and limitations 11# under the License. 12 13"""Identity v3 EC2 Credentials action implementations""" 14 15import logging 16 17from osc_lib.command import command 18from osc_lib import exceptions 19from osc_lib import utils 20 21from openstackclient.i18n import _ 22from openstackclient.identity import common 23 24 25LOG = logging.getLogger(__name__) 26 27 28def _determine_ec2_user(parsed_args, client_manager): 29 """Determine a user several different ways. 30 31 Assumes parsed_args has user and user_domain arguments. Attempts to find 32 the user if domain scoping is provided, otherwise revert to a basic user 33 call. Lastly use the currently authenticated user. 34 35 """ 36 37 user_domain = None 38 if parsed_args.user_domain: 39 user_domain = common.find_domain(client_manager.identity, 40 parsed_args.user_domain) 41 if parsed_args.user: 42 if user_domain is not None: 43 user = utils.find_resource(client_manager.identity.users, 44 parsed_args.user, 45 domain_id=user_domain.id).id 46 else: 47 user = utils.find_resource( 48 client_manager.identity.users, 49 parsed_args.user).id 50 else: 51 # Get the user from the current auth 52 user = client_manager.auth_ref.user_id 53 return user 54 55 56class CreateEC2Creds(command.ShowOne): 57 _description = _("Create EC2 credentials") 58 59 def get_parser(self, prog_name): 60 parser = super(CreateEC2Creds, self).get_parser(prog_name) 61 parser.add_argument( 62 '--project', 63 metavar='<project>', 64 help=_('Create credentials in project ' 65 '(name or ID; default: current authenticated project)'), 66 ) 67 parser.add_argument( 68 '--user', 69 metavar='<user>', 70 help=_('Create credentials for user ' 71 '(name or ID; default: current authenticated user)'), 72 ) 73 common.add_user_domain_option_to_parser(parser) 74 common.add_project_domain_option_to_parser(parser) 75 return parser 76 77 def take_action(self, parsed_args): 78 identity_client = self.app.client_manager.identity 79 client_manager = self.app.client_manager 80 user = _determine_ec2_user(parsed_args, client_manager) 81 82 project_domain = None 83 if parsed_args.project_domain: 84 project_domain = common.find_domain(identity_client, 85 parsed_args.project_domain) 86 87 if parsed_args.project: 88 if project_domain is not None: 89 project = utils.find_resource(identity_client.projects, 90 parsed_args.project, 91 domain_id=project_domain.id).id 92 else: 93 project = utils.find_resource( 94 identity_client.projects, 95 parsed_args.project).id 96 else: 97 # Get the project from the current auth 98 project = self.app.client_manager.auth_ref.project_id 99 100 creds = identity_client.ec2.create(user, project) 101 102 info = {} 103 info.update(creds._info) 104 105 if 'tenant_id' in info: 106 info.update( 107 {'project_id': info.pop('tenant_id')} 108 ) 109 110 return zip(*sorted(info.items())) 111 112 113class DeleteEC2Creds(command.Command): 114 _description = _("Delete EC2 credentials") 115 116 def get_parser(self, prog_name): 117 parser = super(DeleteEC2Creds, self).get_parser(prog_name) 118 parser.add_argument( 119 'access_key', 120 metavar='<access-key>', 121 nargs='+', 122 help=_('Credentials access key(s)'), 123 ) 124 parser.add_argument( 125 '--user', 126 metavar='<user>', 127 help=_('Delete credentials for user (name or ID)'), 128 ) 129 common.add_user_domain_option_to_parser(parser) 130 return parser 131 132 def take_action(self, parsed_args): 133 client_manager = self.app.client_manager 134 user = _determine_ec2_user(parsed_args, client_manager) 135 result = 0 136 for i in parsed_args.access_key: 137 try: 138 client_manager.identity.ec2.delete(user, i) 139 except Exception as e: 140 result += 1 141 LOG.error(_("Failed to delete EC2 credentials with " 142 "access key '%(access_key)s': %(e)s"), 143 {'access_key': i, 'e': e}) 144 145 if result > 0: 146 total = len(parsed_args.access_key) 147 msg = (_("%(result)s of %(total)s EC2 keys failed " 148 "to delete.") % {'result': result, 'total': total}) 149 raise exceptions.CommandError(msg) 150 151 152class ListEC2Creds(command.Lister): 153 _description = _("List EC2 credentials") 154 155 def get_parser(self, prog_name): 156 parser = super(ListEC2Creds, self).get_parser(prog_name) 157 parser.add_argument( 158 '--user', 159 metavar='<user>', 160 help=_('Filter list by user (name or ID)'), 161 ) 162 common.add_user_domain_option_to_parser(parser) 163 return parser 164 165 def take_action(self, parsed_args): 166 client_manager = self.app.client_manager 167 user = _determine_ec2_user(parsed_args, client_manager) 168 169 columns = ('access', 'secret', 'tenant_id', 'user_id') 170 column_headers = ('Access', 'Secret', 'Project ID', 'User ID') 171 data = client_manager.identity.ec2.list(user) 172 173 return (column_headers, 174 (utils.get_item_properties( 175 s, columns, 176 formatters={}, 177 ) for s in data)) 178 179 180class ShowEC2Creds(command.ShowOne): 181 _description = _("Display EC2 credentials details") 182 183 def get_parser(self, prog_name): 184 parser = super(ShowEC2Creds, self).get_parser(prog_name) 185 parser.add_argument( 186 'access_key', 187 metavar='<access-key>', 188 help=_('Credentials access key'), 189 ) 190 parser.add_argument( 191 '--user', 192 metavar='<user>', 193 help=_('Show credentials for user (name or ID)'), 194 ) 195 common.add_user_domain_option_to_parser(parser) 196 return parser 197 198 def take_action(self, parsed_args): 199 client_manager = self.app.client_manager 200 user = _determine_ec2_user(parsed_args, client_manager) 201 creds = client_manager.identity.ec2.get(user, parsed_args.access_key) 202 203 info = {} 204 info.update(creds._info) 205 206 if 'tenant_id' in info: 207 info.update( 208 {'project_id': info.pop('tenant_id')} 209 ) 210 211 return zip(*sorted(info.items())) 212