Skip to content

Conversation

@fghanmi
Copy link
Member

@fghanmi fghanmi commented Oct 30, 2025

This PR updates the Rekor monitor to work with the latest Rekor Monitor image and integrate TUF repository awareness and readiness:

  • Rekor Monitor StatefulSet:

    • Adds TUF integration: passes --tuf-repository (TUF service URL) and --tuf-root-path to the monitor command, sets HOME to the mounted data path, and mounts a persistent volume at /data.
    • Introduces an init container (tuf-init) that waits for the TUF service to be available and downloads root.json into the mounted volume before the monitor starts.
    • Refactors constants and mount paths (mountPath = /data) and prepares a dedicated volume name for a TUF repository mount (tuf-repository constant), though only the storage volume is mounted in this diff.
  • E2E tests:

    • Shift test setup to use a full Securesign stack (tas.VerifyAllComponents), enabling Rekor monitor via the Securesign CR, rather than managing Trillian/Rekor CRs individually.
    • Update log expectation for empty log behavior to the new message (“skipping write of checkpoint: size is 0”).
    • Adjust references to the Securesign resource name where needed.
  • Images and dependencies:

    • Bump RELATED_IMAGE_REKOR_MONITOR and RELATED_IMAGE_TUF to newer digests.
    • Minor dependency alignment in go.mod/go.sum (e.g., OpenShift API and other indirect deps).

Overall, it enables cross-component TUF usage by Rekor monitor (waiting for TUF readiness and consuming TUF root), aligns tests with the new behavior, and updates images to the latest versions.

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 30, 2025

Reviewer's Guide

This PR enhances CRDs with EnvFiles support (fileKeyRef), introduces a ConfigMap-based PVC reference for TUF (with new API fields, constants, and controller action), and updates the Rekor monitor StatefulSet to retrieve and mount the TUF PVC from that ConfigMap while adapting its init container.

Sequence diagram for Rekor monitor retrieving and mounting TUF PVC via ConfigMap

sequenceDiagram
    participant RekorMonitor
    participant K8sAPI
    participant TUF_PVC_ConfigMap
    participant TUF_PVC
    RekorMonitor->>K8sAPI: Get TUF_PVC_ConfigMap
    K8sAPI-->>RekorMonitor: Return pvcName
    RekorMonitor->>K8sAPI: Mount PVC (using pvcName)
    K8sAPI-->>RekorMonitor: PVC mounted as /tuf-repository
Loading

Entity relationship diagram for updated TUF and Rekor CRDs

erDiagram
    TufStatus {
        string PvcName
        string Url
        LocalObjectReference PvcConfig
    }
    LocalObjectReference {
        string Name
    }
    TufStatus ||--|{ LocalObjectReference : "pvcConfig"

    RekorEnvVarSource {
        string key
        boolean optional
        string path
        string volumeName
    }
    RekorEnvVarSource }|--|| LocalObjectReference : "volumeName"
Loading

Class diagram for new and updated TUF controller types

classDiagram
    class TufStatus {
        +[]TufKey Keys
        +string PvcName
        +LocalObjectReference PvcConfig
        +string Url
    }
    class LocalObjectReference {
        +string Name
    }
    TufStatus --> LocalObjectReference : PvcConfig

    class pvcConfigAction {
        +Name() string
        +CanHandle(ctx, instance) bool
        +Handle(ctx, instance) *action.Result
    }
    pvcConfigAction --|> BaseAction
Loading

File-Level Changes

Change Details Files
Extend CRDs with fileKeyRef and pvcConfig fields
  • Add fileKeyRef schema block (key, optional, path, volumeName) in rhtas.redhat.com_securesigns.yaml at three locations
  • Add pvcConfig LocalObjectReference to rhtas.redhat.com_tufs.yaml
config/crd/bases/rhtas.redhat.com_securesigns.yaml
config/crd/bases/rhtas.redhat.com_tufs.yaml
Introduce TUF PVC ConfigMap support in API and controller
  • Add PvcConfig field to TufStatus and update API types
  • Define TufPvcConfigName constant
  • Implement NewPvcConfigAction to create/update the PVC ConfigMap
  • Insert pvcConfigAction into tuf_controller reconcile sequence
api/v1alpha1/tuf_types.go
internal/controller/tuf/constants/constants.go
internal/controller/tuf/tuf_controller.go
internal/controller/tuf/actions/tuf_pvc_config.go
Modify Rekor monitor StatefulSet to use TUF PVC ConfigMap
  • Refactor ensureMonitorStatefulSet signature to accept context
  • Fetch the TUF PVC ConfigMap, extract pvcName, and configure volume & mount
  • Update init container to wait for TUF service instead of Rekor
internal/controller/rekor/actions/monitor/statefulset.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@qodo-merge-pro
Copy link

qodo-merge-pro bot commented Oct 30, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
ConfigMap trust and PVC mount

Description: The code reads the PVC name from a ConfigMap and mounts a PVC into the Rekor monitor pod
without validating that the PVC is intended for read-only sharing across components, which
could risk unauthorized access if the ConfigMap is tampered or misconfigured.
statefulset.go [149-171]

