openSUSE/zypper

Keys listed in gpgkey= not used for repo metadata signature verification

DaanDeMeyer opened this issue · 18 comments

When I run zypper with gpgkeys listed in gpgkey= in the individual repo files, zypper fails with an error saying it can't verify the repo metadata signature, even though the key that the repository metadata is signed with is listed in gpgkey=.

Version: 1.14.59

Repo file:

[repo-oss]
name=repo-oss
baseurl=https://download.opensuse.org/tumbleweed/repo/oss/
enabled=1
autorefresh=0
keeppackages=1
gpgcheck=0
repo_gpgcheck=1
pkg_gpgcheck=1
gpgkey=file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE-Tumbleweed
       file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE

Log: https://gist.github.com/DaanDeMeyer/7babbb3adb9464d2ce964a569ed92cde

I have this problem in zypper 1.14.71 but do not have it in 1.14.68.

zypper 1.14.68

# cat /etc/zypp/repos.d/nginx.repo && zypper --version && zypper refs && zypper --gpg-auto-import-keys refresh -r nginx-stable
[nginx]
name=nginx-stable
enabled=1
autorefresh=1
baseurl=https://nginx.org/packages/sles/15/
gpgcheck=1
gpgkey=https://nginx.org/keys/nginx_signing.key
path=/
type=yum
keeppackages=0
zypper 1.14.68
All services have been refreshed.
Looking for gpg key ID 7BD9BF62 in cache /var/cache/zypp/pubkeys.
Looking for gpg key ID 7BD9BF62 in repository nginx-stable.
  gpgkey=https://nginx.org/keys/nginx_signing.key

Automatically importing the following key:

  Repository:       nginx-stable
  Key Fingerprint:  573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
  Key Name:         nginx signing key <signing-key@nginx.com>
  Key Algorithm:    RSA 2048
  Key Created:      Sat May 25 00:31:01 2024
  Key Expires:      Tue May 25 00:31:01 2027
  Rpm Name:         gpg-pubkey-7bd9bf62-6650b2b5



    Note: A GPG pubkey is clearly identified by its fingerprint. Do not rely on the key's name. If
    you are not sure whether the presented key is authentic, ask the repository provider or check
    their web site. Many providers maintain a web page showing the fingerprints of the GPG keys they
    are using.
Retrieving repository 'nginx-stable' metadata ...............................................................................[done]
Building repository 'nginx-stable' cache ....................................................................................[done]
Specified repositories have been refreshed.

zypper 1.14.71

# cat /etc/zypp/repos.d/nginx.repo && zypper --version && zypper refs && zypper --gpg-auto-import-keys refresh -r nginx-stable
[nginx]
name=nginx-stable
enabled=1
autorefresh=1
baseurl=https://nginx.org/packages/sles/15/
gpgcheck=1
gpgkey=https://nginx.org/keys/nginx_signing.key
path=/
type=yum
keeppackages=0
zypper 1.14.71
All services have been refreshed.
Looking for gpg key ID 7BD9BF62 in cache /var/cache/zypp/pubkeys.
Looking for gpg key ID 7BD9BF62 in repository nginx-stable.
  gpgkey=https://nginx.org/keys/nginx_signing.key
Warning: File 'repomd.xml' from repository 'nginx-stable' is signed with an unknown key 'ABF5BD827BD9BF62'.

    Note: Signing data enables the recipient to verify that no modifications occurred after the data
    were signed. Accepting data with no, wrong or unknown signature can lead to a corrupted system
    and in extreme cases even to a system compromise.

    Note: File 'repomd.xml' is the repositories master index file. It ensures the integrity of the
    whole repo.

    Warning: We can't verify that no one meddled with this file, so it might not be trustworthy
    anymore! You should not continue unless you know it's safe.

