Support shared vim for policy action execution

Change-Id: Ib58255e5b860f95b6c95c1373ee2c2e70722cd81
Co-Authored-By: Yan Xing an <yanxingan@cmss.chinamobile.com>
Implements: blueprint shared-barbican-secret
This commit is contained in:
Li Jiale 2018-07-05 20:31:47 +08:00
parent a4eb97ff50
commit 210d8f93bb
16 changed files with 176 additions and 71 deletions

View File

@ -110,6 +110,7 @@ function create_tacker_accounts {
create_service_user "tacker" create_service_user "tacker"
get_or_create_role "advsvc" get_or_create_role "advsvc"
create_service_user "tacker" "advsvc" create_service_user "tacker" "advsvc"
create_service_user "tacker" "admin"
local tacker_service=$(get_or_create_service "tacker" \ local tacker_service=$(get_or_create_service "tacker" \
"nfv-orchestration" "Tacker NFV Orchestration Service") "nfv-orchestration" "Tacker NFV Orchestration Service")

View File

@ -10,16 +10,36 @@ vim key in devstack environment.
The brief code workflow is described as following: The brief code workflow is described as following:
When creating a vim: When creating a vim:
We use fernet to encrypt vim password, save the fernet key into barbican We use fernet to encrypt the VIM password, then use the tacker service tenant
as a secret, save encrypted into vim db's field **password**, configured in the tacker.conf to save the fernet key to the barbican as
and then save the secret uuid into vim db field **secret_uuid**. a secret. barbican will return **secret_uuid**.
then save encrypted into vim db's field **password**, and save the secret uuid
into vim db field **secret_uuid**.
Tacker service tenant configured in the tacker.conf as follows:
.. code-block:: ini
[keystone_authtoken]
memcached_servers = localhost:11211
signing_dir = /var/cache/tacker
cafile = /opt/stack/data/ca-bundle.pem
project_domain_name = <DOMAIN_NAME>
project_name = service
user_domain_name = <DOMAIN_NAME>
username = <TACKER_USER_NAME>
password = <TACKER_SERVICE_USER_PASSWORD>
auth_url = http://127.0.0.1/identity
auth_type = password
When retrieving vim password: When retrieving vim password:
We use **secret_uuid** to get the fernet key from barbican, and decode with We use the tacker service tenant configured in the tacker.conf and
**password** using fernet. **secret_uuid** to get the fernet key from barbican, and decode
with **password** using fernet.
When deleting a vim: When deleting a vim:
We delete the secret by the **secret_uuid** in vim db from barbican. We use the tacker service tenant configured in the tacker.conf to delete
the secret by the **secret_uuid** in vim db from barbican.
How to test How to test
@ -48,7 +68,7 @@ Create a vim and verify it works:
$ openstack role add --project test --user test admin $ openstack role add --project test --user test admin
$ cat vim-test.yaml $ cat vim-test.yaml
auth_url: 'http://127.0.0.1:5000' auth_url: 'http://127.0.0.1/identity'
username: 'test' username: 'test'
password: 'Passw0rd' password: 'Passw0rd'
project_name: 'test' project_name: 'test'
@ -63,7 +83,7 @@ Create a vim and verify it works:
export OS_PROJECT_NAME=test export OS_PROJECT_NAME=test
export OS_USER_DOMAIN_NAME=Default export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default export OS_PROJECT_DOMAIN_NAME=Default
export OS_AUTH_URL=http://127.0.0.1:5000/v3 export OS_AUTH_URL=http://127.0.0.1/identity
export OS_IDENTITY_API_VERSION=3 export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2 export OS_IMAGE_API_VERSION=2
export OS_NETWORK_API_VERSION=2 export OS_NETWORK_API_VERSION=2
@ -79,9 +99,9 @@ Create a vim and verify it works:
| auth_cred | {"username": "test", "password": "***", "project_name": | | auth_cred | {"username": "test", "password": "***", "project_name": |
| | "test", "user_domain_name": "Default", "key_type": | | | "test", "user_domain_name": "Default", "key_type": |
| | "barbican_key", "secret_uuid": "***", "auth_url": | | | "barbican_key", "secret_uuid": "***", "auth_url": |
| | "http://127.0.0.1:5000/v3", "project_id": null, | | | "http://127.0.0.1/identity/v3", "project_id": null, |
| | "project_domain_name": "Default"} | | | "project_domain_name": "Default"} |
| auth_url | http://127.0.0.1:5000/v3 | | auth_url | http://127.0.0.1/identity/v3 |
| created_at | 2017-06-20 14:56:05.622612 | | created_at | 2017-06-20 14:56:05.622612 |
| description | | | description | |
| id | 7c0b73c7-554b-46d3-a35c-c368019716a0 | | id | 7c0b73c7-554b-46d3-a35c-c368019716a0 |

View File

@ -8,6 +8,7 @@ Babel==2.3.4
bcrypt==3.1.4 bcrypt==3.1.4
beautifulsoup4==4.6.0 beautifulsoup4==4.6.0
cachetools==2.0.1 cachetools==2.0.1
castellan==0.16.0
certifi==2018.1.18 certifi==2018.1.18
cffi==1.11.5 cffi==1.11.5
chardet==3.0.4 chardet==3.0.4

View File

@ -0,0 +1,13 @@
---
features:
- |
Support shared vim for policy action execution
upgrade:
- |
Because this version uses the tacker service tenant to manage the fernet key,
please remove the registered VIM before upgrading this version.
The upgrade steps are as follows.
1.Delete the registered VIM. If there is a VNF instance on the VIM,
you need to delete the VNF instance first.
2.Upgrade with this version.
3.Register the deleted VIM.

View File

@ -43,6 +43,7 @@ paramiko>=2.0.0 # LGPLv2.1+
pyroute2>=0.4.21;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2) pyroute2>=0.4.21;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2)
python-mistralclient!=3.2.0,>=3.1.0 # Apache-2.0 python-mistralclient!=3.2.0,>=3.1.0 # Apache-2.0
python-barbicanclient>=4.5.2 # Apache-2.0 python-barbicanclient>=4.5.2 # Apache-2.0
castellan>=0.16.0 # Apache-2.0
kubernetes>=5.0.0 # Apache-2.0 kubernetes>=5.0.0 # Apache-2.0
setuptools!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0,>=21.0.0 # PSF/ZPL setuptools!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0,>=21.0.0 # PSF/ZPL
PyYAML>=3.12 # MIT PyYAML>=3.12 # MIT

