Skip to content

feat: Custom Certificate Upload & Management#928

Merged
Wikid82 merged 72 commits intodevelopmentfrom
feature/beta-release
Apr 15, 2026
Merged

feat: Custom Certificate Upload & Management#928
Wikid82 merged 72 commits intodevelopmentfrom
feature/beta-release

Conversation

@Wikid82
Copy link
Copy Markdown
Owner

@Wikid82 Wikid82 commented Apr 10, 2026

Summary

Add full custom certificate upload, validation, and management to Charon. Users can upload PEM certificates and private keys, validate them before acceptance, view certificate chain details, export in multiple formats, and receive expiry warnings — all through the management UI.

Closes #22


What Changed

Backend (Go)

Certificate Service (certificate_service.go, certificate_validator.go)

  • Upload with PEM parsing, chain validation, and domain extraction
  • AES-encrypted private key storage (private_key_enc column, never plaintext at rest)
  • Export in PEM and PKCS#12/PFX formats with optional password protection
  • Certificate-in-use checks before deletion (linked proxy host validation)
  • Expiry checking with configurable warning thresholds
  • Migration utility to encrypt any legacy plaintext private keys
  • Dedicated validator module with chain-of-trust verification and key-pair matching

API Handlers (certificate_handler.go)

  • POST /certificates/upload — upload cert + optional key
  • POST /certificates/validate — validate without persisting
  • PUT /certificates/:id — update name/metadata
  • GET /certificates/:id — fetch single certificate with chain info
  • POST /certificates/:id/export — export as PEM or PFX
  • DELETE /certificates/:id — delete with in-use guard

Caddy Integration (caddy/config.go, caddy/manager.go)

  • Custom certificates are injected into Caddy TLS automation policies
  • Proxy hosts referencing a custom certificate use it directly instead of ACME

Model (ssl_certificate.go)

  • New fields: CertificateChain, KeyType, Issuer, Fingerprint, Domains
  • PrivateKey excluded from GORM (gorm:"-"); only PrivateKeyEncrypted persists

Frontend (React/TypeScript)

New Components

  • CertificateUploadDialog — drag-and-drop PEM file upload with real-time validation preview
  • CertificateExportDialog — PEM/PFX export with optional password and key inclusion
  • CertificateDetailDialog — full certificate details, chain viewer, and metadata
  • CertificateChainViewer — visual intermediate/root chain display
  • CertificateValidationPreview — pre-upload validation feedback
  • FileDropZone — reusable accessible file drop target

Updated Components

  • CertificateList — integrated upload, export, and detail actions
  • CertificateStatusCard — domain-aware status badges
  • ProxyHostForm — custom certificate selection in SSL configuration
  • Certificates page — simplified with hook-based data flow

API Client (certificates.ts)

  • New endpoints: uploadCertificate, validateCertificate, exportCertificate
  • Updated deleteCertificate to accept UUID strings

Hook (useCertificates.ts)

  • Added upload, validate, export actions
  • Domain-to-certificate status mapping for proxy host integration

i18n (translation.json)

  • 60+ new translation keys for certificate UI strings

Testing

Backend Unit Tests (125+ tests across 8 files)

  • certificate_service_coverage_test.go — 33 subtests covering all service functions
  • certificate_handler_coverage_test.go — 21 handler endpoint tests
  • certificate_validator_test.go — chain, key-pair, and format validation
  • certificate_handler_test.go / certificate_handler_security_test.go — updated for new routes

Frontend Unit Tests (14 test files)

  • Dialog tests: upload, export, detail, delete, bulk delete, cleanup
  • Component tests: chain viewer, validation preview, file drop zone, status card
  • Hook tests: useCertificates lifecycle
  • Page tests: corrected UUID-based deletion assertions, fixed mock property names

E2E Tests (Playwright)

  • certificate-export.spec.ts — 14 end-to-end tests covering export dialog flows

Infrastructure

  • Dockerfile: CVE-2026-40200 remediation (musl musl-utils in apk upgrade)
  • package.json: Playwright @axe-core/playwright added for accessibility testing
  • Dependencies: axios@1.15.0, vite@8.0.8 (security patches)

Acceptance Criteria Status

Criteria Status
Can upload custom certificates
Certificates validated before acceptance
Private keys securely stored (AES encrypted)
Expiry warnings work
Certificate chain/intermediate support
Certificate assignment to proxy hosts
Certificate export (PEM, PFX)
Certificate-in-use deletion guard

Quality Gates

  • Backend line coverage: 87.6% (gate: 87%)
  • Frontend tests: all passing
  • E2E Playwright: 14 export flow tests
  • Security: Trivy, CodeQL, gosec, semgrep — zero critical/high
  • Pre-commit: all 14 lefthook hooks passing

@Wikid82 Wikid82 self-assigned this Apr 10, 2026
@Wikid82 Wikid82 added this to Charon Apr 10, 2026
@github-project-automation github-project-automation bot moved this to Backlog in Charon Apr 10, 2026
@Wikid82 Wikid82 added enhancement New feature or request high Important feature, should be included feature New functionality ssl SSL/TLS certificates labels Apr 10, 2026
…g model

- Rewrote commit slicing guidance in Management, Planning, and subagent
  instruction files to enforce one-feature-one-PR with ordered logical commits
