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:
parent
bc7f7a4c36
commit
afb539f748
@ -44,6 +44,7 @@ from castellan.i18n import _
|
|||||||
from castellan.key_manager import key_manager
|
from castellan.key_manager import key_manager
|
||||||
|
|
||||||
DEFAULT_VAULT_URL = "http://127.0.0.1:8200"
|
DEFAULT_VAULT_URL = "http://127.0.0.1:8200"
|
||||||
|
DEFAULT_MOUNTPOINT = "secret"
|
||||||
|
|
||||||
vault_opts = [
|
vault_opts = [
|
||||||
cfg.StrOpt('root_token_id',
|
cfg.StrOpt('root_token_id',
|
||||||
@ -52,6 +53,10 @@ vault_opts = [
|
|||||||
help='AppRole role_id for authentication with vault'),
|
help='AppRole role_id for authentication with vault'),
|
||||||
cfg.StrOpt('approle_secret_id',
|
cfg.StrOpt('approle_secret_id',
|
||||||
help='AppRole secret_id for authentication with vault'),
|
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',
|
cfg.StrOpt('vault_url',
|
||||||
default=DEFAULT_VAULT_URL,
|
default=DEFAULT_VAULT_URL,
|
||||||
help='Use this endpoint to connect to Vault, for example: '
|
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._cached_approle_token_id = None
|
||||||
self._approle_token_ttl = None
|
self._approle_token_ttl = None
|
||||||
self._approle_token_issue = None
|
self._approle_token_issue = None
|
||||||
|
self._kv_mountpoint = self._conf.vault.kv_mountpoint
|
||||||
self._vault_url = self._conf.vault.vault_url
|
self._vault_url = self._conf.vault.vault_url
|
||||||
if self._vault_url.startswith("https://"):
|
if self._vault_url.startswith("https://"):
|
||||||
self._verify_server = self._conf.vault.ssl_ca_crt_file or True
|
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:
|
if self._vault_kv_version:
|
||||||
return 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)
|
resp = self._do_http_request(self._session.get, resource_url)
|
||||||
|
|
||||||
if resp.status_code == requests.codes['not_found']:
|
if resp.status_code == requests.codes['not_found']:
|
||||||
@ -125,8 +134,9 @@ class VaultKeyManager(key_manager.KeyManager):
|
|||||||
return self._vault_kv_version
|
return self._vault_kv_version
|
||||||
|
|
||||||
def _get_resource_url(self, key_id=None):
|
def _get_resource_url(self, key_id=None):
|
||||||
return '{}v1/secret/{}{}'.format(
|
return '{}v1/{}/{}{}'.format(
|
||||||
self._get_url(),
|
self._get_url(),
|
||||||
|
self._kv_mountpoint,
|
||||||
|
|
||||||
'' if self._get_api_version() == '1' else
|
'' if self._get_api_version() == '1' else
|
||||||
'data/' if key_id else
|
'data/' if key_id else
|
||||||
|
@ -41,7 +41,7 @@ def set_defaults(conf, backend=None, barbican_endpoint=None,
|
|||||||
retry_delay=None, number_of_retries=None, verify_ssl=None,
|
retry_delay=None, number_of_retries=None, verify_ssl=None,
|
||||||
api_class=None, vault_root_token_id=None,
|
api_class=None, vault_root_token_id=None,
|
||||||
vault_approle_role_id=None, vault_approle_secret_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,
|
vault_ssl_ca_crt_file=None, vault_use_ssl=None,
|
||||||
barbican_endpoint_type=None):
|
barbican_endpoint_type=None):
|
||||||
"""Set defaults for configuration values.
|
"""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_role_id: Use this for the approle role_id for vault.
|
||||||
:param vault_approle_secret_id: Use this for the approle secret_id
|
:param vault_approle_secret_id: Use this for the approle secret_id
|
||||||
for vault.
|
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_url: Use this for the url for vault.
|
||||||
:param vault_use_ssl: Use this to force vault driver to use ssl.
|
: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.
|
: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:
|
if vault_approle_secret_id is not None:
|
||||||
conf.set_default('approle_secret_id', vault_approle_secret_id,
|
conf.set_default('approle_secret_id', vault_approle_secret_id,
|
||||||
group=vkm.VAULT_OPT_GROUP)
|
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:
|
if vault_url is not None:
|
||||||
conf.set_default('vault_url', vault_url,
|
conf.set_default('vault_url', vault_url,
|
||||||
group=vkm.VAULT_OPT_GROUP)
|
group=vkm.VAULT_OPT_GROUP)
|
||||||
|
@ -130,6 +130,8 @@ APPROLE_ENDPOINT = 'v1/auth/approle/role/{role_name}'
|
|||||||
|
|
||||||
class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
|
class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
|
||||||
|
|
||||||
|
mountpoint = 'secret'
|
||||||
|
|
||||||
def _create_key_manager(self):
|
def _create_key_manager(self):
|
||||||
key_mgr = vault_key_manager.VaultKeyManager(cfg.CONF)
|
key_mgr = vault_key_manager.VaultKeyManager(cfg.CONF)
|
||||||
|
|
||||||
@ -147,6 +149,7 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
|
|||||||
self.session = requests.Session()
|
self.session = requests.Session()
|
||||||
self.session.headers.update({'X-Vault-Token': self.root_token_id})
|
self.session.headers.update({'X-Vault-Token': self.root_token_id})
|
||||||
|
|
||||||
|
self._mount_kv(self.mountpoint)
|
||||||
self._enable_approle()
|
self._enable_approle()
|
||||||
self._create_policy(vault_policy)
|
self._create_policy(vault_policy)
|
||||||
self._create_approle(vault_approle, 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 = (
|
key_mgr._approle_role_id, key_mgr._approle_secret_id = (
|
||||||
self._retrieve_approle(vault_approle)
|
self._retrieve_approle(vault_approle)
|
||||||
)
|
)
|
||||||
|
key_mgr._kv_mountpoint = self.mountpoint
|
||||||
key_mgr._vault_url = self.vault_url
|
key_mgr._vault_url = self.vault_url
|
||||||
return key_mgr
|
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):
|
def _enable_approle(self):
|
||||||
params = {
|
params = {
|
||||||
'type': 'approle'
|
'type': 'approle'
|
||||||
@ -171,7 +190,7 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
|
|||||||
|
|
||||||
def _create_policy(self, vault_policy):
|
def _create_policy(self, vault_policy):
|
||||||
params = {
|
params = {
|
||||||
'rules': TEST_POLICY.format(backend='secret'),
|
'rules': TEST_POLICY.format(backend=self.mountpoint),
|
||||||
}
|
}
|
||||||
self.session.put(
|
self.session.put(
|
||||||
'{}/{}'.format(
|
'{}/{}'.format(
|
||||||
@ -213,3 +232,8 @@ class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase):
|
|||||||
)).json()['data']['secret_id']
|
)).json()['data']['secret_id']
|
||||||
)
|
)
|
||||||
return (approle_role_id, approle_secret_id)
|
return (approle_role_id, approle_secret_id)
|
||||||
|
|
||||||
|
|
||||||
|
class VaultKeyManagerAltMountpointTestCase(VaultKeyManagerAppRoleTestCase):
|
||||||
|
|
||||||
|
mountpoint = 'different-secrets'
|
||||||
|
@ -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.
|
Loading…
x
Reference in New Issue
Block a user