View File

@ -18,12 +18,16 @@
import copy import copy
import datetime import datetime
from castellan.common.credentials import keystone_password
from oslo_config import cfg
from oslo_context import context as oslo_context from oslo_context import context as oslo_context
from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import enginefacade
from tacker.db import api as db_api from tacker.db import api as db_api
from tacker import policy from tacker import policy
CONF = cfg.CONF
class ContextBase(oslo_context.RequestContext): class ContextBase(oslo_context.RequestContext):
"""Security context and request information. """Security context and request information.
@ -139,3 +143,13 @@ def get_admin_context_without_session():
return ContextBase(user_id=None, return ContextBase(user_id=None,
tenant_id=None, tenant_id=None,
is_admin=True) is_admin=True)
def generate_tacker_service_context():
return keystone_password.KeystonePassword(
password=CONF.keystone_authtoken.password,
auth_url=CONF.keystone_authtoken.auth_url,
username=CONF.keystone_authtoken.username,
user_domain_name=CONF.keystone_authtoken.user_domain_name,
project_name=CONF.keystone_authtoken.project_name,
project_domain_name=CONF.keystone_authtoken.project_domain_name)

View File

@ -89,6 +89,12 @@ class CommonDbMixin(object):
(model.shared == sql.true())) (model.shared == sql.true()))
else: else:
query_filter = (model.tenant_id == context.tenant_id) query_filter = (model.tenant_id == context.tenant_id)
elif context.is_admin and hasattr(model, 'tenant_id'):
# NOTE(Lijiale) One tenant can not access other tenant's Vim,
# NOTE(Lijiale) even though this tenant has admin role.
if hasattr(model, 'shared'):
query_filter = (model.tenant_id == context.tenant_id)
# Execute query hooks registered from mixins and plugins # Execute query hooks registered from mixins and plugins
for _name, hooks in iteritems(self._model_query_hooks.get(model, {})): for _name, hooks in iteritems(self._model_query_hooks.get(model, {})):
query_hook = hooks.get('query') query_hook = hooks.get('query')

View File

@ -119,7 +119,8 @@ class BarbicanKeyManager(key_manager.KeyManager):
project_id=context.tenant) project_id=context.tenant)
else: else:
msg = _("context must be of type KeystonePassword, " msg = _("context must be of type KeystonePassword, "
"KeystoneToken, RequestContext, or Context.") "KeystoneToken, RequestContext, or Context, got type "
"%s") % context.__class__.__name__
LOG.error(msg) LOG.error(msg)
raise exception.Forbidden(reason=msg) raise exception.Forbidden(reason=msg)

View File

@ -44,7 +44,7 @@ class VimAbstractDriver(extensions.PluginInterface):
pass pass
@abc.abstractmethod @abc.abstractmethod
def register_vim(self, context, vim_obj): def register_vim(self, vim_obj):
"""Register VIM object in to NFVO plugin """Register VIM object in to NFVO plugin
Validate, encode and store VIM information for deploying VNFs. Validate, encode and store VIM information for deploying VNFs.
@ -52,7 +52,7 @@ class VimAbstractDriver(extensions.PluginInterface):
pass pass
@abc.abstractmethod @abc.abstractmethod
def deregister_vim(self, context, vim_obj): def deregister_vim(self, vim_obj):
"""Deregister VIM object from NFVO plugin """Deregister VIM object from NFVO plugin
Cleanup VIM data and delete VIM information Cleanup VIM data and delete VIM information
@ -60,7 +60,7 @@ class VimAbstractDriver(extensions.PluginInterface):
pass pass
@abc.abstractmethod @abc.abstractmethod
def authenticate_vim(self, context, vim_obj): def authenticate_vim(self, vim_obj):
"""Authenticate VIM connection parameters """Authenticate VIM connection parameters
Validate authentication credentials and connectivity of VIM Validate authentication credentials and connectivity of VIM
@ -68,7 +68,7 @@ class VimAbstractDriver(extensions.PluginInterface):
pass pass
@abc.abstractmethod @abc.abstractmethod
def encode_vim_auth(self, context, vim_id, auth): def encode_vim_auth(self, vim_id, auth):
"""Encrypt VIM credentials """Encrypt VIM credentials
Encrypt and store VIM sensitive information such as password Encrypt and store VIM sensitive information such as password
@ -76,7 +76,7 @@ class VimAbstractDriver(extensions.PluginInterface):
pass pass
@abc.abstractmethod @abc.abstractmethod
def delete_vim_auth(self, context, vim_id, auth): def delete_vim_auth(self, vim_id, auth):
"""Delete VIM auth keys """Delete VIM auth keys
Delete VIM sensitive information such as keys from file system or DB Delete VIM sensitive information such as keys from file system or DB

