[NFVBENCH-129] Fix regression to work on Keystone v2
[nfvbench.git] / nfvbench / credentials.py
1 # Copyright 2016 Cisco Systems, Inc.  All rights reserved.
2 #
3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
4 #    not use this file except in compliance with the License. You may obtain
5 #    a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 #    Unless required by applicable law or agreed to in writing, software
10 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 #    License for the specific language governing permissions and limitations
13 #    under the License.
14 #
15
16 import os
17 import re
18
19 # Module for credentials in Openstack
20 import getpass
21 from keystoneauth1.identity import v2
22 from keystoneauth1.identity import v3
23 from keystoneauth1 import session
24 from keystoneclient import client
25 from keystoneclient import utils
26 from log import LOG
27
28
29 class Credentials(object):
30
31     def get_session(self):
32         dct = {
33             'username': self.rc_username,
34             'password': self.rc_password,
35             'auth_url': self.rc_auth_url
36         }
37         auth = None
38
39         if self.rc_identity_api_version == 3:
40             dct.update({
41                 'project_name': self.rc_project_name,
42                 'project_domain_name': self.rc_project_domain_name,
43                 'user_domain_name': self.rc_user_domain_name
44             })
45             auth = v3.Password(**dct)
46         else:
47             dct.update({
48                 'tenant_name': self.rc_tenant_name
49             })
50             auth = v2.Password(**dct)
51         return session.Session(auth=auth, verify=self.rc_cacert)
52
53     def __parse_openrc(self, file):
54         export_re = re.compile('export OS_([A-Z_]*)="?(.*)')
55         for line in file:
56             line = line.strip()
57             mstr = export_re.match(line)
58             if mstr:
59                 # get rif of posible trailing double quote
60                 # the first one was removed by the re
61                 name = mstr.group(1)
62                 value = mstr.group(2)
63                 if value.endswith('"'):
64                     value = value[:-1]
65                 # get rid of password assignment
66                 # echo "Please enter your OpenStack Password: "
67                 # read -sr OS_PASSWORD_INPUT
68                 # export OS_PASSWORD=$OS_PASSWORD_INPUT
69                 if value.startswith('$'):
70                     continue
71                 # Check if api version is provided
72                 # Default is keystone v2
73                 if name == 'IDENTITY_API_VERSION':
74                     self.rc_identity_api_version = int(value)
75
76                 # now match against wanted variable names
77                 elif name == 'USERNAME':
78                     self.rc_username = value
79                 elif name == 'AUTH_URL':
80                     self.rc_auth_url = value
81                 elif name == 'TENANT_NAME':
82                     self.rc_tenant_name = value
83                 elif name == "CACERT":
84                     self.rc_cacert = value
85                 elif name == "REGION_NAME":
86                     self.rc_region_name = value
87                 elif name == "PASSWORD":
88                     self.rc_password = value
89                 elif name == "USER_DOMAIN_NAME":
90                     self.rc_user_domain_name = value
91                 elif name == "PROJECT_NAME":
92                     self.rc_project_name = value
93                 elif name == "PROJECT_DOMAIN_NAME":
94                     self.rc_project_domain_name = value
95
96     #
97     # Read a openrc file and take care of the password
98     # The 2 args are passed from the command line and can be None
99     #
100     def __init__(self, openrc_file, pwd=None, no_env=False):
101         self.rc_password = None
102         self.rc_username = None
103         self.rc_tenant_name = None
104         self.rc_auth_url = None
105         self.rc_cacert = None
106         self.rc_region_name = None
107         self.rc_user_domain_name = None
108         self.rc_project_domain_name = None
109         self.rc_project_name = None
110         self.rc_identity_api_version = 2
111         self.is_admin = False
112         success = True
113
114         if openrc_file:
115             if isinstance(openrc_file, str):
116                 if os.path.exists(openrc_file):
117                     self.__parse_openrc(open(openrc_file))
118                 else:
119                     LOG.error('Error: rc file does not exist %s', openrc_file)
120                     success = False
121             else:
122                 self.__parse_openrc(openrc_file)
123         elif not no_env:
124             # no openrc file passed - we assume the variables have been
125             # sourced by the calling shell
126             # just check that they are present
127             if 'OS_IDENTITY_API_VERSION' in os.environ:
128                 self.rc_identity_api_version = int(os.environ['OS_IDENTITY_API_VERSION'])
129
130             if self.rc_identity_api_version == 2:
131                 for varname in ['OS_USERNAME', 'OS_AUTH_URL', 'OS_TENANT_NAME']:
132                     if varname not in os.environ:
133                         LOG.warning('%s is missing', varname)
134                         success = False
135                 if success:
136                     self.rc_username = os.environ['OS_USERNAME']
137                     self.rc_auth_url = os.environ['OS_AUTH_URL']
138                     self.rc_tenant_name = os.environ['OS_TENANT_NAME']
139                 if 'OS_REGION_NAME' in os.environ:
140                     self.rc_region_name = os.environ['OS_REGION_NAME']
141             elif self.rc_identity_api_version == 3:
142                 for varname in ['OS_USERNAME', 'OS_AUTH_URL', 'OS_PROJECT_NAME',
143                                 'OS_PROJECT_DOMAIN_NAME', 'OS_USER_DOMAIN_NAME']:
144                     if varname not in os.environ:
145                         LOG.warning('%s is missing', varname)
146                         success = False
147                 if success:
148                     self.rc_username = os.environ['OS_USERNAME']
149                     self.rc_auth_url = os.environ['OS_AUTH_URL']
150                     self.rc_project_name = os.environ['OS_PROJECT_NAME']
151                     self.rc_project_domain_name = os.environ['OS_PROJECT_DOMAIN_NAME']
152                     self.rc_user_domain_name = os.environ['OS_USER_DOMAIN_NAME']
153             if 'OS_CACERT' in os.environ:
154                 self.rc_cacert = os.environ['OS_CACERT']
155
156
157         # always override with CLI argument if provided
158         if pwd:
159             self.rc_password = pwd
160         # if password not know, check from env variable
161         elif self.rc_auth_url and not self.rc_password and success:
162             if 'OS_PASSWORD' in os.environ and not no_env:
163                 self.rc_password = os.environ['OS_PASSWORD']
164             else:
165                 # interactively ask for password
166                 self.rc_password = getpass.getpass(
167                     'Please enter your OpenStack Password: ')
168         if not self.rc_password:
169             self.rc_password = ""
170
171         # check if user has admin role in OpenStack project
172         try:
173             keystone = client.Client(session=self.get_session())
174             user = utils.find_resource(keystone.users, self.rc_username)
175             if self.rc_identity_api_version == 2:
176                 tenant = utils.find_resource(keystone.tenants, self.rc_tenant_name)
177                 roles = keystone.roles.roles_for_user(user, tenant=tenant.id)
178             elif self.rc_identity_api_version == 3:
179                 project = utils.find_resource(keystone.projects, self.rc_project_name)
180                 roles = keystone.roles.list(user=user.id, project=project.id)
181             for role in roles:
182                 if role.name == 'admin':
183                     self.is_admin = True
184         except Exception:
185             LOG.warning("User is not admin, no permission to list user roles")