-
Notifications
You must be signed in to change notification settings - Fork 41
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
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I'll wait for @di to approve since I've been modifying things.
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