Referred Code
var cm coreV1.ConfigMap
if err := i.Client.Get(ctx, types.NamespacedName{
	Namespace: instance.Namespace,
	Name:      tufConstants.TufPvcConfigName,
}, &cm); err != nil {
	return fmt.Errorf("failed to get TUF PVC ConfigMap: %w", err)
}
pvcName, ok := cm.Data["pvcName"]
if !ok || pvcName == "" {
	return fmt.Errorf("PVC name not found in ConfigMap %q", tufConstants.TufPvcConfigName)
}

tufRepositoryVolume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, tufRepoVolumeName)
if tufRepositoryVolume.PersistentVolumeClaim == nil {
	tufRepositoryVolume.PersistentVolumeClaim = &coreV1.PersistentVolumeClaimVolumeSource{}
}
tufRepositoryVolume.PersistentVolumeClaim.ClaimName = pvcName
tufRepositoryVolume.PersistentVolumeClaim.ReadOnly = true

tufVolumeMount := kubernetes.FindVolumeMountByNameOrCreate(container, tufRepoVolumeName)
tufVolumeMount.MountPath = "/tuf-repository"


 ... (clipped 2 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing nil checks: The code assumes the ConfigMap exists and contains 'pvcName' and fails hard
without fallback or requeue hints, lacking edge-case handling and actionable context.

Referred Code
var cm coreV1.ConfigMap
if err := i.Client.Get(ctx, types.NamespacedName{
	Namespace: instance.Namespace,
	Name:      tufConstants.TufPvcConfigName,
}, &cm); err != nil {
	return fmt.Errorf("failed to get TUF PVC ConfigMap: %w", err)
}
pvcName, ok := cm.Data["pvcName"]
if !ok || pvcName == "" {
	return fmt.Errorf("PVC name not found in ConfigMap %q", tufConstants.TufPvcConfigName)
}

tufRepositoryVolume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, tufRepoVolumeName)
if tufRepositoryVolume.PersistentVolumeClaim == nil {
	tufRepositoryVolume.PersistentVolumeClaim = &coreV1.PersistentVolumeClaimVolumeSource{}
}
tufRepositoryVolume.PersistentVolumeClaim.ClaimName = pvcName
tufRepositoryVolume.PersistentVolumeClaim.ReadOnly = true

tufVolumeMount := kubernetes.FindVolumeMountByNameOrCreate(container, tufRepoVolumeName)
tufVolumeMount.MountPath = "/tuf-repository"


 ... (clipped 1 lines)
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit logs: New actions create/update a ConfigMap and update status without emitting structured audit
logs of the operation, user/actor, and outcome.

Referred Code
if _, err := kubernetes.CreateOrUpdate(ctx, i.Client,
	configMap,
	ensure.ControllerReference[*corev1.ConfigMap](instance, i.Client),
	kubernetes.EnsureConfigMapData(true, data),
); err != nil {
	return i.Error(ctx, fmt.Errorf("could not create TUF PVC config: %w", err), instance)
}

i.Logger.Info("TUF PVC ConfigMap ensured", "name", configMap.Name, "pvcName", instance.Status.PvcName)

instance.Status.PvcConfig = &rhtasv1alpha1.LocalObjectReference{Name: configMap.Name}
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
	Type:    constants.Ready,
	Status:  metav1.ConditionFalse,
	Reason:  constants.Creating,
	Message: "TUF PVC Config created",
})

return i.StatusUpdate(ctx, instance)
Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured logging: The added log uses free-form text and may not adhere to structured logging requirements,
and no explicit safeguards against sensitive data in logs are shown.

Referred Code
i.Logger.Info("TUF PVC ConfigMap ensured", "name", configMap.Name, "pvcName", instance.Status.PvcName)
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
External input trust: The code trusts 'pvcName' from a ConfigMap without validating allowed
characters/length, which could lead to invalid volume mounts if misconfigured.

Referred Code
pvcName, ok := cm.Data["pvcName"]
if !ok || pvcName == "" {
	return fmt.Errorf("PVC name not found in ConfigMap %q", tufConstants.TufPvcConfigName)
}

tufRepositoryVolume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, tufRepoVolumeName)
if tufRepositoryVolume.PersistentVolumeClaim == nil {
	tufRepositoryVolume.PersistentVolumeClaim = &coreV1.PersistentVolumeClaimVolumeSource{}
}
tufRepositoryVolume.PersistentVolumeClaim.ClaimName = pvcName
tufRepositoryVolume.PersistentVolumeClaim.ReadOnly = true

tufVolumeMount := kubernetes.FindVolumeMountByNameOrCreate(container, tufRepoVolumeName)
tufVolumeMount.MountPath = "/tuf-repository"
tufVolumeMount.ReadOnly = true
  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link

qodo-merge-pro bot commented Oct 30, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Consider a simpler resource discovery method

Instead of using a ConfigMap to share the TUF PVC name, the Rekor controller
should discover it by directly reading the status field of the TUF custom
resource. This simplifies the design by removing the intermediate ConfigMap and
its management logic.

Examples:

