Skip to content

Conversation

@Rizwana777
Copy link
Collaborator

@Rizwana777 Rizwana777 commented Oct 30, 2025

JIRA - https://issues.redhat.com/browse/GITOPS-7958
Commands implemented via cobra

Implemented check-config with principal and agent subcommands

Principal: requires --principal-namespace; --principal-context is available and optional.

Agent: requires all four flags (--agent-context, --agent-namespace, --principal-context, --principal-namespace).

Principal checks implemented:
Verify CA secret exists and is valid: argocd-agent-ca
Verify principal gRPC TLS secret exists and is valid: argocd-agent-principal-tls
Verify resource proxy TLS secret exists and is valid: argocd-agent-resource-proxy-tls
Verify JWT signing key secret exists and parses: argocd-agent-jwt
Argo CD cluster-scoped, apps-any-namespace, OpenShift Route host matches IPS/DNS.

Agent checks implemented:
Verify agent CA secret with ca.crt exists: argocd-agent-ca
Verify agent client TLS secret exists, not expired, and signed by principal CA: argocd-agent-client-tls
Verify a namespace on principal matches agent cert CN (e.g., CN jonathans-cluster => namespace jonathans-cluster)
Also runs all principal checks (above) using provided principal context/namespace

Steps to verify this -
make setup-e2e
make cli
principal -
argocd-agentctl check-config principal --principal-namespace argocd --principal-context

agent -
argocd-agentctl check-config agent --agent-context --agent-namespace argocd --principal-context --principal-namespace argocd

Summary by CodeRabbit

  • New Features

    • Added a check-config CLI with principal and agent modes to validate cluster and cross-cluster configuration: Argo CD scope, TLS/CA and JWT key validity, certificate signing and expiration, route host/SAN alignment, and namespace presence; prints per-check results and exits on failures.
  • Tests

    • Added integration-style tests covering positive and negative TLS/CA, JWT, certificate signing/expiration, route/SAN, and namespace scenarios.

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Walkthrough

Adds a new check-config CLI command with principal and agent subcommands that run local and cross-cluster validations: detect Argo CD scope, read TLS/JWT secrets, parse and verify x509 certs (expiry/signature/SAN/CN), validate RSA JWT keys, check OpenShift Route SANs, aggregate per-check results and exit accordingly.

Changes

Cohort / File(s) Summary
Configuration validation CLI
cmd/ctl/check_config.go
New check-config command and subcommands (NewCheckConfigCommand, NewCheckConfigPrincipalCommand, NewCheckConfigAgentCommand), plus RunPrincipalChecks and RunAgentChecks. Implements Argo CD scope detection, secret/CR retrieval (with CR overrides/defaults), x509/TLS parsing and expiry/signature/SAN/CN checks, RSA JWT key parsing, OpenShift Route SAN checks, cross-cluster certificate verification, unified per-check rendering and exit semantics.
Tests
cmd/ctl/check_config_test.go
New tests (TestCheckConfigPrincipal, TestCheckConfigAgent) with PKI helpers (create TLS secrets, expired certs, CA-signed variants, empty CN). Uses fake Kubernetes/dynamic clients and fake discovery to simulate Argo CD CRs and Route API presence; covers positive and many negative validation scenarios.
CLI registration
cmd/ctl/main.go
Registers the check-config command on the root CLI via AddCommand(NewCheckConfigCommand()).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User as U
    participant CLI as "argocd-agentctl:check-config"
    participant Principal as "Principal Cluster API"
    participant Agent as "Agent Cluster API"

    U->>CLI: check-config principal
    activate CLI
    CLI->>Principal: Detect Argo CD scope (CR or defaults)
    CLI->>Principal: Read CA, principal TLS, proxy TLS, JWT secrets
    CLI->>Principal: Parse certs/keys, verify expiry & signature, parse RSA JWT key
    alt Route API present
        CLI->>Principal: Fetch Route(s), verify host in TLS SANs
    end
    CLI-->>U: Print aggregated results & exit
    deactivate CLI

    U->>CLI: check-config agent
    activate CLI
    CLI->>Agent: Read agent TLS/CA secrets, parse cert (CN/expiry)
    CLI->>Principal: Fetch principal CA (cross-cluster)
    CLI->>Agent: Verify agent cert signed by principal CA, check principal namespace presence
    CLI-->>U: Print aggregated results & exit
    deactivate CLI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to:
    • x.509 parsing, expiry and signature verification paths in cmd/ctl/check_config.go
    • RSA JWT key parsing and related error handling
    • OpenShift Route SAN validation and discovery checks
    • Cross-cluster interactions and test fidelity in cmd/ctl/check_config_test.go

