Skip to content

feat: add InitContainers, Volumes, VolumeMounts for Fulcio and CTLog - #2175

Open
sampras343 wants to merge 3 commits into
mainfrom
sachin/feat/generic-signer-extensions
Open

feat: add InitContainers, Volumes, VolumeMounts for Fulcio and CTLog#2175
sampras343 wants to merge 3 commits into
mainfrom
sachin/feat/generic-signer-extensions

Conversation

@sampras343

@sampras343 sampras343 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Add signer-agnostic pod customization fields to FulcioSpec and CTlogSpec, enabling users to inject init containers, volumes, and volume mounts regardless of which signer backend is active. This is the first of two PRs — a follow-up PR (#2181) adds Auth support on FulcioSigner/CTlogSigner.

API Changes

  • InitContainerSpec in common.go — curated corev1.Container subset (name, image, command, args, env, envFrom, volumeMounts, resources, securityContext, imagePullPolicy)
  • InitContainers []InitContainerSpec on FulcioSpec and CTlogSpec — top-level, pod-wide
  • Volumes []corev1.Volume on FulcioSpec and CTlogSpec — additional pod volumes
  • VolumeMounts []corev1.VolumeMount on FulcioSpec and CTlogSpec — main server container mounts

Controller Changes

  • User-defined InitContainers/Volumes/VolumeMounts applied in shared deployment path before branching on signer type — works in file mode, not gated behind any specific backend
  • Shared ReconcileUserPodResources helper in ensure/pod_spec.go called by both Fulcio and CTLog to eliminate duplication
  • Operator-managed volumes (fulcio-config, fulcio-cert, oidc-info, CTLog keys) use full VolumeSource replacement with EnsureVolumeDefaultMode — operator always wins on reserved names, prevents infinite reconciliation loops
  • CTLog operator-managed keys volume set after user volumes so operator always wins if a user volume has the same name
  • Fulcio ensureCommonDeployment extracted for shared scaffolding across signer modes
  • Shared helpers: HasVolume, EnsureVolumeDefaultMode, ReconcileInitContainers, ReconcileUserPodResources

Housekeeping

  • Remove dead HasMountPath function
  • Fix findVolume test helper: return &volumes[i] instead of &v (pointer to range-variable copy)
  • v1alpha1 conversion preserves new fields via MarshalData annotations
  • Roundtrip fuzzer generates roundtrip-safe values exercising the MarshalData/UnmarshalData restore path

Review Comments Addressed

(from PR #2128):

# Comment Status
2 Move InitContainers/Volumes/VolumeMounts to top level Done
3 Extract hasVolume/ensureVolumeDefaultMode to shared package Done — ensure/pod_spec.go
5 Extract shared deployment scaffolding Done — ensureCommonDeployment + ReconcileUserPodResources
7 Rename PKCS11InitContainerSpec → InitContainerSpec, move to common.go Done
8 Fix fuzzer to exercise MarshalData restore path Done — signerVolumesFuzzerFuncs + ctlogVolumesFuzzerFuncs
10 InitContainers/Volumes silently ignored in Fulcio file mode Done — applied in shared path
11 Same for CTLog Done
12 Extract helpers to ensure package, remove nolint Done — ReconcileUserPodResources shared helper

Test plan

  • go build ./... and go vet ./... pass
  • Shared helper unit tests: ReconcileInitContainers, EnsureVolumeDefaultMode, HasVolume
  • Fulcio deployment tests: volumes, init containers, operator volume precedence in file mode
  • CTLog deployment tests: volumes, init containers, operator volume precedence
  • v1alpha1 roundtrip fuzz tests pass
  • E2E: deploy file-mode CR on OCP 4.22, cosign sign + verify passes
  • Deploy CR with custom initContainers/volumes in file mode — fields applied to pod

Depends on: #2179

🤖 Generated with Claude Code

@qodo-for-securesign

Copy link
Copy Markdown

PR Summary by Qodo

feat: signer-agnostic InitContainers, Volumes, VolumeMounts and Auth for Fulcio/CTlog

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add signer-agnostic pod customization fields to Fulcio/CTlog APIs (initContainers, volumes,
 mounts, auth).
• Apply these fields in the shared deployment path so they work in file mode.
• Extract shared pod-spec reconciliation helpers and add unit/roundtrip coverage.
Diagram

graph TD
  A["FulcioSpec / CTlogSpec"] --> B["Controllers"] --> C["ensure/pod_spec.go"]
  C --> D["PodSpec (Deployment)"] --> E["Signer type branch"]
  E --> F["File signer"]
  E --> G["Future signers"]
  subgraph Legend
    direction LR
    _api(["API Spec"]) ~~~ _ctl(["Controller"]) ~~~ _mod(["Ensure helpers"]) ~~~ _pod(["PodSpec"]) 
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move HSM-specific init-container behavior out of generic helper
  • ➕ Keeps ensure.ReconcileInitContainers fully signer-agnostic
  • ➕ Avoids surprising HSM assumptions (volume names, lib-export container) for non-HSM backends
  • ➖ Requires additional PKCS11-specific scaffolding in the follow-up PR
  • ➖ Slightly more plumbing between shared and backend-specific code

Recommendation: The top-level, signer-agnostic fields on FulcioSpec/CTlogSpec are the right API shape because they avoid per-backend duplication and can be applied before signer branching (fixing file-mode gaps). The main architectural concern is that ReconcileInitContainers, while positioned as a shared helper, still contains HSM/PKCS#11-specific conventions (e.g., hsm volume mounts and optional hsm-lib-export). Consider moving that vendor-specific portion to backend-specific code in a follow-up to keep the shared helper generic.

Files changed (19) +6342 / -74

Enhancement (8) +240 / -0
common.goIntroduce InitContainerSpec for curated init container configuration +37/-0

Introduce InitContainerSpec for curated init container configuration

• Adds InitContainerSpec, a subset of corev1.Container fields intended for user-supplied init containers shared by Fulcio and CTlog.

api/v1/common.go

ctlog_types.goAdd InitContainers/Volumes/VolumeMounts to CTlogSpec and Auth to CTlogSigner +13/-0

Add InitContainers/Volumes/VolumeMounts to CTlogSpec and Auth to CTlogSigner

• Extends CTlogSpec with signer-agnostic pod customization fields and adds Auth to CTlogSigner for consistent credential injection across backends.

api/v1/ctlog_types.go

fulcio_types.goAdd InitContainers/Volumes/VolumeMounts to FulcioSpec and Auth to FulcioSigner +13/-0

Add InitContainers/Volumes/VolumeMounts to FulcioSpec and Auth to FulcioSigner

• Extends FulcioSpec with signer-agnostic pod customization fields and adds Auth to FulcioSigner to support uniform credential injection.

api/v1/fulcio_types.go

ctlog_conversion.goPreserve new CTlog fields via restored MarshalData on conversion +4/-0

Preserve new CTlog fields via restored MarshalData on conversion

• Restores InitContainers/Volumes/VolumeMounts and Signer.Auth from stored marshal data when converting v1alpha1 -> v1.

api/v1alpha1/ctlog_conversion.go

fulcio_conversion.goPreserve new Fulcio fields via restored MarshalData on conversion +4/-0

Preserve new Fulcio fields via restored MarshalData on conversion

• Restores InitContainers/Volumes/VolumeMounts and Signer.Auth from stored marshal data when converting v1alpha1 -> v1.

api/v1alpha1/fulcio_conversion.go

securesign_conversion.goPreserve Fulcio/Ctlog signer extension fields in Securesign conversion +8/-0

Preserve Fulcio/Ctlog signer extension fields in Securesign conversion

• Restores the new extension fields for both Fulcio and Ctlog sub-specs when converting Securesign v1alpha1 -> v1.

api/v1alpha1/securesign_conversion.go

deployment.goApply generic pod extensions (initContainers/volumes/mounts/auth) to CTlog deployment +25/-0

Apply generic pod extensions (initContainers/volumes/mounts/auth) to CTlog deployment

• Reconciles user-provided init containers, volumes, volume mounts, and auth into the CTlog deployment template so they apply regardless of signer type.

internal/controller/ctlog/actions/deployment.go

pod_spec.goAdd shared PodSpec reconciliation helpers for volumes and init containers +136/-0

Add shared PodSpec reconciliation helpers for volumes and init containers

• Introduces HasVolume, HasMountPath, EnsureVolumeDefaultMode (prevents reconcile loops due to nil vs defaulted modes), and ReconcileInitContainers (upsert/remove by name; optional HSM lib-export behavior).

internal/utils/kubernetes/ensure/pod_spec.go

Bug fix (1) +2 / -1
securesign_defaults.goDefault signer types from Securesign umbrella CR +2/-1

Default signer types from Securesign umbrella CR

• Calls Fulcio.Signer.SetDefaults() and Ctlog.Signer.SetDefaults() from Securesign.SetDefaults() so signer.type is explicit on the parent CR.

api/v1/securesign_defaults.go

Refactor (1) +103 / -68
deployment.goRefactor Fulcio deployment scaffolding and apply generic pod extensions +103/-68

Refactor Fulcio deployment scaffolding and apply generic pod extensions

• Extracts ensureCommonDeployment for shared deployment setup, renames ensureDeployment to ensureFileCADeployment, and applies initContainers/volumes/mounts/auth before signer-specific logic so file mode also gets extensions.

internal/controller/fulcio/actions/deployment.go

Other (9) +5997 / -5
zz_generated.deepcopy.goRegenerate deepcopy implementations for new fields +108/-0

Regenerate deepcopy implementations for new fields

• Adds autogenerated DeepCopy support for InitContainerSpec and the new InitContainers/Volumes/VolumeMounts/Auth fields on Fulcio/CTlog types.

api/v1/zz_generated.deepcopy.go

conversion_roundtrip_test.goUpdate conversion fuzzers for v1-only signer extension fields +74/-1

Update conversion fuzzers for v1-only signer extension fields

• Adds fuzzer functions to nil out v1-only extension fields (initContainers/volumes/mounts/auth) that have no v1alpha1 counterpart, preventing false roundtrip failures.

api/v1alpha1/conversion_roundtrip_test.go

zz_generated.conversion.goRegenerate conversion warnings for new non-peer fields +6/-0

Regenerate conversion warnings for new non-peer fields

• Updates autogenerated conversion code to flag InitContainers/Volumes/VolumeMounts as manual-conversion fields (no peer type in v1alpha1).

api/v1alpha1/zz_generated.conversion.go

rhtas.redhat.com_ctlogs.yamlRegenerate CTlog CRD schema for new extension fields +2715/-0

Regenerate CTlog CRD schema for new extension fields

• Adds OpenAPI schema entries for initContainers and other new pod customization fields on CTlog.

config/crd/bases/rhtas.redhat.com_ctlogs.yaml

rhtas.redhat.com_fulcios.yamlRegenerate Fulcio CRD schema for new extension fields +2715/-0

Regenerate Fulcio CRD schema for new extension fields

• Adds OpenAPI schema entries for initContainers and other new pod customization fields on Fulcio.

config/crd/bases/rhtas.redhat.com_fulcios.yaml

kustomization.yamlUpdate manager image reference in kustomization +3/-3

Update manager image reference in kustomization

• Adjusts the controller image name/tag settings for the manager kustomization.

config/manager/kustomization.yaml

rhtas-operator.clusterserviceversion.yamlAdd v1alpha1 owned resource entries to CSV +35/-0

Add v1alpha1 owned resource entries to CSV

• Adds v1alpha1 versions for multiple owned CRDs to the CSV to address previous duplication/omissions.

config/manifests/bases/rhtas-operator.clusterserviceversion.yaml

fulcio_deployment_test.goTest that user-defined volumes/mounts are applied in Fulcio file mode +84/-1

Test that user-defined volumes/mounts are applied in Fulcio file mode

• Adds a regression test ensuring Volumes/VolumeMounts are honored even when Fulcio uses file signer mode, and updates references to the renamed ensure function.

internal/controller/fulcio/actions/fulcio_deployment_test.go

pod_spec_test.goAdd unit tests for pod_spec helpers +257/-0

Add unit tests for pod_spec helpers

• Covers HasVolume, EnsureVolumeDefaultMode across supported volume sources, and ReconcileInitContainers behaviors including pruning stale containers and adding the optional lib-export init container.

internal/utils/kubernetes/ensure/pod_spec_test.go

@codecov-commenter

codecov-commenter commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 47.10425% with 137 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.38%. Comparing base (9da68a1) to head (2ee5264).

Files with missing lines Patch % Lines
api/v1/zz_generated.deepcopy.go 3.66% 102 Missing and 3 partials ⚠️
internal/utils/kubernetes/ensure/pod_spec.go 71.69% 13 Missing and 2 partials ⚠️
api/v1/common.go 0.00% 11 Missing ⚠️
...l/utils/kubernetes/ensure/deployment/deployment.go 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2175      +/-   ##
==========================================
- Coverage   56.71%   56.38%   -0.33%     
==========================================
  Files         285      285              
  Lines       16168    16365     +197     
==========================================
+ Hits         9169     9228      +59     
- Misses       6046     6178     +132     
- Partials      953      959       +6     
Flag Coverage Δ
e2e 68.22% <100.00%> (+0.03%) ⬆️
unit 36.85% <45.17%> (+0.27%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@qodo-for-securesign

qodo-for-securesign Bot commented Jul 31, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. InitContainers never cleared ✓ Resolved 🐞 Bug ☼ Reliability
Description
Fulcio and CTlog only call ReconcileInitContainers when len(spec.initContainers) > 0, so
removing spec.initContainers from the CR will not remove previously-applied init containers from
the Deployment. This makes initContainers sticky and breaks declarative reconciliation.
Code

internal/controller/fulcio/actions/deployment.go[R146-149]

+	// Apply user-defined init containers
+	if len(instance.Spec.InitContainers) > 0 {
+		ensure.ReconcileInitContainers(&template.Spec, instance.Spec.InitContainers, "")
+	}
Relevance

●●● Strong

Sticky initContainers breaks declarative reconciliation; team often accepts controller reliability
hardening.

PR-#1928

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both controllers gate the call on len(initContainers) > 0 while the helper explicitly supports
clearing when the desired set is empty.

internal/controller/fulcio/actions/deployment.go[146-149]
internal/controller/ctlog/actions/deployment.go[152-155]
internal/utils/kubernetes/ensure/pod_spec.go[183-187]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Init container reconciliation is guarded by `len(...) > 0`, preventing cleanup when the user removes `spec.initContainers`.

### Issue Context
`ensure.ReconcileInitContainers()` already contains explicit logic to clear `podSpec.InitContainers` when the desired list is empty, but that branch is unreachable due to the controller guards.

### Fix Focus Areas
- internal/controller/fulcio/actions/deployment.go[146-149]
- internal/controller/ctlog/actions/deployment.go[152-155]
- internal/utils/kubernetes/ensure/pod_spec.go[183-187]

### Suggested fix
Call `ensure.ReconcileInitContainers(&template.Spec, instance.Spec.InitContainers, ...)` unconditionally (or at least whenever the CR field is present), so that empty/nil desired state triggers cleanup.
If you’re concerned about deleting operator-managed init containers, adjust `ReconcileInitContainers` to only manage a clearly owned subset (e.g., names with an operator prefix) instead of clearing all init containers when the desired list is empty.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. HSM mounts without volumes ✓ Resolved 🐞 Bug ≡ Correctness
Description
ReconcileInitContainers always injects volume mounts for hsm-tokens and hsm-lib into every user
init container, but Fulcio/CTlog only add volumes from spec.volumes. If a user sets
spec.initContainers without also defining those volumes, the resulting Pod template references
non-existent volumes and will be rejected by Kubernetes.
Code

internal/utils/kubernetes/ensure/pod_spec.go[R154-168]

+		// Build volume mounts: user-specified + operator-managed (skip duplicates by path).
+		mounts := append([]core.VolumeMount{}, spec.VolumeMounts...)
+		if !hasMountPath(mounts, hsmTokenMountPath) {
+			mounts = append(mounts, core.VolumeMount{
+				Name:      hsmTokensVolumeName,
+				MountPath: hsmTokenMountPath,
+			})
+		}
+		if !hasMountPath(mounts, hsmLibMountPath) {
+			mounts = append(mounts, core.VolumeMount{
+				Name:      hsmLibVolumeName,
+				MountPath: hsmLibMountPath,
+			})
+		}
+		c.VolumeMounts = mounts
Relevance

●●● Strong

Pod would be invalid if injected mounts reference missing volumes; concrete correctness issue likely
to be fixed.

PR-#1243

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The helper injects mounts named hsm-tokens/hsm-lib purely based on mountPath presence, but the
controllers only attach user-provided volumes; there’s no automatic creation of these volumes.

internal/utils/kubernetes/ensure/pod_spec.go[117-169]
internal/controller/fulcio/actions/deployment.go[146-156]
internal/controller/ctlog/actions/deployment.go[152-162]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ReconcileInitContainers()` unconditionally appends mounts that reference volumes `hsm-tokens` and `hsm-lib`. Fulcio/CTlog do not create those volumes automatically, so `spec.initContainers` can produce an invalid PodSpec (volumeMount refers to missing volume).

### Issue Context
This helper is used for the new generic initContainer extension path in Fulcio and CTlog.

### Fix Focus Areas
- internal/utils/kubernetes/ensure/pod_spec.go[154-168]
- internal/controller/fulcio/actions/deployment.go[146-156]
- internal/controller/ctlog/actions/deployment.go[152-162]

### Suggested fix
Choose one:
1) Only inject the `hsm-*` mounts when the corresponding volumes already exist on the PodSpec (or when `modulePath` is non-empty / HSM mode explicitly enabled).
2) If the intent is “initContainers imply HSM”, then automatically create the required volumes (`hsm-tokens`, `hsm-lib`) when reconciling initContainers (e.g., EmptyDir for `hsm-lib`, and require/validate a PVC/volume for `hsm-tokens`).
Also consider validating/rejecting configs where initContainers are set but required volumes are missing, to fail early with a clear error.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Reserved volume name collision ✓ Resolved 🐞 Bug ≡ Correctness
Description
User-defined volumes/mounts are upserted by name and can overwrite operator-required ones. In CTlog,
a user volume named keys overwrites the operator’s keys Secret volume and can break the required
/ctfe-keys mount; in Fulcio, user-supplied VolumeSource for fulcio-config/fulcio-cert can
later be combined with operator-set sources, producing invalid volumes with multiple sources set.
Code

internal/controller/ctlog/actions/deployment.go[R157-170]

+		// Apply user-defined volumes
+		for _, vol := range instance.Spec.Volumes {
+			v := kubernetes.FindVolumeByNameOrCreate(&template.Spec, vol.Name)
+			v.VolumeSource = vol.VolumeSource
+			ensure.EnsureVolumeDefaultMode(v)
+		}
+
+		// Apply user-defined volume mounts
+		for _, vm := range instance.Spec.VolumeMounts {
+			m := kubernetes.FindVolumeMountByNameOrCreate(container, vm.Name)
+			m.MountPath = vm.MountPath
+			m.SubPath = vm.SubPath
+			m.ReadOnly = vm.ReadOnly
+		}
Relevance

●● Moderate

Real correctness risk, but may conflict with intended “user override” customization; no close
precedent found.

PR-#1243

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
CTlog creates a keys Secret volume and mounts it, but the new loop later assigns `v.VolumeSource =
vol.VolumeSource` by name and user mounts can overwrite by name. Fulcio applies user volumes by
assigning the whole VolumeSource, then later sets individual sources like ConfigMap/Projected
without clearing other fields, enabling multi-source invalid volumes on name collisions.

internal/controller/ctlog/actions/deployment.go[117-122]
internal/controller/ctlog/actions/deployment.go[148-150]
internal/controller/ctlog/actions/deployment.go[157-170]
internal/controller/fulcio/actions/deployment.go[151-156]
internal/controller/fulcio/actions/deployment.go[279-288]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new extension reconciliation upserts volumes/mounts purely by name, allowing users to collide with operator-managed names.
- CTlog: user `spec.volumes[].name: keys` overwrites the operator-created Secret-backed `keys` volume (required for `/ctfe-keys`).
- Fulcio: user volumes are applied first by assigning `v.VolumeSource = vol.VolumeSource`, then the operator later sets `config.ConfigMap` / `cert.Projected` without clearing other VolumeSource fields; a colliding user volume can result in multiple volume source fields being set (invalid PodSpec).

### Issue Context
This is enabled by the new generic `spec.volumes` / `spec.volumeMounts` fields.

### Fix Focus Areas
- internal/controller/ctlog/actions/deployment.go[117-122]
- internal/controller/ctlog/actions/deployment.go[157-170]
- internal/controller/fulcio/actions/deployment.go[151-164]
- internal/controller/fulcio/actions/deployment.go[279-288]

### Suggested fix
1) Define a reserved-name set per component (e.g., CTlog: `keys`; Fulcio: `fulcio-config`, `fulcio-cert`, `oidc-info`, etc.).
2) When applying user volumes/mounts, **reject** (return error) or **skip** entries that collide with reserved names.
3) Additionally, when operator configures its own volumes, consider resetting the entire `VolumeSource` (or explicitly clearing other source fields) to guarantee only one source type is set.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Auth config cannot be removed ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new signer auth extension is only applied when non-nil, and ensure.ContainerAuth only adds
env/secret mounts without any cleanup path. Clearing spec.signer.auth later will leave stale auth
volume/mount (and potentially env vars) in the Deployment.
Code

internal/controller/fulcio/actions/deployment.go[R166-169]

+	// Apply auth env vars and secret mounts
+	if auth := instance.Spec.Signer.Auth; auth != nil {
+		ensure.ContainerAuth(container, auth)(&template.Spec)
+	}
Relevance

●●● Strong

Stale auth mounts/env after clearing spec is a clear reconcile bug; similar upgrade/self-heal fixes
were accepted.

PR-#1928

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Controllers only call ContainerAuth when auth is non-nil, and the helper has no branch that
removes the projected volume or mount when auth is nil.

internal/controller/fulcio/actions/deployment.go[166-169]
internal/controller/ctlog/actions/deployment.go[172-175]
internal/utils/kubernetes/ensure/auth.go[22-45]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ContainerAuth()` mutates the PodSpec only when `auth != nil` and never removes the auth volume/mount when `auth` is cleared, making the new `spec.signer.auth` effectively sticky.

### Issue Context
The `auth` volume name is fixed (`auth`), so cleanup can be ownership-safe at least for the volume and mount.

### Fix Focus Areas
- internal/controller/fulcio/actions/deployment.go[166-169]
- internal/controller/ctlog/actions/deployment.go[172-175]
- internal/utils/kubernetes/ensure/auth.go[22-45]

### Suggested fix
- Update `ensure.ContainerAuth` so that when `auth == nil` it removes the `auth` volume mount and the `auth` volume (using existing helpers `RemoveVolumeMountByName` / `RemoveVolumeByName`).
- Consider also removing previously-added env vars in an ownership-safe way (e.g., track managed env var names in an annotation, or only remove env vars that match a recorded prior desired set).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/utils/kubernetes/ensure/pod_spec.go Outdated
Comment thread internal/controller/fulcio/actions/deployment.go Outdated
Comment thread internal/controller/ctlog/actions/deployment.go Outdated
@sampras343 sampras343 changed the title feat: add generic signer extensions — InitContainers, Volumes, Auth feat: add generic signer extensions Jul 31, 2026
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from bbd4fb6 to 6f9e6c1 Compare July 31, 2026 12:43
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from 6f9e6c1 to ac30fc2 Compare August 4, 2026 08:20
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch 2 times, most recently from b2e9985 to 92cf893 Compare August 4, 2026 11:43
@sampras343
sampras343 changed the base branch from main to sachin/fix/trillian-logsigner-conditions August 4, 2026 11:43
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from 92cf893 to 27b64a4 Compare August 4, 2026 12:55
@sampras343 sampras343 changed the title feat: add generic signer extensions feat: add InitContainers, Volumes, VolumeMounts for Fulcio and CTLog Aug 4, 2026
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from 27b64a4 to 9315a79 Compare August 4, 2026 14:22
@sampras343
sampras343 requested a review from osmman August 4, 2026 16:03
@sampras343

Copy link
Copy Markdown
Member Author

/retest

1 similar comment
@sampras343

Copy link
Copy Markdown
Member Author

/retest

@osmman osmman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user pod-resource logic (ReconcileUserPodResources) is nested inside ensureFileCADeployment/ensureCommonDeployment. It should be its own entry in the CreateOrUpdate(...) list, split from the base deployment and from the signer-specific part:

kubernetes.CreateOrUpdate(ctx, i.Client, dp,
    i.ensureDeployment(instance, RBACName, labels),   // generic: replicas, selector, labels, SA, ports, probes
    i.ensureFileSigner(instance),                     // file-CA specific: args, cert/config/oidc volumes+mounts
    deployment.PodResources(instance.Spec.InitContainers, instance.Spec.Volumes,
        instance.Spec.VolumeMounts, containerName),
    ensure.ControllerReference[*v1.Deployment](instance, i.Client),
    ensure.Labels[*v1.Deployment](...),
    deployment.PodRequirements(instance.Spec.PodRequirements, containerName),
    deployment.PodSecurityContext(),
)

Reason: whatever the user sets in Spec.InitContainers/Volumes/VolumeMounts should just get applied to the deployment — the ensure function has no business knowing which signer is active. And since it's generic, the same fields and the same PodResources trait belong on Rekor, TSA, and TUF too, not something reimplemented per component. Nesting it in Fulcio's file-CA function blocks all of that.

Same applies to CTLog's ensureDeployment.

@sampras343

sampras343 commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@osmman Addressed in 0af195e.

ReconcileUserPodResources is now extracted from ensureCommonDeployment/ensureDeployment into a standalone deployment.PodResources(...) ensure function, placed in the CreateOrUpdate chain alongside PodRequirements, Proxy, etc.:

kubernetes.CreateOrUpdate(ctx, i.Client, dp,
    deployment.PodResources(instance.Spec.InitContainers,
        instance.Spec.Volumes, instance.Spec.VolumeMounts, containerName),
    i.ensureFileCADeployment(instance, RBACName, labels),
    ensure.ControllerReference[*v1.Deployment](instance, i.Client),
    ensure.Labels[*v1.Deployment](...),
    deployment.PodRequirements(...),
    deployment.PodSecurityContext(),
    ...
)

The inner ensureCommonDeployment (Fulcio) and ensureDeployment (CTLog) no longer touch user-defined init containers, volumes, or volume mounts — they only handle component-specific scaffolding (replicas, selector, ports, probes, signer-specific args/volumes).

PodResources is placed before the signer-specific function so operator-managed volumes always win on name collision. The function lives in internal/utils/kubernetes/ensure/deployment/ — ready for Rekor, TSA, and TUF to adopt (if needed).

@sampras343
sampras343 requested a review from osmman August 5, 2026 11:26
@sampras343
sampras343 changed the base branch from sachin/fix/trillian-logsigner-conditions to main August 5, 2026 12:39
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from 0af195e to f60f363 Compare August 5, 2026 12:40
@sampras343

Copy link
Copy Markdown
Member Author

/retest

1 similar comment
@sampras343

Copy link
Copy Markdown
Member Author

/retest

@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch 2 times, most recently from 5c4badc to 79aa923 Compare August 5, 2026 18:07
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch 2 times, most recently from 2e02efb to 5411254 Compare August 11, 2026 06:58
Comment thread internal/utils/kubernetes/ensure/pod_spec.go Outdated
Comment thread api/v1/common.go
Comment thread api/v1/ctlog_types.go Outdated
Comment thread api/v1/fulcio_types.go Outdated
Comment thread api/v1/common.go
@sampras343

Copy link
Copy Markdown
Member Author

Addressing all review comments from @bouskaJ in commit 888a83d:

  1. VolumeMount drops fields (pod_spec.go:119) — Fixed. ReconcileUserPodResources now assigns the whole VolumeMount struct instead of field-by-field copy, preserving SubPathExpr, MountPropagation, and RecursiveReadOnly.

  2. Missing SSA markers (common.go:289) — Fixed. Added +listType=map / +listMapKey=name on all list fields: InitContainers, Volumes, VolumeMounts (on PodExtensions) and Env, VolumeMounts (on InitContainerSpec).

  3. Group into reusable struct (ctlog_types.go:77) — Done. Introduced PodExtensions struct in common.go with json:",inline" embedding — same pattern as PodRequirements. JSON paths remain unchanged (spec.initContainers, not spec.podExtensions.initContainers). Ready to embed in Rekor/TSA/TUF when those components adopt it.

  4. Raw core.Volume schema bloat (fulcio_types.go:46) — Done. Introduced AdditionalVolume / AdditionalVolumeSource restricting volume sources to Secret, ConfigMap, EmptyDir, PVC, CSI, and Projected. Includes CEL validation ensuring at least one source is set. CRD schema reduced by ~7400 lines. ToVolume() converter handles the ensure layer translation.

  5. Add restartPolicy for native sidecars (common.go:271) — Done. Added RestartPolicy *core.ContainerRestartPolicy with +kubebuilder:validation:Enum=Always to InitContainerSpec. Wired into ReconcileInitContainers. Setting restartPolicy: Always on an init container creates a native sidecar (Kubernetes 1.29+).

All changes tested on OCP 4.22 — stack deployed in file mode, cosign sign + verify passed.

@sampras343

Copy link
Copy Markdown
Member Author

@osmman — Your review comment about extracting ReconcileUserPodResources into a standalone deployment.PodResources(...) ensure function was addressed in commit 5411254.

With 888a83d, the signature is further simplified — PodResources now takes a single PodExtensions struct (matching the PodRequirements pattern):

deployment.PodResources(instance.Spec.PodExtensions, containerName),

Both Fulcio and CTLog use identical call sites in their CreateOrUpdate chains, fully decoupled from signer-specific logic.

sampras343 and others added 3 commits August 11, 2026 11:36
Add signer-agnostic pod customization fields to FulcioSpec and CTlogSpec,
enabling users to inject init containers, volumes, and volume mounts
regardless of which signer backend is active.

API changes:
- InitContainerSpec in common.go — curated corev1.Container subset
- InitContainers, Volumes, VolumeMounts on FulcioSpec and CTlogSpec

Controller changes:
- User-defined resources applied in shared deployment path before signer
  type branching
- CTLog operator-managed "keys" volume set after user volumes so operator
  always wins on reserved names
- Shared helpers: HasVolume, EnsureVolumeDefaultMode, ReconcileInitContainers
- Fulcio ensureCommonDeployment extracted for shared scaffolding

Housekeeping:
- Remove dead HasMountPath function
- v1alpha1 conversion preserves new fields via MarshalData annotations
- Roundtrip fuzzer coverage for new fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

Move user pod-resource reconciliation (InitContainers, Volumes,
VolumeMounts) from inside ensureCommonDeployment/ensureDeployment
into a standalone deployment.PodResources() ensure function in
the CreateOrUpdate chain.

This makes the user pod-resource logic signer-agnostic and
composable — the same PodResources ensure function can be reused
by Rekor, TSA, and TUF without reimplementation per component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Sachin Sampras M <sampras343@gmail.com>
Address review feedback from bouskaJ:

1. VolumeMount reconciliation now assigns the whole struct instead of
   copying fields individually, preserving SubPathExpr, MountPropagation,
   and RecursiveReadOnly.

2. Add +listType=map / +listMapKey=name SSA markers on InitContainers,
   Volumes, VolumeMounts, and Env fields for server-side apply support.

3. Group InitContainers, Volumes, and VolumeMounts into a reusable
   PodExtensions struct embedded with json:",inline". This enables
   adding the same fields to Rekor, TSA, and TUF without duplication.

4. Replace raw core.Volume with AdditionalVolume, restricting volume
   sources to Secret, ConfigMap, EmptyDir, PVC, CSI, and Projected.
   This reduces CRD OpenAPI schema by ~7400 lines and prevents users
   from specifying unsupported cloud-provider volume types.

5. Add restartPolicy field to InitContainerSpec with Enum=Always
   validation, enabling native sidecar containers (Kubernetes 1.29+).

Tested on OCP 4.22 in file mode with cosign sign/verify.

Signed-off-by: Sachin Sampras M <sampras343@gmail.com>
@sampras343
sampras343 force-pushed the sachin/feat/generic-signer-extensions branch from 888a83d to 2ee5264 Compare August 11, 2026 10:45
@sampras343
sampras343 requested a review from bouskaJ August 11, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants