Merge pull request #24 from msys2/sig-support

packages: show who signed the package and when
This commit is contained in:
Christoph Reiter
2020-07-04 10:46:15 +02:00
committed by GitHub
6 changed files with 106 additions and 3 deletions

View File

@@ -4,6 +4,7 @@
from __future__ import annotations
import re
import base64
import uuid
import time
from functools import cmp_to_key
@@ -12,6 +13,7 @@ from typing import List, Set, Dict, Tuple, Optional, Type, Sequence, NamedTuple
from .appconfig import REPOSITORIES
from .utils import vercmp, version_is_newer_than, extract_upstream_version
from .pgp import parse_signature
CygwinVersions = Dict[str, Tuple[str, str, str]]
@@ -222,7 +224,7 @@ class Package:
makedepends: List[str], md5sum: str, name: str, pgpsig: str, sha256sum: str, arch: str,
base_url: str, repo: str, repo_variant: str, provides: List[str], conflicts: List[str], replaces: List[str],
version: str, base: str, desc: str, groups: List[str], licenses: List[str], optdepends: List[str],
checkdepends: List[str]) -> None:
checkdepends: List[str], sig_data: str) -> None:
self.builddate = int(builddate)
self.csize = csize
@@ -235,6 +237,7 @@ class Package:
r.append((first, second))
return r
self.signature = parse_signature(base64.b64decode(sig_data))
self.depends = split_depends(depends)
self.checkdepends = split_depends(checkdepends)
self.filename = filename
@@ -317,7 +320,7 @@ class Package:
d.get("%REPLACES%", []), d["%VERSION%"][0], base,
d.get("%DESC%", [""])[0], d.get("%GROUPS%", []),
d.get("%LICENSE%", []), d.get("%OPTDEPENDS%", []),
d.get("%CHECKDEPENDS%", []))
d.get("%CHECKDEPENDS%", []), d.get("%PGPSIG%", [""])[0])
class Source:

57
app/pgp.py Normal file
View File

@@ -0,0 +1,57 @@
from pgpdump import BinaryData
from pgpdump.utils import PgpdumpException
from datetime import datetime
from typing import NamedTuple
import struct
import binascii
KNOWN_KEYS = {
"5F92EFC1A47D45A1": "Alexey Pavlov",
"4DF3B7664CA56930": "Ray Donnelly",
"D595C9AB2C51581E": "Martell Malone",
"974C8BE49078F532": "David Macek",
"FA11531AA0AA7F57": "Christoph Reiter",
}
class Signature(NamedTuple):
keyid: str
date: datetime
@property
def url(self) -> str:
return "http://pool.sks-keyservers.net/pks/lookup?op=vindex&fingerprint=on&search=0x" + self.keyid
@property
def name(self) -> str:
return KNOWN_KEYS.get(self.keyid.upper(), "Unknown")
class SigError(Exception):
pass
def parse_signature(sig_data: bytes) -> Signature:
date = None
keyid = None
try:
parsed = BinaryData(sig_data)
except PgpdumpException as e:
raise SigError(e)
for x in parsed.packets():
if x.raw == 2:
for sub in x.subpackets:
if sub.subtype == 2:
date = datetime.utcfromtimestamp(struct.unpack('>I', sub.data)[0])
if sub.subtype == 16:
keyid = binascii.hexlify(sub.data).decode()
if keyid is None:
raise SigError("keyid missing")
if date is None:
raise SigError("date missing")
return Signature(keyid, date)

View File

@@ -43,6 +43,12 @@
<dt class="col-sm-3 text-sm-right">Build Date:</dt>
<dd class="col-sm-9">{{ p.builddate|timestamp }}</dd>
<dt class="col-sm-3 text-sm-right">Signed By:</dt>
<dd class="col-sm-9"><a href="{{ p.signature.url }}">{{ p.signature.name }}</a></dd>
<dt class="col-sm-3 text-sm-right">Signature Date:</dt>
<dd class="col-sm-9">{{ p.signature.date }}</dd>
<dt class="col-sm-3 text-sm-right">Package Size:</dt>
<dd class="col-sm-9">{{ p.csize|filesize }}</dd>

13
poetry.lock generated
View File

@@ -297,6 +297,14 @@ version = "20.4"
pyparsing = ">=2.0.2"
six = "*"
[[package]]
category = "main"
description = "PGP packet parser library"
name = "pgpdump"
optional = false
python-versions = "*"
version = "1.5"
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
@@ -538,7 +546,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
content-hash = "65b0ed368759d67e2016c027ea98952449a27db72c2555fc779d54936ae4f31c"
content-hash = "2c191d8d34f6865392bd1df633bf1ec72ea1ed51f7c6d33940b2e37679c4d78d"
python-versions = "^3.7"
[metadata.files]
@@ -707,6 +715,9 @@ packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
pgpdump = [
{file = "pgpdump-1.5.tar.gz", hash = "sha256:1c4700857bf7ba735b08cfe4101aa3a4f5fd839657af249c17b2697c20829668"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},

View File

@@ -13,6 +13,7 @@ uvicorn = "^0.11.5"
aiofiles = "^0.5.0"
jinja2 = "^2.11.2"
fastapi-etag = "^0.2.1"
pgpdump = "^1.5"
[tool.poetry.dev-dependencies]
mypy = "^0.770"

View File

@@ -1,11 +1,14 @@
# type: ignore
import os
import base64
import datetime
import respx
import pytest
from app import app
from app.fetch import parse_cygwin_versions
from app.pgp import parse_signature, SigError, Signature
from fastapi.testclient import TestClient
@@ -81,3 +84,25 @@ def test_webhook_push(client, monkeypatch):
r.raise_for_status()
assert "msg" in r.json()
assert "1234" in r.json()["msg"]
EXAMPLE_SIG = (
"iHUEABEIAB0WIQStNRxQrghXdetZMztfku/BpH1FoQUCXlOY5wAKCRBfku"
"/BpH1FodQoAP4nQnPNLnx5MVIJgZgCwW/hplW7Ai9MqkmFBqD8/+EXfAD/"
"Rgxtz2XH7RZ1JKh7PN5NsVz9UlBM7977PjFg9WptNGU=")
def test_pgp():
with pytest.raises(SigError):
parse_signature(b"")
with pytest.raises(SigError):
parse_signature(b"foobar")
data = base64.b64decode(EXAMPLE_SIG)
sig = parse_signature(data)
assert isinstance(sig, Signature)
assert sig.keyid == "5f92efc1a47d45a1"
assert sig.date == datetime.datetime(2020, 2, 24, 9, 35, 35)
assert sig.name == "Alexey Pavlov"
assert sig.url == "http://pool.sks-keyservers.net/pks/lookup?op=vindex&fingerprint=on&search=0x5f92efc1a47d45a1"