Possibly related issues

Suggested reviewers

  • jannfis
  • chetan-rns
  • mikeshng

Poem

🐇 I hopped through certs with lantern bright,

I sniffed the CA and counted SANs by night,
Principal and agent stood tidy in a row,
I twitched my whiskers — the checks all show,
A little rabbit nods: configurations right.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a 'check-config' command with principal/agent subcommands for configuration verification, which aligns with the implementation across three modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch 3 times, most recently from c1cdde9 to 67b4ce5 Compare October 30, 2025 15:18
@codecov-commenter
Copy link

codecov-commenter commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 45.86895% with 190 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.58%. Comparing base (09584aa) to head (527d8e9).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
cmd/ctl/check_config.go 46.00% 155 Missing and 34 partials ⚠️
cmd/ctl/main.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main     #631    +/-   ##
========================================
  Coverage   45.57%   45.58%            
========================================
  Files          90       91     +1     
  Lines        9977    10328   +351     
========================================
+ Hits         4547     4708   +161     
- Misses       4963     5119   +156     
- Partials      467      501    +34     

☔ View full report in Codecov by Sentry.
📢 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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
cmd/ctl/check_config_test.go (1)

95-105: Add a regression test for wildcard Route hosts

Once the Route/SAN check handles wildcards, please add a test case here exercising a certificate with a *.example.com SAN and a Route host like argocd-server.example.com. That will lock in the fix and prevent the wildcard-support regression from reappearing.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6235cf1 and 67b4ce5.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
cmd/ctl/check_config_test.go (5)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/tlsutil/generate.go (3)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (128-174)
  • RunAgentChecks (178-206)
cmd/ctl/main.go (1)
cmd/ctl/check_config.go (1)
  • NewCheckConfigCommand (49-61)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run unit tests
  • GitHub Check: Run end-to-end tests

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
cmd/ctl/check_config.go (1)

83-111: Consider parameter type consistency.

This function passes kubernetes.Interface to RunAgentChecks (line 106), while RunPrincipalChecks (line 105) accepts *kube.KubernetesClient. This inconsistency makes the API less predictable.

Consider refactoring RunAgentChecks to accept *kube.KubernetesClient for both agent and principal parameters, matching the pattern used by RunPrincipalChecks. This would make the API more consistent and potentially allow agent checks to access DynamicClient if needed in the future.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6235cf1 and 67b4ce5.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
cmd/ctl/check_config_test.go (5)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/tlsutil/generate.go (3)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (128-174)
  • RunAgentChecks (178-206)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
cmd/ctl/main.go (1)
cmd/ctl/check_config.go (1)
  • NewCheckConfigCommand (49-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run end-to-end tests
🔇 Additional comments (9)
cmd/ctl/main.go (1)

52-52: LGTM!

The integration of the new check-config command follows the established pattern and correctly wires the new functionality into the CLI.

cmd/ctl/check_config_test.go (3)

25-36: LGTM!

The test helper correctly uses t.Helper() and creates properly structured TLS secrets for testing.


38-111: Good happy-path coverage.

The test properly validates the principal checks workflow with appropriate test fixtures and fake clients.


113-152: LGTM!

The test correctly validates cross-cluster agent checks, including CA signature verification and namespace matching.

cmd/ctl/check_config.go (5)

37-61: LGTM!

The checkResult type and command constructor follow appropriate patterns for Cobra-based CLIs.


63-81: LGTM!

The command properly validates required flags and handles errors appropriately.


176-206: LGTM!

The agent checks are well-structured and cover the essential cross-cluster validation scenarios.


208-234: LGTM!

These validation helpers are well-focused with appropriate error handling and clear requirements (e.g., RSA-only for JWT keys).


315-395: LGTM!

These helper functions implement cross-cluster validation logic correctly, including CA signature verification, certificate expiration checks, and namespace matching. The x509FromTLSSecret utility function is well-designed and reusable.

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch from 67b4ce5 to 7afd305 Compare October 30, 2025 16:19
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
cmd/ctl/check_config.go (1)

356-358: Remove or properly handle the agent namespace check.

Lines 357-358 check if the agent's own namespace exists but discard the result with _, _. This is dead code that serves no purpose.

Choose one of these solutions:

Solution 1 (recommended): Remove the dead code:

 	}
