Skip to content

Unable to replicate keyless cosign sign ... using basic Env #1609

@tarilabs

Description

@tarilabs

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions