Skip to content

[DRAFT] Rekor v1 and v2 support via signing-config #1387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 103 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
d76d72e
set endpoint to v2
ramonpetgrave64 Apr 25, 2025
1c9885c
test with local rekorv2
ramonpetgrave64 Apr 25, 2025
c0a278c
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 5, 2025
e602ee9
seems to work, but no kind-version
ramonpetgrave64 May 5, 2025
79a6d31
no trailing slash for post to /entries
ramonpetgrave64 May 6, 2025
2d658ba
signing worksa
ramonpetgrave64 May 6, 2025
f2e6479
signing, but no verify
ramonpetgrave64 May 6, 2025
e4470a9
cache the kindversion
ramonpetgrave64 May 7, 2025
f69efca
parse kind_version earlier
ramonpetgrave64 May 7, 2025
a6025a5
Revert "no trailing slash for post to /entries"
ramonpetgrave64 May 7, 2025
b06b4b5
lint
ramonpetgrave64 May 8, 2025
7777935
add PR link
ramonpetgrave64 May 8, 2025
0172eed
Merge branch 'main' into kindversion
ramonpetgrave64 May 8, 2025
088a452
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 8, 2025
ac4f29d
semi-working verification
ramonpetgrave64 May 8, 2025
313da43
Merge branch 'main' into kindversion
ramonpetgrave64 May 9, 2025
0b765a0
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 9, 2025
8e4c394
add support for ed25519 keys
ramonpetgrave64 May 9, 2025
d03cb47
Merge branch 'main' into ed25519
ramonpetgrave64 May 9, 2025
ee73bb4
add changelog self link
ramonpetgrave64 May 9, 2025
dad8ff6
lint
ramonpetgrave64 May 9, 2025
95d6e11
use latest tsa release, not latest tag
ramonpetgrave64 May 9, 2025
da72b8a
add changelog for tsa test fix
ramonpetgrave64 May 9, 2025
ec37a9e
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 9, 2025
146f85e
use all verified timestamps
ramonpetgrave64 May 9, 2025
830ea64
additional test
ramonpetgrave64 May 9, 2025
17a9716
cleanup
ramonpetgrave64 May 9, 2025
2e93051
pr backlink
ramonpetgrave64 May 9, 2025
f1058e8
attempt at root hash hex parse for v1 and v2
ramonpetgrave64 May 9, 2025
9fb64c3
Revert "cache the kindversion"
ramonpetgrave64 May 12, 2025
ceeb367
Reapply "cache the kindversion"
ramonpetgrave64 May 12, 2025
6642f12
add test and data for a late timestamp
ramonpetgrave64 May 12, 2025
0375ed2
better documentation
ramonpetgrave64 May 12, 2025
6d9d7a8
lint
ramonpetgrave64 May 12, 2025
c6b6981
Merge branch 'main' into verify-artifact-signing-time
ramonpetgrave64 May 12, 2025
95b6fdb
Merge branch 'main' into kindversion
ramonpetgrave64 May 12, 2025
d5da6e1
Merge branch 'main' into ed25519
ramonpetgrave64 May 12, 2025
d9ca17e
Revert "attempt at root hash hex parse for v1 and v2"
ramonpetgrave64 May 12, 2025
1d9a669
inclusion_promise typing
ramonpetgrave64 May 12, 2025
b7403d3
post inclusion promise check
ramonpetgrave64 May 12, 2025
46b0087
betterproto: avoid assigning a var of type Optional[InclusionPromise]…
ramonpetgrave64 May 12, 2025
c961b52
add test
ramonpetgrave64 May 12, 2025
43dc468
Revert "betterproto: avoid assigning a var of type Optional[Inclusion…
ramonpetgrave64 May 12, 2025
274dc23
cleanup
ramonpetgrave64 May 12, 2025
3f58569
Reapply "betterproto: avoid assigning a var of type Optional[Inclusio…
ramonpetgrave64 May 12, 2025
d61a004
cleanup
ramonpetgrave64 May 12, 2025
76f7701
format
ramonpetgrave64 May 12, 2025
1110d20
add tests
ramonpetgrave64 May 13, 2025
f1bcac7
Merge branch 'ed25519' of github.com:ramonpetgrave64/sigstore-python …
ramonpetgrave64 May 13, 2025
ea6d659
dosctring for test
ramonpetgrave64 May 13, 2025
676294a
format
ramonpetgrave64 May 13, 2025
ac63406
fix filename
ramonpetgrave64 May 13, 2025
fa4696c
Merge branch 'ed25519' into rekor-v2
ramonpetgrave64 May 13, 2025
8e5036b
undo sighash comment
ramonpetgrave64 May 13, 2025
99b9c99
Merge branch 'main' into kindversion
ramonpetgrave64 May 14, 2025
c3d70e9
Merge branch 'main' into verify-artifact-signing-time
ramonpetgrave64 May 14, 2025
7e3ef0a
also delete integrated_time
ramonpetgrave64 May 14, 2025
41a5a10
lint
ramonpetgrave64 May 14, 2025
457ba8c
private .__kind_version
ramonpetgrave64 May 14, 2025
f47ef16
test with missing inclusion promise
ramonpetgrave64 May 14, 2025
65e9a1a
add demo v2 types
ramonpetgrave64 May 14, 2025
f65654e
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 14, 2025
3a84612
Merge branch 'verify-artifact-signing-time' into rekor-v2
ramonpetgrave64 May 14, 2025
a1def04
some types
ramonpetgrave64 May 15, 2025
c0c44db
edit the fields before instantiating the bundle
ramonpetgrave64 May 15, 2025
618be8a
gen from rekor-tiles
ramonpetgrave64 May 15, 2025
48217d4
pydantic types
ramonpetgrave64 May 15, 2025
1b0c7d9
branching on api_major_version
ramonpetgrave64 May 16, 2025
5b79cc2
verification
ramonpetgrave64 May 16, 2025
07566cf
both v1 and v2 signing and verifying
ramonpetgrave64 May 16, 2025
72aad2b
reformat
ramonpetgrave64 May 16, 2025
7eaa090
cleanup
ramonpetgrave64 May 16, 2025
609c974
add trust_configs
ramonpetgrave64 May 16, 2025
68a9bb3
Merge branch 'verify-artifact-signing-time' into rekor-v2
ramonpetgrave64 May 16, 2025
37da294
actual_body = rekor_types.Hashedrekord.model
ramonpetgrave64 May 16, 2025
203b9c0
merge
ramonpetgrave64 May 16, 2025
6872749
3.10 style types
ramonpetgrave64 May 16, 2025
c3b32c9
reformat
ramonpetgrave64 May 16, 2025
b2fd364
py39 types
ramonpetgrave64 May 16, 2025
b09afa3
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 16, 2025
ace0dfb
independent RekorV2Client
ramonpetgrave64 May 16, 2025
7ad3185
cleanup
ramonpetgrave64 May 16, 2025
b4f148a
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 16, 2025
578758f
use HashOutput from protobuf specs
ramonpetgrave64 May 16, 2025
9a066e8
back to imported HasHOutput
ramonpetgrave64 May 16, 2025
a0e6616
refactor the building of the hashedrekord preposed entries
ramonpetgrave64 May 16, 2025
895ea51
specific kindversions when verifying
ramonpetgrave64 May 16, 2025
2c0508c
import from typing_extensions import TypeAlias
ramonpetgrave64 May 16, 2025
686ccf8
smaller diff
ramonpetgrave64 May 16, 2025
b9a8bae
no google bufs
ramonpetgrave64 May 16, 2025
e272425
unused var
ramonpetgrave64 May 16, 2025
2d50e48
list not List
ramonpetgrave64 May 16, 2025
cdd6de2
add cli test for v2, using local rekorv2
ramonpetgrave64 May 17, 2025
f8a198e
xfail and comment
ramonpetgrave64 May 17, 2025
f057e81
test local env
ramonpetgrave64 May 19, 2025
1f96143
add workflow
ramonpetgrave64 May 19, 2025
95cff0a
sign and verify dsse
ramonpetgrave64 May 19, 2025
e759b8a
alpha ytsu_config
ramonpetgrave64 May 22, 2025
ac517e8
with v1 key
ramonpetgrave64 May 22, 2025
144ac9b
Merge branch 'main' into rekor-v2
ramonpetgrave64 May 23, 2025
435ddb0
no V002 workaround
ramonpetgrave64 May 23, 2025
cd52b93
sign but cant parse entry
ramonpetgrave64 May 23, 2025
6258926
worarkound entry body parsing
ramonpetgrave64 May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/with-setup-sigstore-env.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: test-with-setup-sigstore-env

