sign, verify: Expose sign and verify as importable modules#383
sign, verify: Expose sign and verify as importable modules#383
Conversation
Signed-off-by: Alex Cameron <asc@tetsuo.sh>
|
Do we also want to somehow expose the web browser workflow and ambient credential detection? The signing side of the API is hard to use without these. Either that or only expose verification initially. I'm writing a simple example to test the verify API to get an idea for what this looks like for users. |
import base64
from pathlib import Path
from sigstore.verify import Verifier, VerificationMaterials
from sigstore.verify.policy import Identity
artifact = Path("README.md")
cert = Path("README.md.crt")
signature = Path("README.md.sig")
with artifact.open("rb") as a, cert.open("r") as c, signature.open("rb") as s:
materials = VerificationMaterials(
input_=a,
cert_pem=c.read(),
signature=base64.b64decode(s.read()),
offline_rekor_entry=None,
)
verifier = Verifier.production()
result = verifier.verify(
materials,
Identity(
identity="alex.cameron@trailofbits.com",
issuer="https://accounts.google.com",
),
)
print(result) |
Yeah, let's expose these as well. Let's make sure to expose the minimum surface necessary for each -- probably just the top-level functions/classes. |
Signed-off-by: Alex Cameron <asc@tetsuo.sh>
6fa4cfa to
a184741
Compare
| ) | ||
|
|
||
| def to_bundle(self) -> RekorBundle: | ||
| def from_entry(cls, entry: RekorEntry) -> RekorBundle: |
There was a problem hiding this comment.
I moved this to_bundle method from the RekorEntry to a from_entry class method. This minimises the public API and means that it doesn't have to know about this bundle type.
There was a problem hiding this comment.
That works for me. IMO it would also be acceptable to have the RekorBundle be part of the public API, since it's a well-defined public format already. But we can move forwards with this for now.
Signed-off-by: Alex Cameron <asc@tetsuo.sh>
| Raises `AmbientCredentialError` if any detector fails internally (i.e. | ||
| detects a credential, but cannot retrieve it). | ||
| """ | ||
| from sigstore._internal.oidc.ambient import detect_gcp, detect_github |
There was a problem hiding this comment.
Had to do this to avoid circular imports. I figured this would be better than further complicating the tree with more modules, but I can try fixing this another way if you'd like.
Signed-off-by: Alex Cameron <asc@tetsuo.sh>
9f6f6f9 to
4a8b76f
Compare
|
The sign workflow looks reasonable too. from pathlib import Path
from sigstore.sign import Signer
from sigstore.oidc import get_identity_token, Issuer
artifact = Path("README.md")
token = get_identity_token("sigstore", "", Issuer("https://oauth2.sigstore.dev/auth"))
with artifact.open("rb") as a:
signer = Signer.production()
result = signer.sign(input_=a, identity_token=token)
print(result) |
|
One thing to note. The constructors for The only issue is that |
|
Thanks @tetsuo-cpp! I'll review in a bit. |
Yeah, I don't think we want to expose those directly. I'll see about maybe hiding the constructor in the docs. |
Signed-off-by: William Woodruff <william@trailofbits.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
| @@ -122,9 +119,14 @@ def _set_default_verify_subparser(parser: argparse.ArgumentParser, name: str) -> | |||
| def _add_shared_instance_options(group: argparse._ArgumentGroup) -> None: | |||
There was a problem hiding this comment.
N.B.: Conceptually these common options belong at the global sigstore level, rather than embedded into each subcommand. I've moved one of them in this PR (--staging) because I needed to fix its behavior with get-identity-token, but I'll move the rest in a follow-up.
NB, this is now: from pathlib import Path
from sigstore.sign import Signer
from sigstore.oidc import Issuer
artifact = Path("README.md")
token = Issuer.production().identity_token()
with artifact.open("rb") as a:
signer = Signer.production()
result = signer.sign(input_=a, identity_token=token)
print(result) |
Signed-off-by: William Woodruff <william@trailofbits.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
|
Thanks @woodruffw. Those changes to the I can't approve my own PR but your changes LGTM. |
|
I'll go ahead and merge then! 🤞 |
Closes #4