-
Notifications
You must be signed in to change notification settings - Fork 63
Description
Description
I'm trying to do the python analogous of:
echo $TUF_URL
echo $FULCIO_URL
cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.json
cosign sign -y --fulcio-url=$FULCIO_URL --identity-token=$TOKEN <SOMETHING TO SIGN>programmatically using sigstore (python) but I'm not able to understand how to Initalize/TUF and how to use the Token I have "on hand" which I typically pass as $TOKEN above.
I've followed the documentation, and I'm currently stuck at trying to find the equivalent of initializing.
If I try:
from pathlib import Path
from sigstore.models import ClientTrustConfig
from sigstore.oidc import Issuer
from sigstore.sign import SigningContext
artifact_path = Path("README.txt")
trust_config = ClientTrustConfig.from_tuf(os.environ["TUF_URL"])I get:
FileNotFoundError: [Errno 2] No such file or directory: '/opt/app-root/src/.local/share/sigstore-python/tuf/<TUF_URL VALUE>/root.json'
The above exception was the direct cause of the following exception:
TUFError Traceback (most recent call last)
Cell In[12], line 8
4 from sigstore.sign import SigningContext
6 artifact_path = Path("README.txt")
----> 8 trust_config = ClientTrustConfig.from_tuf("asd")
File [/opt/app-root/lib64/python3.12/site-packages/sigstore/models.py:963](https://....openshiftapps.com/opt/app-root/lib64/python3.12/site-packages/sigstore/models.py#line=962), in ClientTrustConfig.from_tuf(cls, url, offline, bootstrap_root)
951 @classmethod
952 def from_tuf(
953 cls,
(...) 956 bootstrap_root: Path | None = None,
957 ) -> ClientTrustConfig:
958 """Create a new trust config from a TUF repository.
959
960 If `offline`, will use data in local TUF cache. Otherwise will
961 update the trust config from remote TUF repository.
962 """
--> 963 updater = TrustUpdater(url, offline, bootstrap_root)
965 tr_path = updater.get_trusted_root_path()
966 inner_tr = trustroot_v1.TrustedRoot.from_json(Path(tr_path).read_bytes())
File [/opt/app-root/lib64/python3.12/site-packages/sigstore/_internal/tuf.py:129](https://....openshiftapps.com/opt/app-root/lib64/python3.12/site-packages/sigstore/_internal/tuf.py#line=128), in TrustUpdater.__init__(self, url, offline, bootstrap_root)
127 self._updater.refresh()
128 except Exception as e:
--> 129 raise TUFError("Failed to refresh TUF metadata") from e
TUFError: Failed to refresh TUF metadata
So, I assume I need to download from the TUF server the root.json and place it in that location?
I do so with:
import os, urllib.parse, requests, pathlib
tuf_url = os.environ["TUF_URL"]
encoded = urllib.parse.quote(tuf_url, safe='')
dest = pathlib.Path(f"/opt/app-root/src/.local/share/sigstore-python/tuf/{encoded}")
dest.mkdir(parents=True, exist_ok=True)
r = requests.get(f"{tuf_url}/root.json")
r.raise_for_status()
(dest / "root.json").write_bytes(r.content)
print(f"Saved to {dest / 'root.json'}")Then, I try again the above
from pathlib import Path
from sigstore.models import ClientTrustConfig
from sigstore.oidc import Issuer
from sigstore.sign import SigningContext
artifact_path = Path("README.txt")
trust_config = ClientTrustConfig.from_tuf(os.environ["TUF_URL"])But this time I get:
ValidationError Traceback (most recent call last)
Cell In[11], line 8
4 from sigstore.sign import SigningContext
6 artifact_path = Path("README.txt")
----> 8 trust_config = ClientTrustConfig.from_tuf(os.environ["TUF_URL"])
File [/opt/app-root/lib64/python3.12/site-packages/sigstore/models.py:966](https://....openshiftapps.com/opt/app-root/lib64/python3.12/site-packages/sigstore/models.py#line=965), in ClientTrustConfig.from_tuf(cls, url, offline, bootstrap_root)
963 updater = TrustUpdater(url, offline, bootstrap_root)
965 tr_path = updater.get_trusted_root_path()
--> 966 inner_tr = trustroot_v1.TrustedRoot.from_json(Path(tr_path).read_bytes())
968 try:
969 sc_path = updater.get_signing_config_path()
File [/opt/app-root/lib64/python3.12/site-packages/sigstore_models/_core.py:22](https://....openshiftapps.com/opt/app-root/lib64/python3.12/site-packages/sigstore_models/_core.py#line=21), in Base.from_json(cls, json)
20 @classmethod
21 def from_json(cls, json: str | bytes) -> te.Self:
---> 22 return cls.model_validate_json(json)
File [/opt/app-root/lib64/python3.12/site-packages/pydantic/main.py:766](https://....openshiftapps.com/opt/app-root/lib64/python3.12/site-packages/pydantic/main.py#line=765), in BaseModel.model_validate_json(cls, json_data, strict, extra, context, by_alias, by_name)
760 if by_alias is False and by_name is not True:
761 raise PydanticUserError(
762 'At least one of `by_alias` or `by_name` must be set to True.',
763 code='validate-by-alias-and-name-false',
764 )
--> 766 return cls.__pydantic_validator__.validate_json(
767 json_data, strict=strict, extra=extra, context=context, by_alias=by_alias, by_name=by_name
768 )
ValidationError: 2 validation errors for TrustedRoot
tlogs.0.logId
Field required [type=missing, input_value={'baseUrl': 'https://reko...jdepp+ybrrskst3yax5c=/'}}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/missing
ctlogs.0.logId
Field required [type=missing, input_value={'baseUrl': 'https://ctlo...oof955zem9hfxi8ejbz4=/'}}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/missing
How do I setup the root of trust?
How do I pass the Fulcio URL and my Token when signing?
When I'm trying this overall keyless sign flow inside a K8s Pod with cosign (binary) it works with the top above snippet without any issue, keyless signing using the SA Token. My Fulcio instance seems to connects to the setup OIDC instance and the artifact is signed with the expected identity.
Thanks in advance!
Version
Collecting sigstore
Downloading sigstore-4.1.0-py3-none-any.whl.metadata (16 kB)
while using tutorial for cosign
cosign: 2.5.3