Comment 6 for bug 2028683

Revision history for this message
Alex Kavanagh (ajkavanagh) wrote :

I think this may be related to the vault caching issue as the show-unit for octavia/0 is

     vault/0:
        in-scope: true
        data:
          ca: |-
            -----BEGIN CERTIFICATE-----
            MIID7TCCAtWgAwIBAgIUfk0uomNXrMmdlGzOur44HWh/v5gwDQYJKoZIhvcNAQEL
            ...
            lots of data ...
            ...
            /3VHMeHB6G8kcfYZtdq5LeLtrC0eRstDY6uXlLz1afXWAwqxwbtt9FlRNttK2ZNh
            dnueH3hzZlhhITaN2Tsg+GDYb0McdBTPEDUeeaVP2R5LZZl+OnG7OA==
            -----END RSA PRIVATE KEY-----
          private-address: 10.246.168.166
      vault/1:
        in-scope: true
        data:
          egress-subnets: 10.246.168.167/32
          ingress-address: 10.246.168.167
          private-address: 10.246.168.167
      vault/2:
        in-scope: true
        data:
          egress-subnets: 10.246.168.168/32
          ingress-address: 10.246.168.168
          private-address: 10.246.168.168

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.