-	// optional: ensure agent's own namespace exists (sanity)
-	_, _ = agentKube.CoreV1().Namespaces().Get(ctx, agentNS, metav1.GetOptions{})
 	return nil
 }

Solution 2: If the sanity check is valuable, handle or log the result:

 	}
-	// optional: ensure agent's own namespace exists (sanity)
-	_, _ = agentKube.CoreV1().Namespaces().Get(ctx, agentNS, metav1.GetOptions{})
+	// Verify agent's own namespace exists (sanity check)
+	if _, err := agentKube.CoreV1().Namespaces().Get(ctx, agentNS, metav1.GetOptions{}); err != nil {
+		return fmt.Errorf("agent namespace '%s' not found on agent cluster: %w", agentNS, err)
+	}
 	return nil
 }
cmd/ctl/check_config_test.go (2)

38-111: Consider expanding test coverage for robustness.

The test validates the happy path comprehensively but doesn't cover failure scenarios such as:

  • Expired or not-yet-valid certificates
  • Missing secrets
  • Invalid JWT keys (non-RSA)
  • Mismatched Route hosts and certificate SANs
  • ArgoCD configured in namespaced mode (the test registers the CRD but doesn't create any ArgoCD CR or ConfigMap, so it only tests the "no resources found" path of verifyArgoCDClusterScoped)

Consider adding negative test cases to improve confidence in error handling. For example:

func TestCheckConfigPrincipal_ExpiredCertificate(t *testing.T) {
	// Create a certificate that expired yesterday
	// Assert that certSecretValid returns an error
}

func TestCheckConfigPrincipal_NamespacedMode(t *testing.T) {
	// Create an ArgoCD CR with spec.applicationNamespaces set
	// Assert that verifyArgoCDClusterScoped returns an error
}

113-152: Consider expanding test coverage for agent checks.

Similar to the principal test, this validates only the happy path. Consider adding tests for failure scenarios:

  • Expired agent client certificate
  • Agent certificate not signed by principal CA
  • Missing namespace on principal cluster (mismatched agent CN)
  • Missing or invalid agent CA secret
  • Invalid ca.crt field in agent CA secret

Example negative test case:

func TestCheckConfigAgent_MismatchedNamespace(t *testing.T) {
	// Issue client cert with CN "test-cluster"
	// Don't create namespace "test-cluster" on principal
	// Assert that namespaceMatchesAgentSubject returns an error
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67b4ce5 and 7afd305.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/ctl/main.go
🧰 Additional context used
🧬 Code graph analysis (2)
cmd/ctl/check_config_test.go (5)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/tlsutil/generate.go (3)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (128-168)
  • RunAgentChecks (172-200)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build and push image
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Run unit tests
  • GitHub Check: Build & cache Go code
  • GitHub Check: Lint Go code
  • GitHub Check: Analyze (go)

return nil
}

// verifyArgoCDClusterScoped checks operator CR or argocd-cm to ensure no namespaced mode is configured.
Copy link
Member

Choose a reason for hiding this comment

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

It appears that this logic is not checking for cluster scoped, but is instead checking if source namespaces field is non-empty. Which is a fine thing to check, but is different from whether the cluster is cluster-scoped.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Now I have added kubectl get applications --all-namespaces logic to check whether it is cluster scoped, please let me know if this is correct or is there any other way we can check this, thank you

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch 2 times, most recently from ba71141 to 30858d9 Compare November 6, 2025 07:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
cmd/ctl/check_config_test.go (2)

170-258: Update deprecated API version.

Line 180 uses v1alpha1 for the applications API, which is deprecated according to a previous review comment. Use v1beta1 instead to align with current API versions.

Apply this diff:

 		dynCl := dynamicfake.NewSimpleDynamicClientWithCustomListKinds(scheme, map[schema.GroupVersionResource]string{
 			{Group: "argoproj.io", Version: "v1beta1", Resource: "argocds"}:       "ArgoCDList",
-			{Group: "argoproj.io", Version: "v1alpha1", Resource: "applications"}: "ApplicationList",
+			{Group: "argoproj.io", Version: "v1beta1", Resource: "applications"}: "ApplicationList",
 			{Group: "route.openshift.io", Version: "v1", Resource: "routes"}:      "RouteList",
 		})

260-784: Update deprecated API version across all test cases.

The v1alpha1 version for the applications API appears throughout all principal test cases (lines 267, 308, 354, 408, 466, 520, 579, 621, 694). This version is deprecated. Update all occurrences to use v1beta1 instead.

Example for one occurrence (apply similar changes to all):

 		dynCl := dynamicfake.NewSimpleDynamicClientWithCustomListKinds(scheme, map[schema.GroupVersionResource]string{
 			{Group: "argoproj.io", Version: "v1beta1", Resource: "argocds"}:       "ArgoCDList",
-			{Group: "argoproj.io", Version: "v1alpha1", Resource: "applications"}: "ApplicationList",
+			{Group: "argoproj.io", Version: "v1beta1", Resource: "applications"}: "ApplicationList",
 		})
🧹 Nitpick comments (2)
cmd/ctl/check_config_test.go (2)

61-91: Consider erroring on invalid IPs in test helpers.

Lines 65-69 silently skip invalid IP addresses. For test clarity, it's better to fail fast when test data is malformed so issues are caught during test setup rather than causing subtle test failures.

Apply this diff:

 func createExpiredCertificate(t *testing.T, name string, signerCert *x509.Certificate, signerKey crypto.PrivateKey, ips []string, dns []string) (string, string) {
 	t.Helper()
 	ipAddresses := []net.IP{}
 	for _, ip := range ips {
 		addr := net.ParseIP(ip)
-		if addr != nil {
-			ipAddresses = append(ipAddresses, addr)
-		}
+		require.NotNil(t, addr, "invalid IP address in test: %s", ip)
+		ipAddresses = append(ipAddresses, addr)
 	}

93-146: Simplify CA parsing and handle invalid IPs.

Lines 100-115 use an indirect approach (creating a fake client and secret) to parse the CA certificate. This can be simplified by parsing the PEM directly. Additionally, lines 118-123 silently skip invalid IPs, which could hide test setup issues.

Apply this diff:

 func createCertSignedByDifferentCA(t *testing.T, name string, ips []string, dns []string) (string, string) {
 	t.Helper()
-	// Create a different CA
 	differentCAPEM, differentCAKeyPEM, err := tlsutil.GenerateCaCertificate("different-ca")
 	require.NoError(t, err, "generate different CA")
 
-	// Create a fake client to parse the CA
-	cl := fake.NewSimpleClientset()
-	_, err = cl.CoreV1().Secrets("default").Create(context.TODO(), &corev1.Secret{
-		ObjectMeta: metav1.ObjectMeta{Name: "temp-ca", Namespace: "default"},
-		Type:       corev1.SecretTypeTLS,
-		Data: map[string][]byte{
-			"tls.crt": []byte(differentCAPEM),
-			"tls.key": []byte(differentCAKeyPEM),
-		},
-	}, metav1.CreateOptions{})
-	require.NoError(t, err, "create temp CA secret")
-
-	differentCA, err := tlsutil.TLSCertFromSecret(context.TODO(), cl, "default", "temp-ca")
+	// Parse CA cert and key directly
+	differentCA, err := tls.X509KeyPair([]byte(differentCAPEM), []byte(differentCAKeyPEM))
 	require.NoError(t, err, "read different CA")
 	differentCASigner, err := x509.ParseCertificate(differentCA.Certificate[0])
 	require.NoError(t, err, "parse different CA")
 
-	// Create certificate signed by different CA
 	ipAddresses := []net.IP{}
 	for _, ip := range ips {
 		addr := net.ParseIP(ip)
-		if addr != nil {
-			ipAddresses = append(ipAddresses, addr)
-		}
+		require.NotNil(t, addr, "invalid IP address in test: %s", ip)
+		ipAddresses = append(ipAddresses, addr)
 	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7afd305 and ba71141.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • cmd/ctl/check_config.go
  • cmd/ctl/main.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T10:37:27.987Z
Learnt from: chetan-rns
Repo: argoproj-labs/argocd-agent PR: 632
File: test/data/pre-sync/pre-sync-job.yaml:2-17
Timestamp: 2025-10-31T10:37:27.987Z
Learning: In the argocd-agent repository, Kubernetes manifests under test/data/ directories are test fixtures for e2e testing and do not require production-grade security hardening such as securityContext settings for runAsNonRoot or allowPrivilegeEscalation.

Applied to files:

  • cmd/ctl/check_config_test.go
🧬 Code graph analysis (1)
cmd/ctl/check_config_test.go (5)
internal/tlsutil/generate.go (4)
  • GenerateCertificate (148-177)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (226-271)
  • RunAgentChecks (275-307)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Run unit tests
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Build & cache Go code
  • GitHub Check: Lint Go code
  • GitHub Check: Build and push image
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
cmd/ctl/check_config_test.go (4)

48-59: LGTM!

The helper function correctly creates TLS secrets and follows Go testing best practices with t.Helper() and descriptive error messages.


148-168: LGTM!

This helper correctly creates a certificate with an empty CommonName for testing error scenarios.


786-847: LGTM!

The valid agent configuration test correctly sets up both agent and principal clusters, creates matching namespaces, and verifies cross-cluster certificate validation.


170-1195: Excellent test coverage addressing previous review feedback.

These tests comprehensively cover both success and failure scenarios, directly addressing the previous review comment about checking error cases. Each test validates specific error conditions (missing secrets, expired certificates, mismatched configurations, etc.) and verifies appropriate error messages.

Based on learnings: A previous reviewer requested tests for error cases, and this implementation provides thorough coverage.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba71141 and 30858d9.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T10:37:27.987Z
Learnt from: chetan-rns
Repo: argoproj-labs/argocd-agent PR: 632
File: test/data/pre-sync/pre-sync-job.yaml:2-17
Timestamp: 2025-10-31T10:37:27.987Z
Learning: In the argocd-agent repository, Kubernetes manifests under test/data/ directories are test fixtures for e2e testing and do not require production-grade security hardening such as securityContext settings for runAsNonRoot or allowPrivilegeEscalation.

Applied to files:

  • cmd/ctl/check_config_test.go
🧬 Code graph analysis (3)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
cmd/ctl/main.go (1)
cmd/ctl/check_config.go (1)
  • NewCheckConfigCommand (49-61)
cmd/ctl/check_config_test.go (5)
internal/tlsutil/generate.go (4)
  • GenerateCertificate (148-177)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (226-271)
  • RunAgentChecks (275-307)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build and push image
  • GitHub Check: Run unit tests
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Lint Go code
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
cmd/ctl/check_config_test.go (1)

170-784: Thorough negative-path coverage keeps regressions in check

The matrix of principal/agent failure cases (missing secrets, bad certs, mismatched routes, etc.) is exhaustive and mirrors production misconfigurations well. Thanks for putting in this depth of testing.

cmd/ctl/main.go (1)

52-52: Good to see the new command wired in

Hooking NewCheckConfigCommand() into the root CLI ensures the new validations are reachable; looks good.

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch from 30858d9 to 7cc945d Compare November 6, 2025 10:14
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
cmd/ctl/check_config.go (1)

554-555: Consider removing unused optional check.

These lines perform an optional check to ensure the agent's namespace exists, but the result is intentionally ignored. If the check isn't needed, remove it to avoid confusion. If it serves a purpose (e.g., logging side-effects), add a comment explaining why.

Apply this diff to remove the dead code:

 	}
-	// optional: ensure agent's own namespace exists
-	_, _ = agentKube.CoreV1().Namespaces().Get(ctx, agentNS, metav1.GetOptions{})
 	return nil
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30858d9 and 7cc945d.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T10:37:27.987Z
Learnt from: chetan-rns
Repo: argoproj-labs/argocd-agent PR: 632
File: test/data/pre-sync/pre-sync-job.yaml:2-17
Timestamp: 2025-10-31T10:37:27.987Z
Learning: In the argocd-agent repository, Kubernetes manifests under test/data/ directories are test fixtures for e2e testing and do not require production-grade security hardening such as securityContext settings for runAsNonRoot or allowPrivilegeEscalation.

Applied to files:

  • cmd/ctl/check_config_test.go
🧬 Code graph analysis (3)
cmd/ctl/main.go (1)
cmd/ctl/check_config.go (1)
  • NewCheckConfigCommand (49-61)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
cmd/ctl/check_config_test.go (5)
internal/tlsutil/generate.go (4)
  • GenerateCertificate (148-177)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (224-269)
  • RunAgentChecks (273-305)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Lint Go code
  • GitHub Check: Run unit tests
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Build & cache Go code
  • GitHub Check: Build and push image
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
cmd/ctl/main.go (1)

52-52: LGTM!

Clean integration of the new check-config command into the CLI hierarchy.

cmd/ctl/check_config_test.go (1)

170-1195: Excellent test coverage!

The test suite comprehensively covers both success and failure scenarios for principal and agent validation, including edge cases like expired certificates, signature mismatches, empty CNs, and missing secrets. The test helpers effectively reduce duplication.

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch from 7cc945d to 87ab1c5 Compare November 6, 2025 12:34
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cc945d and 87ab1c5.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T10:37:27.987Z
Learnt from: chetan-rns
Repo: argoproj-labs/argocd-agent PR: 632
File: test/data/pre-sync/pre-sync-job.yaml:2-17
Timestamp: 2025-10-31T10:37:27.987Z
Learning: In the argocd-agent repository, Kubernetes manifests under test/data/ directories are test fixtures for e2e testing and do not require production-grade security hardening such as securityContext settings for runAsNonRoot or allowPrivilegeEscalation.

Applied to files:

  • cmd/ctl/check_config_test.go
🧬 Code graph analysis (3)
cmd/ctl/main.go (1)
cmd/ctl/check_config.go (1)
  • NewCheckConfigCommand (49-61)
cmd/ctl/check_config_test.go (5)
internal/tlsutil/generate.go (4)
  • GenerateCertificate (148-177)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (224-275)
  • RunAgentChecks (279-311)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build & cache Go code
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Run unit tests
  • GitHub Check: Lint Go code
  • GitHub Check: Build and push image
  • GitHub Check: Analyze (go)

@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch 2 times, most recently from 7f9bd1c to 6dcc31a Compare November 11, 2025 10:54
…entctl which will verify the user's configuration

Assisted-by: Cursor
Signed-off-by: Rizwana777 <[email protected]>
@Rizwana777 Rizwana777 force-pushed the issue-7958-check-config branch from 6dcc31a to 527d8e9 Compare November 13, 2025 06:16
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6dcc31a and 527d8e9.

📒 Files selected for processing (3)
  • cmd/ctl/check_config.go (1 hunks)
  • cmd/ctl/check_config_test.go (1 hunks)
  • cmd/ctl/main.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/ctl/main.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T10:37:28.008Z
Learnt from: chetan-rns
Repo: argoproj-labs/argocd-agent PR: 632
File: test/data/pre-sync/pre-sync-job.yaml:2-17
Timestamp: 2025-10-31T10:37:28.008Z
Learning: In the argocd-agent repository, Kubernetes manifests under test/data/ directories are test fixtures for e2e testing and do not require production-grade security hardening such as securityContext settings for runAsNonRoot or allowPrivilegeEscalation.

Applied to files:

  • cmd/ctl/check_config_test.go
🧬 Code graph analysis (2)
cmd/ctl/check_config_test.go (5)
internal/tlsutil/generate.go (4)
  • GenerateCertificate (148-177)
  • GenerateCaCertificate (42-84)
  • GenerateServerCertificate (114-142)
  • GenerateClientCertificate (91-107)
internal/tlsutil/kubernetes.go (1)
  • TLSCertFromSecret (44-66)
internal/kube/client.go (1)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
cmd/ctl/check_config.go (2)
  • RunPrincipalChecks (221-292)
  • RunAgentChecks (296-345)
cmd/ctl/check_config.go (3)
internal/kube/client.go (2)
  • NewKubernetesClientFromConfig (58-98)
  • KubernetesClient (37-44)
internal/config/constants.go (6)
  • SecretNamePrincipalCA (9-9)
  • SecretNamePrincipalTLS (17-17)
  • SecretNameProxyTLS (21-21)
  • SecretNameJWT (29-29)
  • SecretNameAgentCA (13-13)
  • SecretNameAgentClientCert (25-25)
internal/tlsutil/kubernetes.go (3)
  • TLSCertFromSecret (44-66)
  • JWTSigningKeyFromSecret (167-191)
  • X509CertPoolFromSecret (106-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build & cache Go code
  • GitHub Check: Lint Go code
  • GitHub Check: Run end-to-end tests
  • GitHub Check: Run unit tests
  • GitHub Check: Build and push image
  • GitHub Check: Analyze (go)

Comment on lines +610 to +616
if len(cert.Certificate) == 0 || cert.Certificate[0] == nil {
return nil, fmt.Errorf("%s/%s: secret does not contain certificate data", ns, name)
}
if len(cert.Certificate) > 1 {
return nil, fmt.Errorf("%s/%s: secret contains %d certificates, expected exactly one", ns, name, len(cert.Certificate))
}
parsed, err := x509.ParseCertificate(cert.Certificate[0])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove the single-certificate restriction in x509FromTLSSecret.

Rejecting secrets that contain more than one certificate will flag perfectly valid Kubernetes TLS secrets, because tls.crt commonly bundles the full chain (leaf + intermediates). Operators routinely store chains this way (see the ingress/TLS docs and cert-manager guidance). Our CLI will therefore fail even when the secret is healthy. Please drop the len(cert.Certificate) > 1 guard and just parse the first entry, optionally keeping the rest for follow-up validation.

-	if len(cert.Certificate) == 0 || cert.Certificate[0] == nil {
-		return nil, fmt.Errorf("%s/%s: secret does not contain certificate data", ns, name)
-	}
-	if len(cert.Certificate) > 1 {
-		return nil, fmt.Errorf("%s/%s: secret contains %d certificates, expected exactly one", ns, name, len(cert.Certificate))
-	}
+	if len(cert.Certificate) == 0 || cert.Certificate[0] == nil {
+		return nil, fmt.Errorf("%s/%s: secret does not contain certificate data", ns, name)
+	}
 	parsed, err := x509.ParseCertificate(cert.Certificate[0])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if len(cert.Certificate) == 0 || cert.Certificate[0] == nil {
return nil, fmt.Errorf("%s/%s: secret does not contain certificate data", ns, name)
}
if len(cert.Certificate) > 1 {
return nil, fmt.Errorf("%s/%s: secret contains %d certificates, expected exactly one", ns, name, len(cert.Certificate))
}
parsed, err := x509.ParseCertificate(cert.Certificate[0])
if len(cert.Certificate) == 0 || cert.Certificate[0] == nil {
return nil, fmt.Errorf("%s/%s: secret does not contain certificate data", ns, name)
}
parsed, err := x509.ParseCertificate(cert.Certificate[0])
🤖 Prompt for AI Agents
In cmd/ctl/check_config.go around lines 610 to 616, the function
x509FromTLSSecret incorrectly rejects secrets with more than one certificate
(tls.crt often contains a chain). Remove the guard that returns an error when
len(cert.Certificate) > 1 so the function no longer fails for valid chained
certificates; keep parsing cert.Certificate[0] as the leaf as currently done
and, if desired, retain cert.Certificate slice for any downstream chain
validation or logging rather than rejecting the secret outright.

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.

3 participants