View File

@ -19,6 +19,7 @@ from oslo_log import log as logging
from tacker._i18n import _ from tacker._i18n import _
from tacker.common.container import kubernetes_utils from tacker.common.container import kubernetes_utils
from tacker.common import log from tacker.common import log
from tacker import context as t_context
from tacker.extensions import nfvo from tacker.extensions import nfvo
from tacker.keymgr import API as KEYMGR_API from tacker.keymgr import API as KEYMGR_API
from tacker.nfvo.drivers.vim import abstract_vim_driver from tacker.nfvo.drivers.vim import abstract_vim_driver
@ -127,7 +128,7 @@ class Kubernetes_Driver(abstract_vim_driver.VimAbstractDriver):
self.kubernetes.close_tmp_file(file_descriptor, file_path) self.kubernetes.close_tmp_file(file_descriptor, file_path)
@log.log @log.log
def register_vim(self, context, vim_obj): def register_vim(self, vim_obj):
"""Validate Kubernetes VIM.""" """Validate Kubernetes VIM."""
if 'key_type' in vim_obj['auth_cred']: if 'key_type' in vim_obj['auth_cred']:
vim_obj['auth_cred'].pop(u'key_type') vim_obj['auth_cred'].pop(u'key_type')
@ -135,21 +136,21 @@ class Kubernetes_Driver(abstract_vim_driver.VimAbstractDriver):
vim_obj['auth_cred'].pop(u'secret_uuid') vim_obj['auth_cred'].pop(u'secret_uuid')
self.authenticate_vim(vim_obj) self.authenticate_vim(vim_obj)
self.discover_placement_attr(vim_obj) self.discover_placement_attr(vim_obj)
self.encode_vim_auth(context, vim_obj['id'], self.encode_vim_auth(vim_obj['id'],
vim_obj['auth_cred']) vim_obj['auth_cred'])
LOG.debug('VIM registration completed for %s', vim_obj) LOG.debug('VIM registration completed for %s', vim_obj)
@log.log @log.log
def deregister_vim(self, context, vim_obj): def deregister_vim(self, vim_obj):
"""Deregister Kubernetes VIM from NFVO """Deregister Kubernetes VIM from NFVO
Delete VIM keys from file system Delete VIM keys from file system
""" """
self.delete_vim_auth(context, vim_obj['id'], self.delete_vim_auth(vim_obj['id'],
vim_obj['auth_cred']) vim_obj['auth_cred'])
@log.log @log.log
def delete_vim_auth(self, context, vim_id, auth): def delete_vim_auth(self, vim_id, auth):
"""Delete kubernetes vim information """Delete kubernetes vim information
Delete vim key stored in file system Delete vim key stored in file system
@ -160,10 +161,12 @@ class Kubernetes_Driver(abstract_vim_driver.VimAbstractDriver):
vim_id) vim_id)
if auth.get('key_type') == 'barbican_key': if auth.get('key_type') == 'barbican_key':
try: try:
k_context = \
t_context.generate_tacker_service_context()
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
secret_uuid = auth['secret_uuid'] secret_uuid = auth['secret_uuid']
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
keymgr_api.delete(context, secret_uuid) keymgr_api.delete(k_context, secret_uuid)
LOG.debug('VIM key deleted successfully for vim %s', LOG.debug('VIM key deleted successfully for vim %s',
vim_id) vim_id)
except Exception as exception: except Exception as exception:
@ -175,7 +178,7 @@ class Kubernetes_Driver(abstract_vim_driver.VimAbstractDriver):
raise nfvo.VimEncryptKeyError(vim_id=vim_id) raise nfvo.VimEncryptKeyError(vim_id=vim_id)
@log.log @log.log
def encode_vim_auth(self, context, vim_id, auth): def encode_vim_auth(self, vim_id, auth):
"""Encode VIM credentials """Encode VIM credentials
Store VIM auth using fernet key encryption Store VIM auth using fernet key encryption
@ -196,9 +199,10 @@ class Kubernetes_Driver(abstract_vim_driver.VimAbstractDriver):
if CONF.k8s_vim.use_barbican: if CONF.k8s_vim.use_barbican:
try: try:
k_context = t_context.generate_tacker_service_context()
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
secret_uuid = keymgr_api.store(context, fernet_key) secret_uuid = keymgr_api.store(k_context, fernet_key)
auth['key_type'] = 'barbican_key' auth['key_type'] = 'barbican_key'
auth['secret_uuid'] = secret_uuid auth['secret_uuid'] = secret_uuid

