Comment 0 for bug 2064578

Revision history for this message
Bayani Carbone (bcarbone) wrote :

When trying to run the get-resource-token action with an on-prem contract server using a certificate signed by a private CA, the action fails with this exception:

# ./actions/get-resource-token
Failed to retrieve resource token HTTPSConnectionPool(host='contract.example.com', port=443): Max retries exceeded with url: /v1/resources/livepatch-onprem/context/machines/27d546e7ad6e423f91745bcce44a7147 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)')))

I believe the issue lies in this piece of code:

https://github.com/canonical/livepatch-server/blob/a20a87cf0afe6f5240783015aa4763af2cf468d7/charms/onprem/lib/charms/layer/livepatchserver/resource.py#L51

def get_resource_token(machine_id, machine_token, contracts_url=DEFAULT_CONTRACTS_URL, proxies=None):
    """
    Retrieve a resource token for the livepatch-onprem
    resource.
    """
    if proxies is not None:
        os.environ['http_proxy'] = proxies.get('http_proxy', '')
        os.environ['https_proxy'] = proxies.get('https_proxy', '')
        os.environ['no_proxy'] = proxies.get('no_proxy', '')

    headers = {'Authorization': 'Bearer {}'.format(machine_token)}
    try:
        req = rsession.get(
            '{}/v1/resources/{}/context/machines/{}'.format(
                contracts_url, RESOURCE_NAME, machine_id),
            headers=headers)
        data = req.json()
        return data
    except requests.exceptions.RequestException:
        print("Failed to retrieve resource token")
        return None
    except KeyError:
        print("Resource token not in contracts response.")
        return None

The python requests module in the charm context is using this CA cert file:
/var/lib/juju/agents/unit-livepatch-0/.venv/lib/python3.10/site-packages/certifi/cacert.pem

Which does not contain any certificates imported via `/usr/local/share/ca-certificates/`.

One option to fix this, would be to expose a config option to set the CA cert file to be used and add the `verify` argument to the `get` call e.g.:

        req = rsession.get(
            '{}/v1/resources/{}/context/machines/{}'.format(
                contracts_url, RESOURCE_NAME, machine_id),
            headers=headers, verify=CA_BUNDLE)