internal/controller/tuf/actions/tuf_pvc_config.go [1-77]
package actions

import (
	"context"
	"fmt"

	rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1"
	"github.com/securesign/operator/internal/action"
	"github.com/securesign/operator/internal/constants"
	tufConstants "github.com/securesign/operator/internal/controller/tuf/constants"

 ... (clipped 67 lines)
internal/controller/rekor/actions/monitor/statefulset.go [149-159]
		var cm coreV1.ConfigMap
		if err := i.Client.Get(ctx, types.NamespacedName{
			Namespace: instance.Namespace,
			Name:      tufConstants.TufPvcConfigName,
		}, &cm); err != nil {
			return fmt.Errorf("failed to get TUF PVC ConfigMap: %w", err)
		}
		pvcName, ok := cm.Data["pvcName"]
		if !ok || pvcName == "" {
			return fmt.Errorf("PVC name not found in ConfigMap %q", tufConstants.TufPvcConfigName)

 ... (clipped 1 lines)

Solution Walkthrough:

Before:

// In tuf_controller.go
// Action chain includes creating a ConfigMap
...
actions.NewDeployAction(),
actions.NewPvcConfigAction(), // Creates a ConfigMap with PVC name
actions.NewServiceAction(),
...

// In rekor/actions/monitor/statefulset.go
// Rekor controller reads the ConfigMap
var cm coreV1.ConfigMap
if err := i.Client.Get(ctx, ..., "tuf-pvc-config", &cm); err != nil {
    return err
}
pvcName, ok := cm.Data["pvcName"]
// ... use pvcName to mount volume

After:

// In tuf_controller.go
// Action chain no longer needs to create a ConfigMap
...
actions.NewDeployAction(),
// actions.NewPvcConfigAction() is removed
actions.NewServiceAction(),
...

// In rekor/actions/monitor/statefulset.go
// Rekor controller reads the Tuf CR status directly
var tuf rhtasv1alpha1.Tuf
// Logic to find and get the Tuf instance in the namespace
if err := i.Client.Get(ctx, ..., &tuf); err != nil {
    return err
}
pvcName := tuf.Status.PvcName
// ... use pvcName to mount volume
Suggestion importance[1-10]: 9

__

Why: This is a significant architectural suggestion that simplifies the design by removing an intermediate ConfigMap, which reduces complexity and potential failure points, aligning with common Kubernetes operator patterns.

High
Possible issue
Make init container wait robust

Add the -sf flags to the curl command in the init container to ensure it
correctly waits for the TUF service to be ready and fails on HTTP errors.

internal/controller/rekor/actions/monitor/statefulset.go [184]

-fmt.Sprintf(`until curl %s > /dev/null 2>&1; do echo 'Waiting for tuf to be ready...'; sleep 5; done`, tufHost),
+fmt.Sprintf(`until curl -sf %s > /dev/null 2>&1; do echo 'Waiting for tuf to be ready...'; sleep 5; done`, tufHost),
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a regression where the -sf flags were removed from the curl command, which would cause the init container to exit prematurely on HTTP errors, breaking the dependency check.

High
Use a dedicated status condition

Use a dedicated status condition type, like PvcConfigReady, instead of
incorrectly resetting the main Ready condition to False when the PVC ConfigMap
is created.

internal/controller/tuf/actions/tuf_pvc_config.go [69-74]

 meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
-	Type:    constants.Ready,
-	Status:  metav1.ConditionFalse,
-	Reason:  constants.Creating,
+	Type:    "PvcConfigReady",
+	Status:  metav1.ConditionTrue,
+	Reason:  "Created",
 	Message: "TUF PVC Config created",
 })
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that resetting the Ready condition to False is incorrect and can cause status flapping, proposing a better practice of using a dedicated condition type.

Medium
  • Update

@fghanmi fghanmi force-pushed the SECURESIGN-3179 branch 2 times, most recently from 3014d45 to 5094224 Compare October 31, 2025 15:07
@fghanmi fghanmi changed the title [In progress] [SECURESIGN-3179] create TUF PVC configMap and use it in Rekor monitor statefulSet [SECURESIGN-3179] Updates to use the latest Rekor Monitor Nov 2, 2025
@securesign securesign deleted a comment from qodo-merge-pro bot Nov 4, 2025
@osmman osmman added the enhancement New feature or request label Nov 6, 2025
)

rekorServerHost := fmt.Sprintf("http://%s.%s.svc", actions.ServerComponentName, instance.Namespace)
tufServerHost := fmt.Sprintf("http://%s.%s.svc", tufConstants.ComponentName, instance.Namespace)
Copy link
Collaborator

@osmman osmman Nov 18, 2025

Choose a reason for hiding this comment

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

This will be problem, we cannot expect that Rekor server and Tuf server is running in same namespace. We already have test case for it where every main services are running in their separate namespace.

https://github.com/securesign/secure-sign-operator/blob/main/test/e2e/namespaced.go

Copy link
Member Author

Choose a reason for hiding this comment

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

you're right! I added TufService and used the same logic as other components.

@securesign securesign deleted a comment from qodo-merge-pro bot Nov 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Review effort 3/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants