Add crl-distribution-point to upload-signed-csr action

New configuration parameter updates URI for CRL Distribution points
inside Vault, to a publicly-accessible location. The purpose is not
to impact all users, so I did not add a global configuration
parameter. Instead, only 'upload_signed_csr' action was updated
with an optional parameter introduced named 'crl-distribution-point'.

Closes-bug: #2048237
Change-Id: I8dbfc0deb9f547100bb63bd6b20737734e97667b
This commit is contained in:
selcem 2024-01-04 21:31:16 +03:00
parent e00cb3f3f4
commit aa02567383
5 changed files with 67 additions and 24 deletions

View File

@ -31,7 +31,7 @@ The `channel` option sets the snap channel to use for deployment (e.g.
> 'Post-deployment tasks' covers this.
Vault is often containerised. Here a single unit is deployed to a new
container on machine '1':
container on existing machine '1':
juju deploy --to lxd:1 vault
@ -190,7 +190,7 @@ Sample output:
This temporary token ('token') is then used to authorise the charm:
juju run-action --wait vault/leader authorize-charm token=s.QMhaOED3UGQ4MeH3fmGOpNED
juju run --wait vault/leader authorize-charm token=s.QMhaOED3UGQ4MeH3fmGOpNED
After the action completes execution, the vault unit(s) will become active and
any pending requests for secrets storage will be processed for consuming
@ -232,7 +232,7 @@ Actions allow specific operations to be performed on a per-unit basis.
* `restart`
To display action descriptions run `juju actions --schema vault`. If the charm
is not deployed then see file `actions.yaml`.
is not deployed then see file `actions.yaml`. Here is a sample command:
## High availability

View File

@ -7,11 +7,13 @@ authorize-charm:
required:
- token
refresh-secrets:
description: Refresh secret_id's and re-issue retrieval tokens for secrets endpoints
description: Refresh secret_id's and re-issue retrieval tokens for secrets
endpoints
get-csr:
description: >-
Get intermediate CA csr (DEPRECATED Please use regenerate-intermediate-ca).
WARNING Current certificates will be invalidated and will be recreated after the CSR is signed and uploaded.
WARNING Current certificates will be invalidated and will be recreated
after the CSR is signed and uploaded.
properties:
# Depending on the configuration of CA that will sign the CSRs it
# may be necessary to ensure these fields match the CA
@ -47,7 +49,8 @@ get-csr:
regenerate-intermediate-ca:
description: >-
Create a new intermediate CA and return a csr for it
WARNING Current certificates will be invalidated and will be recreated after the CSR is signed and uploaded.
WARNING Current certificates will be invalidated and will be recreated
after the CSR is signed and uploaded.
properties:
# Depending on the configuration of CA that will sign the CSRs it
# may be necessary to ensure these fields match the CA
@ -107,6 +110,17 @@ upload-signed-csr:
default: '8760h'
description: >-
Specifies the maximum Time To Live
crl-distribution-point:
type: string
default: ''
description: >-
Provide an alternative URL for the Certificate Revocation List (CRL)
distribution point that is included in all certificates issued by
Vault. This relies on an external process to synchronise certificates
revoked in Vault to this external distribution point and should only
be used when the Vault infrastructure is not generally accessible to
client endpoints used to access services secured by the Vault
Intermediate CA.
root-ca:
type: string
description: >-
@ -184,8 +198,8 @@ restart:
description: Restarts the vault unit. Vault will become sealed.
reload:
description: >-
Reloads the vault unit. This allows for limited configuration options to be
re-read. Vault will not become sealed.
Reloads the vault unit. This allows for limited configuration options to
be re-read. Vault will not become sealed.
generate-certificate:
description: Generate a certificate agains the Vault PKI
properties:

View File

@ -131,7 +131,8 @@ def upload_signed_csr(*args):
allow_subdomains=action_config.get('allow-subdomains'),
enforce_hostnames=action_config.get('enforce-hostnames'),
allow_any_name=action_config.get('allow-any-name'),
max_ttl=action_config.get('max-ttl'))
max_ttl=action_config.get('max-ttl'),
crl_distribution_point=action_config.get('crl-distribution-point'))
set_flag('charm.vault.ca.ready')
set_flag('pki.backend.tuned')
# reissue any certificates we might previously have provided

View File

