~zethra/stargazer

9f8ede672bc5c5aaa723b26f01d87c0e87241614 — Ben Aaron Goldberg 18 days ago 4dc46d5 f/cert-conf
tls: Add options to control cert generation

Users can now turn off auto cert generation and expired cert
regeneration.

Signed-off-by: Ben Aaron Goldberg <ben@benaaron.dev>
3 files changed, 34 insertions(+), 2 deletions(-)

M doc/stargazer-ini.scd
M src/config.rs
M src/tls.rs
M doc/stargazer-ini.scd => doc/stargazer-ini.scd +6 -0
@@ 60,6 60,12 @@ The following keys are accepted under the *[:tls]* section:
	the name of the organization responsible for the host and it will be
	filled in as the X.509 /O name.

*gen-certs*
	Set to false to turn off automatic certificate generation.

*regen-certs*
	Set to false to turn off automatic regeneration of expired certificates.

## ROUTING KEYS

To configure *stargazer* to service requests, routing keys must be defined. The

M src/config.rs => src/config.rs +23 -0
@@ 46,6 46,10 @@ pub struct Config {
    pub organization: String,
    /// Logging connections and other info to stdout
    pub conn_logging: bool,
    /// Generate certs?
    pub generate_certs: bool,
    /// Regenerate expired certs?
    pub regen_certs: bool,
}

pub fn load(config_path: impl AsRef<Path>) -> Result<Config> {


@@ 114,6 118,8 @@ pub fn load(config_path: impl AsRef<Path>) -> Result<Config> {
        let organization = tls_section
            .remove("organization")
            .unwrap_or_else(|| "stargazer".to_owned());
        let generate_certs = tls_section.remove_yn_true("gen-certs");
        let regen_certs = tls_section.remove_yn_true("regen-certs");
        check_section_empty(":tls", &tls_section)?;

        let mut sites = Vec::with_capacity(5);


@@ 261,6 267,8 @@ pub fn load(config_path: impl AsRef<Path>) -> Result<Config> {
            request_timeout,
            response_timeout,
            organization,
            generate_certs,
            regen_certs,
        })
    })();
    res.with_context(|| {


@@ 300,6 308,8 @@ pub fn dev_config() -> Result<Config> {
        response_timeout: 10,
        organization: "stargazer".to_owned(),
        conn_logging: false,
        generate_certs: true,
        regen_certs: true,
    };
    fs::create_dir_all(&conf.store).with_context(|| {
        format!(


@@ 356,6 366,7 @@ fn check_section_empty(name: &str, section: &Properties) -> Result<()> {

trait RemoveYN {
    fn remove_yn(self, name: &str) -> bool;
    fn remove_yn_true(self, name: &str) -> bool;
}

impl RemoveYN for &mut Properties {


@@ 371,6 382,18 @@ impl RemoveYN for &mut Properties {
            })
            .unwrap_or(false)
    }
    fn remove_yn_true(self, name: &str) -> bool {
        self.remove(name)
            .map(|s| match s.to_lowercase().as_str() {
                "on" | "true" | "yes" => true,
                "off" | "false" | "no" => false,
                s => {
                    warn!("Invalid value for `{}`: '{}'. Turing on", name, s);
                    false
                }
            })
            .unwrap_or(true)
    }
}

fn count_true(bools: &[bool]) -> usize {

M src/tls.rs => src/tls.rs +5 -2
@@ 15,7 15,7 @@
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use crate::CONF;
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use async_rustls::rustls::internal::msgs::handshake::DigitallySignedStruct;
use async_rustls::rustls::{
    internal::pemfile::{certs, pkcs8_private_keys},


@@ 172,7 172,7 @@ fn get_cert_and_key(domain: &str) -> Result<(Vec<Certificate>, PrivateKey)> {
    for cert in &cert_chain {
        let (_, cert) = parse_x509_certificate(cert.as_ref())
            .with_context(|| format!("Error parsing cert for {}", domain))?;
        if !cert.validity().is_valid() {
        if CONF.regen_certs && !cert.validity().is_valid() {
            let (cert_path, key_path) = gen_cert_and_key(domain)?;
            return Ok((load_cert(&cert_path)?, load_key(&key_path)?));
        }


@@ 181,6 181,9 @@ fn get_cert_and_key(domain: &str) -> Result<(Vec<Certificate>, PrivateKey)> {
}

fn gen_cert_and_key(domain: &str) -> Result<(PathBuf, PathBuf)> {
    if !CONF.generate_certs {
        bail!("Cert not found for domain {} and cert generation is disabled", domain);
    }
    debug!("Generating cert+key for {}", domain);
    let mut params = CertificateParams::new(vec![domain.to_owned()]);
    let mut distinguished_name = DistinguishedName::new();