Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1,818 changes: 1,121 additions & 697 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ zeroize = { version = "1.8", features = ["derive"] }

# CLI and async/runtime
clap = { version = "4.6", features = ["derive"] }
tokio = "1.50.0"
tokio = { version = "1.50.0", features = ["rt-multi-thread"] }

# Serialization
serde = { version = "1.0", features = ["derive"] }
Expand All @@ -72,6 +72,13 @@ protobuf-json-mapping = "3.7.2"
reqwest = { version = "0.13.2", features = ["blocking", "json"] }
subtle = "2.6.1"

# Sigstore
sigstore-types = "0.6.5"
sigstore-rekor = { version = "0.6.5", default-features = false, features = ["rustls"] }
sigstore-fulcio = { version = "0.6.5", default-features = false, features = ["rustls"] }
sigstore-oidc = { version = "0.6.5", default-features = false, features = ["rustls"] }
sigstore-crypto = "0.6.5"

[dev-dependencies]
tempfile = "3.27.0"

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ A command-line interface tool for creating, managing, and verifying Content Prov
- **Model & Dataset Manifests**: Create C2PA-compliant manifests for ML models and datasets
- **Cryptographic Signing**: Sign manifests with cryptographic keys for authenticity verification, incl. support for the [OpenSSF Model Signing] (OMS) specification.
- **Provenance Linking**: Create verifiable links between models, datasets, and ML assets
- **Multiple Storage Types**: Store manifests in [Atlas Transparency Log](https://github.com/IntelLabs/atlas-transparency-log), Rekor log, or filesystem backends
- **Multiple Storage Types**: Store manifests in [Atlas Transparency Log](https://github.com/IntelLabs/atlas-transparency-log), [Sigstore Rekor](https://docs.sigstore.dev/logging/overview/) transparency log, or filesystem backends
- **Rekor Verification**: Verify manifests against Rekor entries (payload hash + DSSE signature)
- **Format Support**: Work with models in ONNX, TensorFlow, PyTorch, and Keras formats
- **TEE Attestation**: Optional support for Trusted Execution Environment (TDX) integration

Expand Down
57 changes: 57 additions & 0 deletions docs/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,63 @@ atlas-cli software link-model \
--model-id=$MODEL_ID
```

## Rekor Transparency Log Examples

### Storing a Manifest in Rekor

```bash
# Store a model manifest in the public Rekor log
atlas-cli model create \
--paths=model.onnx \
--ingredient-names="Model" \
--name="My Model" \
--key=private.pem \
--cert=cert.pem \
Comment thread
marcelamelara marked this conversation as resolved.
--storage-type=rekor \
--storage-url=https://rekor.sigstore.dev
# Output: Rekor entry UUID
# Save the UUID and keep the manifest JSON for later verification
```

### Storing a Manifest with Fulcio (OIDC)

Instead of providing your own key and certificate, you can use Fulcio to obtain a short-lived certificate via an OIDC identity token. An ephemeral signing key is generated automatically.

```bash
atlas-cli model create \
--paths=model.onnx \
--ingredient-names="Model" \
--name="My Model" \
--fulcio \
--oidc-token=<OIDC_TOKEN> \
--storage-type=rekor \
--storage-url=https://rekor.sigstore.dev
```

### Verifying a Manifest Against Rekor

```bash
# Verify that a local manifest matches the Rekor entry
atlas-cli rekor verify \
--uuid <REKOR_UUID> \
--manifest manifest.json

# Example output:
# Rekor Verification Result:
# Log index: 1367633236
# Integrated time: 1777010403
# Payload hash: MATCH
# Signature: VALID
#
# Verification PASSED: manifest matches Rekor entry.
```

### Looking Up a Rekor Entry

```bash
atlas-cli rekor get --uuid <REKOR_UUID>
```

## Output Format Examples

### JSON Output Format
Expand Down
54 changes: 51 additions & 3 deletions docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ Subcommands:
- `link-model` - Link software to a model
- `link-dataset` - Link software to a dataset

### Rekor Commands

```
atlas-cli rekor [SUBCOMMAND]
```

Subcommands:
- `verify` - Verify a local manifest against a Rekor transparency log entry
- `get` - Look up a Rekor entry by UUID

## Configuration Options

### Keys for Signing
Expand Down Expand Up @@ -169,15 +179,53 @@ atlas-cli model create \

### Rekor Storage

Stores manifests in a Rekor transparency log:
Stores manifests as DSSE envelopes in a [Sigstore Rekor](https://docs.sigstore.dev/logging/overview/) transparency log. Rekor records the payload hash, signature, and certificate — not the full manifest content. You must keep the manifest file locally for later verification.
Comment thread
marcelamelara marked this conversation as resolved.

**Note:** The default Rekor URL is the public Sigstore instance (`https://rekor.sigstore.dev`). Use `--storage-url` to point to a private instance.

Requires a signing key (`--key`) and either a certificate (`--cert`) or Fulcio OIDC flow (`--fulcio --oidc-token`):

```bash
export REKOR_URL=https://rekor.example.com
# Store with a certificate file
atlas-cli model create \
--paths=model.onnx \
--ingredient-names="Model" \
--name="My Model" \
--key=private.pem \
--cert=cert.pem \
--storage-type=rekor \
...
--storage-url=https://rekor.sigstore.dev
# Output: Rekor entry UUID

# Store with Fulcio (OIDC-based certificate)
atlas-cli model create \
--paths=model.onnx \
--ingredient-names="Model" \
--name="My Model" \
--fulcio \
--oidc-token=<TOKEN> \
--storage-type=rekor \
--storage-url=https://rekor.sigstore.dev
```

### Rekor Commands

Look up and verify Rekor entries directly:

```bash
# Verify a local manifest against a Rekor entry
atlas-cli rekor verify \
--uuid <REKOR_UUID> \
--manifest manifest.json

# Look up a Rekor entry
atlas-cli rekor get --uuid <REKOR_UUID>
```

Verification checks:
1. **Payload hash** — SHA-256 of the local manifest matches the hash recorded in Rekor
2. **Signature** — the DSSE signature is valid against the certificate stored in the entry
Comment thread
marcelamelara marked this conversation as resolved.

## TDX Attestation

When built with the `with-tdx` feature, you can both create attested manifests and verify
Expand Down
76 changes: 76 additions & 0 deletions src/cli/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ pub enum DatasetCommands {
#[arg(long = "key")]
key: Option<PathBuf>,

/// Path to X.509 certificate file (PEM format, required for Rekor storage)
#[arg(long = "cert")]
cert: Option<PathBuf>,

/// Use Fulcio to obtain a certificate via OIDC (alternative to --cert)
#[arg(long = "fulcio", default_value = "false")]
fulcio: bool,

/// OIDC identity token for Fulcio (required when --fulcio is set)
#[arg(long = "oidc-token")]
oidc_token: Option<String>,

/// Hash algorithm to use for signing (default: sha384)
#[arg(long = "hash-alg", value_enum, default_value = "sha384")]
hash_alg: HashAlgorithmChoice,
Expand Down Expand Up @@ -137,6 +149,18 @@ pub enum ModelCommands {
#[arg(long = "key")]
key: Option<PathBuf>,

/// Path to X.509 certificate file (PEM format, required for Rekor storage)
#[arg(long = "cert")]
cert: Option<PathBuf>,

/// Use Fulcio to obtain a certificate via OIDC (alternative to --cert)
#[arg(long = "fulcio", default_value = "false")]
fulcio: bool,

/// OIDC identity token for Fulcio (required when --fulcio is set)
#[arg(long = "oidc-token")]
oidc_token: Option<String>,

/// Hash algorithm to use for signing (default: sha384)
#[arg(long = "hash-alg", value_enum, default_value = "sha384")]
hash_alg: HashAlgorithmChoice,
Expand Down Expand Up @@ -343,6 +367,18 @@ pub enum EvaluationCommands {
#[arg(long = "key")]
key: Option<PathBuf>,

/// Path to X.509 certificate file (PEM format, required for Rekor storage)
#[arg(long = "cert")]
cert: Option<PathBuf>,

/// Use Fulcio to obtain a certificate via OIDC (alternative to --cert)
#[arg(long = "fulcio", default_value = "false")]
fulcio: bool,

/// OIDC identity token for Fulcio (required when --fulcio is set)
#[arg(long = "oidc-token")]
oidc_token: Option<String>,

/// Hash algorithm to use for signing (default: sha384)
#[arg(long = "hash-alg", value_enum, default_value = "sha384")]
hash_alg: HashAlgorithmChoice,
Expand Down Expand Up @@ -450,6 +486,18 @@ pub enum SoftwareCommands {
#[arg(long = "key")]
key: Option<PathBuf>,

/// Path to X.509 certificate file (PEM format, required for Rekor storage)
#[arg(long = "cert")]
cert: Option<PathBuf>,

/// Use Fulcio to obtain a certificate via OIDC (alternative to --cert)
#[arg(long = "fulcio", default_value = "false")]
fulcio: bool,

/// OIDC identity token for Fulcio (required when --fulcio is set)
#[arg(long = "oidc-token")]
oidc_token: Option<String>,

/// Hash algorithm to use for signing (default: sha384)
#[arg(long = "hash-alg", value_enum, default_value = "sha384")]
hash_alg: HashAlgorithmChoice,
Expand Down Expand Up @@ -535,6 +583,34 @@ pub enum SoftwareCommands {
},
}

#[derive(Debug, Subcommand)]
pub enum RekorCommands {
/// Verify a local manifest against a Rekor transparency log entry
Verify {
/// Rekor entry UUID
#[arg(long = "uuid")]
uuid: String,

/// Path to the local manifest JSON file
#[arg(long = "manifest")]
manifest: PathBuf,

/// Rekor server URL
#[arg(long = "rekor-url", default_value = "https://rekor.sigstore.dev")]
rekor_url: String,
},
/// Look up a Rekor entry by UUID
Get {
/// Rekor entry UUID
#[arg(long = "uuid")]
uuid: String,

/// Rekor server URL
#[arg(long = "rekor-url", default_value = "https://rekor.sigstore.dev")]
rekor_url: String,
},
}

#[derive(Debug, Subcommand)]
pub enum PipelineCommands {
/// Generate SLSA Build Provenance v1 for the given pipeline
Expand Down
Loading
Loading