Fix disable and re-enable of PKI secrets engine

Several flags were not being managed properly, and certs were not being
re-issued when PKI was re-enabled.

Fixes [lp:1813180](https://bugs.launchpad.net/vault-charm/+bug/1813180)

Change-Id: Ifac75028897d22c277750a747f79d4dfedb4f987
This commit is contained in:
Cory Johns 2019-02-07 17:43:29 -05:00
parent 102b222fce
commit 3b94731520
3 changed files with 28 additions and 6 deletions

View File

@ -32,7 +32,7 @@ import charm.vault as vault
import charm.vault_pki as vault_pki
import charms.reactive
from charms.reactive.flags import set_flag
from charms.reactive.flags import set_flag, clear_flag
def authorize_charm_action(*args):
@ -85,6 +85,9 @@ def upload_signed_csr(*args):
max_ttl=action_config.get('max-ttl'))
set_flag('charm.vault.ca.ready')
set_flag('pki.backend.tuned')
# reissue any certificates we might previously have provided
set_flag('certificates.reissue.requested')
set_flag('certificates.reissue.global.requested')
def generate_root_ca(*args):
@ -106,6 +109,9 @@ def generate_root_ca(*args):
hookenv.action_set({'output': root_ca})
set_flag('charm.vault.ca.ready')
set_flag('pki.backend.tuned')
# reissue any certificates we might previously have provided
set_flag('certificates.reissue.requested')
set_flag('certificates.reissue.global.requested')
def get_root_ca(*args):
@ -117,11 +123,13 @@ def disable_pki(*args):
hookenv.action_fail('Please run action on lead unit')
return
vault_pki.disable_pki_backend()
clear_flag('charm.vault.ca.ready')
clear_flag('pki.backend.tuned')
def reissue_certificates(*args):
charms.reactive.set_flag('certificates.reissue.requested')
charms.reactive.set_flag('certificates.reissue.global.requested')
set_flag('certificates.reissue.requested')
set_flag('certificates.reissue.global.requested')
# Actions to function mapping, to allow for illegal python action names that

View File

@ -34,6 +34,11 @@ def disable_pki_backend():
"""
client = vault.get_local_client()
if vault.is_backend_mounted(client, CHARM_PKI_MP):
client.delete('{}/root'.format(CHARM_PKI_MP))
client.delete('{}/roles/{}'.format(CHARM_PKI_MP,
CHARM_PKI_ROLE_CLIENT))
client.delete('{}/roles/{}'.format(CHARM_PKI_MP,
CHARM_PKI_ROLE))
client.disable_secret_backend(CHARM_PKI_MP)
@ -117,6 +122,8 @@ def generate_certificate(cert_type, common_name, sans):
try:
response = client.write('{}/issue/{}'.format(CHARM_PKI_MP, role),
**config)
if not response['data']:
raise vault.VaultError(response.get('warnings', 'unknown error'))
except hvac.exceptions.InvalidRequest as e:
raise vault.VaultInvalidRequest(str(e)) from e
return response['data']
@ -159,6 +166,8 @@ def get_csr(ttl=None, country=None, province=None,
csr_info = client.write(
'{}/intermediate/generate/internal'.format(CHARM_PKI_MP),
**config)
if not csr_info['data']:
raise vault.VaultError(csr_info.get('warnings', 'unknown error'))
return csr_info['data']['csr']
@ -264,6 +273,8 @@ def generate_root_ca(ttl='87599h', allow_any_name=True, allowed_domains=None,
csr_info = client.write(
'{}/root/generate/internal'.format(CHARM_PKI_MP),
**config)
if not csr_info['data']:
raise vault.VaultError(csr_info.get('warnings', 'unknown error'))
cert = csr_info['data']['certificate']
# Generated certificates can have the CRL location and the location of the
# issuing certificate encoded.

View File

@ -674,7 +674,8 @@ def _assess_status():
@when('leadership.is_leader',
'config.set.auto-generate-root-ca-cert')
@when_not('charm.vault.ca.ready')
@when_not('charm.vault.ca.ready',
'charm.vault.ca.auto-generated')
def auto_generate_root_ca_cert():
actions_yaml = yaml.load(Path('actions.yaml').read_text())
props = actions_yaml['generate-root-ca']['properties']
@ -691,6 +692,7 @@ def auto_generate_root_ca_cert():
max_ttl=action_config['max-ttl'])
leader_set({'root-ca': root_ca})
set_flag('charm.vault.ca.ready')
set_flag('charm.vault.ca.auto-generated')
except vault.VaultError as e:
log("Skipping auto-generate root CA cert: {}".format(e))
@ -733,12 +735,13 @@ def publish_global_client_cert():
@when('leadership.is_leader',
'charm.vault.ca.ready')
'charm.vault.ca.ready',
'certificates.available')
@when_any('certificates.certs.requested',
'certificates.reissue.requested')
def create_certs():
reissue_requested = is_flag_set('certificates.reissue.requested')
tls = endpoint_from_flag('certificates.certs.requested')
tls = endpoint_from_flag('certificates.available')
requests = tls.all_requests if reissue_requested else tls.new_requests
if reissue_requested:
log('Reissuing all certs')