Skip to content
This repository was archived by the owner on Sep 23, 2025. It is now read-only.

Commit d869981

Browse files
committed
Add policy-tester CLI for testing ClusterImagePolicies
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
1 parent 34f36cb commit d869981

6 files changed

Lines changed: 204 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#
2+
# Copyright 2022 The Sigstore Authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
name: policy-tester
17+
18+
on:
19+
workflow_dispatch:
20+
push:
21+
branches: ['main', 'release-*']
22+
pull_request:
23+
24+
permissions: read-all
25+
26+
jobs:
27+
verify:
28+
name: Verify policy-tester
29+
runs-on: ubuntu-latest
30+
31+
env:
32+
GOPATH: ${{ github.workspace }}
33+
34+
steps:
35+
- uses: actions/setup-go@b22fbbc2921299758641fab08929b4ac52b32923
36+
with:
37+
go-version: '1.17'
38+
check-latest: true
39+
40+
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
41+
with:
42+
path: ./src/github.com/${{ github.repository }}
43+
fetch-depth: 0
44+
45+
- working-directory: ./src/github.com/${{ github.repository }}
46+
run: |
47+
# Build the policy-tester CLI
48+
make policy-tester
49+
50+
# Make sure it runs and verifies a policy against valid image
51+
(set -o pipefail && \
52+
./policy-tester \
53+
test/testdata/policy-controller/tester/cip-public-keyless.yaml \
54+
ghcr.io/sigstore/cosign/cosign:v1.9.0 | jq)

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ policyControllerImagerefs
3030
policyImagerefs
3131

3232
**verify-experimental*
33+
34+
policy-tester

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ policy-controller: policy-webhook
9393
policy-webhook: ## Build the policy webhook binary
9494
CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $@ ./cmd/policy_webhook
9595

96+
## Build policy-tester binary
97+
.PHONY: policy-tester
98+
policy-tester:
99+
CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $@ ./cmd/tester
100+
96101
#####################
97102
# lint / test section
98103
#####################

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ Kubernetes webhook for configuring admission policies.
44

55
(TODO: vaikas) Update this README
66

7+
## ClusterImagePolicy Testing
8+
9+
This repo includes a `policy-tester` tool which enables checking a policy against
10+
various images.
11+
12+
In the root of this repo, run the following to build:
13+
```
14+
make policy-tester
15+
```
16+
17+
Then run it pointing to a YAML file containing a ClusterImagePolicy, and an image to evaluate the policy against:
18+
```
19+
(set -o pipefail && \
20+
./policy-tester \
21+
test/testdata/policy-controller/tester/cip-public-keyless.yaml \
22+
ghcr.io/sigstore/cosign/cosign:v1.9.0 | jq)
23+
```
24+
725
## Security
826

927
Should you discover any security issues, please refer to sigstores [security

cmd/tester/main.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//
2+
// Copyright 2022 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package main
17+
18+
import (
19+
"context"
20+
"encoding/json"
21+
"fmt"
22+
"io/ioutil"
23+
"log"
24+
"os"
25+
"strings"
26+
27+
"github.com/google/go-containerregistry/pkg/authn"
28+
"github.com/google/go-containerregistry/pkg/name"
29+
"github.com/google/go-containerregistry/pkg/v1/remote"
30+
ociremote "github.com/sigstore/cosign/pkg/oci/remote"
31+
"go.uber.org/zap"
32+
"knative.dev/pkg/logging"
33+
"sigs.k8s.io/yaml"
34+
35+
"github.com/sigstore/policy-controller/pkg/apis/policy/v1alpha1"
36+
"github.com/sigstore/policy-controller/pkg/webhook"
37+
webhookcip "github.com/sigstore/policy-controller/pkg/webhook/clusterimagepolicy"
38+
)
39+
40+
var (
41+
ns = "unused"
42+
43+
remoteOpts = []ociremote.Option{
44+
ociremote.WithRemoteOptions(
45+
remote.WithAuthFromKeychain(authn.DefaultKeychain),
46+
),
47+
}
48+
49+
ctx = logging.WithLogger(context.Background(), func() *zap.SugaredLogger {
50+
x, _ := zap.NewDevelopmentConfig().Build()
51+
return x.Sugar()
52+
}())
53+
)
54+
55+
type output struct {
56+
Errors []string `json:"errors"`
57+
Result *webhook.PolicyResult `json:"result"`
58+
}
59+
60+
func main() {
61+
args := os.Args[1:]
62+
if len(args) != 2 {
63+
fmt.Println("Usage: policy-tester cluster-image-policy.yaml r.example.com/myrepo/myimage:mytag")
64+
os.Exit(1)
65+
}
66+
cipFilePath := args[0]
67+
image := args[1]
68+
cipRaw, err := ioutil.ReadFile(cipFilePath)
69+
if err != nil {
70+
log.Fatal(err)
71+
}
72+
73+
// TODO(jdolitsky): should this use v1beta1?
74+
var tmp v1alpha1.ClusterImagePolicy
75+
if err := yaml.Unmarshal(cipRaw, &tmp); err != nil {
76+
log.Fatal(err)
77+
}
78+
cip := webhookcip.ConvertClusterImagePolicyV1alpha1ToWebhook(&tmp)
79+
ref, err := name.ParseReference(image)
80+
if err != nil {
81+
log.Fatal(err)
82+
}
83+
84+
result, errs := webhook.ValidatePolicy(ctx, ns, ref, *cip, remoteOpts...)
85+
errStrings := []string{}
86+
for _, err := range errs {
87+
errStrings = append(errStrings, strings.Trim(err.Error(), "\n"))
88+
}
89+
o, err := json.Marshal(&output{
90+
Errors: errStrings,
91+
Result: result,
92+
})
93+
if err != nil {
94+
log.Fatal(err)
95+
}
96+
97+
fmt.Println(string(o))
98+
if len(errs) > 0 {
99+
os.Exit(1)
100+
}
101+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2022 The Sigstore Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: policy.sigstore.dev/v1alpha1
16+
kind: ClusterImagePolicy
17+
metadata:
18+
name: demo
19+
spec:
20+
images:
21+
- glob: "**"
22+
authorities:
23+
- keyless:
24+
url: "https://fulcio.sigstore.dev"

0 commit comments

Comments
 (0)