diff --git a/.github/workflows/kind-cluster-image-policy-resync-period.yaml b/.github/workflows/kind-cluster-image-policy-resync-period.yaml deleted file mode 100644 index 08651d1b4..000000000 --- a/.github/workflows/kind-cluster-image-policy-resync-period.yaml +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright 2022 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. - -name: Test policy-controller with ClusterImagePolicy resync period - -on: - pull_request: - branches: [ 'main', 'release-*' ] - -defaults: - run: - shell: bash - -permissions: read-all - -jobs: - cip-test-policy-resync-period: - name: ClusterImagePolicy e2e tests policy resync period - runs-on: ubuntu-latest - - strategy: - fail-fast: false # Keep running if one leg fails. - matrix: - k8s-version: - - v1.27.x - - v1.28.x - - v1.29.x - - env: - KO_DOCKER_REPO: "registry.local:5000/policy-controller" - SCAFFOLDING_RELEASE_VERSION: "v0.7.1" - GO111MODULE: on - GOFLAGS: -ldflags=-s -ldflags=-w - KOCACHE: ~/ko - - steps: - - name: free up disk space for the release - run: | - rm -rf /usr/share/dotnet/ - rm -rf "$AGENT_TOOLSDIRECTORY" - rm -rf "/usr/local/share/boost" - rm -rf /opt/ghc - docker rmi $(docker image ls -aq) || true - swapoff /swapfile || true - rm -rf /swapfile /usr/share/dotnet /usr/local/lib/android /opt/ghc || true - apt purge aria2 ansible hhvm mono-devel azure-cli shellcheck rpm xorriso zsync \ - clang-6.0 lldb-6.0 lld-6.0 clang-format-6.0 clang-8 lldb-8 lld-8 clang-format-8 \ - clang-9 lldb-9 lld-9 clangd-9 clang-format-9 dotnet-sdk-3.0 dotnet-sdk-3.1=3.1.101-1 \ - esl-erlang firefox g++-8 g++-9 gfortran-8 gfortran-9 google-chrome-stable \ - google-cloud-sdk ghc-8.0.2 ghc-8.2.2 ghc-8.4.4 ghc-8.6.2 ghc-8.6.3 ghc-8.6.4 \ - ghc-8.6.5 ghc-8.8.1 ghc-8.8.2 ghc-8.8.3 ghc-8.10.1 cabal-install-2.0 cabal-install-2.2 \ - cabal-install-2.4 cabal-install-3.0 cabal-install-3.2 heroku imagemagick \ - libmagickcore-dev libmagickwand-dev libmagic-dev ant ant-optional kubectl \ - mercurial apt-transport-https mono-complete mysql-client libmysqlclient-dev \ - mysql-server mssql-tools unixodbc-dev yarn bazel chrpath libssl-dev libxft-dev \ - libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev php7.1 php7.1-bcmath \ - php7.1-bz2 php7.1-cgi php7.1-cli php7.1-common php7.1-curl php7.1-dba php7.1-dev \ - php7.1-enchant php7.1-fpm php7.1-gd php7.1-gmp php7.1-imap php7.1-interbase php7.1-intl \ - php7.1-json php7.1-ldap php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-odbc \ - php7.1-opcache php7.1-pgsql php7.1-phpdbg php7.1-pspell php7.1-readline php7.1-recode \ - php7.1-snmp php7.1-soap php7.1-sqlite3 php7.1-sybase php7.1-tidy php7.1-xml \ - php7.1-xmlrpc php7.1-xsl php7.1-zip php7.2 php7.2-bcmath php7.2-bz2 php7.2-cgi \ - php7.2-cli php7.2-common php7.2-curl php7.2-dba php7.2-dev php7.2-enchant php7.2-fpm \ - php7.2-gd php7.2-gmp php7.2-imap php7.2-interbase php7.2-intl php7.2-json php7.2-ldap \ - php7.2-mbstring php7.2-mysql php7.2-odbc php7.2-opcache php7.2-pgsql php7.2-phpdbg \ - php7.2-pspell php7.2-readline php7.2-recode php7.2-snmp php7.2-soap php7.2-sqlite3 \ - php7.2-sybase php7.2-tidy php7.2-xml php7.2-xmlrpc php7.2-xsl php7.2-zip php7.3 \ - php7.3-bcmath php7.3-bz2 php7.3-cgi php7.3-cli php7.3-common php7.3-curl php7.3-dba \ - php7.3-dev php7.3-enchant php7.3-fpm php7.3-gd php7.3-gmp php7.3-imap php7.3-interbase \ - php7.3-intl php7.3-json php7.3-ldap php7.3-mbstring php7.3-mysql php7.3-odbc \ - php7.3-opcache php7.3-pgsql php7.3-phpdbg php7.3-pspell php7.3-readline php7.3-recode \ - php7.3-snmp php7.3-soap php7.3-sqlite3 php7.3-sybase php7.3-tidy php7.3-xml \ - php7.3-xmlrpc php7.3-xsl php7.3-zip php7.4 php7.4-bcmath php7.4-bz2 php7.4-cgi \ - php7.4-cli php7.4-common php7.4-curl php7.4-dba php7.4-dev php7.4-enchant php7.4-fpm \ - php7.4-gd php7.4-gmp php7.4-imap php7.4-interbase php7.4-intl php7.4-json php7.4-ldap \ - php7.4-mbstring php7.4-mysql php7.4-odbc php7.4-opcache php7.4-pgsql php7.4-phpdbg \ - php7.4-pspell php7.4-readline php7.4-snmp php7.4-soap php7.4-sqlite3 php7.4-sybase \ - php7.4-tidy php7.4-xml php7.4-xmlrpc php7.4-xsl php7.4-zip php-amqp php-apcu \ - php-igbinary php-memcache php-memcached php-mongodb php-redis php-xdebug \ - php-zmq snmp pollinate libpq-dev postgresql-client powershell ruby-full \ - sphinxsearch subversion mongodb-org -yq >/dev/null 2>&1 || true - apt-get remove -y 'php.*' || true - apt-get autoremove -y >/dev/null 2>&1 || true - apt-get autoclean -y >/dev/null 2>&1 || true - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 - with: - go-version-file: './go.mod' - check-latest: true - - # will use the latest release available for ko - - uses: ko-build/setup-ko@ace48d793556083a76f1e3e6068850c1f4a369aa # v0.6 - - - uses: imranismail/setup-kustomize@2ba527d4d055ab63514ba50a99456fc35684947f # v2.1.0 - - - name: Install yq - uses: mikefarah/yq@557dcb87b8efe786f89a12c09e9046b4753ab72e # v4.44.1 - - - name: Setup mirror - uses: chainguard-dev/actions/setup-mirror@main - with: - mirror: mirror.gcr.io - - - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 - - - name: Install cluster + sigstore - uses: sigstore/scaffolding/actions/setup@main - with: - k8s-version: ${{ matrix.k8s-version}} - version: ${{ env.SCAFFOLDING_RELEASE_VERSION }} - - - name: Copy TUF root to policy-controller namespace - run: | - kubectl create ns cosign-system - kubectl -n tuf-system get secrets tuf-root -oyaml | sed 's/namespace: .*/namespace: cosign-system/' | kubectl create -f - - echo "TUF_ROOT_FILE=./root.json" >> $GITHUB_ENV - - - name: Install policy-controller with invalid policy-resync-period - env: - GIT_HASH: ${{ github.sha }} - GIT_VERSION: ci - LDFLAGS: "" - POLICY_CONTROLLER_YAML: test/kustomize-invalid-policy-resync-period/policy-controller-e2e.yaml - KO_PREFIX: registry.local:5000/policy-controller - POLICY_CONTROLLER_ARCHS: linux/amd64 - run: | - make ko-policy-controller - kustomize build test/kustomize-invalid-policy-resync-period | kubectl apply -f - - - sleep 30 - - # And make sure a panic occurred - kubectl -n cosign-system logs deployment/webhook | grep "panic: Failed to parse --policy-resync-period '1d' : time: unknown unit \"d\" in duration \"1d\"" - - sleep 10 - - - name: Install policy-controller with valid policy-resync-period - env: - GIT_HASH: ${{ github.sha }} - GIT_VERSION: ci - LDFLAGS: "" - POLICY_CONTROLLER_YAML: test/kustomize-policy-resync-period/policy-controller-e2e.yaml - KO_PREFIX: registry.local:5000/policy-controller - POLICY_CONTROLLER_ARCHS: linux/amd64 - run: | - make ko-policy-controller - kustomize build test/kustomize-policy-resync-period | kubectl apply -f - - - # Wait for the webhook to come up and become Ready - kubectl rollout status --timeout 5m --namespace cosign-system deployments/webhook - sleep 10 - - - name: Collect diagnostics - if: ${{ failure() }} - uses: chainguard-dev/actions/kind-diag@84c993eaf02da1c325854fb272a4df9184bd80fc # main diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index dea515426..52f329caa 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -97,7 +97,11 @@ var ( // policyResyncPeriod holds the interval which ClusterImagePolicies will resync // This is essential for triggering a reconcile update for potentially stale KMS authorities. - policyResyncPeriod = flag.String("policy-resync-period", "10h", "The resync period for ClusterImagePolicies. The default is 10h.") + policyResyncPeriod = flag.Duration("policy-resync-period", 10*time.Hour, "The resync period for ClusterImagePolicies. The default is 10h.") + + // trustrootResyncPeriod holds the interval which the TrustRoot will resync + // This is essential for triggering a reconcile update for potentially stale TUF metadata. + trustrootResyncPeriod = flag.Duration("trustroot-resync-period", 24*time.Hour, "The resync period for ClusterImagePolicies. The default is 24h.") ) func main() { @@ -130,11 +134,9 @@ func main() { } } - if duration, err := time.ParseDuration(*policyResyncPeriod); err != nil { - logging.FromContext(ctx).Panicf("Failed to parse --policy-resync-period '%s' : %v", *policyResyncPeriod, err) - } else { - ctx = clusterimagepolicy.ToContext(ctx, duration) - } + // Set the policy and trust root resync periods + ctx = clusterimagepolicy.ToContext(ctx, *policyResyncPeriod) + ctx = trustroot.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 3c1658c59..ae4391787 100644 --- a/pkg/reconciler/trustroot/controller.go +++ b/pkg/reconciler/trustroot/controller.go @@ -16,6 +16,7 @@ package trustroot import ( "context" + "time" "k8s.io/client-go/tools/cache" kubeclient "knative.dev/pkg/client/injection/kube/client" @@ -36,6 +37,8 @@ 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, @@ -63,20 +66,34 @@ func NewController( // ConfigMap but there are no changes to the TrustRoot, it needs // to be synced. grCb := func(obj interface{}) { - logging.FromContext(ctx).Info("Doing a global resync on TrustRoot due to ConfigMap changing.") + logging.FromContext(ctx).Info("Doing a global resync on TrustRoot due to ConfigMap changing or resync period.") impl.GlobalResync(trustrootInformer.Informer()) } // Resync on only ConfigMap changes that pertain to the one I care about. // We could also fetch/construct the store and use CM watcher for it, but // since we need a lister for it anyways in the reconciler, just set up // the watch here. - if _, err := configMapInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + if _, err := configMapInformer.Informer().AddEventHandlerWithResyncPeriod(cache.FilteringResourceEventHandler{ FilterFunc: pkgreconciler.ChainFilterFuncs( pkgreconciler.NamespaceFilterFunc(system.Namespace()), pkgreconciler.NameFilterFunc(config.SigstoreKeysConfigName)), Handler: controller.HandleAll(grCb), - }); err != nil { - logging.FromContext(ctx).Warnf("Failed configMapInformer AddEventHandler() %v", err) + }, 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 0377b5621..7d6b442a1 100644 --- a/pkg/reconciler/trustroot/controller_test.go +++ b/pkg/reconciler/trustroot/controller_test.go @@ -16,8 +16,10 @@ package trustroot import ( "testing" + "time" "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" rtesting "knative.dev/pkg/reconciler/testing" // Fake injection informers @@ -37,3 +39,21 @@ 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/test/kustomize-invalid-policy-resync-period/kustomization.yaml b/test/kustomize-invalid-policy-resync-period/kustomization.yaml deleted file mode 100644 index 735110c5e..000000000 --- a/test/kustomize-invalid-policy-resync-period/kustomization.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2022 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 -# -# https://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. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- policy-controller-e2e.yaml - -patches: -- patch: |- - - op: add - path: /spec/template/spec/containers/0/args/- - value: --policy-resync-period=1d - - target: - kind: Deployment - name: webhook diff --git a/test/kustomize-policy-resync-period/kustomization.yaml b/test/kustomize-policy-resync-period/kustomization.yaml deleted file mode 100644 index 5b4a1c943..000000000 --- a/test/kustomize-policy-resync-period/kustomization.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2022 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 -# -# https://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. - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- policy-controller-e2e.yaml - -patches: -- patch: |- - - op: add - path: /spec/template/spec/containers/0/args/- - value: --policy-resync-period=1h - - target: - kind: Deployment - name: webhook