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

Commit 89500a8

Browse files
committed
add configuration to allow CIP with no authorities
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
1 parent 085aeb9 commit 89500a8

7 files changed

Lines changed: 80 additions & 13 deletions

File tree

cmd/policy_webhook/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"knative.dev/pkg/configmap"
2525
"knative.dev/pkg/controller"
2626
"knative.dev/pkg/injection/sharedmain"
27+
"knative.dev/pkg/logging"
2728
"knative.dev/pkg/signals"
2829
"knative.dev/pkg/webhook"
2930
"knative.dev/pkg/webhook/certificates"
@@ -36,6 +37,7 @@ import (
3637
"github.com/sigstore/policy-controller/pkg/apis/policy"
3738
"github.com/sigstore/policy-controller/pkg/apis/policy/v1alpha1"
3839
"github.com/sigstore/policy-controller/pkg/apis/policy/v1beta1"
40+
"github.com/sigstore/policy-controller/pkg/config"
3941
"github.com/sigstore/policy-controller/pkg/reconciler/clusterimagepolicy"
4042

4143
// Register the provider-specific plugins
@@ -96,12 +98,18 @@ func main() {
9698
}
9799

98100
func NewPolicyValidatingAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
101+
store := config.NewStore(logging.FromContext(ctx).Named("config-store"))
102+
store.WatchConfigs(cmw)
103+
policyControllerConfigStore := config.NewStore(logging.FromContext(ctx).Named("config-policy-controller"))
104+
policyControllerConfigStore.WatchConfigs(cmw)
105+
99106
return validation.NewAdmissionController(
100107
ctx,
101108
*validatingWebhookName,
102109
"/validating",
103110
types,
104111
func(ctx context.Context) context.Context {
112+
ctx = policyControllerConfigStore.ToContext(ctx)
105113
return ctx
106114
},
107115
true,

pkg/apis/policy/v1beta1/clusterimagepolicy_validation.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"github.com/sigstore/sigstore/pkg/cryptoutils"
2929
"k8s.io/apimachinery/pkg/util/sets"
3030
"knative.dev/pkg/apis"
31+
32+
policycontrollerconfig "github.com/sigstore/policy-controller/pkg/config"
3133
)
3234

3335
const awsKMSPrefix = "awskms://"
@@ -52,13 +54,17 @@ func (c *ClusterImagePolicy) Validate(ctx context.Context) *apis.FieldError {
5254
}
5355

5456
func (spec *ClusterImagePolicySpec) Validate(ctx context.Context) (errors *apis.FieldError) {
57+
// Check what the configuration is and act accordingly.
58+
pcConfig := policycontrollerconfig.FromContext(ctx)
59+
5560
if len(spec.Images) == 0 {
5661
errors = errors.Also(apis.ErrMissingField("images"))
5762
}
5863
for i, image := range spec.Images {
5964
errors = errors.Also(image.Validate(ctx).ViaFieldIndex("images", i))
6065
}
61-
if len(spec.Authorities) == 0 {
66+
// Check if PolicyControllerConfig is configured to fail when having empty authorities
67+
if len(spec.Authorities) == 0 && pcConfig.FailOnEmptyAuthorities {
6268
errors = errors.Also(apis.ErrMissingField("authorities"))
6369
}
6470
for i, authority := range spec.Authorities {

pkg/apis/policy/v1beta1/clusterimagepolicy_validation_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
v1 "k8s.io/api/core/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626
"knative.dev/pkg/apis"
27+
28+
policycontrollerconfig "github.com/sigstore/policy-controller/pkg/config"
2729
)
2830

2931
const validPublicKey = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaEOVJCFtduYr3xqTxeRWSW32CY/s\nTBNZj4oIUPl8JvhVPJ1TKDPlNcuT4YphSt6t3yOmMvkdQbCj8broX6vijw==\n-----END PUBLIC KEY-----"
@@ -87,7 +89,9 @@ func TestImagePatternValidation(t *testing.T) {
8789

8890
for _, test := range tests {
8991
t.Run(test.name, func(t *testing.T) {
90-
err := test.policy.Validate(context.TODO())
92+
testContext := policycontrollerconfig.ToContext(context.TODO(), &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: policycontrollerconfig.AllowAll, FailOnEmptyAuthorities: true})
93+
94+
err := test.policy.Validate(testContext)
9195
validateError(t, test.errorString, "", err)
9296
})
9397
}
@@ -795,7 +799,9 @@ func TestAuthoritiesValidation(t *testing.T) {
795799

796800
for _, test := range tests {
797801
t.Run(test.name, func(t *testing.T) {
798-
err := test.policy.Validate(context.TODO())
802+
testContext := policycontrollerconfig.ToContext(context.TODO(), &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: policycontrollerconfig.AllowAll, FailOnEmptyAuthorities: true})
803+
804+
err := test.policy.Validate(testContext)
799805
validateError(t, test.errorString, test.warnString, err)
800806
})
801807
}

pkg/config/store.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package config
1717

1818
import (
1919
"context"
20+
"strconv"
2021

2122
corev1 "k8s.io/api/core/v1"
2223
"knative.dev/pkg/configmap"
@@ -40,6 +41,8 @@ const (
4041
WarnAll = "warn"
4142

4243
NoMatchPolicyKey = "no-match-policy"
44+
45+
FailOnEmptyAuthorities = "fail-on-empty-authorities"
4346
)
4447

4548
// PolicyControllerConfig controls the behaviour of policy-controller that needs
@@ -51,10 +54,12 @@ type PolicyControllerConfig struct {
5154
// NoMatchPolicy says what do in the case where an image does not match
5255
// any policy.
5356
NoMatchPolicy string `json:"no-match-policy"`
57+
// FailOnEmptyAuthorities configures the validating webhook to allow creating CIP without a list authorities
58+
FailOnEmptyAuthorities bool `json:"fail-on-empty-authorities"`
5459
}
5560

5661
func NewPolicyControllerConfigFromMap(data map[string]string) (*PolicyControllerConfig, error) {
57-
ret := &PolicyControllerConfig{NoMatchPolicy: "deny"}
62+
ret := &PolicyControllerConfig{NoMatchPolicy: "deny", FailOnEmptyAuthorities: true}
5863
switch data[NoMatchPolicyKey] {
5964
case DenyAll:
6065
ret.NoMatchPolicy = DenyAll
@@ -65,6 +70,12 @@ func NewPolicyControllerConfigFromMap(data map[string]string) (*PolicyController
6570
default:
6671
ret.NoMatchPolicy = DenyAll
6772
}
73+
if val, ok := data[FailOnEmptyAuthorities]; ok {
74+
var err error
75+
ret.FailOnEmptyAuthorities, err = strconv.ParseBool(val)
76+
return ret, err
77+
}
78+
ret.FailOnEmptyAuthorities = true
6879
return ret, nil
6980
}
7081

@@ -89,7 +100,8 @@ func FromContextOrDefaults(ctx context.Context) *PolicyControllerConfig {
89100
return cfg
90101
}
91102
return &PolicyControllerConfig{
92-
NoMatchPolicy: DenyAll,
103+
NoMatchPolicy: DenyAll,
104+
FailOnEmptyAuthorities: true,
93105
}
94106
}
95107

pkg/config/store_test.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@ import (
2424
. "knative.dev/pkg/configmap/testing"
2525
)
2626

27-
var testfiles = map[string]string{
28-
"allow-all": AllowAll,
29-
"deny-all-explicit": DenyAll,
30-
"warn-all": WarnAll,
31-
"deny-all-default": DenyAll,
27+
type testData struct {
28+
noMatchPolicy string
29+
failOnEmptyAuthorities bool
30+
}
31+
32+
var testfiles = map[string]testData{
33+
"allow-all": {noMatchPolicy: AllowAll, failOnEmptyAuthorities: true},
34+
"deny-all-explicit": {noMatchPolicy: DenyAll, failOnEmptyAuthorities: true},
35+
"warn-all": {noMatchPolicy: WarnAll, failOnEmptyAuthorities: true},
36+
"deny-all-default": {noMatchPolicy: DenyAll, failOnEmptyAuthorities: true},
37+
"allow-empty-authorities": {noMatchPolicy: DenyAll, failOnEmptyAuthorities: false},
3238
}
3339

3440
func TestStoreLoadWithContext(t *testing.T) {
@@ -43,7 +49,10 @@ func TestStoreLoadWithContext(t *testing.T) {
4349

4450
t.Run("policy-controller-config-test-"+file, func(t *testing.T) {
4551
expected, _ := NewPolicyControllerConfigFromConfigMap(policyControllerConfig)
46-
if diff := cmp.Diff(want, expected.NoMatchPolicy); diff != "" {
52+
if diff := cmp.Diff(want.noMatchPolicy, expected.NoMatchPolicy); diff != "" {
53+
t.Error("Unexpected defaults config (-want, +got):", diff)
54+
}
55+
if diff := cmp.Diff(want.failOnEmptyAuthorities, expected.FailOnEmptyAuthorities); diff != "" {
4756
t.Error("Unexpected defaults config (-want, +got):", diff)
4857
}
4958
if diff := cmp.Diff(expected, config); diff != "" {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
# http://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: v1
16+
kind: ConfigMap
17+
metadata:
18+
name: config-policy-controller
19+
namespace: cosign-system
20+
labels:
21+
policy.sigstore.dev/release: devel
22+
23+
data:
24+
_example: |
25+
no-match-policy: deny
26+
fail-on-empty-authorities: false

pkg/webhook/validator_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,7 @@ func TestValidatePodSpecNonDefaultNamespace(t *testing.T) {
24122412
testContext = attachHTTPRequestToContext(testContext)
24132413
// Set the policy config to pass anything that doesn't match any
24142414
// policies.
2415-
testContext = policycontrollerconfig.ToContext(testContext, &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: policycontrollerconfig.AllowAll})
2415+
testContext = policycontrollerconfig.ToContext(testContext, &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: policycontrollerconfig.AllowAll, FailOnEmptyAuthorities: true})
24162416

24172417
got = v.ValidatePod(testContext, pod)
24182418
want := test.want.ViaField("spec")
@@ -2720,7 +2720,7 @@ func TestPolicyControllerConfigNoMatchPolicy(t *testing.T) {
27202720
noMatchPolicy: "allow",
27212721
}}
27222722
for _, tc := range tests {
2723-
testCtx := policycontrollerconfig.ToContext(ctx, &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: tc.noMatchPolicy})
2723+
testCtx := policycontrollerconfig.ToContext(ctx, &policycontrollerconfig.PolicyControllerConfig{NoMatchPolicy: tc.noMatchPolicy, FailOnEmptyAuthorities: true})
27242724

27252725
got := v.validatePodSpec(testCtx, system.Namespace(), "pod", "v1", map[string]string{}, testPodSpec, k8schain.Options{})
27262726
if (got != nil) != (tc.want != nil) {

0 commit comments

Comments
 (0)