Skip to content

Commit 3d64e42

Browse files
Certificate settings (#2500)
Implements #2196. - Certificates settings tab - CA cert settings section - Core/Edge settings section
1 parent f31f074 commit 3d64e42

61 files changed

Lines changed: 2965 additions & 1191 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/defguard/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ async fn main() -> Result<(), anyhow::Error> {
233233
update_counts(&pool).await?;
234234

235235
let (proxy_control_tx, proxy_control_rx) = channel::<ProxyControlMessage>(100);
236+
let (web_reload_tx, _web_reload_rx) = tokio::sync::broadcast::channel::<()>(8);
236237
let proxy_secret_key = settings.secret_key_required()?;
237238
let proxy_manager = ProxyManager::new(
238239
pool.clone(),
@@ -270,6 +271,7 @@ async fn main() -> Result<(), anyhow::Error> {
270271
webhook_tx,
271272
webhook_rx,
272273
gateway_tx.clone(),
274+
web_reload_tx,
273275
pool.clone(),
274276
failed_logins,
275277
api_event_tx,

crates/defguard_certs/src/lib.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use rcgen::{
99
use rustls_pki_types::{CertificateDer, CertificateSigningRequestDer, pem::PemObject};
1010
use thiserror::Error;
1111
use time::{Duration, OffsetDateTime};
12-
use x509_parser::parse_x509_certificate;
12+
use x509_parser::{
13+
extensions::{GeneralName, ParsedExtension},
14+
parse_x509_certificate,
15+
};
1316

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

145148
pub struct CertificateInfo {
146149
pub subject_common_name: String,
150+
pub subject_email: Option<String>,
147151
pub not_before: NaiveDateTime,
148152
pub not_after: NaiveDateTime,
149153
pub serial: String,
@@ -158,6 +162,19 @@ impl CertificateInfo {
158162

159163
let subject = &parsed.tbs_certificate.subject;
160164
let serial = parsed.raw_serial_as_string();
165+
let subject_email = parsed
166+
.tbs_certificate
167+
.extensions()
168+
.iter()
169+
.filter_map(|ext| match ext.parsed_extension() {
170+
ParsedExtension::SubjectAlternativeName(san) => Some(san),
171+
_ => None,
172+
})
173+
.flat_map(|san| san.general_names.iter())
174+
.find_map(|name| match name {
175+
GeneralName::RFC822Name(email) => Some(email.to_string()),
176+
_ => None,
177+
});
161178

162179
let cn = subject
163180
.iter_common_name()
@@ -174,6 +191,7 @@ impl CertificateInfo {
174191

175192
Ok(Self {
176193
subject_common_name: cn.to_string(),
194+
subject_email,
177195
not_before: chrono::DateTime::from_timestamp(not_before.unix_timestamp(), 0)
178196
.ok_or_else(|| {
179197
CertificateError::ParsingError(format!(
@@ -425,30 +443,15 @@ mod tests {
425443

426444
#[test]
427445
fn test_ca_email() {
428-
use x509_parser::parse_x509_certificate;
429-
430446
let expected_email = "contact@defguard.net";
431447
let ca = CertificateAuthority::new("Test CA", expected_email, 365).unwrap();
432448

433-
let (_rem, parsed) = parse_x509_certificate(ca.cert_der()).unwrap();
449+
let info = CertificateInfo::from_der(ca.cert_der()).unwrap();
434450

435-
let san_ext = parsed
436-
.tbs_certificate
437-
.extensions()
438-
.iter()
439-
.find(|ext| ext.oid == x509_parser::oid_registry::OID_X509_EXT_SUBJECT_ALT_NAME)
440-
.expect("Subject Alternative Name extension not found");
441-
442-
let san_value = san_ext.value;
443-
444-
let email_bytes = expected_email.as_bytes();
445-
let email_found = san_value
446-
.windows(email_bytes.len())
447-
.any(|window| window == email_bytes);
448-
449-
assert!(
450-
email_found,
451-
"Email '{expected_email}' should be present in Subject Alternative Names"
451+
assert_eq!(
452+
info.subject_email.as_deref(),
453+
Some(expected_email),
454+
"Email should be parsed from Subject Alternative Names"
452455
);
453456
}
454457

crates/defguard_common/src/types/proxy.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub enum ProxyControlMessage {
1414
cert_pem: String,
1515
key_pem: String,
1616
},
17+
ClearHttpsCerts,
1718
}
1819

1920
#[derive(ToSchema, Serialize)]

crates/defguard_core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ rand = { workspace = true }
4646
reqwest = { workspace = true }
4747
rsa = { workspace = true }
4848
rust-ini = { workspace = true }
49+
rustls = { workspace = true }
4950
secrecy = { workspace = true }
5051
semver = { workspace = true }
5152
serde = { workspace = true }

crates/defguard_core/src/appstate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct AppState {
3030
pub pool: PgPool,
3131
tx: UnboundedSender<AppEvent>,
3232
pub wireguard_tx: Sender<GatewayEvent>,
33+
pub web_reload_tx: tokio::sync::broadcast::Sender<()>,
3334
pub failed_logins: Arc<Mutex<FailedLoginMap>>,
3435
key: Key,
3536
pub event_tx: UnboundedSender<ApiEvent>,
@@ -116,6 +117,7 @@ impl AppState {
116117
tx: UnboundedSender<AppEvent>,
117118
rx: UnboundedReceiver<AppEvent>,
118119
wireguard_tx: Sender<GatewayEvent>,
120+
web_reload_tx: tokio::sync::broadcast::Sender<()>,
119121
key: Key,
120122
failed_logins: Arc<Mutex<FailedLoginMap>>,
121123
event_tx: UnboundedSender<ApiEvent>,
@@ -128,6 +130,7 @@ impl AppState {
128130
pool,
129131
tx,
130132
wireguard_tx,
133+
web_reload_tx,
131134
failed_logins,
132135
key,
133136
event_tx,

0 commit comments

Comments
 (0)