mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
Add tunnel security setup fields
This commit is contained in:
@@ -93,6 +93,22 @@ impl ServerTab {
|
|||||||
required: true,
|
required: true,
|
||||||
help: "Node name for identification in Aether dashboard",
|
help: "Node name for identification in Aether dashboard",
|
||||||
},
|
},
|
||||||
|
Field {
|
||||||
|
label: "Tunnel Security",
|
||||||
|
key: "tunnel_security",
|
||||||
|
value: "off".into(),
|
||||||
|
kind: FieldKind::Text,
|
||||||
|
required: false,
|
||||||
|
help: "off or non_tls_required for secure ws:// tunnel MVP",
|
||||||
|
},
|
||||||
|
Field {
|
||||||
|
label: "Tunnel Encryption Key",
|
||||||
|
key: "tunnel_encryption_key",
|
||||||
|
value: String::new(),
|
||||||
|
kind: FieldKind::Secret,
|
||||||
|
required: false,
|
||||||
|
help: "Base64 32-byte PSK; required when Tunnel Security is non_tls_required",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,6 +120,12 @@ impl ServerTab {
|
|||||||
if let Some(ref name) = entry.node_name {
|
if let Some(ref name) = entry.node_name {
|
||||||
tab.fields[2].value = name.clone();
|
tab.fields[2].value = name.clone();
|
||||||
}
|
}
|
||||||
|
if let Some(security) = entry.tunnel_security {
|
||||||
|
tab.fields[3].value = security.to_string();
|
||||||
|
}
|
||||||
|
if let Some(ref key) = entry.tunnel_encryption_key {
|
||||||
|
tab.fields[4].value = key.clone();
|
||||||
|
}
|
||||||
tab
|
tab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,12 +438,33 @@ impl App {
|
|||||||
cfg.servers = self
|
cfg.servers = self
|
||||||
.server_tabs
|
.server_tabs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tab| ServerEntry {
|
.map(|tab| {
|
||||||
aether_url: get_tab(tab, "aether_url").unwrap_or_default(),
|
let tunnel_security = get_tab(tab, "tunnel_security")
|
||||||
management_token: get_tab(tab, "management_token").unwrap_or_default(),
|
.map(|value| value.parse().map_err(anyhow::Error::msg))
|
||||||
node_name: get_tab(tab, "node_name"),
|
.transpose()?;
|
||||||
|
Ok(ServerEntry {
|
||||||
|
aether_url: get_tab(tab, "aether_url").unwrap_or_default(),
|
||||||
|
management_token: get_tab(tab, "management_token").unwrap_or_default(),
|
||||||
|
node_name: get_tab(tab, "node_name"),
|
||||||
|
tunnel_security,
|
||||||
|
tunnel_encryption_key: get_tab(tab, "tunnel_encryption_key"),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<anyhow::Result<Vec<_>>>()?;
|
||||||
|
for server in &cfg.servers {
|
||||||
|
if server.tunnel_security == Some(crate::config::TunnelSecurity::NonTlsRequired)
|
||||||
|
&& server
|
||||||
|
.tunnel_encryption_key
|
||||||
|
.as_deref()
|
||||||
|
.map(str::trim)
|
||||||
|
.filter(|value| !value.is_empty())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
anyhow::bail!(
|
||||||
|
"Tunnel Encryption Key is required when Tunnel Security is non_tls_required"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(cfg)
|
Ok(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,11 +1151,46 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
server_keys,
|
server_keys,
|
||||||
vec!["aether_url", "management_token", "node_name"]
|
vec![
|
||||||
|
"aether_url",
|
||||||
|
"management_token",
|
||||||
|
"node_name",
|
||||||
|
"tunnel_security",
|
||||||
|
"tunnel_encryption_key"
|
||||||
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(global_keys.first().copied(), Some("upstream_proxy_url"));
|
assert_eq!(global_keys.first().copied(), Some("upstream_proxy_url"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_config_persists_tunnel_security_fields_per_server() {
|
||||||
|
let mut app = sample_app();
|
||||||
|
set_server_field(&mut app, "tunnel_security", "non_tls_required");
|
||||||
|
set_server_field(&mut app, "tunnel_encryption_key", "base64-32-bytes");
|
||||||
|
|
||||||
|
let cfg = app.to_config().expect("config should serialize");
|
||||||
|
assert_eq!(cfg.servers.len(), 1);
|
||||||
|
assert_eq!(
|
||||||
|
cfg.servers[0].tunnel_security,
|
||||||
|
Some(crate::config::TunnelSecurity::NonTlsRequired)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cfg.servers[0].tunnel_encryption_key.as_deref(),
|
||||||
|
Some("base64-32-bytes")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_config_rejects_non_tls_security_without_key() {
|
||||||
|
let mut app = sample_app();
|
||||||
|
set_server_field(&mut app, "tunnel_security", "non_tls_required");
|
||||||
|
|
||||||
|
let error = app
|
||||||
|
.to_config()
|
||||||
|
.expect_err("secure non-TLS mode should require a key");
|
||||||
|
assert!(error.to_string().contains("Tunnel Encryption Key"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_config_enables_pretty_file_logging_with_defaults() {
|
fn to_config_enables_pretty_file_logging_with_defaults() {
|
||||||
let mut app = sample_app();
|
let mut app = sample_app();
|
||||||
@@ -1226,6 +1304,8 @@ mod tests {
|
|||||||
aether_url: "https://aether-2.example.com".to_string(),
|
aether_url: "https://aether-2.example.com".to_string(),
|
||||||
management_token: "ae_test_2".to_string(),
|
management_token: "ae_test_2".to_string(),
|
||||||
node_name: Some("jp-proxy-02".to_string()),
|
node_name: Some("jp-proxy-02".to_string()),
|
||||||
|
tunnel_security: None,
|
||||||
|
tunnel_encryption_key: None,
|
||||||
}));
|
}));
|
||||||
app.active_tab = 1;
|
app.active_tab = 1;
|
||||||
|
|
||||||
@@ -1245,6 +1325,8 @@ mod tests {
|
|||||||
aether_url: "https://aether-2.example.com".to_string(),
|
aether_url: "https://aether-2.example.com".to_string(),
|
||||||
management_token: "ae_test_2".to_string(),
|
management_token: "ae_test_2".to_string(),
|
||||||
node_name: Some("jp-proxy-02".to_string()),
|
node_name: Some("jp-proxy-02".to_string()),
|
||||||
|
tunnel_security: None,
|
||||||
|
tunnel_encryption_key: None,
|
||||||
}));
|
}));
|
||||||
app.active_tab = 0;
|
app.active_tab = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user