Skip to content

Commit f782b54

Browse files
committed
feature: add policy.json support
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
1 parent a5c8b77 commit f782b54

File tree

10 files changed

+3170
-0
lines changed

10 files changed

+3170
-0
lines changed

docs/policy.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Policy Package
2+
3+
The `policy` package provides support for the `containers-policy.json` format used for OCI image signature verification policies.
4+
5+
## Overview
6+
7+
This package implements parsing, validation, and evaluation of container image policies as defined in the [containers-policy.json specification](https://man.archlinux.org/man/containers-policy.json.5.en).
8+
9+
## Features
10+
11+
- **Policy Management**: Load, save, and validate policy configurations
12+
- **Multiple Transports**: Support for docker, oci, and other transport types
13+
- **Policy Requirements**:
14+
- `insecureAcceptAnything` - Accept any image without verification
15+
- `reject` - Reject all images
16+
- `signedBy` - Require GPG signature verification (placeholder)
17+
- `sigstoreSigned` - Require sigstore signature verification (placeholder)
18+
- **Scope-based Policies**: Define different policies for different image scopes
19+
- **Identity Matching**: Support for various identity matching strategies
20+
21+
## Usage
22+
23+
### Creating a Policy
24+
25+
```go
26+
import "oras.land/oras-go/v2/registry/remote/policy"
27+
28+
// Create a basic policy
29+
p := &policy.Policy{
30+
Default: policy.PolicyRequirements{&policy.Reject{}},
31+
Transports: map[policy.TransportName]policy.TransportScopes{
32+
policy.TransportDocker: {
33+
"": policy.PolicyRequirements{&policy.InsecureAcceptAnything{}},
34+
},
35+
},
36+
}
37+
```
38+
39+
### Loading and Saving Policies
40+
41+
```go
42+
// Load from default location
43+
policy, err := policy.LoadDefaultPolicy()
44+
if err != nil {
45+
log.Fatal(err)
46+
}
47+
48+
// Load from specific path
49+
policy, err := policy.LoadPolicy("/path/to/policy.json")
50+
if err != nil {
51+
log.Fatal(err)
52+
}
53+
54+
// Save policy
55+
err = policy.SavePolicy(p, "/path/to/policy.json")
56+
if err != nil {
57+
log.Fatal(err)
58+
}
59+
```
60+
61+
### Evaluating Policies
62+
63+
```go
64+
import "context"
65+
66+
// Create an evaluator
67+
evaluator, err := policy.NewEvaluator(p)
68+
if err != nil {
69+
log.Fatal(err)
70+
}
71+
72+
// Check if an image is allowed
73+
image := policy.ImageReference{
74+
Transport: policy.TransportDocker,
75+
Scope: "docker.io/library/nginx",
76+
Reference: "docker.io/library/nginx:latest",
77+
}
78+
79+
allowed, err := evaluator.IsImageAllowed(context.Background(), image)
80+
if err != nil {
81+
log.Fatal(err)
82+
}
83+
84+
fmt.Printf("Image allowed: %v\n", allowed)
85+
```
86+
87+
### Signature Verification Policies
88+
89+
```go
90+
// GPG signature verification
91+
signedByReq := &policy.PRSignedBy{
92+
KeyType: "GPGKeys",
93+
KeyPath: "/path/to/trusted-key.gpg",
94+
SignedIdentity: &policy.SignedIdentity{
95+
Type: policy.MatchRepository,
96+
},
97+
}
98+
99+
// Sigstore signature verification
100+
sigstoreReq := &policy.PRSigstoreSigned{
101+
KeyPath: "/path/to/cosign.pub",
102+
Fulcio: &policy.FulcioConfig{
103+
CAPath: "/path/to/fulcio-ca.pem",
104+
OIDCIssuer: "https://oauth2.sigstore.dev/auth",
105+
SubjectEmail: "user@example.com",
106+
},
107+
RekorPublicKeyPath: "/path/to/rekor.pub",
108+
SignedIdentity: &policy.SignedIdentity{
109+
Type: policy.MatchRepository,
110+
},
111+
}
112+
```
113+
114+
## Policy File Format
115+
116+
The policy.json file follows this structure:
117+
118+
```json
119+
{
120+
"default": [
121+
{"type": "reject"}
122+
],
123+
"transports": {
124+
"docker": {
125+
"": [
126+
{"type": "insecureAcceptAnything"}
127+
],
128+
"docker.io/library/nginx": [
129+
{"type": "reject"}
130+
]
131+
}
132+
}
133+
}
134+
```
135+
136+
## Default Policy Locations
137+
138+
The package checks for policy files in the following order:
139+
140+
1. `$HOME/.config/containers/policy.json` (user-specific)
141+
2. `/etc/containers/policy.json` (system-wide)
142+
143+
## Supported Transports
144+
145+
- `docker` - Docker registries
146+
- `atomic` - Atomic registries
147+
- `containers-storage` - Local containers storage
148+
- `dir` - Directory transport
149+
- `docker-archive` - Docker archive files
150+
- `docker-daemon` - Docker daemon
151+
- `oci` - OCI layout
152+
- `oci-archive` - OCI archive files
153+
- `sif` - Singularity Image Format
154+
- `tarball` - Tarball transport
155+
156+
## Identity Matching Types
157+
158+
- `matchExact` - Exact identity match
159+
- `matchRepoDigestOrExact` - Repository digest or exact match
160+
- `matchRepository` - Repository match
161+
- `exactReference` - Exact reference match
162+
- `exactRepository` - Exact repository match
163+
- `remapIdentity` - Remap identity with prefix
164+
165+
## Limitations
166+
167+
- The `signedBy` and `sigstoreSigned` requirement types are currently placeholders
168+
- Full signature verification requires integration with GPG and sigstore libraries
169+
- Advanced identity matching strategies are defined but not fully implemented
170+
171+
## Testing
172+
173+
Run the tests with:
174+
175+
```bash
176+
go test ./registry/remote/policy/...
177+
```
178+
179+
## References
180+
181+
- [containers-policy.json specification](https://man.archlinux.org/man/containers-policy.json.5.en)
182+
- [OCI Image Spec](https://github.com/opencontainers/image-spec)
183+
- [OCI Distribution Spec](https://github.com/opencontainers/distribution-spec)

0 commit comments

Comments
 (0)