summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Pavlov <andrey.mp@gmail.com>2016-09-14 10:23:21 +0300
committerAndrey Pavlov <andrey.mp@gmail.com>2016-09-16 17:20:55 +0300
commitd67adb7223d6b1a9fbfb8f84b4a2e48c87ae4d6f (patch)
tree3e8567f768a9293eee54f7e934649142adc3576c
parent590ff04f076c706f833c775bd632ed03482e05b9 (diff)
rework creating admin context - use keystoneauth1 lib
rather than own creator of session and auth_plugin from keystoneclient library. Change-Id: Id7f71e08de13e77586832f6d12cba1caff3772fe
Notes
Notes (review): Code-Review+2: Feodor Tersin <ftersin@hotmail.com> Workflow+1: Feodor Tersin <ftersin@hotmail.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Mon, 19 Sep 2016 13:41:08 +0000 Reviewed-on: https://review.openstack.org/368475 Project: openstack/ec2-api Branch: refs/heads/master
-rwxr-xr-xdevstack/plugin.sh6
-rw-r--r--ec2api/api/__init__.py4
-rw-r--r--ec2api/clients.py67
-rw-r--r--ec2api/opts.py24
-rw-r--r--ec2api/tests/unit/test_context.py45
-rw-r--r--etc/ec2api/ec2api-config-generator.conf1
-rwxr-xr-xinstall.sh17
-rw-r--r--requirements.txt1
-rw-r--r--setup.cfg1
9 files changed, 139 insertions, 27 deletions
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
index 407bb49..64d74a5 100755
--- a/devstack/plugin.sh
+++ b/devstack/plugin.sh
@@ -28,6 +28,7 @@ EC2API_CONF_DIR=${EC2API_CONF_DIR:-/etc/ec2api}
28EC2API_CONF_FILE=${EC2API_CONF_DIR}/ec2api.conf 28EC2API_CONF_FILE=${EC2API_CONF_DIR}/ec2api.conf
29EC2API_DEBUG=${EC2API_DEBUG:-True} 29EC2API_DEBUG=${EC2API_DEBUG:-True}
30EC2API_STATE_PATH=${EC2API_STATE_PATH:=$DATA_DIR/ec2api} 30EC2API_STATE_PATH=${EC2API_STATE_PATH:=$DATA_DIR/ec2api}
31EC2API_AUTH_CACHE_DIR=${EC2API_AUTH_CACHE_DIR:-/var/cache/ec2api}
31 32
32EC2API_SERVICE_PORT=${EC2API_SERVICE_PORT:-8788} 33EC2API_SERVICE_PORT=${EC2API_SERVICE_PORT:-8788}
33EC2API_S3_SERVICE_PORT=${EC2API_S3_SERVICE_PORT:-3334} 34EC2API_S3_SERVICE_PORT=${EC2API_S3_SERVICE_PORT:-3334}
@@ -178,12 +179,9 @@ function configure_ec2api {
178 # ec2api Api Configuration 179 # ec2api Api Configuration
179 #------------------------- 180 #-------------------------
180 181
181 iniset $EC2API_CONF_FILE DEFAULT admin_tenant_name $SERVICE_TENANT_NAME 182 configure_auth_token_middleware $EC2API_CONF_FILE $EC2API_ADMIN_USER $EC2API_AUTH_CACHE_DIR
182 iniset $EC2API_CONF_FILE DEFAULT admin_user $EC2API_ADMIN_USER
183 iniset $EC2API_CONF_FILE DEFAULT admin_password $SERVICE_PASSWORD
184 183
185 iniset $EC2API_CONF_FILE DEFAULT ec2api_workers "$API_WORKERS" 184 iniset $EC2API_CONF_FILE DEFAULT ec2api_workers "$API_WORKERS"
186 iniset $EC2API_CONF_FILE DEFAULT keystone_url "$KEYSTONE_SERVICE_URI"
187 iniset $EC2API_CONF_FILE DEFAULT keystone_ec2_tokens_url "$KEYSTONE_SERVICE_URI_V3/ec2tokens" 185 iniset $EC2API_CONF_FILE DEFAULT keystone_ec2_tokens_url "$KEYSTONE_SERVICE_URI_V3/ec2tokens"
188 iniset $EC2API_CONF_FILE DEFAULT region_list "$REGION_NAME" 186 iniset $EC2API_CONF_FILE DEFAULT region_list "$REGION_NAME"
189 187
diff --git a/ec2api/api/__init__.py b/ec2api/api/__init__.py
index 06fe893..d783b47 100644
--- a/ec2api/api/__init__.py
+++ b/ec2api/api/__init__.py
@@ -47,6 +47,10 @@ LOG = logging.getLogger(__name__)
47ec2_opts = [ 47ec2_opts = [
48 cfg.StrOpt('keystone_url', 48 cfg.StrOpt('keystone_url',
49 default='http://localhost:5000/', 49 default='http://localhost:5000/',
50 deprecated_for_removal=True,
51 deprecated_reason='code was switched to common section '
52 '"keystone_authtoken"',
53 deprecated_since='Newton',
50 help='URL for getting admin session.'), 54 help='URL for getting admin session.'),
51 cfg.StrOpt('keystone_ec2_tokens_url', 55 cfg.StrOpt('keystone_ec2_tokens_url',
52 default='http://localhost:5000/v3/ec2tokens', 56 default='http://localhost:5000/v3/ec2tokens',
diff --git a/ec2api/clients.py b/ec2api/clients.py
index 9334553..6703dea 100644
--- a/ec2api/clients.py
+++ b/ec2api/clients.py
@@ -14,6 +14,7 @@
14 14
15from cinderclient import client as cinderclient 15from cinderclient import client as cinderclient
16from glanceclient import client as glanceclient 16from glanceclient import client as glanceclient
17from keystoneauth1 import loading as ks_loading
17from keystoneclient.auth.identity.generic import password as keystone_auth 18from keystoneclient.auth.identity.generic import password as keystone_auth
18from keystoneclient import client as keystoneclient 19from keystoneclient import client as keystoneclient
19from keystoneclient import session as keystone_session 20from keystoneclient import session as keystone_session
@@ -31,8 +32,16 @@ logger = logging.getLogger(__name__)
31ec2_opts = [ 32ec2_opts = [
32 cfg.BoolOpt('ssl_insecure', 33 cfg.BoolOpt('ssl_insecure',
33 default=False, 34 default=False,
35 deprecated_for_removal=True,
36 deprecated_reason='code was switched to common section '
37 '"keystone_authtoken"',
38 deprecated_since='Newton',
34 help="Verify HTTPS connections."), 39 help="Verify HTTPS connections."),
35 cfg.StrOpt('ssl_ca_file', 40 cfg.StrOpt('ssl_ca_file',
41 deprecated_for_removal=True,
42 deprecated_reason='code was switched to common section '
43 '"keystone_authtoken"',
44 deprecated_since='Newton',
36 help="CA certificate file to use to verify " 45 help="CA certificate file to use to verify "
37 "connecting clients"), 46 "connecting clients"),
38 cfg.StrOpt('nova_service_type', 47 cfg.StrOpt('nova_service_type',
@@ -45,20 +54,34 @@ ec2_opts = [
45 default='volumev2', 54 default='volumev2',
46 help='Service type of Volume API, registered in Keystone ' 55 help='Service type of Volume API, registered in Keystone '
47 'catalog.'), 56 'catalog.'),
48 # TODO(andrey-mp): keystone v3 allows to pass domain_name
49 # or domain_id to auth. This code should support this feature.
50 cfg.StrOpt('admin_user', 57 cfg.StrOpt('admin_user',
58 deprecated_for_removal=True,
59 deprecated_reason='code was switched to common section '
60 '"keystone_authtoken"',
61 deprecated_since='Newton',
51 help=_("Admin user to access specific cloud resourses")), 62 help=_("Admin user to access specific cloud resourses")),
52 cfg.StrOpt('admin_password', 63 cfg.StrOpt('admin_password',
64 deprecated_for_removal=True,
65 deprecated_reason='code was switched to common section '
66 '"keystone_authtoken"',
67 deprecated_since='Newton',
53 help=_("Admin password"), 68 help=_("Admin password"),
54 secret=True), 69 secret=True),
55 cfg.StrOpt('admin_tenant_name', 70 cfg.StrOpt('admin_tenant_name',
71 deprecated_for_removal=True,
72 deprecated_reason='code was switched to common section '
73 '"keystone_authtoken"',
74 deprecated_since='Newton',
56 help=_("Admin tenant name")), 75 help=_("Admin tenant name")),
57] 76]
58 77
59CONF = cfg.CONF 78CONF = cfg.CONF
60CONF.register_opts(ec2_opts) 79CONF.register_opts(ec2_opts)
61 80
81GROUP_AUTHTOKEN = 'keystone_authtoken'
82ks_loading.register_session_conf_options(CONF, GROUP_AUTHTOKEN)
83ks_loading.register_auth_conf_options(CONF, GROUP_AUTHTOKEN)
84
62 85
63# Nova API version with microversions support 86# Nova API version with microversions support
64REQUIRED_NOVA_API_VERSION = '2.1' 87REQUIRED_NOVA_API_VERSION = '2.1'
@@ -106,8 +129,8 @@ def cinder(context):
106 129
107 130
108def keystone(context): 131def keystone(context):
109 auth_url = context.session.get_endpoint(service_type='identity') 132 url = context.session.get_endpoint(service_type='identity')
110 return keystoneclient.Client(auth_url=auth_url, 133 return keystoneclient.Client(auth_url=url,
111 session=context.session) 134 session=context.session)
112 135
113 136
@@ -202,27 +225,41 @@ class _rpc_RequestContextSerializer(messaging.NoOpSerializer):
202_admin_session = None 225_admin_session = None
203 226
204 227
228def get_session_from_deprecated():
229 auth = keystone_auth.Password(
230 username=CONF.admin_user,
231 password=CONF.admin_password,
232 project_name=CONF.admin_tenant_name,
233 tenant_name=CONF.admin_tenant_name,
234 auth_url=CONF.keystone_url,
235 )
236 params = {'auth': auth}
237 update_request_params_with_ssl(params)
238 return keystone_session.Session(**params)
239
240
205def get_os_admin_session(): 241def get_os_admin_session():
206 """Create a context to interact with OpenStack as an administrator.""" 242 """Create a context to interact with OpenStack as an administrator."""
207 # NOTE(ft): this is a singletone because keystone's session looks thread 243 # NOTE(ft): this is a singletone because keystone's session looks thread
208 # safe for both regular and token renewal requests 244 # safe for both regular and token renewal requests
209 global _admin_session 245 global _admin_session
210 if not _admin_session: 246 if not _admin_session:
211 auth = keystone_auth.Password( 247 if not CONF[GROUP_AUTHTOKEN].auth_type:
212 username=CONF.admin_user, 248 _admin_session = get_session_from_deprecated()
213 password=CONF.admin_password, 249 else:
214 project_name=CONF.admin_tenant_name, 250 auth_plugin = ks_loading.load_auth_from_conf_options(
215 tenant_name=CONF.admin_tenant_name, 251 CONF, GROUP_AUTHTOKEN)
216 auth_url=CONF.keystone_url, 252 _admin_session = ks_loading.load_session_from_conf_options(
217 ) 253 CONF, GROUP_AUTHTOKEN, auth=auth_plugin)
218 params = {'auth': auth}
219 update_request_params_with_ssl(params)
220 _admin_session = keystone_session.Session(**params)
221 254
222 return _admin_session 255 return _admin_session
223 256
224 257
225def update_request_params_with_ssl(params): 258def update_request_params_with_ssl(params):
226 verify = CONF.ssl_ca_file or not CONF.ssl_insecure 259 if not CONF[GROUP_AUTHTOKEN].auth_type:
260 verify = CONF.ssl_ca_file or not CONF.ssl_insecure
261 else:
262 verify = (CONF[GROUP_AUTHTOKEN].cafile or
263 not CONF[GROUP_AUTHTOKEN].insecure)
227 if verify is not True: 264 if verify is not True:
228 params['verify'] = verify 265 params['verify'] = verify
diff --git a/ec2api/opts.py b/ec2api/opts.py
index d8014e3..775078a 100644
--- a/ec2api/opts.py
+++ b/ec2api/opts.py
@@ -11,6 +11,10 @@
11# limitations under the License. 11# limitations under the License.
12 12
13import itertools 13import itertools
14import operator
15
16from keystoneauth1 import loading as ks_loading
17from oslo_config import cfg
14 18
15import ec2api.clients 19import ec2api.clients
16import ec2api.db.api 20import ec2api.db.api
@@ -21,6 +25,9 @@ import ec2api.utils
21import ec2api.wsgi 25import ec2api.wsgi
22 26
23 27
28CONF = cfg.CONF
29
30
24def list_opts(): 31def list_opts():
25 return [ 32 return [
26 ('DEFAULT', 33 ('DEFAULT',
@@ -34,3 +41,20 @@ def list_opts():
34 ec2api.wsgi.wsgi_opts, 41 ec2api.wsgi.wsgi_opts,
35 )), 42 )),
36 ] 43 ]
44
45
46GROUP_AUTHTOKEN = 'keystone_authtoken'
47
48
49def list_auth_opts():
50 opt_list = ks_loading.register_session_conf_options(CONF, GROUP_AUTHTOKEN)
51 opt_list.insert(0, ks_loading.get_auth_common_conf_options()[0])
52 # NOTE(mhickey): There are a lot of auth plugins, we just generate
53 # the config options for a few common ones
54 plugins = ['password', 'v2password', 'v3password']
55 for name in plugins:
56 for plugin_option in ks_loading.get_auth_plugin_conf_options(name):
57 if all(option.name != plugin_option.name for option in opt_list):
58 opt_list.append(plugin_option)
59 opt_list.sort(key=operator.attrgetter('name'))
60 return [(GROUP_AUTHTOKEN, opt_list)]
diff --git a/ec2api/tests/unit/test_context.py b/ec2api/tests/unit/test_context.py
index adc4ae9..a007e2f 100644
--- a/ec2api/tests/unit/test_context.py
+++ b/ec2api/tests/unit/test_context.py
@@ -20,22 +20,59 @@ from oslo_config import fixture as config_fixture
20from oslo_context import context 20from oslo_context import context
21from oslotest import base as test_base 21from oslotest import base as test_base
22 22
23from ec2api import clients
23from ec2api import context as ec2_context 24from ec2api import context as ec2_context
24 25
26
25cfg.CONF.import_opt('keystone_url', 'ec2api.api') 27cfg.CONF.import_opt('keystone_url', 'ec2api.api')
28GROUP_AUTHTOKEN = 'keystone_authtoken'
26 29
27 30
28class ContextTestCase(test_base.BaseTestCase): 31class ContextTestCase(test_base.BaseTestCase):
29 32
30 def setUp(self): 33 @mock.patch('keystoneauth1.loading.load_auth_from_conf_options')
31 super(ContextTestCase, self).setUp() 34 @mock.patch('keystoneauth1.loading.load_session_from_conf_options')
35 def test_get_os_admin_context(self, session, auth):
36 conf = config_fixture.Config()
37 clients._admin_session = None
38 conf.config(auth_type='fake', group=GROUP_AUTHTOKEN)
39
40 imp.reload(ec2_context)
41 # NOTE(ft): initialize a regular context to populate oslo_context's
42 # local storage to prevent admin context to populate it.
43 # Used to implicitly validate overwrite=False argument of the call
44 # RequestContext constructor from inside get_os_admin_context
45 if not context.get_current():
46 ec2_context.RequestContext(None, None)
47
48 ctx = ec2_context.get_os_admin_context()
49 conf = cfg.CONF
50 auth.assert_called_once_with(conf, GROUP_AUTHTOKEN)
51 auth_plugin = auth.return_value
52 session.assert_called_once_with(conf, GROUP_AUTHTOKEN,
53 auth=auth_plugin)
54 self.assertIsNone(ctx.user_id)
55 self.assertIsNone(ctx.project_id)
56 self.assertIsNone(ctx.auth_token)
57 self.assertEqual([], ctx.service_catalog)
58 self.assertTrue(ctx.is_os_admin)
59 self.assertIsNotNone(ctx.session)
60 self.assertIsNotNone(ctx.session.auth)
61 self.assertNotEqual(context.get_current(), ctx)
62
63 session.reset_mock()
64 ec2_context.get_os_admin_context()
65 self.assertFalse(session.called)
66
67 @mock.patch('keystoneclient.auth.identity.generic.password.Password')
68 def test_get_os_admin_context_deprecated(self, password_plugin):
32 conf = config_fixture.Config() 69 conf = config_fixture.Config()
70 clients._admin_session = None
71 conf.config(auth_type=None, group=GROUP_AUTHTOKEN)
33 conf.config(admin_user='admin', 72 conf.config(admin_user='admin',
34 admin_password='password', 73 admin_password='password',
35 admin_tenant_name='service') 74 admin_tenant_name='service')
36 75
37 @mock.patch('keystoneclient.auth.identity.generic.password.Password')
38 def test_get_os_admin_context(self, password_plugin):
39 imp.reload(ec2_context) 76 imp.reload(ec2_context)
40 # NOTE(ft): initialize a regular context to populate oslo_context's 77 # NOTE(ft): initialize a regular context to populate oslo_context's
41 # local storage to prevent admin context to populate it. 78 # local storage to prevent admin context to populate it.
diff --git a/etc/ec2api/ec2api-config-generator.conf b/etc/ec2api/ec2api-config-generator.conf
index a302613..825566e 100644
--- a/etc/ec2api/ec2api-config-generator.conf
+++ b/etc/ec2api/ec2api-config-generator.conf
@@ -2,6 +2,7 @@
2output_file = etc/ec2api/ec2api.conf.sample 2output_file = etc/ec2api/ec2api.conf.sample
3wrap_width = 79 3wrap_width = 79
4namespace = ec2api 4namespace = ec2api
5namespace = keystoneauth1
5namespace = ec2api.api 6namespace = ec2api.api
6namespace = ec2api.metadata 7namespace = ec2api.metadata
7namespace = ec2api.s3 8namespace = ec2api.s3
diff --git a/install.sh b/install.sh
index 31fc781..00359db 100755
--- a/install.sh
+++ b/install.sh
@@ -4,6 +4,8 @@
4SERVICE_USERNAME=ec2api 4SERVICE_USERNAME=ec2api
5SERVICE_PASSWORD=ec2api 5SERVICE_PASSWORD=ec2api
6SERVICE_TENANT=service 6SERVICE_TENANT=service
7# this domain name will be used for project and user
8SERVICE_DOMAIN_NAME=Default
7EC2API_PORT=8788 9EC2API_PORT=8788
8CONNECTION="mysql://ec2api:ec2api@127.0.0.1/ec2api?charset=utf8" 10CONNECTION="mysql://ec2api:ec2api@127.0.0.1/ec2api?charset=utf8"
9LOG_DIR=/var/log/ec2api 11LOG_DIR=/var/log/ec2api
@@ -267,15 +269,22 @@ iniset $CONF_FILE DEFAULT api_paste_config $APIPASTE_FILE
267iniset $CONF_FILE DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s" 269iniset $CONF_FILE DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
268iniset $CONF_FILE DEFAULT log_dir "$LOG_DIR" 270iniset $CONF_FILE DEFAULT log_dir "$LOG_DIR"
269iniset $CONF_FILE DEFAULT verbose True 271iniset $CONF_FILE DEFAULT verbose True
270iniset $CONF_FILE DEFAULT keystone_url "$OS_AUTH_URL"
271iniset $CONF_FILE DEFAULT keystone_ec2_tokens_url "$OS_AUTH_URL/v3/ec2tokens" 272iniset $CONF_FILE DEFAULT keystone_ec2_tokens_url "$OS_AUTH_URL/v3/ec2tokens"
272iniset $CONF_FILE database connection "$CONNECTION" 273iniset $CONF_FILE database connection "$CONNECTION"
273iniset $CONF_FILE DEFAULT full_vpc_support "$VPC_SUPPORT" 274iniset $CONF_FILE DEFAULT full_vpc_support "$VPC_SUPPORT"
274iniset $CONF_FILE DEFAULT external_network "$EXTERNAL_NETWORK" 275iniset $CONF_FILE DEFAULT external_network "$EXTERNAL_NETWORK"
275 276
276iniset $CONF_FILE DEFAULT admin_user $SERVICE_USERNAME 277GROUP_AUTHTOKEN="keystone_authtoken"
277iniset $CONF_FILE DEFAULT admin_password $SERVICE_PASSWORD 278iniset $CONF_FILE $GROUP_AUTHTOKEN signing_dir "$AUTH_CACHE_DIR"
278iniset $CONF_FILE DEFAULT admin_tenant_name $SERVICE_TENANT 279iniset $CONF_FILE $GROUP_AUTHTOKEN auth_uri "$OS_AUTH_URL"
280iniset $CONF_FILE $GROUP_AUTHTOKEN auth_url "$OS_AUTH_URL"
281iniset $CONF_FILE $GROUP_AUTHTOKEN username $SERVICE_USERNAME
282iniset $CONF_FILE $GROUP_AUTHTOKEN password $SERVICE_PASSWORD
283iniset $CONF_FILE $GROUP_AUTHTOKEN project_name $SERVICE_TENANT
284iniset $CONF_FILE $GROUP_AUTHTOKEN project_domain_name $SERVICE_DOMAIN_NAME
285iniset $CONF_FILE $GROUP_AUTHTOKEN user_domain_name $SERVICE_DOMAIN_NAME
286iniset $CONF_FILE $GROUP_AUTHTOKEN auth_type password
287
279 288
280if [[ -f "$NOVA_CONF" ]]; then 289if [[ -f "$NOVA_CONF" ]]; then
281 # NOTE(ft): use swift instead internal s3 server if enabled 290 # NOTE(ft): use swift instead internal s3 server if enabled
diff --git a/requirements.txt b/requirements.txt
index 7da8cf8..1a79c3e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -20,6 +20,7 @@ oslo.utils>=3.16.0 # Apache-2.0
20Paste # MIT 20Paste # MIT
21PasteDeploy>=1.5.0 # MIT 21PasteDeploy>=1.5.0 # MIT
22pbr>=1.6 # Apache-2.0 22pbr>=1.6 # Apache-2.0
23keystoneauth1>=2.10.0 # Apache-2.0
23python-cinderclient!=1.7.0,!=1.7.1,>=1.6.0 # Apache-2.0 24python-cinderclient!=1.7.0,!=1.7.1,>=1.6.0 # Apache-2.0
24python-glanceclient!=2.4.0,>=2.3.0 # Apache-2.0 25python-glanceclient!=2.4.0,>=2.3.0 # Apache-2.0
25python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0 26python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index e9d3122..d5ea456 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -28,6 +28,7 @@ setup-hooks =
28oslo.config.opts = 28oslo.config.opts =
29 ec2api = ec2api.opts:list_opts 29 ec2api = ec2api.opts:list_opts
30 ec2api.api = ec2api.api.opts:list_opts 30 ec2api.api = ec2api.api.opts:list_opts
31 keystoneauth1 = ec2api.opts:list_auth_opts
31 ec2api.metadata = ec2api.metadata.opts:list_opts 32 ec2api.metadata = ec2api.metadata.opts:list_opts
32 ec2api.s3 = ec2api.s3.opts:list_opts 33 ec2api.s3 = ec2api.s3.opts:list_opts
33 34