on:
push:
branches:
- main
- series/*
pull_request:
schedule:
- cron: '0 12 * * *'

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: sigstore/scaffolding/actions/setup-sigstore-env
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ matrix.conf.py }}
allow-prereleases: true
cache: "pip"
cache-dependency-path: pyproject.toml
- env:
TEST_SETUP_SIGSTORE_ENV: true
run: pytest -k test_sign_prehashed_rekorv2
126 changes: 124 additions & 2 deletions sigstore/_internal/rekor/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from __future__ import annotations

import base64
import json
import logging
from abc import ABC
Expand All @@ -26,15 +27,23 @@

import rekor_types
import requests
from cryptography.hazmat.primitives import serialization
from cryptography.x509 import Certificate

from sigstore._internal import USER_AGENT
from sigstore._internal.rekor_tiles.dev.sigstore.common import v1
from sigstore._internal.rekor_tiles.dev.sigstore.rekor import v2
from sigstore.hashes import Hashed
from sigstore.models import LogEntry

_logger = logging.getLogger(__name__)

DEFAULT_REKOR_URL = "https://rekor.sigstore.dev"
STAGING_REKOR_URL = "https://rekor.sigstage.dev"

REKOR_V1_API_MAJOR_VERSION = 1
REKOR_V2_API_MAJOR_VERSION = 2


@dataclass(frozen=True)
class RekorLogInfo:
Expand Down Expand Up @@ -144,8 +153,7 @@ def get(
return LogEntry._from_response(resp.json())

def post(
self,
proposed_entry: rekor_types.Hashedrekord | rekor_types.Dsse,
self, proposed_entry: rekor_types.Hashedrekord | rekor_types.Dsse
) -> LogEntry:
"""
Submit a new entry for inclusion in the Rekor log.
Expand Down Expand Up @@ -239,6 +247,34 @@ def __del__(self) -> None:
"""
self.session.close()

@classmethod
def _build_hashed_rekord_request(
cls,
hashed_input: Hashed,
signature: bytes,
certificate: Certificate,
) -> rekor_types.Hashedrekordkord:
return rekor_types.Hashedrekord(
spec=rekor_types.hashedrekord.HashedrekordV001Schema(
signature=rekor_types.hashedrekord.Signature(
content=base64.b64encode(signature).decode(),
public_key=rekor_types.hashedrekord.PublicKey(
content=base64.b64encode(
certificate.public_bytes(
encoding=serialization.Encoding.PEM
)
).decode()
),
),
data=rekor_types.hashedrekord.Data(
hash=rekor_types.hashedrekord.Hash(
algorithm=hashed_input._as_hashedrekord_algorithm(),
value=hashed_input.digest.hex(),
)
),
),
)

@classmethod
def production(cls) -> RekorClient:
"""
Expand All @@ -261,3 +297,89 @@ def log(self) -> RekorLog:
Returns a `RekorLog` adapter for making requests to a Rekor log.
"""
return RekorLog(f"{self.url}/log", session=self.session)


class RekorV2Client:
"""The internal Rekor client for the v2 API"""

# TODO: implement get_tile, get_entry_bundle, get_checkpoint.

def __init__(self, base_url: str) -> None:
"""
Create a new `RekorV2Client` from the given URL.
"""
self.url = f"{base_url}/api/v2"
self.session = requests.Session()
self.session.headers.update(
{
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": USER_AGENT,
}
)

def __del__(self) -> None:
"""
Terminates the underlying network session.
"""
self.session.close()

def create_entry(self, request: v2.CreateEntryRequest) -> LogEntry:
"""
Submit a new entry for inclusion in the Rekor log.
"""
# There may be a bug in betterproto, where the V_0_0_2 is changed to V002.
payload = request.to_dict()
_logger.debug(f"request: {json.dumps(payload)}")
resp = self.session.post(f"{self.url}/log/entries", json=payload)

try:
resp.raise_for_status()
except requests.HTTPError as http_error:
raise RekorClientError(http_error)

integrated_entry = resp.json()
_logger.debug(f"integrated: {integrated_entry}")
return LogEntry._from_dict_rekor(integrated_entry)

@classmethod
def _build_create_entry_request(
cls,
hashed_input: Hashed,
signature: bytes,
certificate: Certificate,
key_details: v1.PublicKeyDetails,
) -> v2.CreateEntryRequest:
return v2.CreateEntryRequest(
hashed_rekord_request_v0_0_2=v2.HashedRekordRequestV002(
digest=hashed_input.digest,
signature=v2.Signature(
content=signature,
verifier=v2.Verifier(
public_key=v2.PublicKey(
raw_bytes=certificate.public_key().public_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
),
key_details=key_details,
),
),
)
)

@classmethod
def production(cls) -> RekorClient:
"""
Returns a `RekorClient` populated with the default Rekor production instance.
"""
return cls(
DEFAULT_REKOR_URL,
)

@classmethod
def staging(cls) -> RekorClient:
"""
Returns a `RekorClient` populated with the default Rekor staging instance.
"""
return cls(STAGING_REKOR_URL)
Empty file.
Empty file.
Empty file.
Empty file.
Loading
Loading