Skip to content

Commit 73fc3b0

Browse files
committed
add sigstore-cache
1 parent 2c0362a commit 73fc3b0

File tree

15 files changed

+1419
-2
lines changed

15 files changed

+1419
-2
lines changed

Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"crates/sigstore-tsa",
88
"crates/sigstore-trust-root",
99
"crates/sigstore-bundle",
10+
"crates/sigstore-cache",
1011
"crates/sigstore-rekor",
1112
"crates/sigstore-fulcio",
1213
"crates/sigstore-oidc",
@@ -94,5 +95,6 @@ sigstore-bundle = { path = "crates/sigstore-bundle", version = "0.2.0" }
9495
sigstore-rekor = { path = "crates/sigstore-rekor", version = "0.2.0" }
9596
sigstore-fulcio = { path = "crates/sigstore-fulcio", version = "0.2.0" }
9697
sigstore-oidc = { path = "crates/sigstore-oidc", version = "0.2.0" }
98+
sigstore-cache = { path = "crates/sigstore-cache", version = "0.2.0" }
9799
sigstore-verify = { path = "crates/sigstore-verify", version = "0.2.0" }
98100
sigstore-sign = { path = "crates/sigstore-sign", version = "0.2.0" }

crates/sigstore-cache/Cargo.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "sigstore-cache"
3+
description = "Flexible caching support for Sigstore clients"
4+
version.workspace = true
5+
edition.workspace = true
6+
license.workspace = true
7+
repository.workspace = true
8+
rust-version.workspace = true
9+
10+
[dependencies]
11+
# Error handling
12+
thiserror.workspace = true
13+
14+
# Serialization
15+
serde.workspace = true
16+
serde_json.workspace = true
17+
18+
# Async
19+
tokio = { workspace = true, features = ["fs", "sync", "time"] }
20+
21+
# Directory utilities
22+
directories.workspace = true
23+
24+
# Time
25+
chrono.workspace = true
26+
27+
[dev-dependencies]
28+
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }

crates/sigstore-cache/README.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# sigstore-cache
2+
3+
Flexible caching support for [sigstore-rust](https://github.com/sigstore/sigstore-rust) clients.
4+
5+
## Overview
6+
7+
This crate provides a pluggable caching mechanism for Sigstore operations. It allows caching of frequently-accessed resources like public keys, trust bundles, and configuration data to reduce network requests and improve performance.
8+
9+
## Features
10+
11+
- **Pluggable adapters**: Choose between filesystem, in-memory, or custom cache backends
12+
- **TTL support**: Automatic expiration of cached entries
13+
- **Platform-aware**: Default cache locations follow OS conventions
14+
- **Thread-safe**: All adapters are safe for concurrent use
15+
16+
## Cache Adapters
17+
18+
| Adapter | Description | Use Case |
19+
|---------|-------------|----------|
20+
| `FileSystemCache` | Persistent disk-based cache | Production use, offline support |
21+
| `InMemoryCache` | Fast in-process cache with TTL | High-performance, single-session |
22+
| `NoCache` | No-op cache (disabled) | Testing, when caching is not desired |
23+
24+
## Cached Resources
25+
26+
| Resource | Default TTL | Description |
27+
|----------|-------------|-------------|
28+
| Rekor Public Key | 24 hours | Transparency log signing key |
29+
| Rekor Log Info | 1 hour | Log tree size and root hash |
30+
| Fulcio Trust Bundle | 24 hours | CA certificates |
31+
| Fulcio Configuration | 7 days | OIDC issuer configuration |
32+
33+
## Usage
34+
35+
```rust
36+
use sigstore_cache::{FileSystemCache, InMemoryCache, CacheAdapter, CacheKey};
37+
use std::time::Duration;
38+
39+
// Filesystem cache (persistent)
40+
let cache = FileSystemCache::default_location()?;
41+
42+
// Or in-memory cache (fast, non-persistent)
43+
let cache = InMemoryCache::new();
44+
45+
// Store and retrieve values
46+
cache.set(CacheKey::RekorPublicKey, b"key-data", Duration::from_secs(86400)).await?;
47+
if let Some(data) = cache.get(CacheKey::RekorPublicKey).await? {
48+
println!("Got cached data");
49+
}
50+
```
51+
52+
### With Sigstore Clients
53+
54+
Enable the `cache` feature on the client crates:
55+
56+
```rust
57+
use sigstore_cache::FileSystemCache;
58+
use sigstore_fulcio::FulcioClient;
59+
use sigstore_rekor::RekorClient;
60+
61+
let cache = FileSystemCache::default_location()?;
62+
63+
let fulcio = FulcioClient::builder("https://fulcio.sigstore.dev")
64+
.with_cache(cache.clone())
65+
.build();
66+
67+
let rekor = RekorClient::builder("https://rekor.sigstore.dev")
68+
.with_cache(cache)
69+
.build();
70+
```
71+
72+
## Cache Locations
73+
74+
`FileSystemCache::default_location()` uses platform-specific directories:
75+
76+
- **Linux**: `~/.cache/sigstore-rust/`
77+
- **macOS**: `~/Library/Caches/dev.sigstore.sigstore-rust/`
78+
- **Windows**: `C:\Users\<User>\AppData\Local\sigstore\sigstore-rust\cache\`
79+
80+
## Custom Adapters
81+
82+
Implement the `CacheAdapter` trait for custom backends:
83+
84+
```rust
85+
use sigstore_cache::{CacheAdapter, CacheKey, Result};
86+
use std::time::Duration;
87+
use std::pin::Pin;
88+
use std::future::Future;
89+
90+
struct MyCache;
91+
92+
impl CacheAdapter for MyCache {
93+
fn get(&self, key: CacheKey) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>>> + Send + '_>> {
94+
Box::pin(async { Ok(None) })
95+
}
96+
97+
fn set(&self, key: CacheKey, value: &[u8], ttl: Duration) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>> {
98+
Box::pin(async { Ok(()) })
99+
}
100+
101+
fn remove(&self, key: CacheKey) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>> {
102+
Box::pin(async { Ok(()) })
103+
}
104+
105+
fn clear(&self) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>> {
106+
Box::pin(async { Ok(()) })
107+
}
108+
}
109+
```
110+
111+
## Related Crates
112+
113+
Used by:
114+
115+
- [`sigstore-fulcio`](../sigstore-fulcio) - Caches configuration and trust bundles
116+
- [`sigstore-rekor`](../sigstore-rekor) - Caches public keys and log info
117+
118+
## License
119+
120+
BSD-3-Clause

crates/sigstore-cache/src/error.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! Error types for the cache crate
2+
3+
/// Result type for cache operations
4+
pub type Result<T> = std::result::Result<T, Error>;
5+
6+
/// Errors that can occur during cache operations
7+
#[derive(Debug, thiserror::Error)]
8+
pub enum Error {
9+
/// I/O error (file operations, etc.)
10+
#[error("I/O error: {0}")]
11+
Io(String),
12+
13+
/// Serialization/deserialization error
14+
#[error("Serialization error: {0}")]
15+
Serialization(String),
16+
17+
/// Cache entry has expired
18+
#[error("Cache entry has expired")]
19+
Expired,
20+
}
21+
22+
impl From<std::io::Error> for Error {
23+
fn from(err: std::io::Error) -> Self {
24+
Error::Io(err.to_string())
25+
}
26+
}
27+
28+
impl From<serde_json::Error> for Error {
29+
fn from(err: serde_json::Error) -> Self {
30+
Error::Serialization(err.to_string())
31+
}
32+
}

0 commit comments

Comments
 (0)