diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index 52f329ca..6f84894f 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -56,6 +56,7 @@ import ( "github.com/sigstore/sigstore/pkg/tuf" "github.com/sigstore/policy-controller/pkg/apis/config" + pctuf "github.com/sigstore/policy-controller/pkg/tuf" cwebhook "github.com/sigstore/policy-controller/pkg/webhook" ) @@ -136,7 +137,7 @@ func main() { // Set the policy and trust root resync periods ctx = clusterimagepolicy.ToContext(ctx, *policyResyncPeriod) - ctx = trustroot.ToContext(ctx, *trustrootResyncPeriod) + ctx = pctuf.ToContext(ctx, *trustrootResyncPeriod) // This must match the set of resources we configure in // cmd/webhook/main.go in the "types" map. diff --git a/pkg/reconciler/trustroot/controller.go b/pkg/reconciler/trustroot/controller.go index 8373b980..66fffe2a 100644 --- a/pkg/reconciler/trustroot/controller.go +++ b/pkg/reconciler/trustroot/controller.go @@ -16,7 +16,6 @@ package trustroot import ( "context" - "time" "k8s.io/client-go/tools/cache" kubeclient "knative.dev/pkg/client/injection/kube/client" @@ -30,6 +29,7 @@ import ( "github.com/sigstore/policy-controller/pkg/apis/config" trustrootinformer "github.com/sigstore/policy-controller/pkg/client/injection/informers/policy/v1alpha1/trustroot" trustrootreconciler "github.com/sigstore/policy-controller/pkg/client/injection/reconciler/policy/v1alpha1/trustroot" + "github.com/sigstore/policy-controller/pkg/tuf" cminformer "knative.dev/pkg/injection/clients/namespacedkube/informers/core/v1/configmap" ) @@ -37,8 +37,6 @@ import ( // use it in tests as well. const FinalizerName = "trustroots.policy.sigstore.dev" -type trustrootResyncPeriodKey struct{} - // NewController creates a Reconciler and returns the result of NewImpl. func NewController( ctx context.Context, @@ -78,22 +76,8 @@ func NewController( pkgreconciler.NamespaceFilterFunc(system.Namespace()), pkgreconciler.NameFilterFunc(config.SigstoreKeysConfigName)), Handler: controller.HandleAll(grCb), - }, FromContextOrDefaults(ctx)); err != nil { + }, tuf.FromContextOrDefaults(ctx)); err != nil { logging.FromContext(ctx).Warnf("Failed configMapInformer AddEventHandlerWithResyncPeriod() %v", err) } return impl } - -func ToContext(ctx context.Context, duration time.Duration) context.Context { - return context.WithValue(ctx, trustrootResyncPeriodKey{}, duration) -} - -// FromContextOrDefaults returns a stored trustrootResyncPeriod if attached. -// If not found, it returns a default duration -func FromContextOrDefaults(ctx context.Context) time.Duration { - x, ok := ctx.Value(trustrootResyncPeriodKey{}).(time.Duration) - if ok { - return x - } - return controller.DefaultResyncPeriod -} diff --git a/pkg/reconciler/trustroot/controller_test.go b/pkg/reconciler/trustroot/controller_test.go index 7d6b442a..0377b562 100644 --- a/pkg/reconciler/trustroot/controller_test.go +++ b/pkg/reconciler/trustroot/controller_test.go @@ -16,10 +16,8 @@ package trustroot import ( "testing" - "time" "knative.dev/pkg/configmap" - "knative.dev/pkg/controller" rtesting "knative.dev/pkg/reconciler/testing" // Fake injection informers @@ -39,21 +37,3 @@ func TestNew(t *testing.T) { t.Fatal("Expected NewController to return a non-nil value") } } - -func TestContextDuration(t *testing.T) { - ctx, _ := rtesting.SetupFakeContext(t) - - expected := controller.DefaultResyncPeriod - actual := FromContextOrDefaults(ctx) - if expected != actual { - t.Fatal("Expected the context to store the value and be retrievable") - } - - expected = time.Hour - ctx = ToContext(ctx, expected) - actual = FromContextOrDefaults(ctx) - - if expected != actual { - t.Fatal("Expected the context to store the value and be retrievable") - } -} diff --git a/pkg/tuf/context.go b/pkg/tuf/context.go new file mode 100644 index 00000000..3c9f8153 --- /dev/null +++ b/pkg/tuf/context.go @@ -0,0 +1,41 @@ +// +// Copyright 2024 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tuf + +import ( + "context" + "time" + + "knative.dev/pkg/controller" +) + +type trustrootResyncPeriodKey struct{} + +// ToContext returns a context that includes a key trustrootResyncPeriod +// set to the included duration +func ToContext(ctx context.Context, duration time.Duration) context.Context { + return context.WithValue(ctx, trustrootResyncPeriodKey{}, duration) +} + +// FromContextOrDefaults returns a stored trustrootResyncPeriod if attached. +// If not found, it returns a default duration +func FromContextOrDefaults(ctx context.Context) time.Duration { + x, ok := ctx.Value(trustrootResyncPeriodKey{}).(time.Duration) + if ok { + return x + } + return controller.DefaultResyncPeriod +} diff --git a/pkg/tuf/context_test.go b/pkg/tuf/context_test.go new file mode 100644 index 00000000..5537cb0a --- /dev/null +++ b/pkg/tuf/context_test.go @@ -0,0 +1,42 @@ +// +// Copyright 2024 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tuf + +import ( + "testing" + "time" + + "knative.dev/pkg/controller" + rtesting "knative.dev/pkg/reconciler/testing" +) + +func TestContextDuration(t *testing.T) { + ctx, _ := rtesting.SetupFakeContext(t) + + expected := controller.DefaultResyncPeriod + actual := FromContextOrDefaults(ctx) + if expected != actual { + t.Fatal("Expected the context to store the value and be retrievable") + } + + expected = time.Hour + ctx = ToContext(ctx, expected) + actual = FromContextOrDefaults(ctx) + + if expected != actual { + t.Fatal("Expected the context to store the value and be retrievable") + } +} diff --git a/pkg/tuf/repo.go b/pkg/tuf/repo.go index 46405348..dda2cdd9 100644 --- a/pkg/tuf/repo.go +++ b/pkg/tuf/repo.go @@ -300,11 +300,12 @@ var ( ) // GetTrustedRoot returns the trusted root for the TUF repository. -func GetTrustedRoot() (*root.TrustedRoot, error) { +func GetTrustedRoot(ctx context.Context) (*root.TrustedRoot, error) { + resyncPeriodDuration := FromContextOrDefaults(ctx) now := time.Now().UTC() - // check if timestamp has never been or if the current time is more - // than 24 hours after the current value of timestamp - if timestamp.IsZero() || now.After(timestamp.Add(24*time.Hour)) { + // check if timestamp has never been set or if the current time + // is after the current timestamp value plus the included resync duration + if timestamp.IsZero() || now.After(timestamp.Add(resyncPeriodDuration)) { mu.Lock() defer mu.Unlock() diff --git a/pkg/webhook/validator.go b/pkg/webhook/validator.go index 0f986a6e..4d155418 100644 --- a/pkg/webhook/validator.go +++ b/pkg/webhook/validator.go @@ -1055,7 +1055,7 @@ func trustedMaterialFromAuthority(ctx context.Context, authority webhookcip.Auth return nil, fmt.Errorf("trusted root \"%s\" does not exist", authority.Keyless.TrustRootRef) } } - trustedMaterial, err := pctuf.GetTrustedRoot() + trustedMaterial, err := pctuf.GetTrustedRoot(ctx) if err != nil { return nil, fmt.Errorf("failed to parse trusted root from protobuf: %w", err) }