View File

@ -30,6 +30,7 @@ from oslo_log import log as logging
from tacker._i18n import _ from tacker._i18n import _
from tacker.common import log from tacker.common import log
from tacker import context as t_context
from tacker.extensions import nfvo from tacker.extensions import nfvo
from tacker.keymgr import API as KEYMGR_API from tacker.keymgr import API as KEYMGR_API
from tacker.mistral import mistral_client from tacker.mistral import mistral_client
@ -195,7 +196,7 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
return vim_obj return vim_obj
@log.log @log.log
def register_vim(self, context, vim_obj): def register_vim(self, vim_obj):
"""Validate and set VIM placements.""" """Validate and set VIM placements."""
if 'key_type' in vim_obj['auth_cred']: if 'key_type' in vim_obj['auth_cred']:
@ -205,19 +206,19 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
ks_client = self.authenticate_vim(vim_obj) ks_client = self.authenticate_vim(vim_obj)
self.discover_placement_attr(vim_obj, ks_client) self.discover_placement_attr(vim_obj, ks_client)
self.encode_vim_auth(context, vim_obj['id'], vim_obj['auth_cred']) self.encode_vim_auth(vim_obj['id'], vim_obj['auth_cred'])
LOG.debug('VIM registration completed for %s', vim_obj) LOG.debug('VIM registration completed for %s', vim_obj)
@log.log @log.log
def deregister_vim(self, context, vim_obj): def deregister_vim(self, vim_obj):
"""Deregister VIM from NFVO """Deregister VIM from NFVO
Delete VIM keys from file system Delete VIM keys from file system
""" """
self.delete_vim_auth(context, vim_obj['id'], vim_obj['auth_cred']) self.delete_vim_auth(vim_obj['id'], vim_obj['auth_cred'])
@log.log @log.log
def delete_vim_auth(self, context, vim_id, auth): def delete_vim_auth(self, vim_id, auth):
"""Delete vim information """Delete vim information
Delete vim key stored in file system Delete vim key stored in file system
@ -226,10 +227,11 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
if auth.get('key_type') == 'barbican_key': if auth.get('key_type') == 'barbican_key':
try: try:
k_context = t_context.generate_tacker_service_context()
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
secret_uuid = auth['secret_uuid'] secret_uuid = auth['secret_uuid']
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
keymgr_api.delete(context, secret_uuid) keymgr_api.delete(k_context, secret_uuid)
LOG.debug('VIM key deleted successfully for vim %s', LOG.debug('VIM key deleted successfully for vim %s',
vim_id) vim_id)
except Exception as ex: except Exception as ex:
@ -248,7 +250,7 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
vim_id) vim_id)
@log.log @log.log
def encode_vim_auth(self, context, vim_id, auth): def encode_vim_auth(self, vim_id, auth):
"""Encode VIM credentials """Encode VIM credentials
Store VIM auth using fernet key encryption Store VIM auth using fernet key encryption
@ -259,9 +261,10 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver,
if CONF.vim_keys.use_barbican: if CONF.vim_keys.use_barbican:
try: try:
k_context = t_context.generate_tacker_service_context()
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
secret_uuid = keymgr_api.store(context, fernet_key) secret_uuid = keymgr_api.store(k_context, fernet_key)
auth['key_type'] = 'barbican_key' auth['key_type'] = 'barbican_key'
auth['secret_uuid'] = secret_uuid auth['secret_uuid'] = secret_uuid

View File