- Removed multi-PR branching logic from the execution workflow
- Prevents partial feature merges that cause user confusion on self-hosted tools
- All cross-references now use "Commit N" instead of "PR-N"
@github-advanced-security
Copy link
Copy Markdown
Contributor

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 11, 2026

✅ Supply Chain Verification Results

PASSED

📦 SBOM Summary

  • Components: 1485

🔍 Vulnerability Scan

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 4
🟢 Low 0
Total 4

📎 Artifacts

  • SBOM (CycloneDX JSON) and Grype results available in workflow artifacts

Generated by Supply Chain Verification workflow • View Details

…traction

- Implemented certificate parsing for PEM, DER, and PFX formats.
- Added functions to validate key matches and certificate chains.
- Introduced metadata extraction for certificates including common name, domains, and issuer organization.
- Created unit tests for all new functionalities to ensure reliability and correctness.
Comment thread backend/internal/api/handlers/certificate_handler.go Fixed
Comment thread backend/internal/api/handlers/certificate_handler.go Fixed
Comment thread backend/internal/api/handlers/certificate_handler.go Fixed
Comment thread backend/internal/api/handlers/certificate_handler.go Fixed
actions-user and others added 13 commits April 11, 2026 17:33
…n-major-updates

fix(deps): update non-major-updates (feature/beta-release)
…n-major-updates

fix(deps): update non-major-updates (feature/beta-release)
…ftprops-action-gh-release-3.x

chore(deps): update softprops/action-gh-release action to v3 (feature/beta-release)
- Implemented CertificateExportDialog for exporting certificates in various formats (PEM, PFX, DER) with options to include private keys and set passwords.
- Created CertificateUploadDialog for uploading certificates, including validation and support for multiple file types (certificates, private keys, chain files).
- Updated DeleteCertificateDialog to use 'domains' instead of 'domain' for consistency.
- Refactored BulkDeleteCertificateDialog and DeleteCertificateDialog tests to accommodate changes in certificate structure.
- Added FileDropZone component for improved file upload experience.
- Enhanced translation files with new keys for certificate management features.
- Updated Certificates page to utilize the new CertificateUploadDialog and clean up the upload logic.
- Adjusted Dashboard and ProxyHosts pages to reflect changes in certificate data structure.
…/query-core, globals, builtin-modules, knip, and undici to latest versions for improved functionality and security
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 76 out of 80 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (6)

backend/internal/services/certificate_validator.go:1

  • In the DER key fallback path, if x509.ParseECPrivateKey fails the code returns an error wrapping err (from ParsePKCS8PrivateKey) instead of the last failure (err2). This can produce misleading errors and hides the actual parsing failure. Prefer returning/wrapping err2 (or the most relevant/last error) in that branch.
    frontend/src/components/ProxyHostForm.tsx:1
  • This select still uses cert.id for the option value, but the certificate API changes in this PR emphasize UUID-based operations (and id is deprecated/optional in the type). If id is missing, multiple options will collapse to value=\"0\", breaking selection and submission. Use cert.uuid as the stable key/value (and update the proxy host API/contract to accept UUID), or guarantee that id is always provided by the certificates list endpoint and remove the ?? 0 fallback.
    backend/internal/services/certificate_validator_test.go:1
  • The subtest name says "self-signed cert validates" but the assertion expects an error (and the inline comment explains why). Rename the test case to match the expected behavior (e.g., "self-signed cert fails chain validation without trusted root") to keep intent clear.
    package.json:1
  • The added vitest version ^4.1.4 is not a version I’m aware of (as of my 2025-08 knowledge cutoff). Please double-check that this version exists in npm and aligns with your Vite/TypeScript setup; if not, pin to an available Vitest major that matches the repo’s tooling.
    frontend/src/components/CertificateList.tsx:1
  • selectedIds now stores certificate UUID strings rather than numeric IDs. Renaming to something like selectedUuids (and corresponding setters) would reduce confusion and help prevent future misuse.
    backend/pkg/dnsprovider/custom/rfc2136_provider_test.go:1
  • t.Fatal(...) already stops the test goroutine (via FailNow), so the return is redundant and adds noise. Consider removing the return unless it’s needed to satisfy a specific linter rule in this repo (in which case, documenting that rationale would help).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 91 out of 95 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

Comment thread docs/reports/qa_report_pr928.md
Comment thread tests/core/certificates.spec.ts Outdated
Comment thread frontend/src/components/dialogs/CertificateUploadDialog.tsx
Comment thread frontend/src/components/ProxyHostForm.tsx Outdated
Comment thread backend/internal/api/routes/routes_coverage_test.go
actions-user and others added 11 commits April 14, 2026 16:33
…onents

- Implement test to deselect a row checkbox in CertificateList by clicking it a second time.
- Add test to close detail dialog via the close button in CertificateList.
- Add test to close export dialog via the cancel button in CertificateList.
- Add test to show KEY format badge when a .key file is uploaded in CertificateUploadDialog.
- Add test to ensure no format badge is shown for unknown file extensions in CertificateUploadDialog.
…n-major-updates

fix(deps): update non-major-updates (feature/beta-release)
@Wikid82 Wikid82 merged commit c63e4a3 into development Apr 15, 2026
38 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in Charon Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request feature New functionality high Important feature, should be included ssl SSL/TLS certificates

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants