The code in question (from charm-helpers/charmhelpers/contrib/openstack
/cert_utils.py) is:
def get_requests_for_local_unit(relation_name=None):
"""Extract any certificates data targeted at this unit down relation_name.
:param relation_name: str Name of relation to check for data.
:returns: List of bundles of certificates.
:rtype: List of dicts
"""
local_name = local_unit().replace('/', '_')
raw_certs_key = '{}.processed_requests'.format(local_name)
relation_name = relation_name or 'certificates'
bundles = []
for rid in relation_ids(relation_name):
sent = relation_get(rid=rid, unit=local_unit())
legacy_keys = ['certificate_name', 'common_name'] is_legacy_request = set(sent).intersection(legacy_keys)
for unit in related_units(rid):
data = relation_get(rid=rid, unit=unit)
if data.get(raw_certs_key): bundles.append({ 'ca': data['ca'], 'chain': data.get('chain'), 'certs': json.loads(data[raw_certs_key])})
elif is_legacy_request: bundles.append({ 'ca': data['ca'], 'chain': data.get('chain'), 'certs': {sent['common_name']: {'cert': data.get(local_name + '.server.cert'), 'key': data.get(local_name + '.server.key')}}})
But the main issue is, I believe, a timing. Octavia requests a certificate using the old form, but it has not yet been processed. i.e. raw_certs_key == {localname}processed_requests is not present in the data bag from vault, but the two keys 'certificate_name' and 'common_name' are present in the outbound relation from octavia. This results in the "elif is_legacy_request" being true, and thus the erroneous access to data['ca'] which isn't available in the data bag.
And essentially, it's a timing issue. Vault hasn't been initialised, so it's not sending any certs, but due to how hooks are handled in reactive charms, it's still running the handler render which goes off to look at all the relations for the context.
Fixing this may be as simple as just checking that 'ca' is available, and if not, bailing on attempting either bundle. I'll have a ponder on that one.
I think this may be related to the vault caching issue as the show-unit for octavia/0 is
vault/0:
-- ---BEGIN CERTIFICATE-----
MIID7TCCAt WgAwIBAgIUfk0uo mNXrMmdlGzOur44 HWh/v5gwDQYJKoZ IhvcNAQEL
/3VHMeHB6G 8kcfYZtdq5LeLtr C0eRstDY6uXlLz1 afXWAwqxwbtt9Fl RNttK2ZNh
dnueH3hzZl hhITaN2Tsg+ GDYb0McdBTPEDUe eaVP2R5LZZl+ OnG7OA= =
-- ---END RSA PRIVATE KEY-----
private- address: 10.246.168.166
egress- subnets: 10.246.168.167/32
ingress- address: 10.246.168.167
private- address: 10.246.168.167
egress- subnets: 10.246.168.168/32
ingress- address: 10.246.168.168
private- address: 10.246.168.168
in-scope: true
data:
ca: |-
...
lots of data ...
...
vault/1:
in-scope: true
data:
vault/2:
in-scope: true
data:
The code in question (from charm-helpers/ charmhelpers/ contrib/ openstack
/cert_utils.py) is:
def get_requests_ for_local_ unit(relation_ name=None) :
"""Extract any certificates data targeted at this unit down relation_name.
:param relation_name: str Name of relation to check for data. ).replace( '/', '_') requests' .format( local_name) ids(relation_ name): get(rid= rid, unit=local_unit()) name', 'common_name']
is_legacy_ request = set(sent) .intersection( legacy_ keys) get(rid= rid, unit=unit) raw_certs_ key):
bundles. append( {
' ca': data['ca'],
' chain': data.get('chain'),
' certs': json.loads( data[raw_ certs_key] )})
bundles. append( {
' ca': data['ca'],
' chain': data.get('chain'),
' certs': {sent[' common_ name']:
{'cert' : data.get(local_name + '.server.cert'),
'key' : data.get(local_name + '.server.key')}}})
:returns: List of bundles of certificates.
:rtype: List of dicts
"""
local_name = local_unit(
raw_certs_key = '{}.processed_
relation_name = relation_name or 'certificates'
bundles = []
for rid in relation_
sent = relation_
legacy_keys = ['certificate_
for unit in related_units(rid):
data = relation_
if data.get(
elif is_legacy_request:
But the main issue is, I believe, a timing. Octavia requests a certificate using the old form, but it has not yet been processed. i.e. raw_certs_key == {localname} processed_ requests is not present in the data bag from vault, but the two keys 'certificate_name' and 'common_name' are present in the outbound relation from octavia. This results in the "elif is_legacy_request" being true, and thus the erroneous access to data['ca'] which isn't available in the data bag.
And essentially, it's a timing issue. Vault hasn't been initialised, so it's not sending any certs, but due to how hooks are handled in reactive charms, it's still running the handler render which goes off to look at all the relations for the context.
Fixing this may be as simple as just checking that 'ca' is available, and if not, bailing on attempting either bundle. I'll have a ponder on that one.