@ -33,6 +33,7 @@ from tacker._i18n import _
from tacker.common import driver_manager from tacker.common import driver_manager
from tacker.common import log from tacker.common import log
from tacker.common import utils from tacker.common import utils
from tacker import context as t_context
from tacker.db.nfvo import nfvo_db_plugin from tacker.db.nfvo import nfvo_db_plugin
from tacker.db.nfvo import ns_db from tacker.db.nfvo import ns_db
from tacker.db.nfvo import vnffg_db from tacker.db.nfvo import vnffg_db
@ -109,14 +110,12 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
try: try:
self._vim_drivers.invoke(vim_type, self._vim_drivers.invoke(vim_type,
'register_vim', 'register_vim',
context=context,
vim_obj=vim_obj) vim_obj=vim_obj)
res = super(NfvoPlugin, self).create_vim(context, vim_obj) res = super(NfvoPlugin, self).create_vim(context, vim_obj)
except Exception: except Exception:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
self._vim_drivers.invoke(vim_type, self._vim_drivers.invoke(vim_type,
'delete_vim_auth', 'delete_vim_auth',
context=context,
vim_id=vim_obj['id'], vim_id=vim_obj['id'],
auth=vim_obj['auth_cred']) auth=vim_obj['auth_cred'])
@ -170,7 +169,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
# Notice: vim_obj may be updated in vim driver's # Notice: vim_obj may be updated in vim driver's
self._vim_drivers.invoke(vim_type, self._vim_drivers.invoke(vim_type,
'register_vim', 'register_vim',
context=context,
vim_obj=vim_obj) vim_obj=vim_obj)
new_auth_created = True new_auth_created = True
@ -185,7 +183,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
try: try:
self._vim_drivers.invoke(vim_type, self._vim_drivers.invoke(vim_type,
'delete_vim_auth', 'delete_vim_auth',
context=context,
vim_id=old_vim_obj['id'], vim_id=old_vim_obj['id'],
auth=old_vim_obj['auth_cred']) auth=old_vim_obj['auth_cred'])
except Exception as ex: except Exception as ex:
@ -200,7 +197,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
# delete new-created vim auth, old auth is still used. # delete new-created vim auth, old auth is still used.
self._vim_drivers.invoke(vim_type, self._vim_drivers.invoke(vim_type,
'delete_vim_auth', 'delete_vim_auth',
context=context,
vim_id=vim_obj['id'], vim_id=vim_obj['id'],
auth=vim_obj['auth_cred']) auth=vim_obj['auth_cred'])
@ -209,7 +205,6 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
vim_obj = self._get_vim(context, vim_id) vim_obj = self._get_vim(context, vim_id)
self._vim_drivers.invoke(vim_obj['type'], self._vim_drivers.invoke(vim_obj['type'],
'deregister_vim', 'deregister_vim',
context=context,
vim_obj=vim_obj) vim_obj=vim_obj)
try: try:
auth_dict = self.get_auth_dict(context) auth_dict = self.get_auth_dict(context)
@ -519,14 +514,13 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
vim_obj = self.get_vim(context, vim_id['vim_id'], mask_password=False) vim_obj = self.get_vim(context, vim_id['vim_id'], mask_password=False)
if vim_obj is None: if vim_obj is None:
raise nfvo.VimFromVnfNotFoundException(vnf_id=vnf_id) raise nfvo.VimFromVnfNotFoundException(vnf_id=vnf_id)
self._build_vim_auth(context, vim_obj) self._build_vim_auth(vim_obj)
return vim_obj return vim_obj
def _build_vim_auth(self, context, vim_info): def _build_vim_auth(self, vim_info):
LOG.debug('VIM id is %s', vim_info['id']) LOG.debug('VIM id is %s', vim_info['id'])
vim_auth = vim_info['auth_cred'] vim_auth = vim_info['auth_cred']
vim_auth['password'] = self._decode_vim_auth(context, vim_auth['password'] = self._decode_vim_auth(vim_info['id'],
vim_info['id'],
vim_auth) vim_auth)
vim_auth['auth_url'] = vim_info['auth_url'] vim_auth['auth_url'] = vim_info['auth_url']
@ -538,7 +532,7 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
vim_auth.pop(attr, None) vim_auth.pop(attr, None)
return vim_auth return vim_auth
def _decode_vim_auth(self, context, vim_id, auth): def _decode_vim_auth(self, vim_id, auth):
"""Decode Vim credentials """Decode Vim credentials
Decrypt VIM cred, get fernet Key from local_file_system or Decrypt VIM cred, get fernet Key from local_file_system or
@ -546,10 +540,11 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
""" """
cred = auth['password'].encode('utf-8') cred = auth['password'].encode('utf-8')
if auth.get('key_type') == 'barbican_key': if auth.get('key_type') == 'barbican_key':
k_context = t_context.generate_tacker_service_context()
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
secret_uuid = auth['secret_uuid'] secret_uuid = auth['secret_uuid']
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
secret_obj = keymgr_api.get(context, secret_uuid) secret_obj = keymgr_api.get(k_context, secret_uuid)
vim_key = secret_obj.payload vim_key = secret_obj.payload
else: else:
vim_key = self._find_vim_key(vim_id) vim_key = self._find_vim_key(vim_id)

View File

