From a550a719dc1d7523e9234241d81f00909e57eed3 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Wed, 7 Jan 2026 14:17:00 -0600
Subject: [PATCH 01/16] chore: bump gofalcon v0.19.0
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 402bc8f2..a0ad0d5a 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.7
github.com/cert-manager/cert-manager v1.12.14
github.com/containers/image/v5 v5.31.1
- github.com/crowdstrike/gofalcon v0.18.1-0.20251219213215-c969f34e7808
+ github.com/crowdstrike/gofalcon v0.19.0
github.com/go-logr/logr v1.4.2
github.com/go-openapi/swag v0.23.0
github.com/google/go-cmp v0.6.0
diff --git a/go.sum b/go.sum
index 1ae41c9e..5e10e71f 100644
--- a/go.sum
+++ b/go.sum
@@ -90,8 +90,8 @@ github.com/containers/storage v1.54.0 h1:xwYAlf6n9OnIlURQLLg3FYHbO74fQ/2W2N6EtQE
github.com/containers/storage v1.54.0/go.mod h1:PlMOoinRrBSnhYODLxt4EXl0nmJt+X0kjG0Xdt9fMTw=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/crowdstrike/gofalcon v0.18.1-0.20251219213215-c969f34e7808 h1:4u5t0ieUKpeKH59ZR7W6wGXuL0KsoE3hFliaQOJrmyA=
-github.com/crowdstrike/gofalcon v0.18.1-0.20251219213215-c969f34e7808/go.mod h1:a12GB+md+hRSgVCb3Pv6CakeTIsDIUCIVWRlJelIhY0=
+github.com/crowdstrike/gofalcon v0.19.0 h1:pKvA8Az85wD6OR7aq/tvc+tORtR5CSyKp3+LDQXc4pc=
+github.com/crowdstrike/gofalcon v0.19.0/go.mod h1:a12GB+md+hRSgVCb3Pv6CakeTIsDIUCIVWRlJelIhY0=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
From 4e240b927bad501939c04d92e312704d61adde21 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Mon, 22 Dec 2025 14:33:36 -0600
Subject: [PATCH 02/16] fix: Remove bump release workflow
---
.github/workflows/bump-release.yml | 110 -----------------------------
1 file changed, 110 deletions(-)
delete mode 100644 .github/workflows/bump-release.yml
diff --git a/.github/workflows/bump-release.yml b/.github/workflows/bump-release.yml
deleted file mode 100644
index a26ab40e..00000000
--- a/.github/workflows/bump-release.yml
+++ /dev/null
@@ -1,110 +0,0 @@
-name: Bump Release
-
-on:
- workflow_dispatch:
- inputs:
- version:
- description: 'Version to release'
- required: true
- type: string
-
-permissions: read-all
-
-env:
- PROJECT_DIR: falcon-operator
- IMAGE_NAME: falcon-operator
- IMAGE_TAG: latest
- IMAGE_REGISTRY: quay.io
- IMAGE_NAMESPACE: crowdstrike
- RELEASE_TAG: ${{ github.event.inputs.version }}
- RELEASE_BRANCH: maint-1.0
-
-jobs:
- validate_branch:
- runs-on: ubuntu-latest
- steps:
- - name: Check if on correct branch
- if: github.ref != format('refs/heads/{0}', env.RELEASE_BRANCH)
- run: |
- echo "This workflow can only be run on ${{ env.RELEASE_BRANCH }} branch"
- exit 1
- validate_version:
- runs-on: ubuntu-latest
- steps:
- - name: Check version format
- run: |
- if [[ ! ${{ github.event.inputs.version }} =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
- echo "Invalid version format. Must be in the format vX.X.X"
- exit 1
- fi
- bump_release:
- runs-on: ubuntu-latest
- needs: [validate_branch, validate_version]
- permissions:
- contents: write
- id-token: write
- timeout-minutes: 10
- steps:
- - name: Harden the runner (Audit all outbound calls)
- uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
- with:
- egress-policy: audit
-
- - name: Checkout full repository
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- fetch-depth: 0
-
- - name: Install dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y libgpgme-dev libbtrfs-dev libdevmapper-dev
- - name: Checkout release branch
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- with:
- fetch-depth: 0
- ref: ${{ env.RELEASE_BRANCH }}
- fetch-tags: true
-
- - name: Configure Git
- id: config_git
- run: |
- git config user.name github-actions
- git config user.email github-actions@github.com
- VERSION=${{ env.RELEASE_TAG }}
- NEWVERSION=${VERSION:1}
- echo "NEWVERSION=${NEWVERSION}" >> $GITHUB_ENV
- - name: Generate Changelog
- id: changelog
- run: |
- release=${{ env.NEWVERSION }}
- cl=CHANGELOG.md
- today=$(date +%F)
- header=$(head -n7 ${cl})
- older=$(tail -n+7 ${cl})
- # get all commits on head since the latest tag
- changes=$(git log --no-merges --pretty=format:"- %s" $(git describe --tags --abbrev=0 HEAD^)..HEAD)
- echo "${header}" > ${cl}
- echo "" >> ${cl}
- echo "## [${release}] - ${today}" >> ${cl}
- echo "" >> ${cl}
- echo "### Changed" >> ${cl}
- echo "" >> ${cl}
- echo "${changes}" >> ${cl}
- echo "${older}" >> ${cl}
- env:
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
-
- - name: Update release changes
- id: git_commit
- run: |
- OLDVERSION=$(grep ^VERSION Makefile | awk '{print $NF}')
- sed -i "s/$OLDVERSION/${{ env.NEWVERSION }}/g" -i Makefile
- mkdir -p $HOME/go/bin
- export PATH=$HOME/go/bin:$PATH
- make operator-sdk
- make manifests bundle non-olm IMG=${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.NEWVERSION }}
- git checkout -b version-bump-build-${{ github.run_number }}
- git add -u
- git commit -m "Bumping to version ${{ env.NEWVERSION }}"
- git push origin version-bump-build-${{ github.run_number }}
From 5c5bfa7947e0f56f088fe0b7a0324b2e5e53449a Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Thu, 15 Jan 2026 13:46:56 -0600
Subject: [PATCH 03/16] chore(falconcontainer): Add injector tests
---
.../controller/falcon_container/injector.go | 2 +-
.../falcon_container/injector_test.go | 284 ++++++++++++++++++
2 files changed, 285 insertions(+), 1 deletion(-)
create mode 100644 internal/controller/falcon_container/injector_test.go
diff --git a/internal/controller/falcon_container/injector.go b/internal/controller/falcon_container/injector.go
index 6d23e641..7aa3eacd 100644
--- a/internal/controller/falcon_container/injector.go
+++ b/internal/controller/falcon_container/injector.go
@@ -58,7 +58,7 @@ func (r *FalconContainerReconciler) reconcileInjectorTLSSecret(ctx context.Conte
}
return injectorTLSSecret, r.Create(ctx, log, falconContainer, injectorTLSSecret)
}
- return &corev1.Secret{}, fmt.Errorf("unable to query existing injector TL secret %s: %v", injectorTLSSecretName, err)
+ return &corev1.Secret{}, fmt.Errorf("unable to query existing injector TLS secret %s: %v", injectorTLSSecretName, err)
}
return existingInjectorTLSSecret, nil
diff --git a/internal/controller/falcon_container/injector_test.go b/internal/controller/falcon_container/injector_test.go
new file mode 100644
index 00000000..180d8248
--- /dev/null
+++ b/internal/controller/falcon_container/injector_test.go
@@ -0,0 +1,284 @@
+package falcon
+
+import (
+ "context"
+ "testing"
+
+ falconv1alpha1 "github.com/crowdstrike/falcon-operator/api/falcon/v1alpha1"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
+ "sigs.k8s.io/controller-runtime/pkg/log/zap"
+)
+
+// Mock client that returns errors for testing error handling
+type erroringClient struct {
+ client.Client
+}
+
+func (e *erroringClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
+ return errors.NewBadRequest("test error")
+}
+
+func TestReconcileInjectorTLSSecretLogic(t *testing.T) {
+ ctx := context.Background()
+ log := zap.New(zap.UseDevMode(true))
+
+ // Create test scheme
+ scheme := runtime.NewScheme()
+ require.NoError(t, corev1.AddToScheme(scheme))
+ require.NoError(t, falconv1alpha1.AddToScheme(scheme))
+
+ t.Run("should return existing secret when found", func(t *testing.T) {
+ existingSecret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: injectorTLSSecretName,
+ Namespace: "test-namespace",
+ },
+ Type: corev1.SecretTypeTLS,
+ Data: map[string][]byte{
+ "tls.crt": []byte("existing-cert"),
+ "tls.key": []byte("existing-key"),
+ "ca.crt": []byte("existing-ca"),
+ },
+ }
+
+ falconContainer := &falconv1alpha1.FalconContainer{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-falcon-container",
+ Namespace: "test-namespace",
+ },
+ Spec: falconv1alpha1.FalconContainerSpec{
+ InstallNamespace: "test-namespace",
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{},
+ },
+ },
+ }
+
+ fakeClient := fake.NewClientBuilder().
+ WithScheme(scheme).
+ WithObjects(existingSecret, falconContainer).
+ Build()
+
+ reconciler := &FalconContainerReconciler{
+ Client: fakeClient,
+ Reader: fakeClient,
+ Scheme: scheme,
+ }
+
+ secret, err := reconciler.reconcileInjectorTLSSecret(ctx, log, falconContainer)
+
+ require.NoError(t, err)
+ assert.NotNil(t, secret)
+ assert.Equal(t, injectorTLSSecretName, secret.Name)
+ assert.Equal(t, "test-namespace", secret.Namespace)
+ assert.Equal(t, []byte("existing-cert"), secret.Data["tls.crt"])
+ assert.Equal(t, []byte("existing-key"), secret.Data["tls.key"])
+ assert.Equal(t, []byte("existing-ca"), secret.Data["ca.crt"])
+ })
+
+ t.Run("should handle default validity configuration", func(t *testing.T) {
+ falconContainer := &falconv1alpha1.FalconContainer{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-falcon-container",
+ Namespace: "test-namespace",
+ },
+ Spec: falconv1alpha1.FalconContainerSpec{
+ InstallNamespace: "test-namespace",
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{
+ Validity: nil, // Should use default 3650
+ },
+ },
+ },
+ }
+
+ validity := 3650
+ if falconContainer.Spec.Injector.TLS.Validity != nil {
+ validity = *falconContainer.Spec.Injector.TLS.Validity
+ }
+
+ assert.Equal(t, 3650, validity)
+ })
+
+ t.Run("should handle custom validity configuration", func(t *testing.T) {
+ customValidity := 1000
+ falconContainer := &falconv1alpha1.FalconContainer{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-falcon-container",
+ Namespace: "test-namespace",
+ },
+ Spec: falconv1alpha1.FalconContainerSpec{
+ InstallNamespace: "test-namespace",
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{
+ Validity: &customValidity,
+ },
+ },
+ },
+ }
+
+ validity := 3650
+ if falconContainer.Spec.Injector.TLS.Validity != nil {
+ validity = *falconContainer.Spec.Injector.TLS.Validity
+ }
+
+ assert.Equal(t, 1000, validity)
+ })
+
+ t.Run("should handle errors from GetNamespacedObject", func(t *testing.T) {
+ falconContainer := &falconv1alpha1.FalconContainer{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-falcon-container",
+ Namespace: "test-namespace",
+ },
+ Spec: falconv1alpha1.FalconContainerSpec{
+ InstallNamespace: "test-namespace",
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{},
+ },
+ },
+ }
+
+ // Create a fake client that will return an error
+ fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
+
+ reconciler := &FalconContainerReconciler{
+ Client: &erroringClient{Client: fakeClient},
+ Reader: &erroringClient{Client: fakeClient},
+ Scheme: scheme,
+ }
+
+ secret, err := reconciler.reconcileInjectorTLSSecret(ctx, log, falconContainer)
+
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "unable to query existing injector TLS secret")
+ assert.NotNil(t, secret) // Should return empty secret on error
+ })
+
+ t.Run("should handle validity boundary values", func(t *testing.T) {
+ testCases := []struct {
+ name string
+ validity *int
+ expectedValidity int
+ }{
+ {
+ name: "nil validity uses default",
+ validity: nil,
+ expectedValidity: 3650,
+ },
+ {
+ name: "minimum validity (0)",
+ validity: &[]int{0}[0],
+ expectedValidity: 0,
+ },
+ {
+ name: "single digit validity",
+ validity: &[]int{1}[0],
+ expectedValidity: 1,
+ },
+ {
+ name: "maximum validity (9999)",
+ validity: &[]int{9999}[0],
+ expectedValidity: 9999,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ falconContainer := &falconv1alpha1.FalconContainer{
+ Spec: falconv1alpha1.FalconContainerSpec{
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{
+ Validity: tc.validity,
+ },
+ },
+ },
+ }
+
+ validity := 3650
+ if falconContainer.Spec.Injector.TLS.Validity != nil {
+ validity = *falconContainer.Spec.Injector.TLS.Validity
+ }
+
+ assert.Equal(t, tc.expectedValidity, validity)
+ })
+ }
+ })
+}
+
+func TestReconcileInjectorTLSSecretIntegrationScenarios(t *testing.T) {
+ ctx := context.Background()
+ log := zap.New(zap.UseDevMode(true))
+
+ // Create test scheme
+ scheme := runtime.NewScheme()
+ require.NoError(t, corev1.AddToScheme(scheme))
+ require.NoError(t, falconv1alpha1.AddToScheme(scheme))
+
+ t.Run("secret data should have correct TLS structure", func(t *testing.T) {
+ existingSecret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: injectorTLSSecretName,
+ Namespace: "test-namespace",
+ },
+ Type: corev1.SecretTypeTLS,
+ Data: map[string][]byte{
+ "tls.crt": []byte("-----BEGIN CERTIFICATE-----\nfake-cert\n-----END CERTIFICATE-----"),
+ "tls.key": []byte("-----BEGIN PRIVATE KEY-----\nfake-key\n-----END PRIVATE KEY-----"),
+ "ca.crt": []byte("-----BEGIN CERTIFICATE-----\nfake-ca\n-----END CERTIFICATE-----"),
+ },
+ }
+
+ falconContainer := &falconv1alpha1.FalconContainer{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-falcon-container",
+ Namespace: "test-namespace",
+ },
+ Spec: falconv1alpha1.FalconContainerSpec{
+ InstallNamespace: "test-namespace",
+ Injector: falconv1alpha1.FalconContainerInjectorSpec{
+ TLS: falconv1alpha1.FalconContainerInjectorTLS{},
+ },
+ },
+ }
+
+ fakeClient := fake.NewClientBuilder().
+ WithScheme(scheme).
+ WithObjects(existingSecret, falconContainer).
+ Build()
+
+ reconciler := &FalconContainerReconciler{
+ Client: fakeClient,
+ Reader: fakeClient,
+ Scheme: scheme,
+ }
+
+ secret, err := reconciler.reconcileInjectorTLSSecret(ctx, log, falconContainer)
+
+ require.NoError(t, err)
+ assert.Equal(t, corev1.SecretTypeTLS, secret.Type)
+
+ // Verify all required TLS keys are present
+ requiredKeys := []string{"tls.crt", "tls.key", "ca.crt"}
+ for _, key := range requiredKeys {
+ assert.Contains(t, secret.Data, key, "Secret should contain %s", key)
+ assert.NotEmpty(t, secret.Data[key], "Secret key %s should not be empty", key)
+ }
+
+ // Verify certificate-like structure (basic validation)
+ tlsCert := string(secret.Data["tls.crt"])
+ tlsKey := string(secret.Data["tls.key"])
+ caCert := string(secret.Data["ca.crt"])
+
+ assert.Contains(t, tlsCert, "CERTIFICATE", "tls.crt should contain certificate markers")
+ assert.Contains(t, tlsKey, "PRIVATE KEY", "tls.key should contain private key markers")
+ assert.Contains(t, caCert, "CERTIFICATE", "ca.crt should contain certificate markers")
+ })
+}
From 100949a3262e7b0becc93474993bd8e8e391eb8b Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Tue, 20 Jan 2026 12:27:21 -0600
Subject: [PATCH 04/16] feat(falcon-imageanalyzer): Add image exclusions
---
api/falcon/v1alpha1/falconimageanalyzer_types.go | 4 ++++
api/falcon/v1alpha1/zz_generated.deepcopy.go | 5 +++++
.../falcon.crowdstrike.com_falcondeployments.yaml | 6 ++++++
.../falcon.crowdstrike.com_falconimageanalyzers.yaml | 6 ++++++
deploy/falcon-operator.yaml | 12 ++++++++++++
.../openshift/resources/imageanalyzer/README.md | 1 +
docs/resources/imageanalyzer/README.md | 1 +
docs/src/resources/imageanalyzer.md.tmpl | 1 +
.../controller/falcon_image_analyzer/configmap.go | 4 ++++
.../controller/falcon_image_analyzer/image_push.go | 6 +++---
pkg/registry/falcon_registry/container.go | 2 +-
11 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/api/falcon/v1alpha1/falconimageanalyzer_types.go b/api/falcon/v1alpha1/falconimageanalyzer_types.go
index 8d601397..e82cc9be 100644
--- a/api/falcon/v1alpha1/falconimageanalyzer_types.go
+++ b/api/falcon/v1alpha1/falconimageanalyzer_types.go
@@ -180,6 +180,10 @@ type Exclusions struct {
// Configure a list of namespaces for Image Analyzer to ignore.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Ignore Namespace List",order=2
Namespaces []string `json:"namespaces,omitempty"`
+
+ // Configure a list of image names for Image Analyzer to ignore.
+ // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Ignore Images List",order=3
+ ImageNames []string `json:"imageNames,omitempty"`
}
type RegistryConfig struct {
diff --git a/api/falcon/v1alpha1/zz_generated.deepcopy.go b/api/falcon/v1alpha1/zz_generated.deepcopy.go
index d4808454..2c6e20ed 100644
--- a/api/falcon/v1alpha1/zz_generated.deepcopy.go
+++ b/api/falcon/v1alpha1/zz_generated.deepcopy.go
@@ -258,6 +258,11 @@ func (in *Exclusions) DeepCopyInto(out *Exclusions) {
*out = make([]string, len(*in))
copy(*out, *in)
}
+ if in.ImageNames != nil {
+ in, out := &in.ImageNames, &out.ImageNames
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Exclusions.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
index ac2e2d25..876990b1 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
@@ -3364,6 +3364,12 @@ spec:
exclusions:
description: Exclusions for the Falcon Image Analyzer.
properties:
+ imageNames:
+ description: Configure a list of image names for Image
+ Analyzer to ignore.
+ items:
+ type: string
+ type: array
namespaces:
description: Configure a list of namespaces for Image
Analyzer to ignore.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml b/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
index 212a4ad1..3d6b6216 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
@@ -125,6 +125,12 @@ spec:
exclusions:
description: Exclusions for the Falcon Image Analyzer.
properties:
+ imageNames:
+ description: Configure a list of image names for Image Analyzer
+ to ignore.
+ items:
+ type: string
+ type: array
namespaces:
description: Configure a list of namespaces for Image Analyzer
to ignore.
diff --git a/deploy/falcon-operator.yaml b/deploy/falcon-operator.yaml
index 117f9a40..1f480527 100644
--- a/deploy/falcon-operator.yaml
+++ b/deploy/falcon-operator.yaml
@@ -6766,6 +6766,12 @@ spec:
exclusions:
description: Exclusions for the Falcon Image Analyzer.
properties:
+ imageNames:
+ description: Configure a list of image names for Image
+ Analyzer to ignore.
+ items:
+ type: string
+ type: array
namespaces:
description: Configure a list of namespaces for Image
Analyzer to ignore.
@@ -8143,6 +8149,12 @@ spec:
exclusions:
description: Exclusions for the Falcon Image Analyzer.
properties:
+ imageNames:
+ description: Configure a list of image names for Image Analyzer
+ to ignore.
+ items:
+ type: string
+ type: array
namespaces:
description: Configure a list of namespaces for Image Analyzer
to ignore.
diff --git a/docs/deployment/openshift/resources/imageanalyzer/README.md b/docs/deployment/openshift/resources/imageanalyzer/README.md
index afd45bbb..71ea06a6 100644
--- a/docs/deployment/openshift/resources/imageanalyzer/README.md
+++ b/docs/deployment/openshift/resources/imageanalyzer/README.md
@@ -59,6 +59,7 @@ spec:
| imageAnalyzerConfig.priorityClass.name | (optional) Set to avoid pod evictions due to resource limits. |
| imageAnalyzerConfig.exclusions.registries | (optional) Set the value as a list of registries to be excluded. All images in that registry(s) will be excluded |
| imageAnalyzerConfig.exclusions.namespaces | (optional) Set the value as a list of namespaces to be excluded. All pods in that namespace(s) will be excluded |
+| imageAnalyzerConfig.exclusions.imageNames | (optional) Set the value as a list of fully qualified image names to be excluded. |
| imageAnalyzerConfig.imagePullPolicy | (optional) Configure the image pull policy of the Falcon Image Analyzer |
| imageAnalyzerConfig.imagePullSecrets | (optional) Configure the image pull secrets of the Falcon Image Analyzer |
| imageAnalyzerConfig.registryConfig.credentials | (optional) Use this to provide registry secrets in the form of a list of maps. e.g.
- namespace: ns1
secretName: mysecretname
To scan OpenShift control plane components, specify the cluster's pull secret: - namespace: openshift-config
secretName: pull-secret
|
diff --git a/docs/resources/imageanalyzer/README.md b/docs/resources/imageanalyzer/README.md
index 84418ba6..78556819 100644
--- a/docs/resources/imageanalyzer/README.md
+++ b/docs/resources/imageanalyzer/README.md
@@ -59,6 +59,7 @@ spec:
| imageAnalyzerConfig.priorityClass.name | (optional) Set to avoid pod evictions due to resource limits. |
| imageAnalyzerConfig.exclusions.registries | (optional) Set the value as a list of registries to be excluded. All images in that registry(s) will be excluded |
| imageAnalyzerConfig.exclusions.namespaces | (optional) Set the value as a list of namespaces to be excluded. All pods in that namespace(s) will be excluded |
+| imageAnalyzerConfig.exclusions.imageNames | (optional) Set the value as a list of fully qualified image names to be excluded. |
| imageAnalyzerConfig.imagePullPolicy | (optional) Configure the image pull policy of the Falcon Image Analyzer |
| imageAnalyzerConfig.imagePullSecrets | (optional) Configure the image pull secrets of the Falcon Image Analyzer |
| imageAnalyzerConfig.registryConfig.credentials | (optional) Use this to provide registry secrets in the form of a list of maps. e.g.- namespace: ns1
secretName: mysecretname
To scan OpenShift control plane components, specify the cluster's pull secret: - namespace: openshift-config
secretName: pull-secret
|
diff --git a/docs/src/resources/imageanalyzer.md.tmpl b/docs/src/resources/imageanalyzer.md.tmpl
index cf94cc21..5289df8b 100644
--- a/docs/src/resources/imageanalyzer.md.tmpl
+++ b/docs/src/resources/imageanalyzer.md.tmpl
@@ -59,6 +59,7 @@ spec:
| imageAnalyzerConfig.priorityClass.name | (optional) Set to avoid pod evictions due to resource limits. |
| imageAnalyzerConfig.exclusions.registries | (optional) Set the value as a list of registries to be excluded. All images in that registry(s) will be excluded |
| imageAnalyzerConfig.exclusions.namespaces | (optional) Set the value as a list of namespaces to be excluded. All pods in that namespace(s) will be excluded |
+| imageAnalyzerConfig.exclusions.imageNames | (optional) Set the value as a list of fully qualified image names to be excluded. |
| imageAnalyzerConfig.imagePullPolicy | (optional) Configure the image pull policy of the Falcon Image Analyzer |
| imageAnalyzerConfig.imagePullSecrets | (optional) Configure the image pull secrets of the Falcon Image Analyzer |
| imageAnalyzerConfig.registryConfig.credentials | (optional) Use this to provide registry secrets in the form of a list of maps. e.g.- namespace: ns1
secretName: mysecretname
To scan OpenShift control plane components, specify the cluster's pull secret: - namespace: openshift-config
secretName: pull-secret
|
diff --git a/internal/controller/falcon_image_analyzer/configmap.go b/internal/controller/falcon_image_analyzer/configmap.go
index 6a20da70..e2d1e6fa 100644
--- a/internal/controller/falcon_image_analyzer/configmap.go
+++ b/internal/controller/falcon_image_analyzer/configmap.go
@@ -106,6 +106,10 @@ func (r *FalconImageAnalyzerReconciler) newConfigMap(ctx context.Context, name s
data["AGENT_REGISTRY_EXCLUSIONS"] = strings.Join(falconImageAnalyzer.Spec.ImageAnalyzerConfig.Exclusions.Registries, ",")
}
+ if len(falconImageAnalyzer.Spec.ImageAnalyzerConfig.Exclusions.ImageNames) > 0 {
+ data["AGENT_IMAGE_EXCLUSIONS"] = strings.Join(falconImageAnalyzer.Spec.ImageAnalyzerConfig.Exclusions.ImageNames, ",")
+ }
+
data["AGENT_DEBUG"] = strconv.FormatBool(falconImageAnalyzer.Spec.ImageAnalyzerConfig.EnableDebug)
// Registry auto-discovery configuration
diff --git a/internal/controller/falcon_image_analyzer/image_push.go b/internal/controller/falcon_image_analyzer/image_push.go
index 06b1d786..d0386bcf 100644
--- a/internal/controller/falcon_image_analyzer/image_push.go
+++ b/internal/controller/falcon_image_analyzer/image_push.go
@@ -49,7 +49,7 @@ func (r *FalconImageAnalyzerReconciler) PushImage(ctx context.Context, log logr.
image := image.NewImageRefresher(ctx, log, falconApiConfig, pushAuth, falconImageAnalyzer.Spec.Registry.TLS.InsecureSkipVerify)
version := falconImageAnalyzer.Spec.Version
- tag, err := image.Refresh(registryUri, falcon.ImageSensor, version)
+ tag, err := image.Refresh(registryUri, falcon.RegionedImageSensor, version)
if err != nil {
return fmt.Errorf("Cannot push Falcon Image Analyzer Image: %v", err)
}
@@ -139,7 +139,7 @@ func (r *FalconImageAnalyzerReconciler) registryUri(ctx context.Context, falconI
return "", err
}
- return falcon.FalconContainerSensorImageURI(cloud, falcon.ImageSensor), nil
+ return falcon.FalconContainerSensorImageURI(cloud, falcon.RegionedImageSensor), nil
default:
return "", fmt.Errorf("Unrecognized registry type: %s", falconImageAnalyzer.Spec.Registry.Type)
}
@@ -209,7 +209,7 @@ func (r *FalconImageAnalyzerReconciler) setImageTag(ctx context.Context, falconI
return "", err
}
- tag, err := registry.LastContainerTag(ctx, falcon.ImageSensor, falconImageAnalyzer.Spec.Version)
+ tag, err := registry.LastContainerTag(ctx, falcon.RegionedImageSensor, falconImageAnalyzer.Spec.Version)
if err == nil {
falconImageAnalyzer.Status.Sensor = common.ImageVersion(tag)
}
diff --git a/pkg/registry/falcon_registry/container.go b/pkg/registry/falcon_registry/container.go
index a33de211..54323685 100644
--- a/pkg/registry/falcon_registry/container.go
+++ b/pkg/registry/falcon_registry/container.go
@@ -24,7 +24,7 @@ func (reg *FalconRegistry) LastContainerTag(ctx context.Context, sensorType falc
regionedFilter := func(tag string) bool {
tagContains := ".container"
- if sensorType == falcon.ImageSensor || sensorType == falcon.KacSensor {
+ if sensorType == falcon.RegionedImageSensor || sensorType == falcon.KacSensor {
tagContains = ""
}
From e5d87008f439c0a67466bfb9a98dcf901be18188 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Tue, 20 Jan 2026 18:08:34 -0600
Subject: [PATCH 05/16] chore(docs): Update CrowdStrike registry usage for
FalconNodeSensor
---
docs/deployment/openshift/resources/node/README.md | 11 ++++++++---
docs/resources/node/README.md | 11 ++++++++---
docs/src/resources/node.md.tmpl | 11 ++++++++---
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/docs/deployment/openshift/resources/node/README.md b/docs/deployment/openshift/resources/node/README.md
index c748da0e..d3103e21 100644
--- a/docs/deployment/openshift/resources/node/README.md
+++ b/docs/deployment/openshift/resources/node/README.md
@@ -60,14 +60,14 @@ spec:
| installNamespace | (optional) Override the default namespace of falcon-system |
| node.tolerations | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ for examples on configuring tolerations |
| node.nodeAffinity | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ for examples on configuring nodeAffinity |
-| node.image | (optional) Location of the Falcon Sensor Image. Specify only when you mirror the original image to your own image repository |
+| node.image | (optional) Location of the Falcon Sensor Image. Use this field only when pulling from non-CrowdStrike registries (e.g., when you mirror the original image to your own image repository). For CrowdStrike registries, use `node.version` instead. |
| node.imagePullPolicy | (optional) Override the default Falcon Container image pull policy of Always |
| node.imagePullSecrets | (optional) list of references to secrets to use for pulling image from image_override location. |
| node.terminationGracePeriod | (optional) Kills pod after a specified amount of time (in seconds). Default is 60 seconds. |
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
-| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207") |
+| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
| node.gke.cleanupAllowListVersion | (optional) WorkloadAllowlist version for the cleanup daemonset when using GKE AutoPilot (example: "v1.0.2" for crowdstrike-falconsensor-cleanup-allowlist-v1.0.2) |
@@ -186,7 +186,12 @@ oc delete falconnodesensors --all
### Sensor upgrades
-To upgrade the sensor version, simply add and/or update the `version` field in the FalconNodeSensor resource and apply the change. Alternatively if the `image` field was used instead of using the Falcon API credentials, add and/or update the `image` field in the FalconNodeSensor resource and apply the change. The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+To upgrade the sensor version:
+
+- **For CrowdStrike registries** (when using Falcon API credentials): Add and/or update the `version` field in the FalconNodeSensor resource and apply the change.
+- **For non-CrowdStrike registries**: Add and/or update the `image` field in the FalconNodeSensor resource and apply the change.
+
+The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
### Troubleshooting
diff --git a/docs/resources/node/README.md b/docs/resources/node/README.md
index e5c289ec..9f007999 100644
--- a/docs/resources/node/README.md
+++ b/docs/resources/node/README.md
@@ -60,14 +60,14 @@ spec:
| installNamespace | (optional) Override the default namespace of falcon-system |
| node.tolerations | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ for examples on configuring tolerations |
| node.nodeAffinity | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ for examples on configuring nodeAffinity |
-| node.image | (optional) Location of the Falcon Sensor Image. Specify only when you mirror the original image to your own image repository |
+| node.image | (optional) Location of the Falcon Sensor Image. Use this field only when pulling from non-CrowdStrike registries (e.g., when you mirror the original image to your own image repository). For CrowdStrike registries, use `node.version` instead. |
| node.imagePullPolicy | (optional) Override the default Falcon Container image pull policy of Always |
| node.imagePullSecrets | (optional) list of references to secrets to use for pulling image from image_override location. |
| node.terminationGracePeriod | (optional) Kills pod after a specified amount of time (in seconds). Default is 60 seconds. |
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
-| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207") |
+| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
| node.gke.cleanupAllowListVersion | (optional) WorkloadAllowlist version for the cleanup daemonset when using GKE AutoPilot (example: "v1.0.2" for crowdstrike-falconsensor-cleanup-allowlist-v1.0.2) |
@@ -186,7 +186,12 @@ kubectl delete falconnodesensors --all
### Sensor upgrades
-To upgrade the sensor version, simply add and/or update the `version` field in the FalconNodeSensor resource and apply the change. Alternatively if the `image` field was used instead of using the Falcon API credentials, add and/or update the `image` field in the FalconNodeSensor resource and apply the change. The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+To upgrade the sensor version:
+
+- **For CrowdStrike registries** (when using Falcon API credentials): Add and/or update the `version` field in the FalconNodeSensor resource and apply the change.
+- **For non-CrowdStrike registries**: Add and/or update the `image` field in the FalconNodeSensor resource and apply the change.
+
+The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
### Troubleshooting
diff --git a/docs/src/resources/node.md.tmpl b/docs/src/resources/node.md.tmpl
index ca856a08..fc6abc37 100644
--- a/docs/src/resources/node.md.tmpl
+++ b/docs/src/resources/node.md.tmpl
@@ -60,14 +60,14 @@ spec:
| installNamespace | (optional) Override the default namespace of falcon-system |
| node.tolerations | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ for examples on configuring tolerations |
| node.nodeAffinity | (optional) See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ for examples on configuring nodeAffinity |
-| node.image | (optional) Location of the Falcon Sensor Image. Specify only when you mirror the original image to your own image repository |
+| node.image | (optional) Location of the Falcon Sensor Image. Use this field only when pulling from non-CrowdStrike registries (e.g., when you mirror the original image to your own image repository). For CrowdStrike registries, use `node.version` instead. |
| node.imagePullPolicy | (optional) Override the default Falcon Container image pull policy of Always |
| node.imagePullSecrets | (optional) list of references to secrets to use for pulling image from image_override location. |
| node.terminationGracePeriod | (optional) Kills pod after a specified amount of time (in seconds). Default is 60 seconds. |
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
-| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207") |
+| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
| node.gke.cleanupAllowListVersion | (optional) WorkloadAllowlist version for the cleanup daemonset when using GKE AutoPilot (example: "v1.0.2" for crowdstrike-falconsensor-cleanup-allowlist-v1.0.2) |
@@ -160,7 +160,12 @@ To uninstall the FalconNodeSensor CR, simply remove the FalconNodeSensor resourc
### Sensor upgrades
-To upgrade the sensor version, simply add and/or update the `version` field in the FalconNodeSensor resource and apply the change. Alternatively if the `image` field was used instead of using the Falcon API credentials, add and/or update the `image` field in the FalconNodeSensor resource and apply the change. The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+To upgrade the sensor version:
+
+- **For CrowdStrike registries** (when using Falcon API credentials): Add and/or update the `version` field in the FalconNodeSensor resource and apply the change.
+- **For non-CrowdStrike registries**: Add and/or update the `image` field in the FalconNodeSensor resource and apply the change.
+
+The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
### Troubleshooting
From ad09abe585fb23869bff91404149b70afde48533 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 27 Jan 2026 22:18:06 +0000
Subject: [PATCH 06/16] chore(deps): bump github.com/opencontainers/selinux
Bumps [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) from 1.11.0 to 1.13.0.
- [Release notes](https://github.com/opencontainers/selinux/releases)
- [Commits](https://github.com/opencontainers/selinux/compare/v1.11.0...v1.13.0)
---
updated-dependencies:
- dependency-name: github.com/opencontainers/selinux
dependency-version: 1.13.0
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
---
go.mod | 7 ++++---
go.sum | 14 ++++++++------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/go.mod b/go.mod
index a0ad0d5a..8f82b6cd 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/onsi/gomega v1.33.1
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50
github.com/operator-framework/operator-lib v0.11.0
- github.com/stretchr/testify v1.9.0
+ github.com/stretchr/testify v1.11.1
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/mod v0.17.0
k8s.io/api v0.31.0
@@ -27,6 +27,7 @@ require (
)
require (
+ cyphar.com/go-pathrs v0.2.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
@@ -79,7 +80,7 @@ require (
github.com/containers/ocicrypt v1.1.10 // indirect
github.com/containers/storage v1.54.0 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
- github.com/cyphar/filepath-securejoin v0.2.5 // indirect
+ github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
@@ -142,7 +143,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
- github.com/opencontainers/selinux v1.11.0 // indirect
+ github.com/opencontainers/selinux v1.13.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/pkg/errors v0.9.1 // indirect
diff --git a/go.sum b/go.sum
index 5e10e71f..cfa139b4 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
+cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
@@ -94,8 +96,8 @@ github.com/crowdstrike/gofalcon v0.19.0 h1:pKvA8Az85wD6OR7aq/tvc+tORtR5CSyKp3+LD
github.com/crowdstrike/gofalcon v0.19.0/go.mod h1:a12GB+md+hRSgVCb3Pv6CakeTIsDIUCIVWRlJelIhY0=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
-github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
-github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
+github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
+github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU=
github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
@@ -357,8 +359,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
-github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
+github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
+github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50 h1:NzPzHF0F5ILvd8arWzzwOZAf/+QLQMG2njzZRX/yiOo=
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50/go.mod h1:LEnw1IVscIxyDnltE3Wi7bQb/QzIM8BfPNKoGA1Qlxw=
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
@@ -432,8 +434,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/sylabs/sif/v2 v2.16.0 h1:2eqaBaQQsn5DZTzm3QZm0HupZQEjNXfxRnCmtyCihEU=
github.com/sylabs/sif/v2 v2.16.0/go.mod h1:d5TxgD/mhMUU3kWLmZmWJQ99Wg0asaTP0bq3ezR1xpg=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
From b1df857faac1a4260bec37af6f66e41cb91dddc5 Mon Sep 17 00:00:00 2001
From: Jonathan Bruchim <50236903+JonBruchim@users.noreply.github.com>
Date: Wed, 28 Jan 2026 18:41:43 +0200
Subject: [PATCH 07/16] add FALCON_CLUSTER_NAME env var for unmanages k8s
clusters (#741)
---
api/falcon/v1alpha1/falconnodesensor_types.go | 4 +++
api/falcon/v1alpha1/zz_generated.deepcopy.go | 5 +++
...con.crowdstrike.com_falcondeployments.yaml | 6 ++++
...con.crowdstrike.com_falconnodesensors.yaml | 6 ++++
deploy/falcon-operator.yaml | 12 +++++++
.../openshift/resources/node/README.md | 1 +
docs/resources/node/README.md | 1 +
docs/src/resources/node.md.tmpl | 1 +
pkg/node/config_cache.go | 33 +++++++++++++++++++
9 files changed, 69 insertions(+)
diff --git a/api/falcon/v1alpha1/falconnodesensor_types.go b/api/falcon/v1alpha1/falconnodesensor_types.go
index d7f2bf33..c9aee8cd 100644
--- a/api/falcon/v1alpha1/falconnodesensor_types.go
+++ b/api/falcon/v1alpha1/falconnodesensor_types.go
@@ -127,6 +127,10 @@ type FalconNodeSensorConfig struct {
// For more information, please see https://github.com/CrowdStrike/falcon-operator/blob/main/docs/ADVANCED.md.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="DaemonSet Advanced Settings"
Advanced FalconAdvanced `json:"advanced,omitempty"`
+
+ // When running on an unmanaged K8S cluster, set a cluster name. When running on managed, K8S cluster name is resolved cloud-side
+ // +kubebuilder:validation:Pattern="^[0-9a-zA-Z]{1}[0-9a-zA-Z_-]{1,99}$"
+ ClusterName *string `json:"clusterName,omitempty"`
}
type PriorityClassConfig struct {
diff --git a/api/falcon/v1alpha1/zz_generated.deepcopy.go b/api/falcon/v1alpha1/zz_generated.deepcopy.go
index 2c6e20ed..8717c54d 100644
--- a/api/falcon/v1alpha1/zz_generated.deepcopy.go
+++ b/api/falcon/v1alpha1/zz_generated.deepcopy.go
@@ -1325,6 +1325,11 @@ func (in *FalconNodeSensorConfig) DeepCopyInto(out *FalconNodeSensorConfig) {
**out = **in
}
in.Advanced.DeepCopyInto(&out.Advanced)
+ if in.ClusterName != nil {
+ in, out := &in.ClusterName, &out.ClusterName
+ *out = new(string)
+ **out = **in
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FalconNodeSensorConfig.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
index 876990b1..2ce772f9 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
@@ -4033,6 +4033,12 @@ spec:
- kernel
- bpf
type: string
+ clusterName:
+ description: When running on an unmanaged K8S cluster, set
+ a cluster name. When running on managed, K8S cluster name
+ is resolved cloud-side
+ pattern: ^[0-9a-zA-Z]{1}[0-9a-zA-Z_-]{1,99}$
+ type: string
disableCleanup:
default: false
description: |-
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml b/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
index e5061000..694f2d4d 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
@@ -217,6 +217,12 @@ spec:
- kernel
- bpf
type: string
+ clusterName:
+ description: When running on an unmanaged K8S cluster, set a cluster
+ name. When running on managed, K8S cluster name is resolved
+ cloud-side
+ pattern: ^[0-9a-zA-Z]{1}[0-9a-zA-Z_-]{1,99}$
+ type: string
disableCleanup:
default: false
description: |-
diff --git a/deploy/falcon-operator.yaml b/deploy/falcon-operator.yaml
index 1f480527..be2045f6 100644
--- a/deploy/falcon-operator.yaml
+++ b/deploy/falcon-operator.yaml
@@ -7435,6 +7435,12 @@ spec:
- kernel
- bpf
type: string
+ clusterName:
+ description: When running on an unmanaged K8S cluster, set
+ a cluster name. When running on managed, K8S cluster name
+ is resolved cloud-side
+ pattern: ^[0-9a-zA-Z]{1}[0-9a-zA-Z_-]{1,99}$
+ type: string
disableCleanup:
default: false
description: |-
@@ -8931,6 +8937,12 @@ spec:
- kernel
- bpf
type: string
+ clusterName:
+ description: When running on an unmanaged K8S cluster, set a cluster
+ name. When running on managed, K8S cluster name is resolved
+ cloud-side
+ pattern: ^[0-9a-zA-Z]{1}[0-9a-zA-Z_-]{1,99}$
+ type: string
disableCleanup:
default: false
description: |-
diff --git a/docs/deployment/openshift/resources/node/README.md b/docs/deployment/openshift/resources/node/README.md
index d3103e21..188212aa 100644
--- a/docs/deployment/openshift/resources/node/README.md
+++ b/docs/deployment/openshift/resources/node/README.md
@@ -67,6 +67,7 @@ spec:
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
+| node.clusterName | (optional) When running on an unmanaged K8S cluster, set a cluster name. When running on managed K8S (e.g. EKS, GKE, AKS), cluster name is resolved cloud-side |
| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
diff --git a/docs/resources/node/README.md b/docs/resources/node/README.md
index 9f007999..34728ec6 100644
--- a/docs/resources/node/README.md
+++ b/docs/resources/node/README.md
@@ -67,6 +67,7 @@ spec:
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
+| node.clusterName | (optional) When running on an unmanaged K8S cluster, set a cluster name. When running on managed K8S (e.g. EKS, GKE, AKS), cluster name is resolved cloud-side |
| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
diff --git a/docs/src/resources/node.md.tmpl b/docs/src/resources/node.md.tmpl
index fc6abc37..5ecbdf28 100644
--- a/docs/src/resources/node.md.tmpl
+++ b/docs/src/resources/node.md.tmpl
@@ -67,6 +67,7 @@ spec:
| node.serviceAccount.annotations | (optional) Annotations that should be added to the Service Account (e.g. for IAM role association) |
| node.backend | (optional) Configure the backend mode for Falcon Sensor (allowed values: kernel, bpf) |
| node.disableCleanup | (optional) Cleans up `/opt/CrowdStrike` on the nodes by deleting the files and directory. |
+| node.clusterName | (optional) When running on an unmanaged K8S cluster, set a cluster name. When running on managed K8S (e.g. EKS, GKE, AKS), cluster name is resolved cloud-side |
| node.version | (optional) Enforce particular Falcon Sensor version to be installed (example: "6.35", "6.35.0-13207"). Use this field when pulling from CrowdStrike registries (when using Falcon API credentials). For non-CrowdStrike registries, use `node.image` instead. |
| node.gke.autopilot | (optional) Enable GKE Autopilot support for FalconNodeSensor. |
| node.gke.deployAllowListVersion | (optional) WorkloadAllowlist version for the sensor daemonset when using GKE AutoPilot. (example: "v1.0.3" for crowdstrike-falconsensor-deploy-allowlist-v1.0.3) |
diff --git a/pkg/node/config_cache.go b/pkg/node/config_cache.go
index 252f68a3..2d848b25 100644
--- a/pkg/node/config_cache.go
+++ b/pkg/node/config_cache.go
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"strings"
+ "unicode"
falconv1alpha1 "github.com/crowdstrike/falcon-operator/api/falcon/v1alpha1"
"github.com/crowdstrike/falcon-operator/internal/controller/common/sensor"
@@ -91,10 +92,42 @@ func (cc *ConfigCache) SensorEnvVars() map[string]string {
if cc.nodesensor.Spec.Falcon.Cloud != "" {
sensorConfig["FALCONCTL_OPT_CLOUD"] = cc.nodesensor.Spec.Falcon.Cloud
}
+ if cc.nodesensor.Spec.Node.ClusterName != nil {
+ sensorConfig["FALCON_CLUSTER_NAME"] = sanitizeClusterName(cc.nodesensor.Spec.Node.ClusterName)
+ }
return sensorConfig
}
+func sanitizeClusterName(clusterName *string) string {
+ if clusterName == nil {
+ return ""
+ }
+
+ if !isClusterNameValid(*clusterName) {
+ return ""
+ }
+
+ return *clusterName
+}
+
+// isClusterNameValid validates the clusterName.
+// Those rules had been taken from EKS (Amazon AWS).
+// See more at: https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#API_CreateCluster_RequestSyntax
+func isClusterNameValid(clusterName string) bool {
+ if len(clusterName) > 100 || len(clusterName) == 0 {
+ return false
+ }
+
+ if !unicode.IsLetter(rune(clusterName[0])) && !unicode.IsNumber(rune(clusterName[0])) {
+ return false
+ }
+
+ return !strings.ContainsFunc(clusterName, func(r rune) bool {
+ return !unicode.IsLetter(r) && !unicode.IsNumber(r) && r != '-' && r != '_'
+ })
+}
+
func (cc *ConfigCache) getFalconImage(ctx context.Context, nodesensor *falconv1alpha1.FalconNodeSensor) (string, error) {
if nodesensor.Spec.Node.Image != "" {
return nodesensor.Spec.Node.Image, nil
From f09383a115d28e92deaa52b110ee358760adc387 Mon Sep 17 00:00:00 2001
From: Jung Choi <17916440+mr-jungchoi@users.noreply.github.com>
Date: Mon, 9 Feb 2026 15:58:07 -0500
Subject: [PATCH 08/16] feat(falcon-node-sensor): add POD_NODE_NAME container
env (#746)
* add POD_NODE_NAME node sensor container env var
* reconcile node sensor container envs + refactor daemonset container updates
* fix variable name collision for env var func
* explicitly set APIVersion + add logging for requeues
* avoid unintended reconciles for container env updates with proxy
* preserve proxy env vars in falcon admission controller deployment reconciles
* include lower case proxy env vars when merging container envs
---
.../admission/falconadmission_controller.go | 77 +++---
internal/controller/assets/daemonset.go | 14 +-
internal/controller/assets/daemonset_test.go | 14 +-
.../falconnodesensor_controller.go | 239 +++++++++---------
pkg/common/funcs.go | 53 +++-
5 files changed, 241 insertions(+), 156 deletions(-)
diff --git a/internal/controller/admission/falconadmission_controller.go b/internal/controller/admission/falconadmission_controller.go
index b79256dd..3830c4e3 100644
--- a/internal/controller/admission/falconadmission_controller.go
+++ b/internal/controller/admission/falconadmission_controller.go
@@ -565,24 +565,6 @@ func (r *FalconAdmissionReconciler) reconcileAdmissionDeployment(ctx context.Con
return err
}
- if len(proxy.ReadProxyVarsFromEnv()) > 0 {
- for i, container := range existingDeployment.Spec.Template.Spec.Containers {
- newContainerEnv := common.AppendUniqueEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
- updatedContainerEnv := common.UpdateEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
- if !equality.Semantic.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[i].Env, newContainerEnv) {
- existingDeployment.Spec.Template.Spec.Containers[i].Env = newContainerEnv
- updated = true
- }
- if !equality.Semantic.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[i].Env, updatedContainerEnv) {
- existingDeployment.Spec.Template.Spec.Containers[i].Env = updatedContainerEnv
- updated = true
- }
- if updated {
- log.Info("Updating FalconNodeSensor Deployment Proxy Settings")
- }
- }
- }
-
if !reflect.DeepEqual(dep.Spec.Template.Spec.ImagePullSecrets, existingDeployment.Spec.Template.Spec.ImagePullSecrets) {
existingDeployment.Spec.Template.Spec.ImagePullSecrets = dep.Spec.Template.Spec.ImagePullSecrets
updated = true
@@ -612,43 +594,66 @@ func (r *FalconAdmissionReconciler) reconcileAdmissionDeployment(ctx context.Con
existingDeployment.Spec.Template.Spec.Containers = dep.Spec.Template.Spec.Containers
updated = true
} else {
- for i, containers := range dep.Spec.Template.Spec.Containers {
- if containers.Name == "falcon-client" || containers.Name == "falcon-watcher" {
- if !reflect.DeepEqual(containers.Ports, existingDeployment.Spec.Template.Spec.Containers[i].Ports) {
- existingDeployment.Spec.Template.Spec.Containers[i].Ports = containers.Ports
+ for i, container := range dep.Spec.Template.Spec.Containers {
+ existingContainer := &existingDeployment.Spec.Template.Spec.Containers[i]
+
+ if container.Name == "falcon-client" || container.Name == "falcon-watcher" {
+ if !reflect.DeepEqual(container.Ports, existingContainer.Ports) {
+ existingContainer.Ports = container.Ports
updated = true
}
}
- if !reflect.DeepEqual(containers.Image, existingDeployment.Spec.Template.Spec.Containers[i].Image) {
- for i := range existingDeployment.Spec.Template.Spec.Containers {
- existingDeployment.Spec.Template.Spec.Containers[i].Image = containers.Image
- }
+ if !reflect.DeepEqual(container.Image, existingContainer.Image) {
+ existingContainer.Image = container.Image
+ updated = true
+ }
+
+ if !reflect.DeepEqual(container.ImagePullPolicy, existingContainer.ImagePullPolicy) {
+ existingContainer.ImagePullPolicy = container.ImagePullPolicy
updated = true
}
- if !reflect.DeepEqual(containers.ImagePullPolicy, existingDeployment.Spec.Template.Spec.Containers[i].ImagePullPolicy) {
- existingDeployment.Spec.Template.Spec.Containers[i].ImagePullPolicy = containers.ImagePullPolicy
+ if !reflect.DeepEqual(container.Resources, existingContainer.Resources) {
+ existingContainer.Resources = container.Resources
updated = true
}
- if !reflect.DeepEqual(containers.Resources, existingDeployment.Spec.Template.Spec.Containers[i].Resources) {
- existingDeployment.Spec.Template.Spec.Containers[i].Resources = containers.Resources
+ if !reflect.DeepEqual(container.LivenessProbe.ProbeHandler.HTTPGet.Port, existingContainer.LivenessProbe.ProbeHandler.HTTPGet.Port) {
+ existingContainer.LivenessProbe.ProbeHandler.HTTPGet.Port = container.LivenessProbe.ProbeHandler.HTTPGet.Port
updated = true
}
- if !reflect.DeepEqual(containers.LivenessProbe.ProbeHandler.HTTPGet.Port, existingDeployment.Spec.Template.Spec.Containers[i].LivenessProbe.ProbeHandler.HTTPGet.Port) {
- existingDeployment.Spec.Template.Spec.Containers[i].LivenessProbe.ProbeHandler.HTTPGet.Port = containers.LivenessProbe.ProbeHandler.HTTPGet.Port
+ if !reflect.DeepEqual(container.StartupProbe.ProbeHandler.HTTPGet.Port, existingContainer.StartupProbe.ProbeHandler.HTTPGet.Port) {
+ existingContainer.StartupProbe.ProbeHandler.HTTPGet.Port = container.StartupProbe.ProbeHandler.HTTPGet.Port
updated = true
}
- if !reflect.DeepEqual(containers.StartupProbe.ProbeHandler.HTTPGet.Port, existingDeployment.Spec.Template.Spec.Containers[i].StartupProbe.ProbeHandler.HTTPGet.Port) {
- existingDeployment.Spec.Template.Spec.Containers[i].StartupProbe.ProbeHandler.HTTPGet.Port = containers.StartupProbe.ProbeHandler.HTTPGet.Port
+ // Merge existing proxy env vars with spec container env to preserve existing proxy envs
+ specContainerEnvWithExistingProxy := common.MergeEnvVars(container.Env, existingContainer.Env, common.ProxyEnvNamesWithLowerCase())
+ if !reflect.DeepEqual(specContainerEnvWithExistingProxy, existingContainer.Env) {
+ existingContainer.Env = container.Env
updated = true
}
- if !reflect.DeepEqual(containers.Env, existingDeployment.Spec.Template.Spec.Containers[i].Env) {
- existingDeployment.Spec.Template.Spec.Containers[i].Env = containers.Env
+ }
+ }
+
+ if len(proxy.ReadProxyVarsFromEnv()) > 0 {
+ proxyUpdated := false
+ for i, container := range existingDeployment.Spec.Template.Spec.Containers {
+ newContainerEnv := common.AppendUniqueEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
+ updatedContainerEnv := common.UpdateEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
+ if !equality.Semantic.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[i].Env, newContainerEnv) {
+ existingDeployment.Spec.Template.Spec.Containers[i].Env = newContainerEnv
+ proxyUpdated = true
+ }
+ if !equality.Semantic.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[i].Env, updatedContainerEnv) {
+ existingDeployment.Spec.Template.Spec.Containers[i].Env = updatedContainerEnv
+ proxyUpdated = true
+ }
+ if proxyUpdated {
updated = true
+ log.Info("Updating FalconAdmission Deployment Proxy Settings")
}
}
}
diff --git a/internal/controller/assets/daemonset.go b/internal/controller/assets/daemonset.go
index 9c8bb7b1..4c0daa46 100644
--- a/internal/controller/assets/daemonset.go
+++ b/internal/controller/assets/daemonset.go
@@ -288,7 +288,8 @@ func Daemonset(dsName, image, serviceAccount string, node *falconv1alpha1.Falcon
Name: "POD_NODE_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
- FieldPath: "spec.nodeName",
+ APIVersion: "v1",
+ FieldPath: "spec.nodeName",
},
},
},
@@ -308,6 +309,17 @@ func Daemonset(dsName, image, serviceAccount string, node *falconv1alpha1.Falcon
Name: "falcon-node-sensor",
Image: image,
ImagePullPolicy: node.Spec.Node.ImagePullPolicy,
+ Env: []corev1.EnvVar{
+ {
+ Name: "POD_NODE_NAME",
+ ValueFrom: &corev1.EnvVarSource{
+ FieldRef: &corev1.ObjectFieldSelector{
+ APIVersion: "v1",
+ FieldPath: "spec.nodeName",
+ },
+ },
+ },
+ },
EnvFrom: []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
diff --git a/internal/controller/assets/daemonset_test.go b/internal/controller/assets/daemonset_test.go
index a3cf53b8..c5ca97bf 100644
--- a/internal/controller/assets/daemonset_test.go
+++ b/internal/controller/assets/daemonset_test.go
@@ -340,7 +340,8 @@ func TestDaemonset(t *testing.T) {
Name: "POD_NODE_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
- FieldPath: "spec.nodeName",
+ APIVersion: "v1",
+ FieldPath: "spec.nodeName",
},
},
},
@@ -359,6 +360,17 @@ func TestDaemonset(t *testing.T) {
Name: "falcon-node-sensor",
Image: image,
ImagePullPolicy: falconNode.Spec.Node.ImagePullPolicy,
+ Env: []corev1.EnvVar{
+ {
+ Name: "POD_NODE_NAME",
+ ValueFrom: &corev1.EnvVarSource{
+ FieldRef: &corev1.ObjectFieldSelector{
+ APIVersion: "v1",
+ FieldPath: "spec.nodeName",
+ },
+ },
+ },
+ },
EnvFrom: []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
diff --git a/internal/controller/falcon_node/falconnodesensor_controller.go b/internal/controller/falcon_node/falconnodesensor_controller.go
index 29cd6832..50c2d21a 100644
--- a/internal/controller/falcon_node/falconnodesensor_controller.go
+++ b/internal/controller/falcon_node/falconnodesensor_controller.go
@@ -143,6 +143,7 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
"FalconNodeSensor progressing",
ctx, req.NamespacedName, nodesensor, logger)
if err != nil {
+ logger.Error(err, "condition update failure, requeue for reconciliation")
return ctrl.Result{Requeue: true}, err
}
}
@@ -168,6 +169,7 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
return ctrl.Result{}, err
}
if created {
+ logger.Info("namespace created, requeue for reconciliation")
return ctrl.Result{Requeue: true}, nil
}
@@ -183,6 +185,7 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
return ctrl.Result{}, err
}
if created {
+ logger.Info("service account and role binding created, requeue for reconciliation")
return ctrl.Result{Requeue: true}, nil
}
@@ -243,7 +246,7 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
// this just got created, so re-queue.
- logger.Info("Configmap was just created. Re-queuing")
+ logger.Info("configmap created, requeue for reconciliation")
return ctrl.Result{Requeue: true}, nil
}
@@ -328,16 +331,11 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
dsTarget := assets.Daemonset(dsUpdate.Name, image, serviceAccount, nodesensor)
// Objects to check for updates to re-spin pods
- imgUpdate := updateDaemonSetImages(dsUpdate, image, logger)
+ containerUpdates := reconcileDaemonSetContainers(dsUpdate, dsTarget, image, logger)
+ containerEnvUpdates := reconcileDaemonSetContainerEnvs(dsUpdate, dsTarget, logger)
affUpdate := updateDaemonSetAffinity(dsUpdate, nodesensor, logger)
- containerVolUpdate := updateDaemonSetContainerVolumes(dsUpdate, dsTarget, logger)
volumeUpdates := updateDaemonSetVolumes(dsUpdate, dsTarget, logger)
- resources := updateDaemonSetResources(dsUpdate, dsTarget, logger)
- initResources := updateDaemonSetInitContainerResources(dsUpdate, dsTarget, logger)
pc := updateDaemonSetPriorityClass(dsUpdate, dsTarget, logger)
- capabilities := updateDaemonSetCapabilities(dsUpdate, dsTarget, logger)
- initArgs := updateDaemonSetInitArgs(dsUpdate, dsTarget, logger)
- proxyUpdates := updateDaemonSetContainerProxy(dsUpdate, logger)
tolsUpdate, err := r.updateDaemonSetTolerations(ctx, dsUpdate, nodesensor, logger)
pullSecretUpdate := r.updateImagePullSecrets(dsUpdate, dsTarget, logger)
if err != nil {
@@ -345,9 +343,8 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
// Update the daemonset and re-spin pods with changes
- if imgUpdate || tolsUpdate || affUpdate || containerVolUpdate ||
- volumeUpdates || resources || pc || capabilities || initArgs ||
- initResources || proxyUpdates || pullSecretUpdate || updated {
+ if containerUpdates || containerEnvUpdates || tolsUpdate || affUpdate ||
+ volumeUpdates || pc || pullSecretUpdate || updated {
err = r.Update(ctx, dsUpdate)
if err != nil {
err = r.conditionsUpdate(falconv1alpha1.ConditionDaemonSetReady,
@@ -400,6 +397,7 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
"FalconNodeSensor installation completed",
ctx, req.NamespacedName, nodesensor, logger)
if err != nil {
+ logger.Error(err, "condition update failure, requeue for reconciliation")
return ctrl.Result{Requeue: true}, err
}
@@ -644,29 +642,6 @@ func (r *FalconNodeSensorReconciler) handleCrowdStrikeSecrets(ctx context.Contex
return nil
}
-func updateDaemonSetContainerProxy(ds *appsv1.DaemonSet, logger logr.Logger) bool {
- updated := false
- if len(proxy.ReadProxyVarsFromEnv()) > 0 {
- for i, container := range ds.Spec.Template.Spec.Containers {
- newContainerEnv := common.AppendUniqueEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
- updatedContainerEnv := common.UpdateEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
- if !equality.Semantic.DeepEqual(ds.Spec.Template.Spec.Containers[i].Env, newContainerEnv) {
- ds.Spec.Template.Spec.Containers[i].Env = newContainerEnv
- updated = true
- }
- if !equality.Semantic.DeepEqual(ds.Spec.Template.Spec.Containers[i].Env, updatedContainerEnv) {
- ds.Spec.Template.Spec.Containers[i].Env = updatedContainerEnv
- updated = true
- }
- if updated {
- logger.Info("Updating FalconNodeSensor DaemonSet Proxy Settings")
- }
- }
- }
-
- return updated
-}
-
func (r *FalconNodeSensorReconciler) updateImagePullSecrets(existingDs *appsv1.DaemonSet, specDs *appsv1.DaemonSet, logger logr.Logger) bool {
if !equality.Semantic.DeepEqual(existingDs.Spec.Template.Spec.ImagePullSecrets, specDs.Spec.Template.Spec.ImagePullSecrets) {
logger.Info("Updating FalconNodeSensor DaemonSet ImagePullSecrets")
@@ -707,25 +682,6 @@ func updateDaemonSetAffinity(ds *appsv1.DaemonSet, nodesensor *falconv1alpha1.Fa
return affinityUpdate
}
-// If an update is needed, this will update the containervolumes from the given DaemonSet
-func updateDaemonSetContainerVolumes(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- containerVolumeMounts := &ds.Spec.Template.Spec.Containers[0].VolumeMounts
- containerVolumeMountsUpdates := !equality.Semantic.DeepEqual(*containerVolumeMounts, origDS.Spec.Template.Spec.Containers[0].VolumeMounts)
- if containerVolumeMountsUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet Container volumeMounts")
- *containerVolumeMounts = origDS.Spec.Template.Spec.Containers[0].VolumeMounts
- }
-
- containerVolumeMounts = &ds.Spec.Template.Spec.InitContainers[0].VolumeMounts
- containerVolumeMountsUpdates = !equality.Semantic.DeepEqual(*containerVolumeMounts, origDS.Spec.Template.Spec.InitContainers[0].VolumeMounts)
- if containerVolumeMountsUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet InitContainer volumeMounts")
- *containerVolumeMounts = origDS.Spec.Template.Spec.InitContainers[0].VolumeMounts
- }
-
- return containerVolumeMountsUpdates
-}
-
// If an update is needed, this will update the volumes from the given DaemonSet
func updateDaemonSetVolumes(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
volumeMounts := &ds.Spec.Template.Spec.Volumes
@@ -738,90 +694,143 @@ func updateDaemonSetVolumes(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bo
return volumeMountsUpdates
}
-// If an update is needed, this will update the InitContainer image reference from the given DaemonSet
-func updateDaemonSetImages(ds *appsv1.DaemonSet, origImg string, logger logr.Logger) bool {
- initImage := &ds.Spec.Template.Spec.InitContainers[0].Image
- imgUpdate := *initImage != origImg
- if imgUpdate {
- logger.Info("Updating FalconNodeSensor DaemonSet InitContainer image", "Original Image", origImg, "Current Image", initImage)
- *initImage = origImg
- }
-
- image := &ds.Spec.Template.Spec.Containers[0].Image
- imgUpdate = *image != origImg
- if imgUpdate {
- logger.Info("Updating FalconNodeSensor DaemonSet image", "Original Image", origImg, "Current Image", image)
- *image = origImg
+// If an update is needed, this will update the priority class from the given DaemonSet
+func updateDaemonSetPriorityClass(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
+ priorityClass := &ds.Spec.Template.Spec.PriorityClassName
+ priorityClassUpdates := *priorityClass != origDS.Spec.Template.Spec.PriorityClassName
+ if priorityClassUpdates {
+ logger.Info("Updating FalconNodeSensor DaemonSet priority class")
+ *priorityClass = origDS.Spec.Template.Spec.PriorityClassName
}
- return imgUpdate
+ return priorityClassUpdates
}
-// If an update is needed, this will update the resources from the given DaemonSet
-func updateDaemonSetResources(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- resources := &ds.Spec.Template.Spec.Containers[0].Resources
- resourcesUpdates := !equality.Semantic.DeepEqual(*resources, origDS.Spec.Template.Spec.Containers[0].Resources)
- if resourcesUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet resources")
- *resources = origDS.Spec.Template.Spec.Containers[0].Resources
+// reconcileDaemonSetContainers handles all init-container and container updates except container envs.
+// Container envs are a special case that is handled separately.
+func reconcileDaemonSetContainers(existingDS, specDS *appsv1.DaemonSet, origImg string, logger logr.Logger) bool {
+ updated := false
+
+ specInitContainer := specDS.Spec.Template.Spec.InitContainers[0]
+ existingInitContainer := &existingDS.Spec.Template.Spec.InitContainers[0]
+ specContainer := specDS.Spec.Template.Spec.Containers[0]
+ existingContainer := &existingDS.Spec.Template.Spec.Containers[0]
+ // Check for sensor image updates
+ if existingInitContainer.Image != origImg {
+ existingInitContainer.Image = origImg
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet InitContainer image", "Original Image", origImg, "Current Image", existingInitContainer.Image)
}
- return resourcesUpdates
-}
+ if existingContainer.Image != origImg {
+ existingContainer.Image = origImg
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet image", "Original Image", origImg, "Current Image", existingContainer.Image)
+ }
-func updateDaemonSetInitContainerResources(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- resources := &ds.Spec.Template.Spec.InitContainers[0].Resources
- resourcesUpdates := !equality.Semantic.DeepEqual(*resources, origDS.Spec.Template.Spec.InitContainers[0].Resources)
- if resourcesUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet InitContainer resources")
- *resources = origDS.Spec.Template.Spec.InitContainers[0].Resources
+ // Check for volume mount updates
+ if !equality.Semantic.DeepEqual(existingInitContainer.VolumeMounts, specInitContainer.VolumeMounts) {
+ existingInitContainer.VolumeMounts = specInitContainer.VolumeMounts
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet InitContainer volumeMounts")
}
- return resourcesUpdates
-}
+ if !equality.Semantic.DeepEqual(existingContainer.VolumeMounts, specContainer.VolumeMounts) {
+ existingContainer.VolumeMounts = specContainer.VolumeMounts
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet Container volumeMounts")
+ }
-// If an update is needed, this will update the priority class from the given DaemonSet
-func updateDaemonSetPriorityClass(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- priorityClass := &ds.Spec.Template.Spec.PriorityClassName
- priorityClassUpdates := *priorityClass != origDS.Spec.Template.Spec.PriorityClassName
- if priorityClassUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet priority class")
- *priorityClass = origDS.Spec.Template.Spec.PriorityClassName
+ // Check for resource updates
+ if !equality.Semantic.DeepEqual(existingInitContainer.Resources, specInitContainer.Resources) {
+ existingInitContainer.Resources = specInitContainer.Resources
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet InitContainer resources")
}
- return priorityClassUpdates
-}
+ if !equality.Semantic.DeepEqual(existingContainer.Resources, specContainer.Resources) {
+ existingContainer.Resources = specContainer.Resources
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet resources")
+ }
-// If an update is needed, this will update the capabilities from the given DaemonSet
-func updateDaemonSetCapabilities(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- capabilities := &ds.Spec.Template.Spec.Containers[0].SecurityContext.Capabilities
- capabilitiesUpdates := !equality.Semantic.DeepEqual(*capabilities, origDS.Spec.Template.Spec.Containers[0].SecurityContext.Capabilities)
- if capabilitiesUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet Container capabilities")
- *capabilities = origDS.Spec.Template.Spec.Containers[0].SecurityContext.Capabilities
+ // Check for security context updates
+ if existingInitContainer.SecurityContext != nil && specInitContainer.SecurityContext != nil {
+ if !equality.Semantic.DeepEqual(existingInitContainer.SecurityContext.Capabilities, specInitContainer.SecurityContext.Capabilities) {
+ existingInitContainer.SecurityContext.Capabilities = specInitContainer.SecurityContext.Capabilities
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet InitContainer capabilities")
+ }
}
- capabilities = &ds.Spec.Template.Spec.InitContainers[0].SecurityContext.Capabilities
- capabilitiesUpdates = !equality.Semantic.DeepEqual(*capabilities, origDS.Spec.Template.Spec.InitContainers[0].SecurityContext.Capabilities)
- if capabilitiesUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet InitContainer capabilities")
- *capabilities = origDS.Spec.Template.Spec.InitContainers[0].SecurityContext.Capabilities
+ if existingContainer.SecurityContext != nil && specContainer.SecurityContext != nil {
+ if !equality.Semantic.DeepEqual(existingContainer.SecurityContext.Capabilities, specContainer.SecurityContext.Capabilities) {
+ existingContainer.SecurityContext.Capabilities = specContainer.SecurityContext.Capabilities
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet Container capabilities")
+ }
+ }
+
+ // Check for init container args updates
+ if !equality.Semantic.DeepEqual(existingInitContainer.Args, specInitContainer.Args) {
+ existingInitContainer.Args = specInitContainer.Args
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet init args")
}
- return capabilitiesUpdates
+ return updated
}
-// If an update is needed, this will update the init args from the given DaemonSet
-func updateDaemonSetInitArgs(ds, origDS *appsv1.DaemonSet, logger logr.Logger) bool {
- initArgs := &ds.Spec.Template.Spec.InitContainers[0].Args
- initArgsUpdates := !equality.Semantic.DeepEqual(*initArgs, origDS.Spec.Template.Spec.InitContainers[0].Args)
- if initArgsUpdates {
- logger.Info("Updating FalconNodeSensor DaemonSet init args")
- *initArgs = origDS.Spec.Template.Spec.InitContainers[0].Args
+// reconcileDaemonSetContainerEnvs handles container env changes while properly handling proxy envs.
+// This should happen in 3 steps to avoid unintended reconciles.
+// 1. Merge existing proxy env vars into spec container env.
+// 2. Compare spec container env with proxy to existing container env.
+// 3. Read proxy env vars from existing pod and compare with existing container env for any changes.
+func reconcileDaemonSetContainerEnvs(existingDS, specDS *appsv1.DaemonSet, logger logr.Logger) bool {
+ updated := false
+
+ specInitContainer := specDS.Spec.Template.Spec.InitContainers[0]
+ existingInitContainer := &existingDS.Spec.Template.Spec.InitContainers[0]
+ specContainer := specDS.Spec.Template.Spec.Containers[0]
+ existingContainer := &existingDS.Spec.Template.Spec.Containers[0]
+
+ if !equality.Semantic.DeepEqual(existingInitContainer.Env, specInitContainer.Env) {
+ existingInitContainer.Env = specInitContainer.Env
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet InitContainer env")
+ }
+
+ // Merge existing proxy env vars with spec container env to preserve existing proxy envs
+ specContainerEnvWithExistingProxy := common.MergeEnvVars(specContainer.Env, existingContainer.Env, common.ProxyEnvNamesWithLowerCase())
+ if !equality.Semantic.DeepEqual(existingContainer.Env, specContainerEnvWithExistingProxy) {
+ existingContainer.Env = specContainerEnvWithExistingProxy
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet Container env")
+ }
+
+ // proxy.ReadProxyVarsFromEnv() also includes lowercase versions of the proxy envs
+ proxyUpdated := false
+ if len(proxy.ReadProxyVarsFromEnv()) > 0 {
+ for i, container := range existingDS.Spec.Template.Spec.Containers {
+ newContainerEnv := common.AppendUniqueEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
+ updatedContainerEnv := common.UpdateEnvVars(container.Env, proxy.ReadProxyVarsFromEnv())
+ if !equality.Semantic.DeepEqual(existingDS.Spec.Template.Spec.Containers[i].Env, newContainerEnv) {
+ existingDS.Spec.Template.Spec.Containers[i].Env = newContainerEnv
+ proxyUpdated = true
+ }
+ if !equality.Semantic.DeepEqual(existingDS.Spec.Template.Spec.Containers[i].Env, updatedContainerEnv) {
+ existingDS.Spec.Template.Spec.Containers[i].Env = updatedContainerEnv
+ proxyUpdated = true
+ }
+ if proxyUpdated {
+ updated = true
+ logger.Info("Updating FalconNodeSensor DaemonSet Proxy Settings")
+ }
+ }
}
- return initArgsUpdates
+ return updated
}
// handlePermissions creates and updates the service account, role and role binding
diff --git a/pkg/common/funcs.go b/pkg/common/funcs.go
index 6a53ac3f..00110bbb 100644
--- a/pkg/common/funcs.go
+++ b/pkg/common/funcs.go
@@ -9,6 +9,7 @@ import (
"regexp"
"strings"
+ "github.com/operator-framework/operator-lib/proxy"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes"
@@ -132,13 +133,22 @@ func CRLabels(instanceName string, instanceKey string, component string) map[str
}
}
+func ProxyEnvNamesWithLowerCase() []string {
+ envs := make([]string, 0, 6)
+ for _, s := range proxy.ProxyEnvNames {
+ envs = append(envs, s, strings.ToLower(s))
+ }
+
+ return envs
+}
+
func AppendUniqueEnvVars(envVars ...[]corev1.EnvVar) []corev1.EnvVar {
base := []corev1.EnvVar{}
- for _, envVars := range envVars {
- if envVars == nil {
+ for _, envVarSlice := range envVars {
+ if envVarSlice == nil {
continue
}
- for _, envVar := range envVars {
+ for _, envVar := range envVarSlice {
if !containsEnvVar(base, envVar) {
base = append(base, envVar)
}
@@ -170,6 +180,43 @@ func UpdateEnvVars(envVars []corev1.EnvVar, updateEnvVars []corev1.EnvVar) []cor
return envVars
}
+// MergeEnvVars merges specific env vars from env B into env A
+func MergeEnvVars(envA, envB []corev1.EnvVar, envVarsToMerge []string) []corev1.EnvVar {
+ if envVarsToMerge == nil || len(envVarsToMerge) == 0 {
+ return envA
+ }
+
+ envVarsToMergeMap := make(map[string]bool)
+ for _, envVarName := range envVarsToMerge {
+ envVarsToMergeMap[envVarName] = true
+ }
+
+ envBMap := make(map[string]corev1.EnvVar)
+ for _, env := range envB {
+ envBMap[env.Name] = env
+ }
+
+ // Copy envA
+ result := make([]corev1.EnvVar, 0, len(envA)+len(envVarsToMerge))
+ for _, envAVar := range envA {
+ if envVarsToMergeMap[envAVar.Name] {
+ // skip envs to merge
+ continue
+ }
+
+ result = append(result, envAVar)
+ }
+
+ // merge env vars from env B
+ for _, envName := range envVarsToMerge {
+ if envBVar, exists := envBMap[envName]; exists {
+ result = append(result, envBVar)
+ }
+ }
+
+ return result
+}
+
func ImageVersion(image string) *string {
switch {
case strings.Contains(image, ":"):
From 26b742539391787bc782ddcea7ff9e7d0abf6615 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Tue, 10 Feb 2026 12:21:40 -0600
Subject: [PATCH 09/16] chore: Update to images to UBI9
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index de7c868b..46033fde 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# Build the manager binary
-FROM registry.access.redhat.com/ubi8/go-toolset:1.23 AS builder
+FROM registry.access.redhat.com/ubi9/go-toolset:1.25 AS builder
ARG TARGETOS
ARG TARGETARCH
ARG VERSION
@@ -36,7 +36,7 @@ RUN GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -tags \
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
-FROM registry.access.redhat.com/ubi8-minimal:8.10
+FROM registry.access.redhat.com/ubi9-minimal:9.7
ARG VERSION
WORKDIR /
COPY LICENSE licenses/
From 62bc09a01387ecdab016a43a51f1cf98adff4df7 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Tue, 10 Feb 2026 12:22:40 -0600
Subject: [PATCH 10/16] chore: Upgrade to go1.25
---
go.mod | 255 ++++----
go.sum | 626 ++++++++++---------
internal/controller/image/image_refresher.go | 8 +-
pkg/registry/auth/credentials.go | 2 +-
pkg/registry/falcon_registry/registry.go | 6 +-
5 files changed, 458 insertions(+), 439 deletions(-)
diff --git a/go.mod b/go.mod
index 8f82b6cd..0f681523 100644
--- a/go.mod
+++ b/go.mod
@@ -1,98 +1,108 @@
module github.com/crowdstrike/falcon-operator
-go 1.23.0
+go 1.25.5
require (
- github.com/Masterminds/sprig/v3 v3.2.3
- github.com/aws/aws-sdk-go-v2 v1.26.0
- github.com/aws/aws-sdk-go-v2/config v1.27.9
+ github.com/Masterminds/sprig/v3 v3.3.0
+ github.com/aws/aws-sdk-go-v2 v1.41.0
+ github.com/aws/aws-sdk-go-v2/config v1.32.5
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.7
github.com/cert-manager/cert-manager v1.12.14
- github.com/containers/image/v5 v5.31.1
github.com/crowdstrike/gofalcon v0.19.0
- github.com/go-logr/logr v1.4.2
+ github.com/go-logr/logr v1.4.3
github.com/go-openapi/swag v0.23.0
- github.com/google/go-cmp v0.6.0
- github.com/onsi/ginkgo/v2 v2.19.0
- github.com/onsi/gomega v1.33.1
+ github.com/google/go-cmp v0.7.0
+ github.com/onsi/ginkgo/v2 v2.27.2
+ github.com/onsi/gomega v1.38.2
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50
github.com/operator-framework/operator-lib v0.11.0
github.com/stretchr/testify v1.11.1
- golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
- golang.org/x/mod v0.17.0
- k8s.io/api v0.31.0
- k8s.io/apimachinery v0.31.0
- k8s.io/client-go v0.31.0
- sigs.k8s.io/controller-runtime v0.19.1
+ go.podman.io/image/v5 v5.39.1
+ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
+ golang.org/x/mod v0.30.0
+ k8s.io/api v0.35.0
+ k8s.io/apimachinery v0.35.0
+ k8s.io/client-go v0.35.0
+ sigs.k8s.io/controller-runtime v0.23.1
)
require (
- cyphar.com/go-pathrs v0.2.1 // indirect
+ cel.dev/expr v0.24.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
- github.com/cenkalti/backoff/v4 v4.3.0 // indirect
- github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+ github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect
+ github.com/cenkalti/backoff/v5 v5.0.3 // indirect
+ github.com/containerd/errdefs/pkg v0.3.0 // indirect
+ github.com/fxamacker/cbor/v2 v2.9.0 // indirect
+ github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
- github.com/google/cel-go v0.20.1 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
+ github.com/google/btree v1.1.3 // indirect
+ github.com/google/cel-go v0.26.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/spf13/cobra v1.8.1 // indirect
- github.com/stoewer/go-strcase v1.2.0 // indirect
+ github.com/moby/sys/capability v0.4.0 // indirect
+ github.com/nxadm/tail v1.4.11 // indirect
+ github.com/sigstore/protobuf-specs v0.5.0 // indirect
+ github.com/smallstep/pkcs7 v0.1.1 // indirect
+ github.com/spf13/cobra v1.10.2 // indirect
+ github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
- go.opentelemetry.io/otel/sdk v1.28.0 // indirect
- go.opentelemetry.io/proto/otlp v1.3.1 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
- gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
- k8s.io/apiserver v0.31.0 // indirect
- k8s.io/component-base v0.31.0 // indirect
- sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.38.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.7.1 // indirect
+ go.podman.io/storage v1.62.0 // indirect
+ go.yaml.in/yaml/v2 v2.4.3 // indirect
+ go.yaml.in/yaml/v3 v3.0.4 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect
+ gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
+ k8s.io/apiserver v0.35.0 // indirect
+ k8s.io/component-base v0.35.0 // indirect
+ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
+ sigs.k8s.io/randfill v1.0.0 // indirect
+ sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect
)
require (
- dario.cat/mergo v1.0.0
- github.com/BurntSushi/toml v1.3.2 // indirect
+ dario.cat/mergo v1.0.2
+ github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
- github.com/Masterminds/semver/v3 v3.2.0 // indirect
+ github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
- github.com/Microsoft/hcsshim v0.12.3 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
- github.com/aws/aws-sdk-go-v2/credentials v1.17.9 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect
- github.com/aws/smithy-go v1.20.1 // indirect
+ github.com/aws/aws-sdk-go-v2/credentials v1.19.5 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.30.7 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
+ github.com/aws/smithy-go v1.24.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/containerd/cgroups/v3 v3.0.3 // indirect
- github.com/containerd/errdefs v0.1.0 // indirect
- github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
+ github.com/containerd/errdefs v1.0.0 // indirect
+ github.com/containerd/stargz-snapshotter/estargz v0.18.1 // indirect
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
- github.com/containers/ocicrypt v1.1.10 // indirect
- github.com/containers/storage v1.54.0 // indirect
- github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
- github.com/cyphar/filepath-securejoin v0.6.0 // indirect
+ github.com/containers/ocicrypt v1.2.1 // indirect
+ github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
+ github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
- github.com/docker/docker v26.1.5+incompatible // indirect
- github.com/docker/docker-credential-helpers v0.8.1 // indirect
- github.com/docker/go-connections v0.5.0 // indirect
+ github.com/docker/docker v28.5.2+incompatible // indirect
+ github.com/docker/docker-credential-helpers v0.9.4 // indirect
+ github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
- github.com/emicklei/go-restful/v3 v3.11.0 // indirect
- github.com/evanphx/json-patch/v5 v5.9.0 // indirect
+ github.com/emicklei/go-restful/v3 v3.12.2 // indirect
+ github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/fsnotify/fsnotify v1.7.0 // indirect
- github.com/go-jose/go-jose/v3 v3.0.4 // indirect
+ github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
@@ -105,104 +115,89 @@ require (
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
- github.com/google/gnostic-models v0.6.8 // indirect
- github.com/google/go-containerregistry v0.19.1 // indirect
+ github.com/google/gnostic-models v0.7.0 // indirect
+ github.com/google/go-containerregistry v0.20.7 // indirect
github.com/google/go-intervals v0.0.2 // indirect
- github.com/google/gofuzz v1.2.0 // indirect
- github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect
+ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
- github.com/hashicorp/errwrap v1.1.0 // indirect
- github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-version v1.7.0
- github.com/huandu/xstrings v1.3.3 // indirect
- github.com/imdario/mergo v0.3.15 // indirect
+ github.com/huandu/xstrings v1.5.0 // indirect
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
- github.com/klauspost/compress v1.17.8 // indirect
+ github.com/klauspost/compress v1.18.1 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
- github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect
github.com/mailru/easyjson v0.7.7 // indirect
- github.com/mattn/go-runewidth v0.0.15 // indirect
- github.com/mattn/go-sqlite3 v1.14.22 // indirect
+ github.com/mattn/go-runewidth v0.0.16 // indirect
+ github.com/mattn/go-sqlite3 v1.14.32 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
- github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
- github.com/mitchellh/copystructure v1.0.0 // indirect
+ github.com/mistifyio/go-zfs/v3 v3.1.0 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/mitchellh/reflectwalk v1.0.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
- github.com/moby/sys/mountinfo v0.7.1 // indirect
- github.com/moby/sys/user v0.1.0 // indirect
+ github.com/moby/sys/mountinfo v0.7.2 // indirect
+ github.com/moby/sys/user v0.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
- github.com/opencontainers/image-spec v1.1.0 // indirect
- github.com/opencontainers/runtime-spec v1.2.0 // indirect
- github.com/opencontainers/selinux v1.13.0 // indirect
+ github.com/opencontainers/image-spec v1.1.1 // indirect
+ github.com/opencontainers/runtime-spec v1.2.1 // indirect
+ github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
- github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- github.com/proglottis/gpgme v0.1.3 // indirect
- github.com/prometheus/client_golang v1.19.1 // indirect
- github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.55.0 // indirect
- github.com/prometheus/procfs v0.15.1 // indirect
+ github.com/proglottis/gpgme v0.1.5 // indirect
+ github.com/prometheus/client_golang v1.23.2 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.67.5 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
- github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
- github.com/shopspring/decimal v1.2.0 // indirect
- github.com/sigstore/fulcio v1.4.5 // indirect
- github.com/sigstore/rekor v1.3.6 // indirect
- github.com/sigstore/sigstore v1.8.3 // indirect
+ github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
+ github.com/sigstore/fulcio v1.8.5 // indirect
+ github.com/sigstore/sigstore v1.10.4 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
- github.com/spf13/cast v1.6.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
+ github.com/spf13/cast v1.7.1 // indirect
+ github.com/spf13/pflag v1.0.10 // indirect
+ github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
github.com/stretchr/objx v0.5.2 // indirect
- github.com/sylabs/sif/v2 v2.16.0 // indirect
- github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
- github.com/tchap/go-patricia/v2 v2.3.1 // indirect
- github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
- github.com/ulikunitz/xz v0.5.14 // indirect
- github.com/vbatts/tar-split v0.11.5 // indirect
- github.com/vbauerster/mpb/v8 v8.7.3 // indirect
+ github.com/sylabs/sif/v2 v2.22.0 // indirect
+ github.com/tchap/go-patricia/v2 v2.3.3 // indirect
+ github.com/ulikunitz/xz v0.5.15 // indirect
+ github.com/vbatts/tar-split v0.12.2 // indirect
+ github.com/vbauerster/mpb/v8 v8.10.2 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
- go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
- go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
- go.opentelemetry.io/otel v1.28.0 // indirect
- go.opentelemetry.io/otel/metric v1.28.0 // indirect
- go.opentelemetry.io/otel/trace v1.28.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
+ go.opentelemetry.io/otel v1.38.0 // indirect
+ go.opentelemetry.io/otel/metric v1.38.0 // indirect
+ go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.27.0 // indirect
- golang.org/x/crypto v0.36.0 // indirect
- golang.org/x/net v0.38.0 // indirect
- golang.org/x/oauth2 v0.30.0 // indirect
- golang.org/x/sync v0.12.0 // indirect
- golang.org/x/sys v0.31.0 // indirect
- golang.org/x/term v0.30.0 // indirect
- golang.org/x/text v0.23.0 // indirect
- golang.org/x/time v0.5.0 // indirect
- golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
+ go.uber.org/zap v1.27.1 // indirect
+ golang.org/x/crypto v0.46.0 // indirect
+ golang.org/x/net v0.48.0 // indirect
+ golang.org/x/oauth2 v0.34.0 // indirect
+ golang.org/x/sync v0.19.0 // indirect
+ golang.org/x/sys v0.39.0 // indirect
+ golang.org/x/term v0.38.0 // indirect
+ golang.org/x/text v0.32.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
+ golang.org/x/tools v0.39.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
- google.golang.org/grpc v1.65.0 // indirect
- google.golang.org/protobuf v1.34.2 // indirect
- gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
+ google.golang.org/grpc v1.78.0 // indirect
+ google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/apiextensions-apiserver v0.31.0 // indirect
+ k8s.io/apiextensions-apiserver v0.35.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
- k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
- k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
+ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
+ k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
sigs.k8s.io/gateway-api v0.7.0 // indirect
- sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
- sigs.k8s.io/yaml v1.4.0 // indirect
+ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
+ sigs.k8s.io/yaml v1.6.0 // indirect
)
diff --git a/go.sum b/go.sum
index cfa139b4..b957d09d 100644
--- a/go.sum
+++ b/go.sum
@@ -1,25 +1,21 @@
+cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
+cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
-cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
-dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
-dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
-github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
-github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
-github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
+github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
-github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
-github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
-github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
+github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
+github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
+github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0=
-github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
@@ -33,71 +29,70 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA=
-github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
-github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg=
-github.com/aws/aws-sdk-go-v2/config v1.27.9/go.mod h1:dK1FQfpwpql83kbD873E9vz4FyAxuJtR22wzoXn3qq0=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4/go.mod h1:84KyjNZdHC6QZW08nfHI6yZgPd+qRgaWcYsyLUo3QY8=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 h1:sHmMWWX5E7guWEFQ9SVo6A3S4xpPrWnd77a6y4WM6PU=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4/go.mod h1:WjpDrhWisWOIoS9n3nk67A3Ll1vfULJ9Kq6h29HTD48=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
+github.com/aws/aws-sdk-go-v2 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4=
+github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
+github.com/aws/aws-sdk-go-v2/config v1.32.5 h1:pz3duhAfUgnxbtVhIK39PGF/AHYyrzGEyRD9Og0QrE8=
+github.com/aws/aws-sdk-go-v2/config v1.32.5/go.mod h1:xmDjzSUs/d0BB7ClzYPAZMmgQdrodNjPPhd6bGASwoE=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.5 h1:xMo63RlqP3ZZydpJDMBsH9uJ10hgHYfQFIk1cHDXrR4=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.5/go.mod h1:hhbH6oRcou+LpXfA/0vPElh/e0M3aFeOblE1sssAAEk=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.7 h1:3iaT/LnGV6jNtbBkvHZDlzz7Ky3wMHDJAyFtGd5GUJI=
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.7/go.mod h1:mtzCLxk6M+KZbkJdq3cUH9GCrudw8qCy5C3EHO+5vLc=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.3/go.mod h1:5HFu51Elk+4oRBZVxmHrSds5jFXmFj8C3w7DVF2gnrs=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 h1:uLq0BKatTmDzWa/Nu4WO0M1AaQDaPpwTKAeByEc6WFM=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3/go.mod h1:b+qdhjnxj8GSR6t5YfphOffeoQSQ1KmpoVVuBn+PWxs=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 h1:J/PpTf/hllOjx8Xu9DMflff3FajfLxqM5+tepvVXmxg=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.5/go.mod h1:0ih0Z83YDH/QeQ6Ori2yGE2XvWYv/Xm+cZc01LC6oK0=
-github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
-github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.7 h1:eYnlt6QxnFINKzwxP5/Ucs1vkG7VT3Iezmvfgc2waUw=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.7/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk=
+github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
+github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
+github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cert-manager/cert-manager v1.12.14 h1:EyQMXPzIHcuXVu2kV4gKgEFQw3K/jMUkIyZhOWStz9I=
github.com/cert-manager/cert-manager v1.12.14/go.mod h1:nApwszKTPUxB+gMZ2SeKtHWVojqJsuWplKvF+qb3fj8=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
-github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
-github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
-github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
+github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
+github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
+github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
+github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
-github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
-github.com/containers/image/v5 v5.31.1 h1:3x9soI6Biml/GiDLpkSmKrkRSwVGctxu/vONpoUdklA=
-github.com/containers/image/v5 v5.31.1/go.mod h1:5QfOqSackPkSbF7Qxc1DnVNnPJKQ+KWLkfEfDpK590Q=
+github.com/containerd/stargz-snapshotter/estargz v0.18.1 h1:cy2/lpgBXDA3cDKSyEfNOFMA/c10O1axL69EU7iirO8=
+github.com/containerd/stargz-snapshotter/estargz v0.18.1/go.mod h1:ALIEqa7B6oVDsrF37GkGN20SuvG/pIMm7FwP7ZmRb0Q=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
-github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic=
-github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8=
-github.com/containers/storage v1.54.0 h1:xwYAlf6n9OnIlURQLLg3FYHbO74fQ/2W2N6EtQEUM4I=
-github.com/containers/storage v1.54.0/go.mod h1:PlMOoinRrBSnhYODLxt4EXl0nmJt+X0kjG0Xdt9fMTw=
-github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=
+github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crowdstrike/gofalcon v0.19.0 h1:pKvA8Az85wD6OR7aq/tvc+tORtR5CSyKp3+LDQXc4pc=
github.com/crowdstrike/gofalcon v0.19.0/go.mod h1:a12GB+md+hRSgVCb3Pv6CakeTIsDIUCIVWRlJelIhY0=
-github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
-github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
-github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
-github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
+github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
+github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
+github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
+github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU=
github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
@@ -109,16 +104,16 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/cli v26.1.3+incompatible h1:bUpXT/N0kDE3VUHI2r5VMsYQgi38kYuoC0oL9yt3lqc=
-github.com/docker/cli v26.1.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v29.0.3+incompatible h1:8J+PZIcF2xLd6h5sHPsp5pvvJA+Sr2wGQxHkRl53a1E=
+github.com/docker/cli v29.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v26.1.5+incompatible h1:NEAxTwEjxV6VbBMBoGG3zPqbiJosIApZjxlbrG9q3/g=
-github.com/docker/docker v26.1.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
-github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
+github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI=
+github.com/docker/docker-credential-helpers v0.9.4/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -127,37 +122,42 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
-github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
-github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
+github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
-github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
+github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
-github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
+github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
-github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
+github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
+github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
+github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
+github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
+github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE=
+github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
@@ -190,14 +190,11 @@ github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3Bum
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
-github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
-github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
+github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
+github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -208,28 +205,27 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
-github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
-github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
+github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
+github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
+github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
+github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
-github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
-github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
+github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
-github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I=
+github.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM=
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -237,9 +233,8 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20181127221834-b4f47329b966/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
-github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -248,39 +243,31 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
-github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
-github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4/go.mod h1:6Nz966r3vQYCqIzWsuEl9d7cf7mRhtDmm++sOxlnfxI=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
-github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
+github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
-github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY=
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=
-github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
+github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
-github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
+github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -291,43 +278,54 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e h1:RLTpX495BXToqxpM90Ws4hXEo4Wfh81jr9DX1n/4WOo=
-github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e/go.mod h1:EAuqr9VFWxBi9nD5jc/EA2MT1RFty9288TF6zdtYoCU=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
-github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
-github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
+github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
+github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
+github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
+github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
-github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
-github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
-github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
-github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mistifyio/go-zfs/v3 v3.1.0 h1:FZaylcg0hjUp27i23VcJJQiuBeAZjrC8lPqCGM1CopY=
+github.com/mistifyio/go-zfs/v3 v3.1.0/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
-github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
-github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
-github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
-github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
-github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
-github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
-github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
+github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
+github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
+github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
+github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
+github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
+github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@@ -336,8 +334,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
-github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -346,21 +344,21 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
-github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
+github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
+github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
-github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
+github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
+github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
-github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
-github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
-github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
-github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
+github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
+github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
+github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50 h1:NzPzHF0F5ILvd8arWzzwOZAf/+QLQMG2njzZRX/yiOo=
github.com/openshift/api v0.0.0-20220630121623-32f1d77b9f50/go.mod h1:LEnw1IVscIxyDnltE3Wi7bQb/QzIM8BfPNKoGA1Qlxw=
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
@@ -368,65 +366,68 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/operator-framework/operator-lib v0.11.0 h1:eYzqpiOfq9WBI4Trddisiq/X9BwCisZd3rIzmHRC9Z8=
github.com/operator-framework/operator-lib v0.11.0/go.mod h1:RpyKhFAoG6DmKTDIwMuO6pI3LRc8IE9rxEYWy476o6g=
-github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M=
-github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/proglottis/gpgme v0.1.3 h1:Crxx0oz4LKB3QXc5Ea0J19K/3ICfy3ftr5exgUK1AU0=
-github.com/proglottis/gpgme v0.1.3/go.mod h1:fPbW/EZ0LvwQtH8Hy7eixhp1eF3G39dtx7GUN+0Gmy0=
-github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
-github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
+github.com/proglottis/gpgme v0.1.5 h1:KCGyOw8sQ+SI96j6G8D8YkOGn+1TwbQTT9/zQXoVlz0=
+github.com/proglottis/gpgme v0.1.5/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM=
+github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
+github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
-github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
-github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
+github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
-github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
-github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
-github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
-github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
-github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
+github.com/sebdah/goldie/v2 v2.7.1 h1:PkBHymaYdtvEkZV7TmyqKxdmn5/Vcj+8TpATWZjnG5E=
+github.com/sebdah/goldie/v2 v2.7.1/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
+github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g=
+github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
-github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
-github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
-github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
-github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/sigstore/fulcio v1.4.5 h1:WWNnrOknD0DbruuZWCbN+86WRROpEl3Xts+WT2Ek1yc=
-github.com/sigstore/fulcio v1.4.5/go.mod h1:oz3Qwlma8dWcSS/IENR/6SjbW4ipN0cxpRVfgdsjMU8=
-github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=
-github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc=
-github.com/sigstore/sigstore v1.8.3 h1:G7LVXqL+ekgYtYdksBks9B38dPoIsbscjQJX/MGWkA4=
-github.com/sigstore/sigstore v1.8.3/go.mod h1:mqbTEariiGA94cn6G3xnDiV6BD8eSLdL/eA7bvJ0fVs=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
+github.com/sigstore/fulcio v1.8.5 h1:HYTD1/L5wlBp8JxsWxUf8hmfaNBBF/x3r3p5l6tZwbA=
+github.com/sigstore/fulcio v1.8.5/go.mod h1:tSLYK3JsKvJpDW1BsIsVHZgHj+f8TjXARzqIUWSsSPQ=
+github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY=
+github.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=
+github.com/sigstore/sigstore v1.10.4 h1:ytOmxMgLdcUed3w1SbbZOgcxqwMG61lh1TmZLN+WeZE=
+github.com/sigstore/sigstore v1.10.4/go.mod h1:tDiyrdOref3q6qJxm2G+JHghqfmvifB7hw+EReAfnbI=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU=
+github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
-github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
-github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
-github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
+github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
-github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
-github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
+github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=
+github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
+github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -436,28 +437,26 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
-github.com/sylabs/sif/v2 v2.16.0 h1:2eqaBaQQsn5DZTzm3QZm0HupZQEjNXfxRnCmtyCihEU=
-github.com/sylabs/sif/v2 v2.16.0/go.mod h1:d5TxgD/mhMUU3kWLmZmWJQ99Wg0asaTP0bq3ezR1xpg=
-github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
-github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=
-github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
-github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
-github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
-github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg=
-github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
-github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
-github.com/vbauerster/mpb/v8 v8.7.3 h1:n/mKPBav4FFWp5fH4U0lPpXfiOmCEgl5Yx/NM3tKJA0=
-github.com/vbauerster/mpb/v8 v8.7.3/go.mod h1:9nFlNpDGVoTmQ4QvNjSLtwLmAFjwmq0XaAF26toHGNM=
+github.com/sylabs/sif/v2 v2.22.0 h1:Y+xXufp4RdgZe02SR3nWEg7S6q4tPWN237WHYzkDSKA=
+github.com/sylabs/sif/v2 v2.22.0/go.mod h1:W1XhWTmG1KcG7j5a3KSYdMcUIFvbs240w/MMVW627hs=
+github.com/tchap/go-patricia/v2 v2.3.3 h1:xfNEsODumaEcCcY3gI0hYPZ/PcpVv5ju6RMAhgwZDDc=
+github.com/tchap/go-patricia/v2 v2.3.3/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
+github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
+github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
+github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
+github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
+github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
+github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
+github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
+github.com/vbauerster/mpb/v8 v8.10.2 h1:2uBykSHAYHekE11YvJhKxYmLATKHAGorZwFlyNw4hHM=
+github.com/vbauerster/mpb/v8 v8.10.2/go.mod h1:+Ja4P92E3/CorSZgfDtK46D7AVbDqmBQRTmyTqPElo0=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
-github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -465,46 +464,56 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
-go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
-go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
-go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
-go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
-go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
-go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
-go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
-go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
-go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
-go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
-go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
-go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
-go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
-go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
+go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
+go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
+go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
+go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
+go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
+go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
+go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
+go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
+go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
+go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
+go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
+go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
+go.podman.io/image/v5 v5.39.1 h1:loIw4qHzZzBlUguYZau40u8HbR5MrTPQhwT4Hy6sCm0=
+go.podman.io/image/v5 v5.39.1/go.mod h1:SlaR6Pra1ATIx4BcuZ16oafb3QcCHISaKcJbtlN/G/0=
+go.podman.io/storage v1.62.0 h1:0QjX1XlzVmbiaulb+aR/CG6p9+pzaqwIeZPe3tEjHbY=
+go.podman.io/storage v1.62.0/go.mod h1:A3UBK0XypjNZ6pghRhuxg62+2NIm5lcUGv/7XyMhMUI=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
-go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
+go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
+go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
-golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
+golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
-golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -514,8 +523,11 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
+golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -527,20 +539,21 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
+golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
-golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
+golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
+golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -549,8 +562,12 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
-golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
+golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -573,33 +590,41 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
+golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
-golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
+golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
-golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
-golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
+golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -614,31 +639,33 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
+golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
-google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
+google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=
+google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
-google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
+google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
+google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -648,23 +675,20 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
-gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
+gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
-gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
@@ -682,27 +706,25 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
-gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
-gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
+gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
+gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I=
-k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
-k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
-k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
-k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
+k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY=
+k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA=
+k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4=
+k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU=
k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
-k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
-k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
-k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY=
-k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk=
-k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8=
-k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU=
+k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8=
+k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
+k8s.io/apiserver v0.35.0 h1:CUGo5o+7hW9GcAEF3x3usT3fX4f9r8xmgQeCBDaOgX4=
+k8s.io/apiserver v0.35.0/go.mod h1:QUy1U4+PrzbJaM3XGu2tQ7U9A4udRRo5cyxkFX0GEds=
+k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE=
+k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o=
k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
-k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
-k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
+k8s.io/component-base v0.35.0 h1:+yBrOhzri2S1BVqyVSvcM3PtPyx5GUxCK2tinZz1G94=
+k8s.io/component-base v0.35.0/go.mod h1:85SCX4UCa6SCFt6p3IKAPej7jSnF3L8EbfSyMZayJR0=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
@@ -711,25 +733,27 @@ k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
-k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
-sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk=
-sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
+k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
+k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
+sigs.k8s.io/controller-runtime v0.23.1 h1:TjJSM80Nf43Mg21+RCy3J70aj/W6KyvDtOlpKf+PupE=
+sigs.k8s.io/controller-runtime v0.23.1/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
sigs.k8s.io/gateway-api v0.7.0 h1:/mG8yyJNBifqvuVLW5gwlI4CQs0NR/5q4BKUlf1bVdY=
sigs.k8s.io/gateway-api v0.7.0/go.mod h1:Xv0+ZMxX0lu1nSSDIIPEfbVztgNZ+3cfiYrJsa2Ooso=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
+sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
+sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
+sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs=
+sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
-sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
+sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
+sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
diff --git a/internal/controller/image/image_refresher.go b/internal/controller/image/image_refresher.go
index 67344783..80209a2a 100644
--- a/internal/controller/image/image_refresher.go
+++ b/internal/controller/image/image_refresher.go
@@ -8,10 +8,10 @@ import (
"github.com/go-logr/logr"
- "github.com/containers/image/v5/copy"
- "github.com/containers/image/v5/signature"
- "github.com/containers/image/v5/transports/alltransports"
- "github.com/containers/image/v5/types"
+ "go.podman.io/image/v5/copy"
+ "go.podman.io/image/v5/signature"
+ "go.podman.io/image/v5/transports/alltransports"
+ "go.podman.io/image/v5/types"
"github.com/crowdstrike/falcon-operator/pkg/registry/auth"
"github.com/crowdstrike/falcon-operator/pkg/registry/falcon_registry"
diff --git a/pkg/registry/auth/credentials.go b/pkg/registry/auth/credentials.go
index 6589e3c4..60bc7a8d 100644
--- a/pkg/registry/auth/credentials.go
+++ b/pkg/registry/auth/credentials.go
@@ -4,7 +4,7 @@ import (
"fmt"
"os"
- "github.com/containers/image/v5/types"
+ "go.podman.io/image/v5/types"
corev1 "k8s.io/api/core/v1"
)
diff --git a/pkg/registry/falcon_registry/registry.go b/pkg/registry/falcon_registry/registry.go
index 625fa4ee..1229d992 100644
--- a/pkg/registry/falcon_registry/registry.go
+++ b/pkg/registry/falcon_registry/registry.go
@@ -7,9 +7,9 @@ import (
"sort"
"strings"
- "github.com/containers/image/v5/docker"
- "github.com/containers/image/v5/docker/reference"
- "github.com/containers/image/v5/types"
+ "go.podman.io/image/v5/docker"
+ "go.podman.io/image/v5/docker/reference"
+ "go.podman.io/image/v5/types"
internalErrors "github.com/crowdstrike/falcon-operator/internal/errors"
"github.com/crowdstrike/falcon-operator/pkg/falcon_api"
From a44b25e860e323129d923aeccc55e744ca778a60 Mon Sep 17 00:00:00 2001
From: Jung Choi <17916440+mr-jungchoi@users.noreply.github.com>
Date: Fri, 13 Feb 2026 09:27:55 -0500
Subject: [PATCH 11/16] docs: add note about sensor uninstall and maintenance
protection (#774)
---
docs/deployment/azure/README.md | 13 ++++++++++++
docs/deployment/eks-fargate/README.md | 7 +++++++
docs/deployment/eks/README.md | 13 ++++++++++++
docs/deployment/generic/README.md | 13 ++++++++++++
docs/deployment/gke/README.md | 13 ++++++++++++
.../openshift/resources/container/README.md | 4 ++++
.../openshift/resources/node/README.md | 14 +++++++++++++
docs/install_guide.md | 7 +++++++
docs/resources/container/README.md | 4 ++++
docs/resources/falcondeployment/README.md | 21 +++++++++++++++++++
docs/resources/node/README.md | 14 +++++++++++++
docs/src/deployment/README.md.tmpl | 13 ++++++++++++
docs/src/resources/container.md.tmpl | 4 ++++
docs/src/resources/falcondeployment.md.tmpl | 21 +++++++++++++++++++
docs/src/resources/node.md.tmpl | 14 +++++++++++++
15 files changed, 175 insertions(+)
diff --git a/docs/deployment/azure/README.md b/docs/deployment/azure/README.md
index b34ae974..5bfdf999 100644
--- a/docs/deployment/azure/README.md
+++ b/docs/deployment/azure/README.md
@@ -32,6 +32,12 @@ This document will guide you through the installation of the Falcon Operator and
+### Sensor uninstall and maintenance protection
+Important notes for Kubernetes and other container deployments of the Falcon sensor.
+- **Falcon Node sensor for Linux with sensor version 7.33 and earlier:** We do not recommend enabling the **Uninstall and maintenance protection** policy setting for DaemonSet deployments. This setting can cause operational issues that require manual intervention.
+- **Falcon Node sensor for Linux with sensors version 7.34 and later:** DaemonSet deployments do not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+- **Falcon Container sensor for Linux:** Deployed as a sidecar container within application pods. This sensor does not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+
### Deploying the Falcon Node Sensor
@@ -158,6 +164,13 @@ kubectl apply -f https://github.com/CrowdStrike/falcon-operator/releases/downloa
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Uninstalling the Falcon Node Sensor
diff --git a/docs/deployment/eks-fargate/README.md b/docs/deployment/eks-fargate/README.md
index 3c363f1b..f18b86bf 100644
--- a/docs/deployment/eks-fargate/README.md
+++ b/docs/deployment/eks-fargate/README.md
@@ -139,6 +139,13 @@ kubectl apply -f https://github.com/CrowdStrike/falcon-operator/releases/downloa
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Uninstalling the Falcon Container Sidecar Sensor
diff --git a/docs/deployment/eks/README.md b/docs/deployment/eks/README.md
index f49bed19..3b17cd7d 100644
--- a/docs/deployment/eks/README.md
+++ b/docs/deployment/eks/README.md
@@ -44,6 +44,12 @@ Please review [AWS documentation](https://docs.aws.amazon.com/eks/latest/usergui
+### Sensor uninstall and maintenance protection
+Important notes for Kubernetes and other container deployments of the Falcon sensor.
+- **Falcon Node sensor for Linux with sensor version 7.33 and earlier:** We do not recommend enabling the **Uninstall and maintenance protection** policy setting for DaemonSet deployments. This setting can cause operational issues that require manual intervention.
+- **Falcon Node sensor for Linux with sensors version 7.34 and later:** DaemonSet deployments do not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+- **Falcon Container sensor for Linux:** Deployed as a sidecar container within application pods. This sensor does not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+
### Deploying the Falcon Node Sensor
@@ -134,6 +140,13 @@ kubectl apply -f https://github.com/CrowdStrike/falcon-operator/releases/downloa
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Uninstalling the Falcon Node Sensor
diff --git a/docs/deployment/generic/README.md b/docs/deployment/generic/README.md
index 475e3e33..4e4dac40 100644
--- a/docs/deployment/generic/README.md
+++ b/docs/deployment/generic/README.md
@@ -32,6 +32,12 @@ This document will guide you through the installation of the Falcon Operator and
+### Sensor uninstall and maintenance protection
+Important notes for Kubernetes and other container deployments of the Falcon sensor.
+- **Falcon Node sensor for Linux with sensor version 7.33 and earlier:** We do not recommend enabling the **Uninstall and maintenance protection** policy setting for DaemonSet deployments. This setting can cause operational issues that require manual intervention.
+- **Falcon Node sensor for Linux with sensors version 7.34 and later:** DaemonSet deployments do not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+- **Falcon Container sensor for Linux:** Deployed as a sidecar container within application pods. This sensor does not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+
### Deploying the Falcon Node Sensor
@@ -112,6 +118,13 @@ kubectl apply -f https://github.com/CrowdStrike/falcon-operator/releases/downloa
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Uninstalling the Falcon Node Sensor
diff --git a/docs/deployment/gke/README.md b/docs/deployment/gke/README.md
index f5d9270e..50ea1bd1 100644
--- a/docs/deployment/gke/README.md
+++ b/docs/deployment/gke/README.md
@@ -32,6 +32,12 @@ This document will guide you through the installation of the Falcon Operator and
+### Sensor uninstall and maintenance protection
+Important notes for Kubernetes and other container deployments of the Falcon sensor.
+- **Falcon Node sensor for Linux with sensor version 7.33 and earlier:** We do not recommend enabling the **Uninstall and maintenance protection** policy setting for DaemonSet deployments. This setting can cause operational issues that require manual intervention.
+- **Falcon Node sensor for Linux with sensors version 7.34 and later:** DaemonSet deployments do not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+- **Falcon Container sensor for Linux:** Deployed as a sidecar container within application pods. This sensor does not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+
### Deploying the Falcon Node Sensor
@@ -158,6 +164,13 @@ kubectl apply -f https://github.com/CrowdStrike/falcon-operator/releases/downloa
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Uninstalling the Falcon Node Sensor
diff --git a/docs/deployment/openshift/resources/container/README.md b/docs/deployment/openshift/resources/container/README.md
index 1cc11289..26740c89 100644
--- a/docs/deployment/openshift/resources/container/README.md
+++ b/docs/deployment/openshift/resources/container/README.md
@@ -130,6 +130,10 @@ See `docs/ADVANCED.md` for more details.
| advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> Falcon Container sensor for Linux does not support the **Uninstall and maintenance protection** policy setting and
+> automatically ignores it.
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
diff --git a/docs/deployment/openshift/resources/node/README.md b/docs/deployment/openshift/resources/node/README.md
index 188212aa..48605192 100644
--- a/docs/deployment/openshift/resources/node/README.md
+++ b/docs/deployment/openshift/resources/node/README.md
@@ -135,6 +135,13 @@ See `docs/ADVANCED.md` for more details.
| node.advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| node.advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
@@ -194,6 +201,13 @@ To upgrade the sensor version:
The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Troubleshooting
- To see the FalconNodeSensor resource on the cluster which includes the operator and sensor versions:
diff --git a/docs/install_guide.md b/docs/install_guide.md
index d6ce824e..9a40772a 100644
--- a/docs/install_guide.md
+++ b/docs/install_guide.md
@@ -42,6 +42,13 @@ To effectively deploy and use the Falcon sensor in a Kubernetes environment, the
4. As soon as the sensor version is changed in Git, a CI/CD pipeline should update the FalconNodeSensor and/or FalconContainer Kind(s) which will then cause the operator to deploy the updated versions to your Kubernetes environments. This is the proper way to handle sensor updates in Kubernetes.
5. Upgrades should usually happen in a rolling update manner to ensure the Kubernetes cluster and deployed resources stay accessible and operational.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
## FAQ - Frequently Asked Questions
### What network connections are required for the operator to work properly?
diff --git a/docs/resources/container/README.md b/docs/resources/container/README.md
index 3fe5bf6a..fea951ee 100644
--- a/docs/resources/container/README.md
+++ b/docs/resources/container/README.md
@@ -130,6 +130,10 @@ See `docs/ADVANCED.md` for more details.
| advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> Falcon Container sensor for Linux does not support the **Uninstall and maintenance protection** policy setting and
+> automatically ignores it.
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
diff --git a/docs/resources/falcondeployment/README.md b/docs/resources/falcondeployment/README.md
index 00d235ea..abd260bb 100644
--- a/docs/resources/falcondeployment/README.md
+++ b/docs/resources/falcondeployment/README.md
@@ -216,6 +216,13 @@ To install Falcon Operator:
**Note:** When deploying the Kubernetes Admission Controller, the Falcon Operator can trigger multiple restarts for the Falcon Admission Controller Pods when deploying alongside other resources. Falcon KAC is designed to ignore namespaces managed by CrowdStrike, so, as new resources are added, such as falconContainer or falconNodeSensor, the KAC pod will redeploy to ignore the new namespaces.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Cloud platform-specific deployments
Some cloud platforms have additional configuration requirements. For details, see the appropriate deployment guide:
@@ -256,8 +263,22 @@ The Falcon Operator will automatically detect these changes and initiate the upg
**Note**: This process works for all components that can be deployed with the Falcon Operator. The operator handles the implementation details of the upgrade based on your changes.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
## Uninstall all Falcon components
To uninstall the Falcon Operator, remove the falcon-operator resource. The operator uninstalls the falcon-operator resource and any CRs deployed from the cluster.
`kubectl delete falcondeployment --all`
+
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
diff --git a/docs/resources/node/README.md b/docs/resources/node/README.md
index 34728ec6..3b458c25 100644
--- a/docs/resources/node/README.md
+++ b/docs/resources/node/README.md
@@ -135,6 +135,13 @@ See `docs/ADVANCED.md` for more details.
| node.advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| node.advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
@@ -194,6 +201,13 @@ To upgrade the sensor version:
The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Troubleshooting
- To see the FalconNodeSensor resource on the cluster which includes the operator and sensor versions:
diff --git a/docs/src/deployment/README.md.tmpl b/docs/src/deployment/README.md.tmpl
index d82710bb..c018ab20 100644
--- a/docs/src/deployment/README.md.tmpl
+++ b/docs/src/deployment/README.md.tmpl
@@ -40,6 +40,12 @@ This document will guide you through the installation of the Falcon Operator and
{{- if ne .Distro "eks-fargate" }}
+### Sensor uninstall and maintenance protection
+Important notes for Kubernetes and other container deployments of the Falcon sensor.
+- **Falcon Node sensor for Linux with sensor version 7.33 and earlier:** We do not recommend enabling the **Uninstall and maintenance protection** policy setting for DaemonSet deployments. This setting can cause operational issues that require manual intervention.
+- **Falcon Node sensor for Linux with sensors version 7.34 and later:** DaemonSet deployments do not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+- **Falcon Container sensor for Linux:** Deployed as a sidecar container within application pods. This sensor does not support the **Uninstall and maintenance protection** policy setting and automatically ignores it.
+
### Deploying the Falcon Node Sensor
@@ -173,6 +179,13 @@ VERSION=1.2.3
> [!WARNING]
> It is essential to uninstall ALL of the deployed custom resources before uninstalling the Falcon Operator to ensure proper cleanup.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
{{- if ne .Distro "eks-fargate" }}
### Uninstalling the Falcon Node Sensor
diff --git a/docs/src/resources/container.md.tmpl b/docs/src/resources/container.md.tmpl
index d7d12d2e..c53abc76 100644
--- a/docs/src/resources/container.md.tmpl
+++ b/docs/src/resources/container.md.tmpl
@@ -130,6 +130,10 @@ See `docs/ADVANCED.md` for more details.
| advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> Falcon Container sensor for Linux does not support the **Uninstall and maintenance protection** policy setting and
+> automatically ignores it.
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
diff --git a/docs/src/resources/falcondeployment.md.tmpl b/docs/src/resources/falcondeployment.md.tmpl
index 00d235ea..abd260bb 100644
--- a/docs/src/resources/falcondeployment.md.tmpl
+++ b/docs/src/resources/falcondeployment.md.tmpl
@@ -216,6 +216,13 @@ To install Falcon Operator:
**Note:** When deploying the Kubernetes Admission Controller, the Falcon Operator can trigger multiple restarts for the Falcon Admission Controller Pods when deploying alongside other resources. Falcon KAC is designed to ignore namespaces managed by CrowdStrike, so, as new resources are added, such as falconContainer or falconNodeSensor, the KAC pod will redeploy to ignore the new namespaces.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Cloud platform-specific deployments
Some cloud platforms have additional configuration requirements. For details, see the appropriate deployment guide:
@@ -256,8 +263,22 @@ The Falcon Operator will automatically detect these changes and initiate the upg
**Note**: This process works for all components that can be deployed with the Falcon Operator. The operator handles the implementation details of the upgrade based on your changes.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
## Uninstall all Falcon components
To uninstall the Falcon Operator, remove the falcon-operator resource. The operator uninstalls the falcon-operator resource and any CRs deployed from the cluster.
`kubectl delete falcondeployment --all`
+
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
diff --git a/docs/src/resources/node.md.tmpl b/docs/src/resources/node.md.tmpl
index 5ecbdf28..d1e557ac 100644
--- a/docs/src/resources/node.md.tmpl
+++ b/docs/src/resources/node.md.tmpl
@@ -135,6 +135,13 @@ See `docs/ADVANCED.md` for more details.
| node.advanced.autoUpdate | `off` | Automatically updates a deployed Falcon sensor as new versions are released. This has no effect if a specific image or version has been requested. Valid settings are:- `force` -- Reconciles the resource after every check for a new version
- `normal` -- Reconciles the resource whenever a new version is detected
- `off` -- No automatic updates
| node.advanced.updatePolicy | _none_ | If set, applies the named Linux sensor update policy, configured in Falcon UI, to select which version of Falcon sensor to install. The policy must be enabled and must match the CPU architecture of the cluster (AMD64 or ARM64). |
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
##### Automatic Update Frequency
The operator checks for new releases of Falcon sensor once every 24 hours by default. This can be adjusted by setting the `--sensor-auto-update-interval` command-line flag to any value acceptable by [Golang's ParseDuration](https://pkg.go.dev/time#ParseDuration) function. However, it is strongly recommended that this be left at the default, as each cycle involves queries to the Falcon API and too many could result in throttling.
@@ -168,6 +175,13 @@ To upgrade the sensor version:
The operator will detect the change and perform the upgrade by restarting the daemonset pods one by one.
+> [!NOTE]
+> DaemonSet deployments of sensor versions 7.33 and earlier of the Falcon sensor for Linux are blocked from updates and
+> uninstallation if their sensor update policy has the **Uninstall and maintenance protection** setting enabled. Before
+> upgrading or uninstalling these versions of the sensor, move the sensors to a new sensor update policy with this
+> policy setting turned off. For more info, see [Sensor update and uninstallation for DaemonSet sensor versions 7.33
+> and lower](https://falcon.crowdstrike.com/documentation/anchor/sc632f2e).
+
### Troubleshooting
- To see the FalconNodeSensor resource on the cluster which includes the operator and sensor versions:
From d90c08596e8f9e2d03b406222bb27ff9da80e7e9 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Tue, 17 Feb 2026 10:57:46 -0600
Subject: [PATCH 12/16] chore: Remove unused operator-deployment.yml workflow
---
.github/workflows/operator-deployment.yml | 64 -----------------------
1 file changed, 64 deletions(-)
delete mode 100644 .github/workflows/operator-deployment.yml
diff --git a/.github/workflows/operator-deployment.yml b/.github/workflows/operator-deployment.yml
deleted file mode 100644
index 4501e0ff..00000000
--- a/.github/workflows/operator-deployment.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-name: Test Operator Deployment
-
-on:
- push:
- branches:
- - main
- paths-ignore:
- - 'docs/**'
- pull_request_target:
- types: [ labeled ]
- branches:
- - main
- paths-ignore:
- - 'docs/**'
-
-env:
- KIND_CLUSTER: operator-testing
- FALCON_CLIENT_ID: ${{ secrets.FALCON_CLIENT_ID }}
- FALCON_CLIENT_SECRET: ${{ secrets.FALCON_CLIENT_SECRET }}
-
-jobs:
- e2e:
- name: e2e
- strategy:
- matrix:
- os: [ubuntu-latest]
- go-version: [1.22.x]
- if: |
- github.event_name == 'push' ||
- (github.event_name == 'pull_request_target' &&
- github.event.label.name == 'ok-to-test')
-
- runs-on: ${{ matrix.os }}
- steps:
- - name: Set up Go ${{ matrix.go-version }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ matrix.go-version }}
- id: go
-
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- if: github.event_name != 'pull_request_target'
-
- - name: Checkout
- uses: actions/checkout@v4
- with:
- ref: ${{github.event.pull_request.head.sha}}
- fetch-depth: 0
- if: github.event_name == 'pull_request_target'
-
- - name: Install dependencies
- run: |
- sudo apt-get update -y
- sudo apt install libgpgme-dev libbtrfs-dev libdevmapper-dev
-
- - name: Create k8s Kind Cluster
- uses: helm/kind-action@v1.12.0
- with:
- cluster_name: operator-testing
-
- - run: sudo rm -rf /usr/local/bin/kustomize
- - run: make test-e2e
From 597b578258343b528dbfb33cbd96683be44d5a07 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Fri, 13 Feb 2026 14:36:48 -0600
Subject: [PATCH 13/16] feat(falcon-iar): Add unified IAR sensor support
---
.../falconimage_controller.go | 2 +-
.../falcon_image_analyzer/image_push.go | 16 ++++--
pkg/registry/falcon_registry/container.go | 51 +++++++++++++++----
3 files changed, 56 insertions(+), 13 deletions(-)
diff --git a/internal/controller/falcon_image_analyzer/falconimage_controller.go b/internal/controller/falcon_image_analyzer/falconimage_controller.go
index f23b6d09..5b2a4907 100644
--- a/internal/controller/falcon_image_analyzer/falconimage_controller.go
+++ b/internal/controller/falcon_image_analyzer/falconimage_controller.go
@@ -202,7 +202,7 @@ func (r *FalconImageAnalyzerReconciler) Reconcile(ctx context.Context, req ctrl.
return ctrl.Result{}, nil
}
if err != nil {
- log.Error(err, "Failed to verify CrowdStrike Image Image Registry access")
+ log.Error(err, "Failed to verify CrowdStrike Image Registry access")
time.Sleep(time.Second * 5)
return ctrl.Result{RequeueAfter: 5 * time.Second}, err
}
diff --git a/internal/controller/falcon_image_analyzer/image_push.go b/internal/controller/falcon_image_analyzer/image_push.go
index d0386bcf..642afd9e 100644
--- a/internal/controller/falcon_image_analyzer/image_push.go
+++ b/internal/controller/falcon_image_analyzer/image_push.go
@@ -49,7 +49,7 @@ func (r *FalconImageAnalyzerReconciler) PushImage(ctx context.Context, log logr.
image := image.NewImageRefresher(ctx, log, falconApiConfig, pushAuth, falconImageAnalyzer.Spec.Registry.TLS.InsecureSkipVerify)
version := falconImageAnalyzer.Spec.Version
- tag, err := image.Refresh(registryUri, falcon.RegionedImageSensor, version)
+ tag, err := image.Refresh(registryUri, falcon.ImageSensor, version)
if err != nil {
return fmt.Errorf("Cannot push Falcon Image Analyzer Image: %v", err)
}
@@ -139,7 +139,7 @@ func (r *FalconImageAnalyzerReconciler) registryUri(ctx context.Context, falconI
return "", err
}
- return falcon.FalconContainerSensorImageURI(cloud, falcon.RegionedImageSensor), nil
+ return falcon.FalconContainerSensorImageURI(cloud, falcon.ImageSensor), nil
default:
return "", fmt.Errorf("Unrecognized registry type: %s", falconImageAnalyzer.Spec.Registry.Type)
}
@@ -165,6 +165,16 @@ func (r *FalconImageAnalyzerReconciler) imageUri(ctx context.Context, falconImag
return "", fmt.Errorf("failed to set Falcon Image Analyzer Image version: %v", err)
}
+ if falconImageAnalyzer.Spec.Registry.Type == falconv1alpha1.RegistryTypeCrowdStrike {
+ if !falcon_registry.IsMinimumUnifiedSensorVersion(imageTag, falcon.ImageSensor) {
+ cloud, err := falconImageAnalyzer.Spec.FalconAPI.FalconCloudWithSecret(ctx, r.Reader, falconImageAnalyzer.Spec.FalconSecret)
+ if err != nil {
+ return "", err
+ }
+ registryUri = falcon.FalconContainerSensorImageURI(cloud, falcon.RegionedImageSensor)
+ }
+ }
+
return fmt.Sprintf("%s:%s", registryUri, imageTag), nil
}
@@ -209,7 +219,7 @@ func (r *FalconImageAnalyzerReconciler) setImageTag(ctx context.Context, falconI
return "", err
}
- tag, err := registry.LastContainerTag(ctx, falcon.RegionedImageSensor, falconImageAnalyzer.Spec.Version)
+ tag, err := registry.LastContainerTag(ctx, falcon.ImageSensor, falconImageAnalyzer.Spec.Version)
if err == nil {
falconImageAnalyzer.Status.Sensor = common.ImageVersion(tag)
}
diff --git a/pkg/registry/falcon_registry/container.go b/pkg/registry/falcon_registry/container.go
index 54323685..50905967 100644
--- a/pkg/registry/falcon_registry/container.go
+++ b/pkg/registry/falcon_registry/container.go
@@ -2,9 +2,11 @@ package falcon_registry
import (
"context"
+ "fmt"
"strings"
"github.com/crowdstrike/gofalcon/falcon"
+ "go.podman.io/image/v5/types"
"golang.org/x/mod/semver"
)
@@ -12,6 +14,7 @@ const (
MinimumUnifiedNodeSensorVersion = "7.31.0"
MinimumUnifiedKacSensorVersion = "7.33.0"
MinimumUnifiedSidecarSensorVersion = "7.33.0"
+ MinimumUnifiedImageSensorVersion = "1.0.24"
)
func (reg *FalconRegistry) LastContainerTag(ctx context.Context, sensorType falcon.SensorType, versionRequested *string) (string, error) {
@@ -24,7 +27,7 @@ func (reg *FalconRegistry) LastContainerTag(ctx context.Context, sensorType falc
regionedFilter := func(tag string) bool {
tagContains := ".container"
- if sensorType == falcon.RegionedImageSensor || sensorType == falcon.KacSensor {
+ if sensorType == falcon.ImageSensor || sensorType == falcon.KacSensor {
tagContains = ""
}
@@ -40,15 +43,23 @@ func (reg *FalconRegistry) LastContainerTag(ctx context.Context, sensorType falc
switch sensorType {
case falcon.KacSensor:
- tag, err = lastTag(ctx, systemContext, falcon.FalconContainerSensorImageURI(reg.falconCloud, falcon.KacSensor), unifiedFilter)
- if err != nil {
- tag, err = lastTag(ctx, systemContext, falcon.FalconContainerSensorImageURI(reg.falconCloud, falcon.RegionedKacSensor), regionedFilter)
- }
+ tag, err = reg.tryUnifiedThenRegioned(
+ ctx, systemContext,
+ falcon.KacSensor, falcon.RegionedKacSensor,
+ unifiedFilter, regionedFilter,
+ )
case falcon.SidecarSensor:
- tag, err = lastTag(ctx, systemContext, falcon.FalconContainerSensorImageURI(reg.falconCloud, falcon.SidecarSensor), unifiedFilter)
- if err != nil {
- tag, err = lastTag(ctx, systemContext, falcon.FalconContainerSensorImageURI(reg.falconCloud, falcon.RegionedSidecarSensor), regionedFilter)
- }
+ tag, err = reg.tryUnifiedThenRegioned(
+ ctx, systemContext,
+ falcon.SidecarSensor, falcon.RegionedSidecarSensor,
+ unifiedFilter, regionedFilter,
+ )
+ case falcon.ImageSensor:
+ tag, err = reg.tryUnifiedThenRegioned(
+ ctx, systemContext,
+ falcon.ImageSensor, falcon.RegionedImageSensor,
+ unifiedFilter, regionedFilter,
+ )
default:
tag, err = lastTag(ctx, systemContext, reg.imageUriContainer(sensorType), regionedFilter)
}
@@ -68,7 +79,29 @@ func IsMinimumUnifiedSensorVersion(version string, sensorType falcon.SensorType)
return semver.Compare("v"+version, "v"+MinimumUnifiedKacSensorVersion) >= 0
case falcon.SidecarSensor:
return semver.Compare("v"+version, "v"+MinimumUnifiedSidecarSensorVersion) >= 0
+ case falcon.ImageSensor:
+ return semver.Compare("v"+version, "v"+MinimumUnifiedImageSensorVersion) >= 0
}
return false
}
+
+func (reg *FalconRegistry) tryUnifiedThenRegioned(
+ ctx context.Context,
+ systemContext *types.SystemContext,
+ unifiedType, regionedType falcon.SensorType,
+ unifiedFilter, regionedFilter func(string) bool,
+) (string, error) {
+ unifiedURI := falcon.FalconContainerSensorImageURI(reg.falconCloud, unifiedType)
+ regionedURI := falcon.FalconContainerSensorImageURI(reg.falconCloud, regionedType)
+
+ tag, err := lastTag(ctx, systemContext, unifiedURI, unifiedFilter)
+ if err != nil {
+ unifiedErr := fmt.Errorf("failed to fetch unified image sensor tag: %w", err)
+ tag, err = lastTag(ctx, systemContext, regionedURI, regionedFilter)
+ if err != nil {
+ return "", fmt.Errorf("failed to fetch regioned image sensor tag: %w; previous error: %v", err, unifiedErr)
+ }
+ }
+ return tag, nil
+}
From 381b25fce9e371e8752963193f52413278e29bac Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Fri, 20 Feb 2026 10:13:26 -0600
Subject: [PATCH 14/16] chore: Update envtest environment to kubernetes api
version 1.30.3
---
Makefile | 6 +-
...lcon.crowdstrike.com_falconadmissions.yaml | 10 +-
...lcon.crowdstrike.com_falconcontainers.yaml | 219 ++++++--
...con.crowdstrike.com_falcondeployments.yaml | 235 +++++++--
....crowdstrike.com_falconimageanalyzers.yaml | 4 +-
...con.crowdstrike.com_falconnodesensors.yaml | 7 +-
deploy/falcon-operator.yaml | 475 ++++++++++++++----
7 files changed, 761 insertions(+), 195 deletions(-)
diff --git a/Makefile b/Makefile
index 0b9fdc28..d677ced1 100644
--- a/Makefile
+++ b/Makefile
@@ -53,7 +53,7 @@ OPERATOR_SDK_VERSION ?= v1.38.0
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
-ENVTEST_K8S_VERSION = 1.28.3
+ENVTEST_K8S_VERSION = 1.30.3
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
@@ -220,7 +220,7 @@ ENVTEST ?= $(LOCALBIN)/setup-envtest
## Tool Versions
KUSTOMIZE_VERSION ?= v5.6.0
-CONTROLLER_TOOLS_VERSION ?= v0.16.5
+CONTROLLER_TOOLS_VERSION ?= v0.20.1
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading.
@@ -240,7 +240,7 @@ $(CONTROLLER_GEN): $(LOCALBIN)
.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
- test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@release-0.17
+ test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@release-0.23
.PHONY: operator-sdk
OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconadmissions.yaml b/config/crd/bases/falcon.crowdstrike.com_falconadmissions.yaml
index 70cd6bce..3c6c4ff2 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconadmissions.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconadmissions.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconadmissions.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -351,7 +351,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -417,7 +417,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -483,7 +483,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -549,7 +549,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml b/config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml
index 91af3568..6b086bb7 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconcontainers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconcontainers.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -226,6 +226,8 @@ spec:
description: |-
awsElasticBlockStore represents an AWS Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree
+ awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore
properties:
fsType:
@@ -257,8 +259,10 @@ spec:
- volumeID
type: object
azureDisk:
- description: azureDisk represents an Azure Data Disk mount
- on the host and bind mount to the pod.
+ description: |-
+ azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.
+ Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type
+ are redirected to the disk.csi.azure.com CSI driver.
properties:
cachingMode:
description: 'cachingMode is the Host Caching mode: None,
@@ -297,8 +301,10 @@ spec:
- diskURI
type: object
azureFile:
- description: azureFile represents an Azure File Service mount
- on the host and bind mount to the pod.
+ description: |-
+ azureFile represents an Azure File Service mount on the host and bind mount to the pod.
+ Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type
+ are redirected to the file.csi.azure.com CSI driver.
properties:
readOnly:
description: |-
@@ -317,8 +323,9 @@ spec:
- shareName
type: object
cephfs:
- description: cephFS represents a Ceph FS mount on the host
- that shares a pod's lifetime
+ description: |-
+ cephFS represents a Ceph FS mount on the host that shares a pod's lifetime.
+ Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported.
properties:
monitors:
description: |-
@@ -370,6 +377,8 @@ spec:
cinder:
description: |-
cinder represents a cinder volume attached and mounted on kubelets host machine.
+ Deprecated: Cinder is deprecated. All operations for the in-tree cinder type
+ are redirected to the cinder.csi.openstack.org CSI driver.
More info: https://examples.k8s.io/mysql-cinder-pd/README.md
properties:
fsType:
@@ -480,7 +489,7 @@ spec:
csi:
description: csi (Container Storage Interface) represents
ephemeral storage that is handled by certain external CSI
- drivers (Beta feature).
+ drivers.
properties:
driver:
description: |-
@@ -794,7 +803,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -882,15 +891,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -946,6 +953,7 @@ spec:
description: |-
flexVolume represents a generic volume resource that is
provisioned/attached using an exec based plugin.
+ Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead.
properties:
driver:
description: driver is the name of the driver to use for
@@ -991,9 +999,9 @@ spec:
- driver
type: object
flocker:
- description: flocker represents a Flocker volume attached
- to a kubelet's host machine. This depends on the Flocker
- control service being running
+ description: |-
+ flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running.
+ Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported.
properties:
datasetName:
description: |-
@@ -1009,6 +1017,8 @@ spec:
description: |-
gcePersistentDisk represents a GCE Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree
+ gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk
properties:
fsType:
@@ -1044,7 +1054,7 @@ spec:
gitRepo:
description: |-
gitRepo represents a git repository at a particular revision.
- DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an
+ Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an
EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir
into the Pod's container.
properties:
@@ -1068,12 +1078,11 @@ spec:
glusterfs:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
+ Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -1127,7 +1136,7 @@ spec:
The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field.
The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images.
The volume will be mounted read-only (ro) and non-executable files (noexec).
- Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath).
+ Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33.
The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.
properties:
pullPolicy:
@@ -1152,7 +1161,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support
@@ -1277,8 +1286,9 @@ spec:
- claimName
type: object
photonPersistentDisk:
- description: photonPersistentDisk represents a PhotonController
- persistent disk attached and mounted on kubelets host machine
+ description: |-
+ photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine.
+ Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.
properties:
fsType:
description: |-
@@ -1294,8 +1304,11 @@ spec:
- pdID
type: object
portworxVolume:
- description: portworxVolume represents a portworx volume attached
- and mounted on kubelets host machine
+ description: |-
+ portworxVolume represents a portworx volume attached and mounted on kubelets host machine.
+ Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type
+ are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate
+ is on.
properties:
fsType:
description: |-
@@ -1568,6 +1581,129 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ userAnnotations:
+ additionalProperties:
+ type: string
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret
data to project
@@ -1660,8 +1796,9 @@ spec:
x-kubernetes-list-type: atomic
type: object
quobyte:
- description: quobyte represents a Quobyte mount on the host
- that shares a pod's lifetime
+ description: |-
+ quobyte represents a Quobyte mount on the host that shares a pod's lifetime.
+ Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.
properties:
group:
description: |-
@@ -1700,7 +1837,7 @@ spec:
rbd:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/rbd/README.md
+ Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
properties:
fsType:
description: |-
@@ -1772,8 +1909,9 @@ spec:
- monitors
type: object
scaleIO:
- description: scaleIO represents a ScaleIO persistent volume
- attached and mounted on Kubernetes nodes.
+ description: |-
+ scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
+ Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.
properties:
fsType:
default: xfs
@@ -1905,8 +2043,9 @@ spec:
type: string
type: object
storageos:
- description: storageOS represents a StorageOS volume attached
- and mounted on Kubernetes nodes.
+ description: |-
+ storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.
+ Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported.
properties:
fsType:
description: |-
@@ -1951,8 +2090,10 @@ spec:
type: string
type: object
vsphereVolume:
- description: vsphereVolume represents a vSphere volume attached
- and mounted on kubelets host machine
+ description: |-
+ vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine.
+ Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type
+ are redirected to the csi.vsphere.vmware.com CSI driver.
properties:
fsType:
description: |-
@@ -1994,7 +2135,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2054,7 +2195,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
index 2ce772f9..885f4e82 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falcondeployments.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falcondeployments.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -406,7 +406,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -472,7 +472,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -538,7 +538,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -604,7 +604,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -1119,6 +1119,8 @@ spec:
description: |-
awsElasticBlockStore represents an AWS Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree
+ awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore
properties:
fsType:
@@ -1150,8 +1152,10 @@ spec:
- volumeID
type: object
azureDisk:
- description: azureDisk represents an Azure Data Disk mount
- on the host and bind mount to the pod.
+ description: |-
+ azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.
+ Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type
+ are redirected to the disk.csi.azure.com CSI driver.
properties:
cachingMode:
description: 'cachingMode is the Host Caching mode:
@@ -1190,8 +1194,10 @@ spec:
- diskURI
type: object
azureFile:
- description: azureFile represents an Azure File Service
- mount on the host and bind mount to the pod.
+ description: |-
+ azureFile represents an Azure File Service mount on the host and bind mount to the pod.
+ Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type
+ are redirected to the file.csi.azure.com CSI driver.
properties:
readOnly:
description: |-
@@ -1210,8 +1216,9 @@ spec:
- shareName
type: object
cephfs:
- description: cephFS represents a Ceph FS mount on the
- host that shares a pod's lifetime
+ description: |-
+ cephFS represents a Ceph FS mount on the host that shares a pod's lifetime.
+ Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported.
properties:
monitors:
description: |-
@@ -1264,6 +1271,8 @@ spec:
cinder:
description: |-
cinder represents a cinder volume attached and mounted on kubelets host machine.
+ Deprecated: Cinder is deprecated. All operations for the in-tree cinder type
+ are redirected to the cinder.csi.openstack.org CSI driver.
More info: https://examples.k8s.io/mysql-cinder-pd/README.md
properties:
fsType:
@@ -1375,7 +1384,7 @@ spec:
csi:
description: csi (Container Storage Interface) represents
ephemeral storage that is handled by certain external
- CSI drivers (Beta feature).
+ CSI drivers.
properties:
driver:
description: |-
@@ -1691,7 +1700,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -1779,15 +1788,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1843,6 +1850,7 @@ spec:
description: |-
flexVolume represents a generic volume resource that is
provisioned/attached using an exec based plugin.
+ Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead.
properties:
driver:
description: driver is the name of the driver to use
@@ -1888,9 +1896,9 @@ spec:
- driver
type: object
flocker:
- description: flocker represents a Flocker volume attached
- to a kubelet's host machine. This depends on the Flocker
- control service being running
+ description: |-
+ flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running.
+ Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported.
properties:
datasetName:
description: |-
@@ -1906,6 +1914,8 @@ spec:
description: |-
gcePersistentDisk represents a GCE Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree
+ gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk
properties:
fsType:
@@ -1941,7 +1951,7 @@ spec:
gitRepo:
description: |-
gitRepo represents a git repository at a particular revision.
- DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an
+ Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an
EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir
into the Pod's container.
properties:
@@ -1965,12 +1975,11 @@ spec:
glusterfs:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
+ Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -2024,7 +2033,7 @@ spec:
The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field.
The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images.
The volume will be mounted read-only (ro) and non-executable files (noexec).
- Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath).
+ Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33.
The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.
properties:
pullPolicy:
@@ -2049,7 +2058,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support
@@ -2174,9 +2183,9 @@ spec:
- claimName
type: object
photonPersistentDisk:
- description: photonPersistentDisk represents a PhotonController
- persistent disk attached and mounted on kubelets host
- machine
+ description: |-
+ photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine.
+ Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.
properties:
fsType:
description: |-
@@ -2192,8 +2201,11 @@ spec:
- pdID
type: object
portworxVolume:
- description: portworxVolume represents a portworx volume
- attached and mounted on kubelets host machine
+ description: |-
+ portworxVolume represents a portworx volume attached and mounted on kubelets host machine.
+ Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type
+ are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate
+ is on.
properties:
fsType:
description: |-
@@ -2472,6 +2484,129 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will
+ be addressed to this signer.
+ type: string
+ userAnnotations:
+ additionalProperties:
+ type: string
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret
data to project
@@ -2564,8 +2699,9 @@ spec:
x-kubernetes-list-type: atomic
type: object
quobyte:
- description: quobyte represents a Quobyte mount on the
- host that shares a pod's lifetime
+ description: |-
+ quobyte represents a Quobyte mount on the host that shares a pod's lifetime.
+ Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.
properties:
group:
description: |-
@@ -2604,7 +2740,7 @@ spec:
rbd:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/rbd/README.md
+ Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
properties:
fsType:
description: |-
@@ -2676,8 +2812,9 @@ spec:
- monitors
type: object
scaleIO:
- description: scaleIO represents a ScaleIO persistent volume
- attached and mounted on Kubernetes nodes.
+ description: |-
+ scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
+ Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.
properties:
fsType:
default: xfs
@@ -2810,8 +2947,9 @@ spec:
type: string
type: object
storageos:
- description: storageOS represents a StorageOS volume attached
- and mounted on Kubernetes nodes.
+ description: |-
+ storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.
+ Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported.
properties:
fsType:
description: |-
@@ -2856,8 +2994,10 @@ spec:
type: string
type: object
vsphereVolume:
- description: vsphereVolume represents a vSphere volume
- attached and mounted on kubelets host machine
+ description: |-
+ vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine.
+ Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type
+ are redirected to the csi.vsphere.vmware.com CSI driver.
properties:
fsType:
description: |-
@@ -2900,7 +3040,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2960,7 +3100,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3492,7 +3632,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4401,9 +4541,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -4447,7 +4588,7 @@ spec:
pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
on that node is marked deleted. If the old pod becomes unavailable for any
reason (Ready transitions to false, is evicted, or is drained) an updated
- pod is immediatedly created on that node without considering surge limits.
+ pod is immediately created on that node without considering surge limits.
Allowing surge implies the possibility that the resources consumed by the
daemonset on any given node can double if the readiness check fails, and
so resource intensive daemonsets should take into account that they may
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml b/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
index 3d6b6216..3e3bccd1 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconimageanalyzers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconimageanalyzers.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -251,7 +251,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
diff --git a/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml b/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
index 694f2d4d..89a7934b 100644
--- a/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
+++ b/config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconnodesensors.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -583,9 +583,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -629,7 +630,7 @@ spec:
pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
on that node is marked deleted. If the old pod becomes unavailable for any
reason (Ready transitions to false, is evicted, or is drained) an updated
- pod is immediatedly created on that node without considering surge limits.
+ pod is immediately created on that node without considering surge limits.
Allowing surge implies the possibility that the resources consumed by the
daemonset on any given node can double if the readiness check fails, and
so resource intensive daemonsets should take into account that they may
diff --git a/deploy/falcon-operator.yaml b/deploy/falcon-operator.yaml
index be2045f6..8af0c06e 100644
--- a/deploy/falcon-operator.yaml
+++ b/deploy/falcon-operator.yaml
@@ -17,7 +17,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconadmissions.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -365,7 +365,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -431,7 +431,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -497,7 +497,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -563,7 +563,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -971,7 +971,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconcontainers.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -1194,6 +1194,8 @@ spec:
description: |-
awsElasticBlockStore represents an AWS Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree
+ awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore
properties:
fsType:
@@ -1225,8 +1227,10 @@ spec:
- volumeID
type: object
azureDisk:
- description: azureDisk represents an Azure Data Disk mount
- on the host and bind mount to the pod.
+ description: |-
+ azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.
+ Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type
+ are redirected to the disk.csi.azure.com CSI driver.
properties:
cachingMode:
description: 'cachingMode is the Host Caching mode: None,
@@ -1263,8 +1267,10 @@ spec:
- diskURI
type: object
azureFile:
- description: azureFile represents an Azure File Service mount
- on the host and bind mount to the pod.
+ description: |-
+ azureFile represents an Azure File Service mount on the host and bind mount to the pod.
+ Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type
+ are redirected to the file.csi.azure.com CSI driver.
properties:
readOnly:
description: |-
@@ -1283,8 +1289,9 @@ spec:
- shareName
type: object
cephfs:
- description: cephFS represents a Ceph FS mount on the host
- that shares a pod's lifetime
+ description: |-
+ cephFS represents a Ceph FS mount on the host that shares a pod's lifetime.
+ Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported.
properties:
monitors:
description: |-
@@ -1336,6 +1343,8 @@ spec:
cinder:
description: |-
cinder represents a cinder volume attached and mounted on kubelets host machine.
+ Deprecated: Cinder is deprecated. All operations for the in-tree cinder type
+ are redirected to the cinder.csi.openstack.org CSI driver.
More info: https://examples.k8s.io/mysql-cinder-pd/README.md
properties:
fsType:
@@ -1446,7 +1455,7 @@ spec:
csi:
description: csi (Container Storage Interface) represents
ephemeral storage that is handled by certain external CSI
- drivers (Beta feature).
+ drivers.
properties:
driver:
description: |-
@@ -1760,7 +1769,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -1848,15 +1857,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1912,6 +1919,7 @@ spec:
description: |-
flexVolume represents a generic volume resource that is
provisioned/attached using an exec based plugin.
+ Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead.
properties:
driver:
description: driver is the name of the driver to use for
@@ -1957,9 +1965,9 @@ spec:
- driver
type: object
flocker:
- description: flocker represents a Flocker volume attached
- to a kubelet's host machine. This depends on the Flocker
- control service being running
+ description: |-
+ flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running.
+ Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported.
properties:
datasetName:
description: |-
@@ -1975,6 +1983,8 @@ spec:
description: |-
gcePersistentDisk represents a GCE Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree
+ gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk
properties:
fsType:
@@ -2010,7 +2020,7 @@ spec:
gitRepo:
description: |-
gitRepo represents a git repository at a particular revision.
- DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an
+ Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an
EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir
into the Pod's container.
properties:
@@ -2034,12 +2044,11 @@ spec:
glusterfs:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
+ Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -2093,7 +2102,7 @@ spec:
The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field.
The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images.
The volume will be mounted read-only (ro) and non-executable files (noexec).
- Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath).
+ Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33.
The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.
properties:
pullPolicy:
@@ -2118,7 +2127,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support
@@ -2242,8 +2251,9 @@ spec:
- claimName
type: object
photonPersistentDisk:
- description: photonPersistentDisk represents a PhotonController
- persistent disk attached and mounted on kubelets host machine
+ description: |-
+ photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine.
+ Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.
properties:
fsType:
description: |-
@@ -2259,8 +2269,11 @@ spec:
- pdID
type: object
portworxVolume:
- description: portworxVolume represents a portworx volume attached
- and mounted on kubelets host machine
+ description: |-
+ portworxVolume represents a portworx volume attached and mounted on kubelets host machine.
+ Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type
+ are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate
+ is on.
properties:
fsType:
description: |-
@@ -2533,6 +2546,129 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ userAnnotations:
+ additionalProperties:
+ type: string
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret
data to project
@@ -2625,8 +2761,9 @@ spec:
x-kubernetes-list-type: atomic
type: object
quobyte:
- description: quobyte represents a Quobyte mount on the host
- that shares a pod's lifetime
+ description: |-
+ quobyte represents a Quobyte mount on the host that shares a pod's lifetime.
+ Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.
properties:
group:
description: |-
@@ -2665,7 +2802,7 @@ spec:
rbd:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/rbd/README.md
+ Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
properties:
fsType:
description: |-
@@ -2734,8 +2871,9 @@ spec:
- monitors
type: object
scaleIO:
- description: scaleIO represents a ScaleIO persistent volume
- attached and mounted on Kubernetes nodes.
+ description: |-
+ scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
+ Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.
properties:
fsType:
description: |-
@@ -2865,8 +3003,9 @@ spec:
type: string
type: object
storageos:
- description: storageOS represents a StorageOS volume attached
- and mounted on Kubernetes nodes.
+ description: |-
+ storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.
+ Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported.
properties:
fsType:
description: |-
@@ -2911,8 +3050,10 @@ spec:
type: string
type: object
vsphereVolume:
- description: vsphereVolume represents a vSphere volume attached
- and mounted on kubelets host machine
+ description: |-
+ vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine.
+ Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type
+ are redirected to the csi.vsphere.vmware.com CSI driver.
properties:
fsType:
description: |-
@@ -2954,7 +3095,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3014,7 +3155,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3413,7 +3554,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falcondeployments.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -3816,7 +3957,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3882,7 +4023,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3948,7 +4089,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4014,7 +4155,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4529,6 +4670,8 @@ spec:
description: |-
awsElasticBlockStore represents an AWS Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree
+ awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore
properties:
fsType:
@@ -4560,8 +4703,10 @@ spec:
- volumeID
type: object
azureDisk:
- description: azureDisk represents an Azure Data Disk mount
- on the host and bind mount to the pod.
+ description: |-
+ azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.
+ Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type
+ are redirected to the disk.csi.azure.com CSI driver.
properties:
cachingMode:
description: 'cachingMode is the Host Caching mode:
@@ -4598,8 +4743,10 @@ spec:
- diskURI
type: object
azureFile:
- description: azureFile represents an Azure File Service
- mount on the host and bind mount to the pod.
+ description: |-
+ azureFile represents an Azure File Service mount on the host and bind mount to the pod.
+ Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type
+ are redirected to the file.csi.azure.com CSI driver.
properties:
readOnly:
description: |-
@@ -4618,8 +4765,9 @@ spec:
- shareName
type: object
cephfs:
- description: cephFS represents a Ceph FS mount on the
- host that shares a pod's lifetime
+ description: |-
+ cephFS represents a Ceph FS mount on the host that shares a pod's lifetime.
+ Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported.
properties:
monitors:
description: |-
@@ -4672,6 +4820,8 @@ spec:
cinder:
description: |-
cinder represents a cinder volume attached and mounted on kubelets host machine.
+ Deprecated: Cinder is deprecated. All operations for the in-tree cinder type
+ are redirected to the cinder.csi.openstack.org CSI driver.
More info: https://examples.k8s.io/mysql-cinder-pd/README.md
properties:
fsType:
@@ -4783,7 +4933,7 @@ spec:
csi:
description: csi (Container Storage Interface) represents
ephemeral storage that is handled by certain external
- CSI drivers (Beta feature).
+ CSI drivers.
properties:
driver:
description: |-
@@ -5099,7 +5249,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -5187,15 +5337,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -5251,6 +5399,7 @@ spec:
description: |-
flexVolume represents a generic volume resource that is
provisioned/attached using an exec based plugin.
+ Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead.
properties:
driver:
description: driver is the name of the driver to use
@@ -5296,9 +5445,9 @@ spec:
- driver
type: object
flocker:
- description: flocker represents a Flocker volume attached
- to a kubelet's host machine. This depends on the Flocker
- control service being running
+ description: |-
+ flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running.
+ Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported.
properties:
datasetName:
description: |-
@@ -5314,6 +5463,8 @@ spec:
description: |-
gcePersistentDisk represents a GCE Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
+ Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree
+ gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver.
More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk
properties:
fsType:
@@ -5349,7 +5500,7 @@ spec:
gitRepo:
description: |-
gitRepo represents a git repository at a particular revision.
- DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an
+ Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an
EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir
into the Pod's container.
properties:
@@ -5373,12 +5524,11 @@ spec:
glusterfs:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
+ Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -5432,7 +5582,7 @@ spec:
The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field.
The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images.
The volume will be mounted read-only (ro) and non-executable files (noexec).
- Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath).
+ Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33.
The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.
properties:
pullPolicy:
@@ -5457,7 +5607,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support
@@ -5581,9 +5731,9 @@ spec:
- claimName
type: object
photonPersistentDisk:
- description: photonPersistentDisk represents a PhotonController
- persistent disk attached and mounted on kubelets host
- machine
+ description: |-
+ photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine.
+ Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.
properties:
fsType:
description: |-
@@ -5599,8 +5749,11 @@ spec:
- pdID
type: object
portworxVolume:
- description: portworxVolume represents a portworx volume
- attached and mounted on kubelets host machine
+ description: |-
+ portworxVolume represents a portworx volume attached and mounted on kubelets host machine.
+ Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type
+ are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate
+ is on.
properties:
fsType:
description: |-
@@ -5879,6 +6032,129 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will
+ be addressed to this signer.
+ type: string
+ userAnnotations:
+ additionalProperties:
+ type: string
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret
data to project
@@ -5971,8 +6247,9 @@ spec:
x-kubernetes-list-type: atomic
type: object
quobyte:
- description: quobyte represents a Quobyte mount on the
- host that shares a pod's lifetime
+ description: |-
+ quobyte represents a Quobyte mount on the host that shares a pod's lifetime.
+ Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.
properties:
group:
description: |-
@@ -6011,7 +6288,7 @@ spec:
rbd:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
- More info: https://examples.k8s.io/volumes/rbd/README.md
+ Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
properties:
fsType:
description: |-
@@ -6080,8 +6357,9 @@ spec:
- monitors
type: object
scaleIO:
- description: scaleIO represents a ScaleIO persistent volume
- attached and mounted on Kubernetes nodes.
+ description: |-
+ scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
+ Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.
properties:
fsType:
description: |-
@@ -6212,8 +6490,9 @@ spec:
type: string
type: object
storageos:
- description: storageOS represents a StorageOS volume attached
- and mounted on Kubernetes nodes.
+ description: |-
+ storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes.
+ Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported.
properties:
fsType:
description: |-
@@ -6258,8 +6537,10 @@ spec:
type: string
type: object
vsphereVolume:
- description: vsphereVolume represents a vSphere volume
- attached and mounted on kubelets host machine
+ description: |-
+ vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine.
+ Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type
+ are redirected to the csi.vsphere.vmware.com CSI driver.
properties:
fsType:
description: |-
@@ -6302,7 +6583,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6362,7 +6643,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6894,7 +7175,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -7803,9 +8084,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -7849,7 +8131,7 @@ spec:
pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
on that node is marked deleted. If the old pod becomes unavailable for any
reason (Ready transitions to false, is evicted, or is drained) an updated
- pod is immediatedly created on that node without considering surge limits.
+ pod is immediately created on that node without considering surge limits.
Allowing surge implies the possibility that the resources consumed by the
daemonset on any given node can double if the readiness check fails, and
so resource intensive daemonsets should take into account that they may
@@ -8033,7 +8315,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconimageanalyzers.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -8281,7 +8563,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -8723,7 +9005,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.16.5
+ controller-gen.kubebuilder.io/version: v0.20.1
name: falconnodesensors.falcon.crowdstrike.com
spec:
group: falcon.crowdstrike.com
@@ -9303,9 +9585,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -9349,7 +9632,7 @@ spec:
pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
on that node is marked deleted. If the old pod becomes unavailable for any
reason (Ready transitions to false, is evicted, or is drained) an updated
- pod is immediatedly created on that node without considering surge limits.
+ pod is immediately created on that node without considering surge limits.
Allowing surge implies the possibility that the resources consumed by the
daemonset on any given node can double if the readiness check fails, and
so resource intensive daemonsets should take into account that they may
From f42128c6123a8ed3e76c77fe0c76c3228689cb19 Mon Sep 17 00:00:00 2001
From: Greg Pontejos <242696964+gpontejos-cs@users.noreply.github.com>
Date: Fri, 20 Feb 2026 10:13:38 -0600
Subject: [PATCH 15/16] fix(falcon-kac): Ensure GVK is present in schema during
kac deployment reconciles
---
internal/controller/admission/falconadmission_controller.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/internal/controller/admission/falconadmission_controller.go b/internal/controller/admission/falconadmission_controller.go
index 3830c4e3..f2cbb932 100644
--- a/internal/controller/admission/falconadmission_controller.go
+++ b/internal/controller/admission/falconadmission_controller.go
@@ -659,6 +659,7 @@ func (r *FalconAdmissionReconciler) reconcileAdmissionDeployment(ctx context.Con
}
if updated {
+ existingDeployment.SetGroupVersionKind(appsv1.SchemeGroupVersion.WithKind("Deployment"))
if err := k8sutils.Update(r.Client, ctx, req, log, falconAdmission, &falconAdmission.Status, existingDeployment); err != nil {
return err
}
From 92257d549edef32c7551cd2ab5a21ead1bb6e766 Mon Sep 17 00:00:00 2001
From: gpontejos-cs <242696964+gpontejos-cs@users.noreply.github.com>
Date: Mon, 23 Feb 2026 13:08:37 -0600
Subject: [PATCH 16/16] fix: Ensure IAR and KAC ImagePullSecrets are updated
during reconciles (#780)
* fix: Ensure IAR and KAC ImagePullSecrets are updated during reconciles
* Update internal/controller/admission/falconadmission_controller.go
Co-authored-by: Jung Choi <17916440+mr-jungchoi@users.noreply.github.com>
* Update internal/controller/falcon_image_analyzer/falconimage_controller.go
Co-authored-by: Jung Choi <17916440+mr-jungchoi@users.noreply.github.com>
* Adding comments for clarity and updating service account reconcile vars
---------
Co-authored-by: Jung Choi <17916440+mr-jungchoi@users.noreply.github.com>
---
.../admission/falconadmission_controller.go | 5 +-
.../falconadmission_controller_test.go | 346 +++++++++++++
internal/controller/admission/rbac.go | 58 ++-
.../falconimage_controller.go | 5 +-
.../falconimage_controller_test.go | 485 +++++++++++++++++-
.../controller/falcon_image_analyzer/rbac.go | 32 +-
6 files changed, 899 insertions(+), 32 deletions(-)
diff --git a/internal/controller/admission/falconadmission_controller.go b/internal/controller/admission/falconadmission_controller.go
index f2cbb932..b7c0650a 100644
--- a/internal/controller/admission/falconadmission_controller.go
+++ b/internal/controller/admission/falconadmission_controller.go
@@ -225,7 +225,8 @@ func (r *FalconAdmissionReconciler) Reconcile(ctx context.Context, req ctrl.Requ
}
}
- if err := r.reconcileServiceAccount(ctx, req, log, falconAdmission); err != nil {
+ serviceAccountUpdateRequiresRestart, err := r.reconcileServiceAccount(ctx, req, log, falconAdmission)
+ if err != nil {
return ctrl.Result{}, err
}
@@ -291,7 +292,7 @@ func (r *FalconAdmissionReconciler) Reconcile(ctx context.Context, req ctrl.Requ
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}
- if configUpdated || clusterNameConfigUpdated || serviceUpdated || webhookUpdated {
+ if configUpdated || clusterNameConfigUpdated || serviceUpdated || webhookUpdated || serviceAccountUpdateRequiresRestart {
err = r.admissionDeploymentUpdate(ctx, req, log, falconAdmission)
if err != nil {
return ctrl.Result{}, err
diff --git a/internal/controller/admission/falconadmission_controller_test.go b/internal/controller/admission/falconadmission_controller_test.go
index be774661..c05bdd9c 100644
--- a/internal/controller/admission/falconadmission_controller_test.go
+++ b/internal/controller/admission/falconadmission_controller_test.go
@@ -19,6 +19,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
@@ -73,6 +74,10 @@ var _ = Describe("FalconAdmission controller", func() {
Expect(err).To(Not(HaveOccurred()))
falconAdmission = &falconv1alpha1.FalconAdmission{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconAdmission",
+ },
ObjectMeta: metav1.ObjectMeta{
Name: controllerName,
Namespace: namespaceName,
@@ -492,5 +497,346 @@ var _ = Describe("FalconAdmission controller", func() {
Expect(falconClientContainer.Resources.Requests.Memory().String()).To(Equal("128Mi"))
Expect(falconClientContainer.Resources.Limits.Memory().String()).To(Equal("128Mi"))
})
+
+ // Testing reconcileServiceAccount return value
+ It("should return false when creating a new service account", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission")
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Calling reconcileServiceAccount when no service account exists")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when creating a new service account")
+
+ By("Verifying the service account was created")
+ Eventually(func() error {
+ found := &corev1.ServiceAccount{}
+ return k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ }, 5*time.Second, time.Second).Should(Succeed())
+ })
+
+ It("should return false when only annotations are updated", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission")
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Updating annotations in FalconAdmission spec")
+ falconAdmission.Spec.AdmissionConfig.ServiceAccount.Annotations = map[string]string{
+ "new-annotation": "new-value",
+ }
+
+ By("Calling reconcileServiceAccount with updated annotations")
+ updated, err = falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when only annotations are updated")
+
+ By("Verifying annotations were updated")
+ Eventually(func() map[string]string {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return found.ObjectMeta.Annotations
+ }, 5*time.Second, time.Second).Should(HaveKey("new-annotation"))
+ })
+
+ It("should return true when imagePullSecrets are updated", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission")
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with default imagePullSecrets")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying initial imagePullSecrets")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ }))
+
+ By("Adding a new imagePullSecret to FalconAdmission spec")
+ falconAdmission.Spec.AdmissionConfig.ImagePullSecrets = []corev1.LocalObjectReference{
+ {Name: "additional-secret"},
+ }
+
+ By("Calling reconcileServiceAccount with updated imagePullSecrets")
+ updated, err = falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeTrue(), "reconcileServiceAccount should return true when imagePullSecrets are updated")
+
+ By("Verifying imagePullSecrets were updated")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ {Name: "additional-secret"},
+ }))
+ })
+
+ It("should return false when no changes are made to service account", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission")
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Calling reconcileServiceAccount again without any changes")
+ updated, err = falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when no changes are made")
+ })
+
+ It("should return true when imagePullSecrets are removed", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission with extra imagePullSecret")
+ falconAdmission.Spec.AdmissionConfig.ImagePullSecrets = []corev1.LocalObjectReference{
+ {Name: "extra-secret"},
+ }
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with multiple imagePullSecrets")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying initial imagePullSecrets include extra secret")
+ Eventually(func() int {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return len(found.ImagePullSecrets)
+ }, 5*time.Second, time.Second).Should(Equal(2))
+
+ By("Removing extra imagePullSecret from FalconAdmission spec")
+ falconAdmission.Spec.AdmissionConfig.ImagePullSecrets = []corev1.LocalObjectReference{}
+
+ By("Calling reconcileServiceAccount with removed imagePullSecret")
+ updated, err = falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeTrue(), "reconcileServiceAccount should return true when imagePullSecrets are removed")
+
+ By("Verifying imagePullSecrets were reduced to default only")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ }))
+ })
+
+ It("should not trigger reconciliation loop when external annotations are added", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconAdmission with operator-managed annotations")
+ falconAdmission.Spec.AdmissionConfig.ServiceAccount.Annotations = map[string]string{
+ "operator-managed-annotation": "value1",
+ }
+ err := k8sClient.Create(ctx, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconAdmission{}
+ return k8sClient.Get(ctx, admissionNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconAdmissionReconciler := &FalconAdmissionReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with operator-managed annotations")
+ updated, err := falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying service account was created with operator-managed annotation")
+ Eventually(func() map[string]string {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return found.Annotations
+ }, 5*time.Second, time.Second).Should(HaveKeyWithValue("operator-managed-annotation", "value1"))
+
+ By("Simulating external system (like OpenShift) adding annotations to the service account")
+ serviceAccount := &corev1.ServiceAccount{}
+ err = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+
+ serviceAccount.Annotations["openshift.io/sa.scc.mcs"] = "s0:c27,c4"
+ serviceAccount.Annotations["openshift.io/sa.scc.supplemental-groups"] = "1000710000/10000"
+ serviceAccount.Annotations["openshift.io/sa.scc.uid-range"] = "1000710000/10000"
+ err = k8sClient.Update(ctx, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Verifying external annotations were added")
+ Eventually(func() bool {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, found)
+ return len(found.Annotations) == 4 // 1 operator-managed + 3 openshift
+ }, 5*time.Second, time.Second).Should(BeTrue())
+
+ By("Calling reconcileServiceAccount again - should not trigger update for external annotations")
+ updated, err = falconAdmissionReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: admissionNamespacedName,
+ }, log, falconAdmission)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when only external annotations exist")
+
+ By("Verifying external annotations are preserved after reconciliation")
+ serviceAccount = &corev1.ServiceAccount{}
+ err = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.AdmissionServiceAccountName,
+ Namespace: namespaceName,
+ }, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.mcs", "s0:c27,c4"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.supplemental-groups", "1000710000/10000"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.uid-range", "1000710000/10000"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("operator-managed-annotation", "value1"))
+ })
})
})
diff --git a/internal/controller/admission/rbac.go b/internal/controller/admission/rbac.go
index 4b312591..117f749b 100644
--- a/internal/controller/admission/rbac.go
+++ b/internal/controller/admission/rbac.go
@@ -23,8 +23,11 @@ const (
admissionControllerRoleBindingName = "falcon-admission-controller-role-binding"
)
-func (r *FalconAdmissionReconciler) reconcileServiceAccount(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) error {
- update := false
+// reconcileServiceAccount only returns true when a service account update requires a deployment restart.
+// Only updates to image pull secrets should trigger a deployment restart.
+func (r *FalconAdmissionReconciler) reconcileServiceAccount(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) (bool, error) {
+ serviceAccountUpdated := false
+ imagePullSecretsUpdated := false
existingServiceAccount := &corev1.ServiceAccount{}
imagePullSecrets := []corev1.LocalObjectReference{{Name: common.FalconPullSecretName}}
@@ -44,33 +47,58 @@ func (r *FalconAdmissionReconciler) reconcileServiceAccount(ctx context.Context,
if err != nil && apierrors.IsNotFound(err) {
err = k8sutils.Create(r.Client, r.Scheme, ctx, req, log, falconAdmission, &falconAdmission.Status, serviceAccount)
if err != nil {
- return err
+ return false, err
}
- return nil
+ return serviceAccountUpdated, nil
} else if err != nil {
log.Error(err, "Failed to get FalconAdmission ServiceAccount")
- return err
+ return serviceAccountUpdated, err
+ }
+
+ // Set GVK on existingServiceAccount since it's not populated when retrieved from the API server
+ existingServiceAccount.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ServiceAccount"))
+
+ // Check if any annotations from serviceAccount need to be added to existingServiceAccount
+ if serviceAccount.ObjectMeta.Annotations != nil {
+ if existingServiceAccount.ObjectMeta.Annotations == nil {
+ existingServiceAccount.ObjectMeta.Annotations = make(map[string]string)
+ }
+ for key, value := range serviceAccount.ObjectMeta.Annotations {
+ if existingValue, exists := existingServiceAccount.ObjectMeta.Annotations[key]; !exists || existingValue != value {
+ existingServiceAccount.ObjectMeta.Annotations[key] = value
+ serviceAccountUpdated = true
+ }
+ }
}
- if !reflect.DeepEqual(serviceAccount.ObjectMeta.Annotations, existingServiceAccount.ObjectMeta.Annotations) {
- existingServiceAccount.ObjectMeta.Annotations = serviceAccount.ObjectMeta.Annotations
- update = true
+ // Check if any labels from serviceAccount need to be added to existingServiceAccount
+ if serviceAccount.ObjectMeta.Labels != nil {
+ if existingServiceAccount.ObjectMeta.Labels == nil {
+ existingServiceAccount.ObjectMeta.Labels = make(map[string]string)
+ }
+ for key, value := range serviceAccount.ObjectMeta.Labels {
+ if existingValue, exists := existingServiceAccount.ObjectMeta.Labels[key]; !exists || existingValue != value {
+ existingServiceAccount.ObjectMeta.Labels[key] = value
+ serviceAccountUpdated = true
+ }
+ }
}
- if !reflect.DeepEqual(serviceAccount.ObjectMeta.Labels, existingServiceAccount.ObjectMeta.Labels) {
- existingServiceAccount.ObjectMeta.Labels = serviceAccount.ObjectMeta.Labels
- update = true
+
+ if !reflect.DeepEqual(serviceAccount.ImagePullSecrets, existingServiceAccount.ImagePullSecrets) {
+ existingServiceAccount.ImagePullSecrets = serviceAccount.ImagePullSecrets
+ imagePullSecretsUpdated = true
}
- if update {
+ if serviceAccountUpdated || imagePullSecretsUpdated {
err = k8sutils.Update(r.Client, ctx, req, log, falconAdmission, &falconAdmission.Status, existingServiceAccount)
if err != nil {
- return err
+ return serviceAccountUpdated, err
}
}
- return nil
-
+ // Only trigger a pod restart if imagePullSecrets are updated
+ return imagePullSecretsUpdated, nil
}
func (r *FalconAdmissionReconciler) reconcileClusterRoleBinding(ctx context.Context, req ctrl.Request, log logr.Logger, falconAdmission *falconv1alpha1.FalconAdmission) error {
diff --git a/internal/controller/falcon_image_analyzer/falconimage_controller.go b/internal/controller/falcon_image_analyzer/falconimage_controller.go
index 5b2a4907..69b11135 100644
--- a/internal/controller/falcon_image_analyzer/falconimage_controller.go
+++ b/internal/controller/falcon_image_analyzer/falconimage_controller.go
@@ -213,7 +213,8 @@ func (r *FalconImageAnalyzerReconciler) Reconcile(ctx context.Context, req ctrl.
}
}
- if err := r.reconcileServiceAccount(ctx, req, log, falconImageAnalyzer); err != nil {
+ serviceAccountUpdateRequiresRestart, err := r.reconcileServiceAccount(ctx, req, log, falconImageAnalyzer)
+ if err != nil {
return ctrl.Result{}, err
}
@@ -246,7 +247,7 @@ func (r *FalconImageAnalyzerReconciler) Reconcile(ctx context.Context, req ctrl.
return ctrl.Result{}, err
}
- if configUpdated {
+ if configUpdated || serviceAccountUpdateRequiresRestart {
err = r.imageAnalyzerDeploymentUpdate(ctx, req, log, falconImageAnalyzer)
if err != nil {
return ctrl.Result{}, err
diff --git a/internal/controller/falcon_image_analyzer/falconimage_controller_test.go b/internal/controller/falcon_image_analyzer/falconimage_controller_test.go
index 2518fe34..248c31c0 100644
--- a/internal/controller/falcon_image_analyzer/falconimage_controller_test.go
+++ b/internal/controller/falcon_image_analyzer/falconimage_controller_test.go
@@ -16,6 +16,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
@@ -70,8 +71,9 @@ var _ = Describe("FalconImageAnalyzer controller", func() {
// Delete cluster level resources
clusterRoleBinding := &rbacv1.ClusterRoleBinding{}
- Expect(k8sClient.Get(ctx, types.NamespacedName{Name: imageClusterRoleBindingName}, clusterRoleBinding)).To(Succeed())
- Expect(k8sClient.Delete(ctx, clusterRoleBinding)).To(Succeed())
+ if err := k8sClient.Get(ctx, types.NamespacedName{Name: imageClusterRoleBindingName}, clusterRoleBinding); err == nil {
+ Expect(k8sClient.Delete(ctx, clusterRoleBinding)).To(Succeed())
+ }
// Delete FalconImageAnalyzer custom resource
falconImageAnalyzerCR := &falconv1alpha1.FalconImageAnalyzer{}
@@ -292,5 +294,484 @@ var _ = Describe("FalconImageAnalyzer controller", func() {
err = k8sClient.Delete(ctx, testSecret)
Expect(err).To(Not(HaveOccurred()))
})
+
+ // Testing reconcileServiceAccount return value
+ It("should return false when creating a new service account", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Calling reconcileServiceAccount when no service account exists")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when creating a new service account")
+
+ By("Verifying the service account was created")
+ Eventually(func() error {
+ found := &corev1.ServiceAccount{}
+ return k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ }, 5*time.Second, time.Second).Should(Succeed())
+ })
+
+ It("should return false when only annotations are updated", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Updating annotations in FalconImageAnalyzer spec")
+ falconImageAnalyzer.Spec.ImageAnalyzerConfig.ServiceAccount.Annotations = map[string]string{
+ "new-annotation": "new-value",
+ }
+
+ By("Calling reconcileServiceAccount with updated annotations")
+ updated, err = falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when only annotations are updated")
+
+ By("Verifying annotations were updated")
+ Eventually(func() map[string]string {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return found.ObjectMeta.Annotations
+ }, 5*time.Second, time.Second).Should(HaveKey("new-annotation"))
+ })
+
+ It("should return true when imagePullSecrets are updated", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with default imagePullSecrets")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying initial imagePullSecrets")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ }))
+
+ By("Adding a new imagePullSecret to FalconImageAnalyzer spec")
+ falconImageAnalyzer.Spec.ImageAnalyzerConfig.ImagePullSecrets = []corev1.LocalObjectReference{
+ {Name: "additional-secret"},
+ }
+
+ By("Calling reconcileServiceAccount with updated imagePullSecrets")
+ updated, err = falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeTrue(), "reconcileServiceAccount should return true when imagePullSecrets are updated")
+
+ By("Verifying imagePullSecrets were updated")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ {Name: "additional-secret"},
+ }))
+ })
+
+ It("should return false when no changes are made to service account", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Calling reconcileServiceAccount again without any changes")
+ updated, err = falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when no changes are made")
+ })
+
+ It("should return true when imagePullSecrets are removed", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer with extra imagePullSecret")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ ImageAnalyzerConfig: falconv1alpha1.FalconImageAnalyzerConfigSpec{
+ ImagePullSecrets: []corev1.LocalObjectReference{
+ {Name: "extra-secret"},
+ },
+ },
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with multiple imagePullSecrets")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying initial imagePullSecrets include extra secret")
+ Eventually(func() int {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return len(found.ImagePullSecrets)
+ }, 5*time.Second, time.Second).Should(Equal(2))
+
+ By("Removing extra imagePullSecret from FalconImageAnalyzer spec")
+ falconImageAnalyzer.Spec.ImageAnalyzerConfig.ImagePullSecrets = []corev1.LocalObjectReference{}
+
+ By("Calling reconcileServiceAccount with removed imagePullSecret")
+ updated, err = falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeTrue(), "reconcileServiceAccount should return true when imagePullSecrets are removed")
+
+ By("Verifying imagePullSecrets were reduced to default only")
+ Eventually(func() []corev1.LocalObjectReference {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return found.ImagePullSecrets
+ }, 5*time.Second, time.Second).Should(Equal([]corev1.LocalObjectReference{
+ {Name: common.FalconPullSecretName},
+ }))
+ })
+
+ It("should not trigger reconciliation loop when external annotations are added", func() {
+ log := zap.New(zap.UseDevMode(true))
+
+ By("Creating the custom resource for the Kind FalconImageAnalyzer")
+ falconImageAnalyzer := &falconv1alpha1.FalconImageAnalyzer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "falcon.crowdstrike.com/v1alpha1",
+ Kind: "FalconImageAnalyzer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ImageAnalyzerName,
+ Namespace: testNamespace.Name,
+ },
+ Spec: falconv1alpha1.FalconImageAnalyzerSpec{
+ InstallNamespace: imageAnalyzerNamespacedName.Namespace,
+ FalconAPI: &falconv1alpha1.FalconAPI{
+ ClientId: "test-client-id",
+ ClientSecret: "test-client-secret",
+ CloudRegion: "us-1",
+ },
+ Registry: falconv1alpha1.RegistrySpec{
+ Type: "crowdstrike",
+ },
+ Image: imageAnalyzerImage,
+ ImageAnalyzerConfig: falconv1alpha1.FalconImageAnalyzerConfigSpec{
+ ServiceAccount: falconv1alpha1.FalconImageAnalyzerServiceAccount{
+ Annotations: map[string]string{
+ "operator-managed-annotation": "value1",
+ },
+ },
+ },
+ },
+ }
+ err := k8sClient.Create(ctx, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Checking if the custom resource was successfully created")
+ Eventually(func() error {
+ found := &falconv1alpha1.FalconImageAnalyzer{}
+ return k8sClient.Get(ctx, imageAnalyzerNamespacedName, found)
+ }, 20*time.Second, time.Second).Should(Succeed())
+
+ By("Creating the reconciler")
+ falconImageAnalyzerReconciler := &FalconImageAnalyzerReconciler{
+ Client: k8sClient,
+ Reader: k8sReader,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ By("Creating initial service account with operator-managed annotations")
+ updated, err := falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse())
+
+ By("Verifying service account was created with operator-managed annotation")
+ Eventually(func() map[string]string {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return found.Annotations
+ }, 5*time.Second, time.Second).Should(HaveKeyWithValue("operator-managed-annotation", "value1"))
+
+ By("Simulating external system (like OpenShift) adding annotations to the service account")
+ serviceAccount := &corev1.ServiceAccount{}
+ err = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+
+ serviceAccount.Annotations["openshift.io/sa.scc.mcs"] = "s0:c27,c4"
+ serviceAccount.Annotations["openshift.io/sa.scc.supplemental-groups"] = "1000710000/10000"
+ serviceAccount.Annotations["openshift.io/sa.scc.uid-range"] = "1000710000/10000"
+ err = k8sClient.Update(ctx, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+
+ By("Verifying external annotations were added")
+ Eventually(func() bool {
+ found := &corev1.ServiceAccount{}
+ _ = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, found)
+ return len(found.Annotations) == 4 // 1 operator-managed + 3 openshift
+ }, 5*time.Second, time.Second).Should(BeTrue())
+
+ By("Calling reconcileServiceAccount again - should not trigger update for external annotations")
+ updated, err = falconImageAnalyzerReconciler.reconcileServiceAccount(ctx, reconcile.Request{
+ NamespacedName: imageAnalyzerNamespacedName,
+ }, log, falconImageAnalyzer)
+
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(updated).To(BeFalse(), "reconcileServiceAccount should return false when only external annotations exist")
+
+ By("Verifying external annotations are preserved after reconciliation")
+ serviceAccount = &corev1.ServiceAccount{}
+ err = k8sClient.Get(ctx, types.NamespacedName{
+ Name: common.ImageServiceAccountName,
+ Namespace: testNamespace.Name,
+ }, serviceAccount)
+ Expect(err).To(Not(HaveOccurred()))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.mcs", "s0:c27,c4"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.supplemental-groups", "1000710000/10000"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("openshift.io/sa.scc.uid-range", "1000710000/10000"))
+ Expect(serviceAccount.Annotations).To(HaveKeyWithValue("operator-managed-annotation", "value1"))
+ })
})
})
diff --git a/internal/controller/falcon_image_analyzer/rbac.go b/internal/controller/falcon_image_analyzer/rbac.go
index 48ff31b2..2cce980f 100644
--- a/internal/controller/falcon_image_analyzer/rbac.go
+++ b/internal/controller/falcon_image_analyzer/rbac.go
@@ -21,8 +21,11 @@ const (
imageClusterRoleBindingName = "falcon-operator-image-controller-rolebinding"
)
-func (r *FalconImageAnalyzerReconciler) reconcileServiceAccount(ctx context.Context, req ctrl.Request, log logr.Logger, falconImageAnalyzer *falconv1alpha1.FalconImageAnalyzer) error {
- update := false
+// reconcileServiceAccount only returns true when a service account update requires a deployment restart.
+// Only updates to image pull secrets should trigger a deployment restart.
+func (r *FalconImageAnalyzerReconciler) reconcileServiceAccount(ctx context.Context, req ctrl.Request, log logr.Logger, falconImageAnalyzer *falconv1alpha1.FalconImageAnalyzer) (bool, error) {
+ serviceAccountUpdated := false
+ imagePullSecretsUpdated := false
existingServiceAccount := &corev1.ServiceAccount{}
imagePullSecrets := []corev1.LocalObjectReference{{Name: common.FalconPullSecretName}}
@@ -42,15 +45,18 @@ func (r *FalconImageAnalyzerReconciler) reconcileServiceAccount(ctx context.Cont
if err != nil && apierrors.IsNotFound(err) {
err = k8sutils.Create(r.Client, r.Scheme, ctx, req, log, falconImageAnalyzer, &falconImageAnalyzer.Status, serviceAccount)
if err != nil {
- return err
+ return serviceAccountUpdated, err
}
- return nil
+ return serviceAccountUpdated, nil
} else if err != nil {
log.Error(err, "Failed to get FalconImageAnalyzer ServiceAccount")
- return err
+ return serviceAccountUpdated, err
}
+ // Set GVK on existingServiceAccount since it's not populated when retrieved from the API server
+ existingServiceAccount.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ServiceAccount"))
+
// Check if any annotations from serviceAccount need to be added to existingServiceAccount
if serviceAccount.ObjectMeta.Annotations != nil {
if existingServiceAccount.ObjectMeta.Annotations == nil {
@@ -59,7 +65,7 @@ func (r *FalconImageAnalyzerReconciler) reconcileServiceAccount(ctx context.Cont
for key, value := range serviceAccount.ObjectMeta.Annotations {
if existingValue, exists := existingServiceAccount.ObjectMeta.Annotations[key]; !exists || existingValue != value {
existingServiceAccount.ObjectMeta.Annotations[key] = value
- update = true
+ serviceAccountUpdated = true
}
}
}
@@ -72,20 +78,24 @@ func (r *FalconImageAnalyzerReconciler) reconcileServiceAccount(ctx context.Cont
for key, value := range serviceAccount.ObjectMeta.Labels {
if existingValue, exists := existingServiceAccount.ObjectMeta.Labels[key]; !exists || existingValue != value {
existingServiceAccount.ObjectMeta.Labels[key] = value
- update = true
+ serviceAccountUpdated = true
}
}
}
- if update {
+ if !reflect.DeepEqual(serviceAccount.ImagePullSecrets, existingServiceAccount.ImagePullSecrets) {
+ existingServiceAccount.ImagePullSecrets = serviceAccount.ImagePullSecrets
+ imagePullSecretsUpdated = true
+ }
+
+ if serviceAccountUpdated || imagePullSecretsUpdated {
err = k8sutils.Update(r.Client, ctx, req, log, falconImageAnalyzer, &falconImageAnalyzer.Status, existingServiceAccount)
if err != nil {
- return err
+ return serviceAccountUpdated, err
}
}
- return nil
-
+ return imagePullSecretsUpdated, nil
}
func (r *FalconImageAnalyzerReconciler) reconcileClusterRoleBinding(ctx context.Context, req ctrl.Request, log logr.Logger, falconImageAnalyzer *falconv1alpha1.FalconImageAnalyzer) error {