'dnf.base.fill_sack() -- how to use the certs in yum.conf?

I have cert information for using HTTPS in my repos stored in /etc/yum.conf at the bottom:

[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
...
sslclientcert=/path/to/cert.pem
sslclientkey=/path/to/privatekey.pem
sslcacert=/path/to/ca.pem

When I use dnf via the terminal, it can communicate with the repos and retrieve repodata/repomd.xml (and package information and all) just fine. However, when I do it via python:

import dnf
with dnf.Base() as base:
    base.read_all_repos()
    base.fill_sack()

I get:

Errors during downloading metadata for repository '<reponame>':
  - Curl error (60): Peer certificate cannot be authenticated with given CA certificates for <repo-path>/repodata/repomd.xml [SSL certificate problem: self signed certificate in certificate chain]
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/dnf/repo.py", line 574, in load
    ret = self._repo.load()
  File "/usr/lib64/python3.6/site-packages/libdnf/repo.py", line 397, in load
    return _repo.Repo_load(self)
libdnf._error.Error: Failed to download metadata for repo '<reponame>': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/dnf/base.py", line 399, in fill_sack
    self._add_repo_to_sack(r)
  File "/usr/lib/python3.6/site-packages/dnf/base.py", line 139, in _add_repo_to_sack
    repo.load()
  File "/usr/lib/python3.6/site-packages/dnf/repo.py", line 581, in load
    raise dnf.exceptions.RepoError(str(e))
dnf.exceptions.RepoError: Failed to download metadata for repo '<reponame>': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried

How I know it's an SSL/HTTPS problem:

  • Implemented HTTPS on my personal repo a few days ago, and that's when the issues started (it worked just fine prior to that)
  • If I change the URL to http:// instead of https://, it works fine (but this isn't a viable solution).
  • If I run the dnf via commandline, it also works just fine.

I know that dnf has the ability to pull those certs in from the yum.conf file, but does anyone know (or can figure out) how it's actually done? I've spent a good while digging through the code now and can't figure it out (I'm not particularly familiar with how swig works, which is what I'm getting caught up on witin the dnf code itself).

Any help is appreciated.



Solution 1:[1]

Figured it out a little while ago, so maybe this'll help someone else out there:)

import dnf
from libdnf.conf import Option

with dnf.Base() as base:
    # Read in the config from yum.conf
    with open('/etc/yum.conf') as inf:
        yum_config = inf.read()

    # Split the config into a dictionary
    yum_settings = yum_config.split('\n')
    yum_settings = {k.split('=')[0]:k.split('=')[1] for k in yum_settings in '=' in k}

    # The settings below will require a priority. This is the third highest one out of about 10, so I went with this one
    priority = Option.Priority_DROPINCONFIG

    base.conf._config.sslclientcert().set(priority, yum_settings['sslclientcert'])
    base.conf._config.sslclientkey().set(priority, yum_settings['sslclientkey'])
    base.conf._config.sslcacert().set(priority, yum_settings['sslcacert'])

    base.read_all_repos()
    base.fill_sack()

And now it works! It uses the SSL certs in the files in /etc/yum.conf to connect to the repos and all is well!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 KnightShadeX