vault: support configuration of KV mountpoint

Support end user configuration of KV store in Vault to use for
key storage allowing more flexibility in Vault configuration.

Change-Id: I625a819c2b9b542677258de709a9c520fb86858b
Closes-Bug: 1797148
This commit is contained in:
James Page 2018-10-10 16:18:52 +01:00
parent bc7f7a4c36
commit afb539f748
4 changed files with 48 additions and 4 deletions

View File

@ -44,6 +44,7 @@ from castellan.i18n import _
from castellan.key_manager import key_manager
DEFAULT_VAULT_URL = "http://127.0.0.1:8200"
DEFAULT_MOUNTPOINT = "secret"
vault_opts = [
cfg.StrOpt('root_token_id',
@ -52,6 +53,10 @@ vault_opts = [
help='AppRole role_id for authentication with vault'),
cfg.StrOpt('approle_secret_id',
help='AppRole secret_id for authentication with vault'),
cfg.StrOpt('kv_mountpoint',
default=DEFAULT_MOUNTPOINT,
help='Mountpoint of KV store in Vault to use, for example: '
'{}'.format(DEFAULT_MOUNTPOINT)),
cfg.StrOpt('vault_url',
default=DEFAULT_VAULT_URL,
help='Use this endpoint to connect to Vault, for example: '
@ -98,6 +103,7 @@ class VaultKeyManager(key_manager.KeyManager):
self._cached_approle_token_id = None
self._approle_token_ttl = None
self._approle_token_issue = None
self._kv_mountpoint = self._conf.vault.kv_mountpoint
self._vault_url = self._conf.vault.vault_url
if self._vault_url.startswith("https://"):
self._verify_server = self._conf.vault.ssl_ca_crt_file or True
@ -114,7 +120,10 @@ class VaultKeyManager(key_manager.KeyManager):
if self._vault_kv_version:
return self._vault_kv_version
resource_url = self._get_url() + 'v1/sys/internal/ui/mounts/secret'
resource_url = '{}v1/sys/internal/ui/mounts/{}'.format(
self._get_url(),
self._kv_mountpoint
)
resp = self._do_http_request(self._session.get, resource_url)
if resp.status_code == requests.codes['not_found']:
@ -125,8 +134,9 @@ class VaultKeyManager(key_manager.KeyManager):
return self._vault_kv_version
def _get_resource_url(self, key_id=None):
return '{}v1/secret/{}{}'.format(
return '{}v1/{}/{}{}'.format(
self._get_url(),
self._kv_mountpoint,
'' if self._get_api_version() == '1' else
'data/' if key_id else

View File

@ -41,7 +41,7 @@ def set_defaults(conf, backend=None, barbican_endpoint=None,
retry_delay=None, number_of_retries=None, verify_ssl=None,
api_class=None, vault_root_token_id=None,
vault_approle_role_id=None, vault_approle_secret_id=None,
vault_url=None,
vault_kv_mountpoint=None, vault_url=None,
vault_ssl_ca_crt_file=None, vault_use_ssl=None,
barbican_endpoint_type=None):
"""Set defaults for configuration values.
@ -59,6 +59,7 @@ def set_defaults(conf, backend=None, barbican_endpoint=None,
:param vault_approle_role_id: Use this for the approle role_id for vault.
:param vault_approle_secret_id: Use this for the approle secret_id
for vault.
:param vault_kv_mountpoint: Mountpoint of KV store in vault to use.
:param vault_url: Use this for the url for vault.
:param vault_use_ssl: Use this to force vault driver to use ssl.
:param vault_ssl_ca_crt_file: Use this for the CA file for vault.
@ -109,6 +110,9 @@ def set_defaults(conf, backend=None, barbican_endpoint=None,
if vault_approle_secret_id is not None:
conf.set_default('approle_secret_id', vault_approle_secret_id,
group=vkm.VAULT_OPT_GROUP)
if vault_kv_mountpoint is not None:
conf.set_default('kv_mountpoint', vault_kv_mountpoint,
group=vkm.VAULT_OPT_GROUP)
if vault_url is not None:
conf.set_default('vault_url', vault_url,
group=vkm.VAULT_OPT_GROUP)

View File

@ -130,6 +130,8 @@ APPROLE_ENDPOINT = 'v1/auth/approle/role/{role_name}'
class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
mountpoint = 'secret'
def _create_key_manager(self):
key_mgr = vault_key_manager.VaultKeyManager(cfg.CONF)
@ -147,6 +149,7 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
self.session = requests.Session()
self.session.headers.update({'X-Vault-Token': self.root_token_id})
self._mount_kv(self.mountpoint)
self._enable_approle()
self._create_policy(vault_policy)
self._create_approle(vault_approle, vault_policy)
@ -154,9 +157,25 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
key_mgr._approle_role_id, key_mgr._approle_secret_id = (
self._retrieve_approle(vault_approle)
)
key_mgr._kv_mountpoint = self.mountpoint
key_mgr._vault_url = self.vault_url
return key_mgr
def _mount_kv(self, vault_mountpoint):
backends = self.session.get(
'{}/v1/sys/mounts'.format(self.vault_url)).json()
if vault_mountpoint not in backends:
params = {
'type': 'kv',
'options': {
'version': 2,
}
}
self.session.post(
'{}/v1/sys/mounts/{}'.format(self.vault_url,
vault_mountpoint),
json=params)
def _enable_approle(self):
params = {
'type': 'approle'
@ -171,7 +190,7 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
def _create_policy(self, vault_policy):
params = {
'rules': TEST_POLICY.format(backend='secret'),
'rules': TEST_POLICY.format(backend=self.mountpoint),
}
self.session.put(
'{}/{}'.format(
@ -213,3 +232,8 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
)).json()['data']['secret_id']
)
return (approle_role_id, approle_secret_id)
class VaultKeyManagerAltMountpointTestCase(VaultKeyManagerAppRoleTestCase):
mountpoint = 'different-secrets'

View File

@ -0,0 +1,6 @@
---
features:
- |
Added configuration option to the Vault key manager to allow
the KV store mountpoint in Vault to be specified; the existing
default of 'secret' is maintained.