Skip to content

Refactor/make certificate provisioning configurable#217

Open
Hermann-Core wants to merge 8 commits into
mainfrom
refactor/make-certificate-provisioning-configurable
Open

Refactor/make certificate provisioning configurable#217
Hermann-Core wants to merge 8 commits into
mainfrom
refactor/make-certificate-provisioning-configurable

Conversation

@Hermann-Core

Copy link
Copy Markdown
Collaborator

Make certificate provisioning configurable to support multiple provisioning strategies and refactor the certificate manager to use the builder pattern for construction, removing the inline startup construction.

Acceptance Criteria

  • Operators can choose between ACME and store-based provisioning.
  • Store-based provisioning loads certs from filesystem or supported secrets store.
  • Hot-reload works for store strategy and invalidates the certificate chain cache.
  • Certificate manager is constructed via a builder pattern.
  • Missing required components produce clear validation errors at build time.
  • All existing tests pass and new tests cover builder and store provisioning paths.

@martcpp

martcpp commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

@Hermann-Core pls resolve this conflict

@Ngha-Boris Ngha-Boris 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.

Hello @Hermann-Core Please take a look at these comments

manager.persist_signing_key(&signing_key_pem).await?;
info!("Store certificate material refreshed");
Ok(certificate_data)
}

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.

Issue: Cache re-population missing after store provisioning

After persisting the certificate data and signing key (lines 217-218), the certificate chain cache is not being updated. The code only persists to storage but doesn't update the in-memory cache that other parts of the system rely on.

Suggestion: Add cache update call after line 218:

manager.cache_provisioned_chain(&certificate_data.certificate).await?;

This ensures the cache is invalidated and re-populated with the new certificate data.


/// Source for directly provisioned certificate material.
#[derive(Debug, Clone)]
pub enum StoreProvisioningSource {

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.

Issue: Missing HashiCorp Vault Support

The ticket deliverables mention implementing Store backend loading from "HashiCorp Vault", but this variant is missing from the StoreProvisioningSource enum. Only Filesystem, Storage, and SecretsStorage are implemented.

Suggestion: Add a HashiCorpVault variant or create a follow-up issue to track this missing deliverable from the ticket requirements.

@@ -0,0 +1,256 @@
use std::{sync::Arc, time::Duration};

use instant_acme::{Account, HttpClient};

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.

Issue: Unused Import

The Account import from instant_acme is not used in this file.

Suggestion: Remove the unused import:

use instant_acme::HttpClient;


let cert_storage = self.cert_storage.ok_or_else(|| {
CertError::Validation("certificate storage backend must be configured".to_string())
})?;

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.

Issue: String-based Strategy Name Comparison

Using string comparison (strategy.name() == "acme") for determining strategy type is fragile. If someone changes the name returned by AcmeProvisioningStrategy, this validation will break.

Suggestion: Consider using a type-based approach or const for the strategy name:

const ACME_STRATEGY_NAME: &str = "acme";
let strategy_uses_acme = strategy.name() == ACME_STRATEGY_NAME;

Or better yet, add a method to the trait:

fn is_acme(&self) -> bool { false }  // default impl

Comment thread src/config.rs
#[derive(Debug, Clone, Deserialize)]
pub struct CertConfig {
pub provisioning_strategy: String,
pub email: String,

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.

Issue: No Validation for provisioning_strategy

The provisioning_strategy field uses String type without validation. This allows invalid values to be passed in.

Suggestion: Consider using an enum for compile-time safety:

pub enum ProvisioningStrategy {
    #[serde(rename = "acme")]
    Acme,
    #[serde(rename = "store")]
    Store,
}

Or add runtime validation in Config::load() to ensure only valid values are accepted.

&self,
_manager: &CertManager,
_certificate: &CertificateData,
) -> bool {

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.

Issue: Store Strategy Always Returns true for should_provision_existing

The StoreProvisioningStrategy::should_provision_existing always returns true, which means the store will be checked on every renewal cycle regardless of whether the certificate is still valid.

Suggestion: Consider if this is the intended behavior. For store provisioning, you might want to:

  1. Check if the file/storage content has changed (hash comparison)
  2. Or add a TTL-based check to avoid unnecessary reloads
  3. Or document why unconditional reloading is the desired behavior

Currently, this could cause unnecessary storage reads.

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.

Make certificate provisioning configurable (ACME or direct store)

3 participants