@ -14,10 +14,42 @@
from collections import namedtuple from collections import namedtuple
import mock import mock
from oslo_config import cfg
from tacker import context as t_context
from tacker.nfvo.drivers.vim import kubernetes_driver from tacker.nfvo.drivers.vim import kubernetes_driver
from tacker.tests.unit import base from tacker.tests.unit import base
OPTS = [cfg.StrOpt('user_domain_id',
default='default',
help='User Domain Id'),
cfg.StrOpt('project_domain_id',
default='default',
help='Project Domain Id'),
cfg.StrOpt('password',
default='default',
help='User Password'),
cfg.StrOpt('username',
default='default',
help='User Name'),
cfg.StrOpt('user_domain_name',
default='default',
help='Use Domain Name'),
cfg.StrOpt('project_name',
default='default',
help='Project Name'),
cfg.StrOpt('project_domain_name',
default='default',
help='Project Domain Name'),
cfg.StrOpt('auth_url',
default='http://localhost:5000/v3',
help='Keystone endpoint')]
cfg.CONF.register_opts(OPTS, 'keystone_authtoken')
CONF = cfg.CONF
class FakeKubernetesAPI(mock.Mock): class FakeKubernetesAPI(mock.Mock):
pass pass
@ -113,15 +145,15 @@ class TestKubernetes_Driver(base.TestCase):
mock_fernet_obj) mock_fernet_obj)
self.kubernetes_api.create_ca_cert_tmp_file.\ self.kubernetes_api.create_ca_cert_tmp_file.\
return_value = ('file_descriptor', 'file_path') return_value = ('file_descriptor', 'file_path')
self.kubernetes_driver.register_vim(None, vim_obj) self.kubernetes_driver.register_vim(vim_obj)
mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY) mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY)
def test_deregister_vim_barbican(self): def test_deregister_vim_barbican(self):
self.keymgr.delete.return_value = None self.keymgr.delete.return_value = None
vim_obj = self.get_vim_obj_barbican() vim_obj = self.get_vim_obj_barbican()
self.kubernetes_driver.deregister_vim(None, vim_obj) self.kubernetes_driver.deregister_vim(vim_obj)
self.keymgr.delete.assert_called_once_with( self.keymgr.delete.assert_called_once_with(
None, 'fake-secret-uuid') t_context.generate_tacker_service_context(), 'fake-secret-uuid')
def test_encode_vim_auth_barbican(self): def test_encode_vim_auth_barbican(self):
self.config_fixture.config(group='k8s_vim', self.config_fixture.config(group='k8s_vim',
@ -135,10 +167,10 @@ class TestKubernetes_Driver(base.TestCase):
vim_obj = self.get_vim_obj() vim_obj = self.get_vim_obj()
self.kubernetes_driver.encode_vim_auth( self.kubernetes_driver.encode_vim_auth(
None, vim_obj['id'], vim_obj['auth_cred']) vim_obj['id'], vim_obj['auth_cred'])
self.keymgr.store.assert_called_once_with( self.keymgr.store.assert_called_once_with(
None, 'test_fernet_key') t_context.generate_tacker_service_context(), 'test_fernet_key')
mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY) mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY)
self.assertEqual(vim_obj['auth_cred']['key_type'], self.assertEqual(vim_obj['auth_cred']['key_type'],
'barbican_key') 'barbican_key')

View File

