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