@ -23,7 +23,9 @@ def configure_pki_backend(client, name, ttl=None, max_ttl=None):
:param name: Name of backend to enable
:type name: str
:param ttl: TTL
:type ttl: str
:type ttl: Optional[str]
:param max_ttl: max TTL
:type max_ttl: Optional[str]
"""
if not vault.is_backend_mounted(client, name):
client.sys.enable_secrets_engine(
@ -53,7 +55,9 @@ def tune_pki_backend(ttl=None, max_ttl=None):
"""Assert tuning options for Charm PKI backend
:param ttl: TTL
:type ttl: str
:type ttl: Optional[str]
:param max_ttl: max TTL
:type max_ttl: Optional[str]
"""
client = vault.get_local_client()
if vault.is_backend_mounted(client, CHARM_PKI_MP):
@ -68,6 +72,10 @@ def is_ca_ready(client, name, role):
:returns: Whether CA is ready
:rtype: bool
:param name: Name of backend to enable
:type name: str
:param role: Name of role
:type role: str
"""
try:
# read_role raises InvalidPath is the role is not available
@ -156,17 +164,17 @@ def get_csr(ttl=None, common_name=None, locality=None,
fields embedded in the CSR may have to match the CA.
:param ttl: TTL
:type ttl: string
:type ttl: Optional[string]
:param country: The C (Country) values in the subject field of the CSR
:type country: string
:type country: Optional[string]
:param province: The ST (Province) values in the subject field of the CSR.
:type province: string
:type province: Optional[string]
:param organization: The O (Organization) values in the subject field of
the CSR
:type organization: string
:type organization: Optional[string]
:param organizational_unit: The OU (OrganizationalUnit) values in the
subject field of the CSR.
:type organizational_unit: string
:type organizational_unit: Optional[string]
:param common_name: The CN (Common_Name) values in the
subject field of the CSR.
:param locality: The L (Locality) values in the
@ -203,22 +211,24 @@ def get_csr(ttl=None, common_name=None, locality=None,
def upload_signed_csr(pem, allowed_domains, allow_subdomains=True,
enforce_hostnames=False, allow_any_name=True,
max_ttl=None):
max_ttl=None, crl_distribution_point=None):
"""Upload signed csr to intermediate pki
:param pem: signed csr in pem format
:type pem: string
:param allow_subdomains: Specifies if clients can request certificates with
CNs that are subdomains of the CNs:
:type allow_subdomains: bool
:type allow_subdomains: Optional[bool]
:param enforce_hostnames: Specifies if only valid host names are allowed
for CNs, DNS SANs, and the host part of email
addresses.
:type enforce_hostnames: bool
:type enforce_hostnames: Optional[bool]
:param allow_any_name: Specifies if clients can request any CN
:type allow_any_name: bool
:type allow_any_name:Optional[bool]
:param max_ttl: Specifies the maximum Time To Live
:type max_ttl: str
:type max_ttl: Optional[str]
:param crl_distribution_point: Defines the CRL Distribution Point URI
:type crl_distribution_point: Optional[str]
"""
client = vault.get_local_client()
# Set the intermediate certificate authorities signing certificate to the
@ -234,7 +244,8 @@ def upload_signed_csr(pem, allowed_domains, allow_subdomains=True,
{
"issuing_certificates": "{}/v1/{}/ca".format(addr, CHARM_PKI_MP),
"crl_distribution_points":
"{}/v1/{}/crl".format(addr, CHARM_PKI_MP),
("{}/v1/{}/crl".format(addr, CHARM_PKI_MP)
if not crl_distribution_point else crl_distribution_point),
},
mount_point=CHARM_PKI_MP
)
@ -388,7 +399,7 @@ def is_cert_from_vault(cert, name=None):
:param cert: the certificate in x509 form
:type cert: str
:param name: the mount point in value, default CHARM_PKI_MP
:type name: str
:type name: Optional[str]
:returns: True if issued by vault, False if unknown.
:raises VaultDown: if vault is down.
:raises VaultNotReady: if vault is sealed.

View File

@ -260,6 +260,23 @@ class TestLibCharmVaultPKI(unit_tests.test_utils.CharmTestCase):
'MYPEM', mount_point=vault_pki.CHARM_PKI_MP
)
@patch.object(vault_pki.vault, 'get_access_address')
@patch.object(vault_pki.vault, 'get_local_client')
def test_upload_signed_csr_cdp(self, get_local_client, get_access_address):
get_access_address.return_value = 'https://vault.local:8200'
client_mock = mock.MagicMock()
get_local_client.return_value = client_mock
local_url = 'https://vault.local:8200/v1/charm-pki-local'
vault_pki.upload_signed_csr(
'MYPEM', 'example.com', crl_distribution_point='https://cdp.com'
)
client_mock.secrets.pki.set_urls.assert_called_once_with(
{
'issuing_certificates': '{}/ca'.format(local_url),
'crl_distribution_points': 'https://cdp.com',
}, mount_point=vault_pki.CHARM_PKI_MP
)
@patch.object(vault_pki.vault, 'get_access_address')
@patch.object(vault_pki.vault, 'get_local_client')
def test_upload_signed_csr_ipv4(
@ -335,7 +352,7 @@ class TestLibCharmVaultPKI(unit_tests.test_utils.CharmTestCase):
allow_subdomains=False,
enforce_hostnames=True,
allow_any_name=False,
max_ttl='42h')
max_ttl='42h', crl_distribution_point=None)
client_mock.secrets.pki.set_signed_intermediate.\
assert_called_once_with(
'MYPEM', mount_point='charm-pki-local'