File 'repomd.xml' from repository 'nginx-stable' is signed with an unknown key 'ABF5BD827BD9BF62'.
Continue? [yes/no] (no):
Retrieving repository 'nginx-stable' metadata ..............................................................................[error]
Repository 'nginx-stable' is invalid.
[nginx|https://nginx.org/packages/sles/15/] Valid metadata not found at specified URL
History:
 - Signature verification failed for repomd.xml

Please check if the URIs defined for this repository are pointing to a valid repository.
Skipping repository 'nginx-stable' because of the above error.
Could not refresh the repositories because of errors.

@jswolf19 to me it looks like the repo is signed with unknown key 'ABF5BD827BD9BF62' and the gpgkey URL provides BCDCD8A38D88A2B3.

ma@hobbes:tmp (0)> wget https://nginx.org/keys/nginx_signing.key
--2024-06-05 09:45:12--  https://nginx.org/keys/nginx_signing.key
Resolving nginx.org (nginx.org)... 2a05:d014:5c0:2601::6, 2a05:d014:5c0:2600::6, 52.58.199.22, ...
Connecting to nginx.org (nginx.org)|2a05:d014:5c0:2601::6|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11809 (12K) [application/octet-stream]
Saving to: ‘nginx_signing.key’

nginx_signing.key             100%[=================================================>]  11.53K  --.-KB/s    in 0s      

2024-06-05 09:45:12 (101 MB/s) - ‘nginx_signing.key’ saved [11809/11809]

ma@hobbes:tmp (0)> zypp-pubkey nginx_signing.key
=== ./nginx_signing.key{- 0644 216/1000 size 11809}
[nginx signing key <signing-key-3@nginx.com>]
 +----[RSA 4096]-----+
 |                   |  fpr 9E9BE90EACBCDE69FE9B204CBCDCD8A38D88A2B3
 |                   |   id BCDCD8A38D88A2B3
 |                   |  alg RSA 4096
 |                   |  cre 1716998629 Wed May 29 18:03:49 2024
 |                   |  exp 0 (does not expire)
 |    .    S         |  ttl 2147483647
 |     ^  . .        |  rpm 8d88a2b3-665751e5
 |    : i  ^         |
 |     i ?  :        |
 |^ . ^ ?.l:.        |
 |E: ..?:l:i.        |
 +----[8D88A2B3]-----+

*** Not in rpm database.

We'll add a message telling why gpgkey= did not work (file not found or does not contain the expected key)

@mlandres I'll have to check once I'm in front of a computer, but I think the file has 3 keys. The one used for signing is the second one.

Update: yes, ABF5BD827BD9BF62 is the second key in the file.

$ curl https://nginx.org/keys/nginx_signing.key | gpg --show-keys --with-fingerprint
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 11809  100 11809    0     0   4438      0  0:00:02  0:00:02 --:--:--  4437pub   rsa4096 2024-05-29 [SC]
      8540 A6F1 8833 A80E 9C16  53A4 2FD2 1310 B49F 6B46
uid                      nginx signing key <signing-key-2@nginx.com>

pub   rsa2048 2011-08-19 [SC] [expires: 2027-05-24]
      573B FD6B 3D8F BC64 1079  A6AB ABF5 BD82 7BD9 BF62
uid                      nginx signing key <signing-key@nginx.com>


pub   rsa4096 2024-05-29 [SC]
      9E9B E90E ACBC DE69 FE9B  204C BCDC D8A3 8D88 A2B3
uid                      nginx signing key <signing-key-3@nginx.com>

@jswolf19 Sorry, then I'll have to check my script.

In any case, there's been an issue with the gpgkey url, but is meanwhile fixed:
libzypp-17.32.6: Fix download from gpgkey URL (bsc#1223430, fixes #546)

Please check your libzypp version. If it's older and 17.32.6 fixes it, we can close this as duplicate of #546

Please check your libzypp version. If it's older and 17.32.6 fixes it, we can close this as duplicate of #546

I'll check tomorrow and get back to you.

@mlandres Upgrading to libzypp-17.32.6 solves my problem. If it's a url issue, I'm not sure if it solves the original issue, though.

The 15.5 repos currently only includes up to libzypp-17.32.5, so I made a temporary repo providing 17.32.6. Any idea if/when that version will be added to the 15.5 update repo?

@mlandres The issue is not fixed for me, see logs and information below:

➜  mkosi git:(main) ✗ mkosi -d opensuse --tools-tree --tools-tree-distribution=fedora --tools-tree-release=rawhide -f --debug-shell
Create subvolume '/home/daandemeyer/.cache/mkosi/mkosi-workspace-7uxw3e_v/root'
‣ Cache manifest mismatch, not reusing cached images
‣ Syncing package manager metadata for default image
Warning: The '--no-refresh' global option has no effect here.

New repository or package signing key received:

  Repository:       repo-oss
  Key Fingerprint:  AD48 5664 E901 B867 051A B15F 35A2 F86E 29B7 00A4
  Key Name:         openSUSE Project Signing Key <opensuse@opensuse.org>
  Key Algorithm:    RSA 4096
  Key Created:      Mon Jun 20 14:03:14 2022
  Key Expires:      Fri Jun 19 14:03:14 2026
  Rpm Name:         gpg-pubkey-29b700a4-62b07e22



    Note: Signing data enables the recipient to verify that no modifications occurred after the data
    were signed. Accepting data with no, wrong or unknown signature can lead to a corrupted system
    and in extreme cases even to a system compromise.

    Note: A GPG pubkey is clearly identified by its fingerprint. Do not rely on the key's name. If
    you are not sure whether the presented key is authentic, ask the repository provider or check
    their web site. Many providers maintain a web page showing the fingerprints of the GPG keys they
    are using.

Do you want to reject the key, trust temporarily, or trust always? [r/t/a/?] (r): r
Retrieving repository 'repo-oss' metadata ...........................................................................................................................................................................................[error]
Repository 'repo-oss' is invalid.
[repo-oss-c0ac3a781fa04059|https://download.opensuse.org/tumbleweed/repo/oss/] Valid metadata not found at specified URL
History:
 - Signature verification failed for repomd.xml

Please check if the URIs defined for this repository are pointing to a valid repository.
Skipping repository 'repo-oss' because of the above error.
Repository 'repo-update' is up to date.                                                                                                                                                                                                     
Some of the repositories have not been refreshed because of an error.
‣ "zypper --installroot=/buildroot --cache-dir=/var/cache/zypp --non-interactive --no-refresh refresh" returned non-zero exit code 4.
bash-5.2# cat /etc/zypp/zypp.conf 

[main]
rpm.install.excludedocs = no
repo.refresh.delay = 2880
bash-5.2# cat /etc/zypp/
repos.d/   zypp.conf  
bash-5.2# cat /etc/zypp/repos.d/
cat: /etc/zypp/repos.d/: Is a directory
bash-5.2# cat /etc/zypp/repos.d/mkosi.repo 
[repo-oss-c0ac3a781fa04059]
name=repo-oss
baseurl=https://download.opensuse.org/tumbleweed/repo/oss/
gpgcheck=1
enabled=1
autorefresh=0
keeppackages=1
gpgkey=file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE-Tumbleweed
       file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE

[repo-update-412afa78017485ce]
name=repo-update
baseurl=https://download.opensuse.org/update/tumbleweed/
gpgcheck=1
enabled=1
autorefresh=0
keeppackages=1
gpgkey=file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE-Tumbleweed
       file:///usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE

bash-5.2# ✗ gpg --show-keys /usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE-Tumbleweed
bash: ✗: command not found
bash-5.2# gpg --show-keys /usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE-Tumbleweed
gpg: directory '//.gnupg' created
pub   rsa4096 2022-06-20 [SC] [expires: 2026-06-19]
      AD485664E901B867051AB15F35A2F86E29B700A4
uid                      openSUSE Project Signing Key <opensuse@opensuse.org>

bash-5.2# gpg --show-keys /usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE
pub   rsa2048 2008-11-07 [SC] [expired: 2024-05-02]
      22C07BA534178CD02EFE22AAB88B2FD43DBDC284
uid                      openSUSE Project Signing Key <opensuse@opensuse.org>

bash-5.2# zypper --version
zypper 1.14.73
bash-5.2# rpm -qi zypper
Name        : zypper
Version     : 1.14.73
Release     : 1.fc41
Architecture: x86_64
Install Date: Fri Jun  7 09:48:38 2024
Group       : Unspecified
Size        : 7436543
License     : GPLv2+
Signature   : RSA/SHA256, Wed Jun  5 22:46:17 2024, Key ID d0622462e99d6ad1
Source RPM  : zypper-1.14.73-1.fc41.src.rpm
Build Date  : Wed Jun  5 22:18:34 2024
Build Host  : buildhw-x86-05.iad2.fedoraproject.org
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://en.opensuse.org/Portal:Zypper
Bug URL     : https://bugz.fedoraproject.org/zypper
Summary     : Command line package manager using libzypp
Description :
Zypper is a command line package manager tool using libzypp,
which can be used to manage software for RPM based systems.
bash-5.2# rpm -qi libzypp
Name        : libzypp
Version     : 17.34.1
Release     : 1.fc41
Architecture: x86_64
Install Date: Fri Jun  7 09:48:37 2024
Group       : Unspecified
Size        : 6799448
License     : GPLv2+
Signature   : RSA/SHA256, Wed Jun  5 22:45:58 2024, Key ID d0622462e99d6ad1
Source RPM  : libzypp-17.34.1-1.fc41.src.rpm
Build Date  : Wed Jun  5 13:25:24 2024
Build Host  : buildvm-x86-08.iad2.fedoraproject.org
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : https://en.opensuse.org/Portal:Libzypp
Bug URL     : https://bugz.fedoraproject.org/libzypp
Summary     : A package management library
Description :
libzypp is a library for package management built on top of the
libsolv library. It is the foundation for the Zypper package manager.

@jswolf19 it's in the maintenance QA queue for a while now. I can't tell how long it will take. We hat a bunch of submissions lately - up to 17.34.1 yesterday. Maybe they head for one of the newer versions.

@DaanDeMeyer sorry, but I don't understand the issue.

Apparently the repo metadata are signed with 35A2F86E29B700A4. The gpgkey=URL is one of the locations where (the fixed) libzypp tries to find a missing key. But the key was found. You got the message:

New repository or package signing key received:
...
  Key Fingerprint:  AD48 5664 E901 B867 051A B15F 35A2 F86E 29B7 00A4
...
Do you want to reject the key, trust temporarily, or trust always? [r/t/a/?] (r): r

But you decided to (r)eject the key. That's why the repo is discarded.

The URL just tells where we can find a key, but it's always up to the user to decide whether the key is trustwothy. Either interactively (trust temporarily, or trust always) or via --gpg-auto-import-keys.

@DaanDeMeyer sorry, but I don't understand the issue.

Apparently the repo metadata are signed with 35A2F86E29B700A4. The gpgkey=URL is one of the locations where (the fixed) libzypp tries to find a missing key. But the key was found. You got the message:

New repository or package signing key received:
...
  Key Fingerprint:  AD48 5664 E901 B867 051A B15F 35A2 F86E 29B7 00A4
...
Do you want to reject the key, trust temporarily, or trust always? [r/t/a/?] (r): r

But you decided to (r)eject the key. That's why the repo is discarded.

The URL just tells where we can find a key, but it's always up to the user to decide whether the key is trustwothy. Either interactively (trust temporarily, or trust always) or via --gpg-auto-import-keys.

@mlandres I expect zypper to trust keys from gpgkey= implicitly without having to explicitly specify --gpg-auto-import-keys. I do not want zypper to fetch gpg keys over the internet, it should only use the keys defined with gpgkey=.

There's no point in asking users to trust keys defined with gpgkey= /etc/zypp/repos.d is a trusted location and as such we can implicitly trust any keys defined in /etc/zypp/repos.d as its only writable by root.

So I would like to be able to tell zypper to only use the local gpg keys defined in gpgkey= and to implicitly trust those keys without having to specify --gpg-auto-import-keys. Alternatively, I'm OK with specifying --gpg-auto-import-keys as long as I can tell zypper to only use the keys from gpgkey= without having it try and download keys from the internet.

@DaanDeMeyer No, /etc/zypp/repos.d is IMO not a 'trusted location'. You can add repos by just downloading the .repo file a repository provides. Just like zypper ar https://download.opensuse.org/repositories/zypp:/Head/openSUSE_Tumbleweed/zypp:Head.repo. We can not assume that all .repo files are reviewed by the user.

If you have all the keys locally and want to trust just them, you could import them into the rpmdb (rpm --import PUBKEY ...). The keys stored in the rpmdb are the trusted ones (rpm -q gpg-pubkey).

@jswolf19 it's in the maintenance QA queue for a while now. I can't tell how long it will take. We hat a bunch of submissions lately - up to 17.34.1 yesterday. Maybe they head for one of the newer versions.

Ok, thanks for your help. I'll use my temporary repo for now, then.

@mlandres Is there a way to tell zypper to not try to read public keys from repodata/repomd.xml and repodata/repomd.xml.key? That would also solve my problem.

No, but may I ask why not?

We know the keyid from the repomd.xml's signature. The keyfiles we find ( repomd.xml.asc or gpgkey= or files in /var/cache/zypp/pubkeys) are imported into a temporary keyring. If the needed key is in the keyring, only this key is exported into the rpm database. We will never import all keys contained in a file.

@mlandres I have users that have concerns about downloading keys remotely and which would much rather that the key is provided out of band (see systemd/mkosi#757 for the full discussion). They would much rather see mkosi (which uses zypper internally for opensuse) use a model where the keys are installed beforehand and out of band rather than the package manager downloading the keys itself.

I'm inclined to agree with them and given that https://pkgs.org/download/distribution-gpg-keys is already somewhat widely packaged, I have an easy way to retrieve the opensuse GPG keys without needing zypper to download them for me from the repository.

So it would be great to have a mechanism available where I can tell zypper to only use the keys that I already provide locally and to not download keys itself.

For your usecase, this would be a new feature.

By manually importing these keys into the rpmdb you basically trust them, but nevertheless zypper will download available repomd.xml.key files and import them IF the key is already trusted, but was re-signed to extend the expiry date.

Also may a repomd.xml signed by a trusted key define additional key ids which should be imported together with the main key. OpenSUSE Leap AFAIK uses this because at least 2 keys are used to sign the the distribution packages (it's a mix of Leap and SLES packages).

Your usecase probably does not want to allow this as well.

For your usecase, this would be a new feature.

By manually importing these keys into the rpmdb you basically trust them, but nevertheless zypper will download available repomd.xml.key files and import them IF the key is already trusted, but was re-signed to extend the expiry date.

Also may a repomd.xml signed by a trusted key define additional key ids which should be imported together with the main key. OpenSUSE Leap AFAIK uses this because at least 2 keys are used to sign the the distribution packages (it's a mix of Leap and SLES packages).

Your usecase probably does not want to allow this as well.

Maybe this is OK in some cases but I would still prefer to be able to block all key downloads completely and to solely rely on local keys