Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
b1aff1f
bootstrap settings certs tab
j-chmielewski Mar 30, 2026
b823485
bootstrap cert settings pages
j-chmielewski Mar 30, 2026
a3b212a
ca cert styling
j-chmielewski Mar 30, 2026
75e71ae
download CA cert button
j-chmielewski Mar 30, 2026
fa18d85
Merge branch 'dev' into certificate-settings
j-chmielewski Mar 31, 2026
8b8156b
settings CA page
j-chmielewski Mar 31, 2026
ee33e57
extract CA email
j-chmielewski Mar 31, 2026
3ed451f
move ca image
j-chmielewski Mar 31, 2026
fffa485
proper icons for settings certs sections
j-chmielewski Mar 31, 2026
ccf0331
Merge branch 'dev' into certificate-settings
j-chmielewski Apr 1, 2026
d6ad6eb
fix firewall test import
j-chmielewski Apr 1, 2026
3267007
fix icons
j-chmielewski Apr 1, 2026
8b06467
bootstrap certs sections
j-chmielewski Apr 1, 2026
07394f2
get_certs API endpoint, None and SelfSigned core certs sections
j-chmielewski Apr 2, 2026
5ab6ea9
core own cert
j-chmielewski Apr 2, 2026
9970ad7
edge: none, self-signed, custom
j-chmielewski Apr 2, 2026
b4921ff
update custom cert description
j-chmielewski Apr 2, 2026
2d74d1c
core certs settings backend
j-chmielewski Apr 2, 2026
00cd7da
core cert settings wizard frontend
j-chmielewski Apr 2, 2026
e509831
edge cert settings wizard backend
j-chmielewski Apr 2, 2026
0e48be6
proxy certs settings
j-chmielewski Apr 2, 2026
7a01983
download CA cert
j-chmielewski Apr 3, 2026
043f9c5
fix retry loop in letsencrypt flow
j-chmielewski Apr 3, 2026
a588932
fix setting LE expiry; add cert info sections
j-chmielewski Apr 3, 2026
052107c
badges
j-chmielewski Apr 7, 2026
eaa4fc3
show badges for all cert types
j-chmielewski Apr 7, 2026
2684fb4
change certs button for self-signed sections
j-chmielewski Apr 7, 2026
f875482
fix "Change certificate" buttons
j-chmielewski Apr 7, 2026
88360bf
all cert-setting paths restart proxy web server
j-chmielewski Apr 7, 2026
da6f52a
restart web server after cert changes
j-chmielewski Apr 7, 2026
54d1df5
defer saving LE state until ACME challenge succeeds
j-chmielewski Apr 7, 2026
16e94c1
remove the restart message
j-chmielewski Apr 8, 2026
930f125
format
j-chmielewski Apr 8, 2026
78b121a
warning badges
j-chmielewski Apr 8, 2026
e0d4ff1
update defguard-ui
j-chmielewski Apr 8, 2026
7716bf8
fix messages
j-chmielewski Apr 8, 2026
ac8002d
remove dividers; fix control buttons
j-chmielewski Apr 8, 2026
2aad8ab
refactor email extraction
j-chmielewski Apr 8, 2026
f68e829
refactor public url hostname extraction
j-chmielewski Apr 8, 2026
eb61224
move cert structs to separate module
j-chmielewski Apr 8, 2026
576acc9
Merge branch 'dev' into certificate-settings
j-chmielewski Apr 8, 2026
d8c7eb7
fix log levels
j-chmielewski Apr 8, 2026
bebe598
validate the certs to avoid bricking the server
j-chmielewski Apr 8, 2026
ca5dc22
remove legacy cert endpoints
j-chmielewski Apr 8, 2026
b2ce0fd
logging tweaks
j-chmielewski Apr 8, 2026
c6ee46b
don't panic
j-chmielewski Apr 8, 2026
7029a12
validate cert and key match
j-chmielewski Apr 8, 2026
431b798
deduplicate generate_test_cert_pem function
j-chmielewski Apr 8, 2026
6a99dc3
fix dividers
j-chmielewski Apr 8, 2026
c887c0c
cache invalidation
j-chmielewski Apr 8, 2026
4f97d39
getDaysUntilExpiry helper
j-chmielewski Apr 8, 2026
cf9bbbb
Merge branch 'dev' into certificate-settings
j-chmielewski Apr 8, 2026
4896feb
cargo fmt
j-chmielewski Apr 8, 2026
c8c6bf5
fix ts typing
j-chmielewski Apr 8, 2026
09d6349
move messages to translations; fix utoipa
j-chmielewski Apr 8, 2026
066179d
comment
j-chmielewski Apr 8, 2026
1f84fa9
fix breadcrumbs
j-chmielewski Apr 8, 2026
d29b1ae
update protos
j-chmielewski Apr 8, 2026
8423468
Merge branch 'dev' into certificate-settings
j-chmielewski Apr 8, 2026
a41d901
updaste defguard-ui and proto submodules
j-chmielewski Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/defguard/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ async fn main() -> Result<(), anyhow::Error> {
update_counts(&pool).await?;

let (proxy_control_tx, proxy_control_rx) = channel::<ProxyControlMessage>(100);
let (web_reload_tx, _web_reload_rx) = tokio::sync::broadcast::channel::<()>(8);
let proxy_secret_key = settings.secret_key_required()?;
let proxy_manager = ProxyManager::new(
pool.clone(),
Expand Down Expand Up @@ -270,6 +271,7 @@ async fn main() -> Result<(), anyhow::Error> {
webhook_tx,
webhook_rx,
gateway_tx.clone(),
web_reload_tx,
pool.clone(),
failed_logins,
api_event_tx,
Expand Down
45 changes: 24 additions & 21 deletions crates/defguard_certs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use rcgen::{
use rustls_pki_types::{CertificateDer, CertificateSigningRequestDer, pem::PemObject};
use thiserror::Error;
use time::{Duration, OffsetDateTime};
use x509_parser::parse_x509_certificate;
use x509_parser::{
extensions::{GeneralName, ParsedExtension},
parse_x509_certificate,
};

const CA_NAME: &str = "Defguard CA";
const NOT_BEFORE_OFFSET_SECS: Duration = Duration::minutes(5);
Expand Down Expand Up @@ -144,6 +147,7 @@ impl CertificateAuthority<'_> {

pub struct CertificateInfo {
pub subject_common_name: String,
pub subject_email: Option<String>,
pub not_before: NaiveDateTime,
pub not_after: NaiveDateTime,
pub serial: String,
Expand All @@ -158,6 +162,19 @@ impl CertificateInfo {

let subject = &parsed.tbs_certificate.subject;
let serial = parsed.raw_serial_as_string();
let subject_email = parsed
.tbs_certificate
.extensions()
.iter()
.filter_map(|ext| match ext.parsed_extension() {
ParsedExtension::SubjectAlternativeName(san) => Some(san),
_ => None,
})
.flat_map(|san| san.general_names.iter())
.find_map(|name| match name {
GeneralName::RFC822Name(email) => Some(email.to_string()),
_ => None,
});

let cn = subject
.iter_common_name()
Expand All @@ -174,6 +191,7 @@ impl CertificateInfo {

Ok(Self {
subject_common_name: cn.to_string(),
subject_email,
not_before: chrono::DateTime::from_timestamp(not_before.unix_timestamp(), 0)
.ok_or_else(|| {
CertificateError::ParsingError(format!(
Expand Down Expand Up @@ -425,30 +443,15 @@ mod tests {

#[test]
fn test_ca_email() {
use x509_parser::parse_x509_certificate;

let expected_email = "contact@defguard.net";
let ca = CertificateAuthority::new("Test CA", expected_email, 365).unwrap();

let (_rem, parsed) = parse_x509_certificate(ca.cert_der()).unwrap();
let info = CertificateInfo::from_der(ca.cert_der()).unwrap();

let san_ext = parsed
.tbs_certificate
.extensions()
.iter()
.find(|ext| ext.oid == x509_parser::oid_registry::OID_X509_EXT_SUBJECT_ALT_NAME)
.expect("Subject Alternative Name extension not found");

let san_value = san_ext.value;

let email_bytes = expected_email.as_bytes();
let email_found = san_value
.windows(email_bytes.len())
.any(|window| window == email_bytes);

assert!(
email_found,
"Email '{expected_email}' should be present in Subject Alternative Names"
assert_eq!(
info.subject_email.as_deref(),
Some(expected_email),
"Email should be parsed from Subject Alternative Names"
);
}

Expand Down
1 change: 1 addition & 0 deletions crates/defguard_common/src/types/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum ProxyControlMessage {
cert_pem: String,
key_pem: String,
},
ClearHttpsCerts,
}

#[derive(ToSchema, Serialize)]
Expand Down
1 change: 1 addition & 0 deletions crates/defguard_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ rand = { workspace = true }
reqwest = { workspace = true }
rsa = { workspace = true }
rust-ini = { workspace = true }
rustls = { workspace = true }
secrecy = { workspace = true }
semver = { workspace = true }
serde = { workspace = true }
Expand Down
3 changes: 3 additions & 0 deletions crates/defguard_core/src/appstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct AppState {
pub pool: PgPool,
tx: UnboundedSender<AppEvent>,
pub wireguard_tx: Sender<GatewayEvent>,
pub web_reload_tx: tokio::sync::broadcast::Sender<()>,
pub failed_logins: Arc<Mutex<FailedLoginMap>>,
key: Key,
pub event_tx: UnboundedSender<ApiEvent>,
Expand Down Expand Up @@ -116,6 +117,7 @@ impl AppState {
tx: UnboundedSender<AppEvent>,
rx: UnboundedReceiver<AppEvent>,
wireguard_tx: Sender<GatewayEvent>,
web_reload_tx: tokio::sync::broadcast::Sender<()>,
key: Key,
failed_logins: Arc<Mutex<FailedLoginMap>>,
event_tx: UnboundedSender<ApiEvent>,
Expand All @@ -128,6 +130,7 @@ impl AppState {
pool,
tx,
wireguard_tx,
web_reload_tx,
failed_logins,
key,
event_tx,
Expand Down
Loading
Loading