tests fixes and some product advisories tunes ups
This commit is contained in:
@@ -739,54 +739,213 @@ sequenceDiagram
|
||||
- Health endpoints: `/health/liveness`, `/health/readiness`, `/status`; verification probe `/api/attestations/verify` once demo bundle is available (see runbook).
|
||||
- Alert hints: signing latency > 1s p99, verification failure spikes, tlog submission lag >10s, key rotation age over policy threshold, backlog above configured threshold.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 17) Rekor Entry Events
|
||||
|
||||
> Sprint: SPRINT_20260112_007_ATTESTOR_rekor_entry_events
|
||||
|
||||
Attestor emits deterministic events when DSSE bundles are logged to Rekor and inclusion proofs become available. These events drive policy reanalysis.
|
||||
|
||||
### Event Types
|
||||
|
||||
| Event Type | Constant | Description |
|
||||
|------------|----------|-------------|
|
||||
| `rekor.entry.logged` | `RekorEventTypes.EntryLogged` | Bundle successfully logged with inclusion proof |
|
||||
| `rekor.entry.queued` | `RekorEventTypes.EntryQueued` | Bundle queued for logging (async mode) |
|
||||
| `rekor.entry.inclusion_verified` | `RekorEventTypes.InclusionVerified` | Inclusion proof independently verified |
|
||||
| `rekor.entry.failed` | `RekorEventTypes.EntryFailed` | Logging or verification failed |
|
||||
|
||||
### RekorEntryEvent Schema
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"eventId": "rekor-evt-sha256:...",
|
||||
"eventType": "rekor.entry.logged",
|
||||
"tenant": "default",
|
||||
"bundleDigest": "sha256:abc123...",
|
||||
"artifactDigest": "sha256:def456...",
|
||||
"predicateType": "StellaOps.ScanResults@1",
|
||||
"rekorEntry": {
|
||||
"uuid": "24296fb24b8ad77a...",
|
||||
"logIndex": 123456789,
|
||||
"logUrl": "https://rekor.sigstore.dev",
|
||||
"integratedTime": "2026-01-15T10:30:02Z"
|
||||
},
|
||||
"reanalysisHints": {
|
||||
"cveIds": ["CVE-2026-1234"],
|
||||
"productKeys": ["pkg:npm/lodash@4.17.21"],
|
||||
"mayAffectDecision": true,
|
||||
"reanalysisScope": "immediate"
|
||||
},
|
||||
"occurredAtUtc": "2026-01-15T10:30:05Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Offline Mode Behavior
|
||||
|
||||
When operating in offline/air-gapped mode:
|
||||
1. Events are not emitted when Rekor is unreachable
|
||||
2. Bundles are queued locally for later submission
|
||||
3. Verification uses bundled checkpoints
|
||||
|
||||
---
|
||||
|
||||
## 17) Rekor Entry Events
|
||||
|
||||
> Sprint: SPRINT_20260112_007_ATTESTOR_rekor_entry_events
|
||||
|
||||
Attestor emits deterministic events when DSSE bundles are logged to Rekor and inclusion proofs become available. These events drive policy reanalysis.
|
||||
|
||||
### Event Types
|
||||
|
||||
| Event Type | Constant | Description |
|
||||
|------------|----------|-------------|
|
||||
| `rekor.entry.logged` | `RekorEventTypes.EntryLogged` | Bundle successfully logged with inclusion proof |
|
||||
| `rekor.entry.queued` | `RekorEventTypes.EntryQueued` | Bundle queued for logging (async mode) |
|
||||
| `rekor.entry.inclusion_verified` | `RekorEventTypes.InclusionVerified` | Inclusion proof independently verified |
|
||||
| `rekor.entry.failed` | `RekorEventTypes.EntryFailed` | Logging or verification failed |
|
||||
|
||||
### RekorEntryEvent Schema
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"eventId": "rekor-evt-sha256:...",
|
||||
"eventType": "rekor.entry.logged",
|
||||
"tenant": "default",
|
||||
"bundleDigest": "sha256:abc123...",
|
||||
"artifactDigest": "sha256:def456...",
|
||||
"predicateType": "StellaOps.ScanResults@1",
|
||||
"rekorEntry": {
|
||||
"uuid": "24296fb24b8ad77a...",
|
||||
"logIndex": 123456789,
|
||||
"logUrl": "https://rekor.sigstore.dev",
|
||||
"integratedTime": "2026-01-15T10:30:02Z"
|
||||
},
|
||||
"reanalysisHints": {
|
||||
"cveIds": ["CVE-2026-1234"],
|
||||
"productKeys": ["pkg:npm/lodash@4.17.21"],
|
||||
"mayAffectDecision": true,
|
||||
"reanalysisScope": "immediate"
|
||||
},
|
||||
"occurredAtUtc": "2026-01-15T10:30:05Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Offline Mode Behavior
|
||||
|
||||
When operating in offline/air-gapped mode:
|
||||
1. Events are not emitted when Rekor is unreachable
|
||||
2. Bundles are queued locally for later submission
|
||||
3. Verification uses bundled checkpoints
|
||||
4. Events are generated when connectivity is restored
|
||||
|
||||
---
|
||||
|
||||
## 18) Identity Watchlist & Monitoring
|
||||
|
||||
> Sprint: SPRINT_0129_001_ATTESTOR_identity_watchlist_alerting
|
||||
|
||||
The Attestor provides proactive monitoring for signing identities appearing in transparency logs. Organizations can define watchlists to receive alerts when specific identities sign artifacts.
|
||||
|
||||
### Purpose
|
||||
|
||||
- **Credential compromise detection**: Alert when your signing identity appears unexpectedly
|
||||
- **Third-party monitoring**: Watch for specific vendors or dependencies signing artifacts
|
||||
- **Compliance auditing**: Track all signing activity for specific issuers
|
||||
|
||||
### Watchlist Entry Model
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "uuid",
|
||||
"tenantId": "tenant-123",
|
||||
"scope": "tenant", // tenant | global | system
|
||||
"displayName": "GitHub Actions Signer",
|
||||
"description": "Watch for GitHub Actions OIDC tokens",
|
||||
|
||||
// Identity fields (at least one required)
|
||||
"issuer": "https://token.actions.githubusercontent.com",
|
||||
"subjectAlternativeName": "repo:org/repo:*", // glob pattern
|
||||
"keyId": null,
|
||||
|
||||
"matchMode": "glob", // exact | prefix | glob | regex
|
||||
|
||||
// Alert configuration
|
||||
"severity": "warning", // info | warning | critical
|
||||
"enabled": true,
|
||||
"channelOverrides": ["slack-security"],
|
||||
"suppressDuplicatesMinutes": 60,
|
||||
|
||||
"tags": ["github", "ci-cd"],
|
||||
"createdAt": "2026-01-29T10:00:00Z",
|
||||
"createdBy": "admin@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Matching Modes
|
||||
|
||||
| Mode | Behavior | Example Pattern | Matches |
|
||||
|------|----------|-----------------|---------|
|
||||
| `exact` | Case-insensitive equality | `alice@example.com` | `Alice@example.com` |
|
||||
| `prefix` | Starts-with match | `https://accounts.google.com/` | Any Google OIDC issuer |
|
||||
| `glob` | Glob pattern (`*`, `?`) | `*@example.com` | `alice@example.com`, `bob@example.com` |
|
||||
| `regex` | Full regex (with timeout) | `repo:org/(frontend\|backend):.*` | `repo:org/frontend:ref:main` |
|
||||
|
||||
### Scope Hierarchy
|
||||
|
||||
| Scope | Visibility | Who Can Create |
|
||||
|-------|------------|----------------|
|
||||
| `tenant` | Owning tenant only | Tenant admins |
|
||||
| `global` | All tenants | Platform admins |
|
||||
| `system` | All tenants (read-only) | System bootstrap |
|
||||
|
||||
### Event Flow
|
||||
|
||||
```
|
||||
New AttestorEntry persisted
|
||||
→ SignerIdentityDescriptor extracted
|
||||
→ IIdentityMatcher.MatchAsync()
|
||||
→ For each match:
|
||||
→ Check dedup window (default 60 min)
|
||||
→ Emit attestor.identity.matched event
|
||||
→ Route via Notifier rules → Slack/Email/Webhook
|
||||
```
|
||||
|
||||
### Event Schema (IdentityAlertEvent)
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"eventId": "uuid",
|
||||
"eventKind": "attestor.identity.matched",
|
||||
"tenantId": "tenant-123",
|
||||
"watchlistEntryId": "uuid",
|
||||
"watchlistEntryName": "GitHub Actions Signer",
|
||||
"matchedIdentity": {
|
||||
"issuer": "https://token.actions.githubusercontent.com",
|
||||
"subjectAlternativeName": "repo:org/repo:ref:refs/heads/main",
|
||||
"keyId": null
|
||||
},
|
||||
"rekorEntry": {
|
||||
"uuid": "24296fb24b8ad77a...",
|
||||
"logIndex": 123456789,
|
||||
"artifactSha256": "sha256:abc123...",
|
||||
"integratedTimeUtc": "2026-01-29T10:30:00Z"
|
||||
},
|
||||
"severity": "warning",
|
||||
"occurredAtUtc": "2026-01-29T10:30:05Z",
|
||||
"suppressedCount": 0
|
||||
}
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/api/v1/watchlist` | Create watchlist entry |
|
||||
| `GET` | `/api/v1/watchlist` | List entries (tenant + optional global) |
|
||||
| `GET` | `/api/v1/watchlist/{id}` | Get single entry |
|
||||
| `PUT` | `/api/v1/watchlist/{id}` | Update entry |
|
||||
| `DELETE` | `/api/v1/watchlist/{id}` | Delete entry |
|
||||
| `POST` | `/api/v1/watchlist/{id}/test` | Test pattern against sample identity |
|
||||
| `GET` | `/api/v1/watchlist/alerts` | List recent alerts (paginated) |
|
||||
|
||||
### CLI Commands
|
||||
|
||||
```bash
|
||||
# Add a watchlist entry
|
||||
stella watchlist add --issuer "https://token.actions.githubusercontent.com" \
|
||||
--san "repo:org/*" --match-mode glob --severity warning
|
||||
|
||||
# List entries
|
||||
stella watchlist list --include-global
|
||||
|
||||
# Test a pattern
|
||||
stella watchlist test <id> --issuer "https://..." --san "repo:org/repo:ref:main"
|
||||
|
||||
# View recent alerts
|
||||
stella watchlist alerts --since 24h --severity warning
|
||||
```
|
||||
|
||||
### Metrics
|
||||
|
||||
| Metric | Description |
|
||||
|--------|-------------|
|
||||
| `attestor.watchlist.entries_scanned_total` | Entries processed by monitor |
|
||||
| `attestor.watchlist.matches_total{severity}` | Pattern matches by severity |
|
||||
| `attestor.watchlist.alerts_emitted_total` | Alerts sent to notification system |
|
||||
| `attestor.watchlist.alerts_suppressed_total` | Alerts deduplicated |
|
||||
| `attestor.watchlist.scan_latency_seconds` | Per-entry scan duration |
|
||||
|
||||
### Configuration
|
||||
|
||||
```yaml
|
||||
attestor:
|
||||
watchlist:
|
||||
enabled: true
|
||||
monitorMode: "changefeed" # changefeed | polling
|
||||
pollingIntervalSeconds: 5 # only for polling mode
|
||||
maxEventsPerSecond: 100 # rate limit
|
||||
defaultDedupWindowMinutes: 60
|
||||
regexTimeoutMs: 100 # safety limit
|
||||
maxWatchlistEntriesPerTenant: 1000
|
||||
```
|
||||
|
||||
### Offline Mode
|
||||
|
||||
In air-gapped environments:
|
||||
- Polling mode used instead of Postgres NOTIFY
|
||||
- Alerts queued locally if notification channels unavailable
|
||||
- Alerts delivered when connectivity restored
|
||||
|
||||
|
||||
Reference in New Issue
Block a user