@ -17,6 +17,7 @@ from keystoneauth1 import exceptions
import mock import mock
from oslo_config import cfg from oslo_config import cfg
from tacker import context as t_context
from tacker.extensions import nfvo from tacker.extensions import nfvo
from tacker.nfvo.drivers.vim import openstack_driver from tacker.nfvo.drivers.vim import openstack_driver
from tacker.tests.unit import base from tacker.tests.unit import base
@ -28,6 +29,21 @@ OPTS = [cfg.StrOpt('user_domain_id',
cfg.StrOpt('project_domain_id', cfg.StrOpt('project_domain_id',
default='default', default='default',
help='Project Domain Id'), help='Project Domain Id'),
cfg.StrOpt('password',
default='default',
help='User Password'),
cfg.StrOpt('username',
default='default',
help='User Name'),
cfg.StrOpt('user_domain_name',
default='default',
help='Use Domain Name'),
cfg.StrOpt('project_name',
default='default',
help='Project Name'),
cfg.StrOpt('project_domain_name',
default='default',
help='Project Domain Name'),
cfg.StrOpt('auth_url', cfg.StrOpt('auth_url',
default='http://localhost:5000/v3', default='http://localhost:5000/v3',
help='Keystone endpoint')] help='Keystone endpoint')]
@ -149,7 +165,7 @@ class TestOpenstack_Driver(base.TestCase):
mock_fernet_obj) mock_fernet_obj)
file_mock = mock.mock_open() file_mock = mock.mock_open()
with mock.patch('six.moves.builtins.open', file_mock, create=True): with mock.patch('six.moves.builtins.open', file_mock, create=True):
self.openstack_driver.register_vim(None, vim_obj) self.openstack_driver.register_vim(vim_obj)
mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY) mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY)
file_mock().write.assert_called_once_with('test_fernet_key') file_mock().write.assert_called_once_with('test_fernet_key')
@ -162,15 +178,15 @@ class TestOpenstack_Driver(base.TestCase):
vim_obj['id'] = vim_id vim_obj['id'] = vim_id
file_path = CONF.vim_keys.openstack + '/' + vim_id file_path = CONF.vim_keys.openstack + '/' + vim_id
mock_os_path.return_value = file_path mock_os_path.return_value = file_path
self.openstack_driver.deregister_vim(None, vim_obj) self.openstack_driver.deregister_vim(vim_obj)
mock_os_remove.assert_called_once_with(file_path) mock_os_remove.assert_called_once_with(file_path)
def test_deregister_vim_barbican(self): def test_deregister_vim_barbican(self):
self.keymgr.delete.return_value = None self.keymgr.delete.return_value = None
vim_obj = self.get_vim_obj_barbican() vim_obj = self.get_vim_obj_barbican()
self.openstack_driver.deregister_vim(None, vim_obj) self.openstack_driver.deregister_vim(vim_obj)
self.keymgr.delete.assert_called_once_with( self.keymgr.delete.assert_called_once_with(
None, 'fake-secret-uuid') t_context.generate_tacker_service_context(), 'fake-secret-uuid')
def test_encode_vim_auth_barbican(self): def test_encode_vim_auth_barbican(self):
self.config_fixture.config(group='vim_keys', self.config_fixture.config(group='vim_keys',
@ -184,10 +200,10 @@ class TestOpenstack_Driver(base.TestCase):
vim_obj = self.get_vim_obj() vim_obj = self.get_vim_obj()
self.openstack_driver.encode_vim_auth( self.openstack_driver.encode_vim_auth(
None, vim_obj['id'], vim_obj['auth_cred']) vim_obj['id'], vim_obj['auth_cred'])
self.keymgr.store.assert_called_once_with( self.keymgr.store.assert_called_once_with(
None, 'test_fernet_key') t_context.generate_tacker_service_context(), 'test_fernet_key')
mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY) mock_fernet_obj.encrypt.assert_called_once_with(mock.ANY)
self.assertEqual(vim_obj['auth_cred']['key_type'], self.assertEqual(vim_obj['auth_cred']['key_type'],
'barbican_key') 'barbican_key')
@ -209,7 +225,6 @@ class TestOpenstack_Driver(base.TestCase):
self.keystone.initialize_client.return_value = mock_ks_client self.keystone.initialize_client.return_value = mock_ks_client
self.assertRaises(nfvo.VimUnauthorizedException, self.assertRaises(nfvo.VimUnauthorizedException,
self.openstack_driver.register_vim, self.openstack_driver.register_vim,
None,
self.vim_obj) self.vim_obj)
mock_ks_client.regions.list.assert_called_once_with() mock_ks_client.regions.list.assert_called_once_with()
self.keystone.initialize_client.assert_called_once_with( self.keystone.initialize_client.assert_called_once_with(

View File

@ -295,8 +295,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
res_state=mock.ANY, res_type=constants.RES_TYPE_VIM, res_state=mock.ANY, res_type=constants.RES_TYPE_VIM,
tstamp=mock.ANY) tstamp=mock.ANY)
self._driver_manager.invoke.assert_any_call( self._driver_manager.invoke.assert_any_call(
vim_type, 'register_vim', vim_type, 'register_vim', vim_obj=vim_dict['vim'])
context=self.context, vim_obj=vim_dict['vim'])
self.assertIsNotNone(res) self.assertIsNotNone(res)
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password']) self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
self.assertIn('id', res) self.assertIn('id', res)
@ -310,11 +309,11 @@ class TestNfvoPlugin(db_base.SqlTestCase):
self._insert_dummy_vim() self._insert_dummy_vim()
vim_type = u'openstack' vim_type = u'openstack'
vim_id = '6261579e-d6f3-49ad-8bc3-a9cb974778ff' vim_id = '6261579e-d6f3-49ad-8bc3-a9cb974778ff'
self.context.tenant_id = 'ad7ebc56538745a08ef7c5e97f8bd437'
vim_obj = self.nfvo_plugin._get_vim(self.context, vim_id) vim_obj = self.nfvo_plugin._get_vim(self.context, vim_id)
self.nfvo_plugin.delete_vim(self.context, vim_id) self.nfvo_plugin.delete_vim(self.context, vim_id)
self._driver_manager.invoke.assert_called_once_with( self._driver_manager.invoke.assert_called_once_with(
vim_type, 'deregister_vim', vim_type, 'deregister_vim',
context=self.context,
vim_obj=vim_obj) vim_obj=vim_obj)
self._cos_db_plugin.create_event.assert_called_with( self._cos_db_plugin.create_event.assert_called_with(
self.context, evt_type=constants.RES_EVT_DELETE, res_id=mock.ANY, self.context, evt_type=constants.RES_EVT_DELETE, res_id=mock.ANY,
@ -330,6 +329,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
vim_auth_username = vim_dict['vim']['auth_cred']['username'] vim_auth_username = vim_dict['vim']['auth_cred']['username']
vim_project = vim_dict['vim']['vim_project'] vim_project = vim_dict['vim']['vim_project']
self._insert_dummy_vim() self._insert_dummy_vim()
self.context.tenant_id = 'ad7ebc56538745a08ef7c5e97f8bd437'
res = self.nfvo_plugin.update_vim(self.context, vim_dict['vim']['id'], res = self.nfvo_plugin.update_vim(self.context, vim_dict['vim']['id'],
vim_dict) vim_dict)
vim_obj = self.nfvo_plugin._get_vim( vim_obj = self.nfvo_plugin._get_vim(
@ -337,7 +337,6 @@ class TestNfvoPlugin(db_base.SqlTestCase):
vim_obj['updated_at'] = None vim_obj['updated_at'] = None
self._driver_manager.invoke.assert_called_with( self._driver_manager.invoke.assert_called_with(
vim_type, 'register_vim', vim_type, 'register_vim',
context=self.context,
vim_obj=vim_obj) vim_obj=vim_obj)
self.assertIsNotNone(res) self.assertIsNotNone(res)
self.assertIn('id', res) self.assertIn('id', res)
@ -360,6 +359,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
vim_auth_username = vim_dict['vim']['auth_cred']['username'] vim_auth_username = vim_dict['vim']['auth_cred']['username']
vim_project = vim_dict['vim']['vim_project'] vim_project = vim_dict['vim']['vim_project']
self._insert_dummy_vim_barbican() self._insert_dummy_vim_barbican()
self.context.tenant_id = 'ad7ebc56538745a08ef7c5e97f8bd437'
old_vim_obj = self.nfvo_plugin._get_vim( old_vim_obj = self.nfvo_plugin._get_vim(
self.context, vim_dict['vim']['id']) self.context, vim_dict['vim']['id'])
res = self.nfvo_plugin.update_vim(self.context, vim_dict['vim']['id'], res = self.nfvo_plugin.update_vim(self.context, vim_dict['vim']['id'],
@ -369,7 +369,6 @@ class TestNfvoPlugin(db_base.SqlTestCase):
vim_obj['updated_at'] = None vim_obj['updated_at'] = None
self._driver_manager.invoke.assert_called_with( self._driver_manager.invoke.assert_called_with(
vim_type, 'delete_vim_auth', vim_type, 'delete_vim_auth',
context=self.context,
vim_id=vim_obj['id'], vim_id=vim_obj['id'],
auth=old_vim_obj['auth_cred']) auth=old_vim_obj['auth_cred'])
self.assertIsNotNone(res) self.assertIsNotNone(res)

View File

@ -19,6 +19,8 @@ from cryptography import fernet
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from tacker import context as t_context
from tacker.extensions import nfvo from tacker.extensions import nfvo
from tacker.keymgr import API as KEYMGR_API from tacker.keymgr import API as KEYMGR_API
from tacker import manager from tacker import manager
@ -57,7 +59,7 @@ class VimClient(object):
['regions'], region_name): ['regions'], region_name):
raise nfvo.VimRegionNotFoundException(region_name=region_name) raise nfvo.VimRegionNotFoundException(region_name=region_name)
vim_auth = self._build_vim_auth(context, vim_info) vim_auth = self._build_vim_auth(vim_info)
vim_res = {'vim_auth': vim_auth, 'vim_id': vim_info['id'], vim_res = {'vim_auth': vim_auth, 'vim_id': vim_info['id'],
'vim_name': vim_info.get('name', vim_info['id']), 'vim_name': vim_info.get('name', vim_info['id']),
'vim_type': vim_info['type']} 'vim_type': vim_info['type']}
@ -67,29 +69,26 @@ class VimClient(object):
def region_valid(vim_regions, region_name): def region_valid(vim_regions, region_name):
return region_name in vim_regions return region_name in vim_regions
def _build_vim_auth(self, context, vim_info): def _build_vim_auth(self, vim_info):
LOG.debug('VIM id is %s', vim_info['id']) LOG.debug('VIM id is %s', vim_info['id'])
vim_auth = vim_info['auth_cred'] vim_auth = vim_info['auth_cred']
# decode password # decode password
if ('password' in vim_auth) and (vim_auth['password'] is not None): if ('password' in vim_auth) and (vim_auth['password'] is not None):
vim_auth['password'] = self._decode_vim_auth(context, vim_auth['password'] = self._decode_vim_auth(vim_info['id'],
vim_info['id'],
vim_auth, vim_auth,
vim_auth['password']) vim_auth['password'])
# decode bearer_token # decode bearer_token
if 'bearer_token' in vim_auth: if 'bearer_token' in vim_auth:
vim_auth['bearer_token'] = self.\ vim_auth['bearer_token'] = self.\
_decode_vim_auth(context, _decode_vim_auth(vim_info['id'],
vim_info['id'],
vim_auth, vim_auth,
vim_auth['bearer_token']) vim_auth['bearer_token'])
# decode ssl_ca_cert # decode ssl_ca_cert
if ('ssl_ca_cert' in vim_auth) and \ if ('ssl_ca_cert' in vim_auth) and \
(vim_auth['ssl_ca_cert'] is not None): (vim_auth['ssl_ca_cert'] is not None):
vim_auth['ssl_ca_cert'] = self.\ vim_auth['ssl_ca_cert'] = self.\
_decode_vim_auth(context, _decode_vim_auth(vim_info['id'],
vim_info['id'],
vim_auth, vim_auth,
vim_auth['ssl_ca_cert']) vim_auth['ssl_ca_cert'])
@ -103,7 +102,7 @@ class VimClient(object):
vim_auth.pop(attr, None) vim_auth.pop(attr, None)
return vim_auth return vim_auth
def _decode_vim_auth(self, context, vim_id, auth, secret_value): def _decode_vim_auth(self, vim_id, auth, secret_value):
"""Decode Vim credentials """Decode Vim credentials
Decrypt VIM cred, get fernet Key from local_file_system or Decrypt VIM cred, get fernet Key from local_file_system or
@ -114,7 +113,8 @@ class VimClient(object):
keystone_conf = CONF.keystone_authtoken keystone_conf = CONF.keystone_authtoken
secret_uuid = auth['secret_uuid'] secret_uuid = auth['secret_uuid']
keymgr_api = KEYMGR_API(keystone_conf.auth_url) keymgr_api = KEYMGR_API(keystone_conf.auth_url)
secret_obj = keymgr_api.get(context, secret_uuid) k_context = t_context.generate_tacker_service_context()
secret_obj = keymgr_api.get(k_context, secret_uuid)
vim_key = secret_obj.payload vim_key = secret_obj.payload
else: else:
vim_key = self._find_vim_key(vim_id) vim_key = self._find_vim_key(vim_id)