6b2bb3029b
* squashing feat: merge intermediate upgrade mode changes #6174 to more easily resolve merge conflicts during rebasing added additional v2 query for metadata endpoint for requesting upgrade mode recheck added additional message to v6 authenticator to request explicit upgrade mode recheck clippy test fixes due to updated keys updated assertion for upgrading v1 top up request to v2 compare attester public key against the expected value within the credential proxy use pre-generated attestation public keys within nym-nodes remove version deprecation bugfix: default bandwidth response for authenticator expose upgrade mode information in authenticator responses adding tests for new v2 server passing upgrade mode information in metadata endpoint v2 wireguard private metadata bugfix: make sure to immediately poll for attestation after spawning task fix gateway probe and remove code duplication for finalizing registration squashing before rebasing post rebasing fixes AuthenticatorVersion helpers additional nits allow unwraps in mocks fixed linux build clippy integrating upgrade mode into authenticator fixed build after adding wrappers to response types conditionally updating peer handle bandwidth cleanup negotiate initial protocol during registration change auth to use highest protocol handler for JWT message dont meter client bandwidth in upgrade mode handling recheck requests sending information about upgrade_mode on client messages gateway watching for upgrade mode attestation wip: gateways to disable bandwidth metering on upgrade mode * fixed ServerResponse deserialisation * fixed incorrect swagger path for upgrade mode check endpoint * moved upgrade mode endpoint out of bandwidth routes * chore: remove unused error variant * removed re-export of UpgradeModeAttestation from credentials-interface * chore: define single source of truth for minimum bandwidth threshold value * moved type definitions out of traits.rs * updated v6 versioning to point to niolo release instead * fixed incorrect error mapping
514 lines
16 KiB
Rust
514 lines
16 KiB
Rust
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
use super::DEFAULT_NYMNODE_ID;
|
|
use crate::config;
|
|
use crate::config::default_config_filepath;
|
|
use crate::env::vars::*;
|
|
use crate::error::NymNodeError;
|
|
use celes::Country;
|
|
use clap::Args;
|
|
use clap::builder::ArgPredicate;
|
|
use std::net::{IpAddr, SocketAddr};
|
|
use std::path::{Path, PathBuf};
|
|
use url::Url;
|
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
|
|
|
#[derive(Args, Debug)]
|
|
pub(crate) struct ConfigArgs {
|
|
/// Id of the nym-node to use
|
|
#[clap(
|
|
long,
|
|
default_value = DEFAULT_NYMNODE_ID,
|
|
default_value_if("config_file", ArgPredicate::IsPresent, None),
|
|
env = NYMNODE_ID_ARG,
|
|
group = "config"
|
|
)]
|
|
id: Option<String>,
|
|
|
|
/// Path to a configuration file of this node.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_CONFIG_PATH_ARG,
|
|
group = "config"
|
|
)]
|
|
config_file: Option<PathBuf>,
|
|
}
|
|
|
|
impl ConfigArgs {
|
|
pub(crate) fn id(&self) -> &Option<String> {
|
|
&self.id
|
|
}
|
|
|
|
pub(crate) fn config_path(&self) -> PathBuf {
|
|
// SAFETY:
|
|
// if `config_file` hasn't been specified, `id` will default to "DEFAULT_NYMNODE_ID",
|
|
// so some value will always be available to use
|
|
#[allow(clippy::unwrap_used)]
|
|
self.config_file
|
|
.clone()
|
|
.unwrap_or_else(|| default_config_filepath(self.id.as_ref().unwrap()))
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct HostArgs {
|
|
/// Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients.
|
|
/// In nearly all circumstances, it's going to be identical to the address you're going to use for bonding.
|
|
#[clap(
|
|
long,
|
|
value_delimiter = ',',
|
|
env = NYMNODE_PUBLIC_IPS_ARG
|
|
)]
|
|
pub(crate) public_ips: Option<Vec<IpAddr>>,
|
|
|
|
/// Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HOSTNAME_ARG
|
|
)]
|
|
pub(crate) hostname: Option<String>,
|
|
|
|
/// Optional **physical** location of this node's server.
|
|
/// Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g. 'PL'),
|
|
/// three-letter alpha3 (e.g. 'POL') or three-digit numeric-3 (e.g. '616') can be provided.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_LOCATION_ARG
|
|
)]
|
|
pub(crate) location: Option<Country>,
|
|
}
|
|
|
|
impl HostArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section(self) -> config::Host {
|
|
self.override_config_section(config::Host::default())
|
|
}
|
|
|
|
pub(crate) fn override_config_section(self, mut section: config::Host) -> config::Host {
|
|
if let Some(public_ips) = self.public_ips {
|
|
section.public_ips = public_ips
|
|
}
|
|
if let Some(hostname) = self.hostname {
|
|
section.hostname = Some(hostname)
|
|
}
|
|
if let Some(location) = self.location {
|
|
section.location = Some(location)
|
|
}
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct HttpArgs {
|
|
/// Socket address this node will use for binding its http API.
|
|
/// default: `[::]:8080`
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_BIND_ADDRESS_ARG
|
|
)]
|
|
pub(crate) http_bind_address: Option<SocketAddr>,
|
|
|
|
/// Path to assets directory of custom landing page of this node.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_LANDING_ASSETS_ARG
|
|
)]
|
|
pub(crate) landing_page_assets_path: Option<PathBuf>,
|
|
|
|
/// An optional bearer token for accessing certain http endpoints.
|
|
/// Currently only used for prometheus metrics.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_ACCESS_TOKEN_ARG,
|
|
alias = "http-bearer-token"
|
|
)]
|
|
pub(crate) http_access_token: Option<String>,
|
|
|
|
/// Specify whether basic system information should be exposed.
|
|
/// default: true
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_EXPOSE_SYSTEM_INFO_ARG,
|
|
)]
|
|
pub(crate) expose_system_info: Option<bool>,
|
|
|
|
/// Specify whether basic system hardware information should be exposed.
|
|
/// default: true
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE_ARG
|
|
)]
|
|
pub(crate) expose_system_hardware: Option<bool>,
|
|
|
|
/// Specify whether detailed system crypto hardware information should be exposed.
|
|
/// default: true
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE_ARG
|
|
)]
|
|
pub(crate) expose_crypto_hardware: Option<bool>,
|
|
}
|
|
|
|
impl HttpArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section(self) -> config::Http {
|
|
self.override_config_section(config::Http::default())
|
|
}
|
|
|
|
pub(crate) fn override_config_section(self, mut section: config::Http) -> config::Http {
|
|
if let Some(bind_address) = self.http_bind_address {
|
|
section.bind_address = bind_address
|
|
}
|
|
if let Some(landing_page_assets_path) = self.landing_page_assets_path {
|
|
section.landing_page_assets_path = Some(landing_page_assets_path)
|
|
}
|
|
if let Some(access_token) = self.http_access_token {
|
|
section.access_token = Some(access_token)
|
|
}
|
|
if let Some(expose_system_info) = self.expose_system_info {
|
|
section.expose_system_info = expose_system_info
|
|
}
|
|
if let Some(expose_hardware_info) = self.expose_system_hardware {
|
|
section.expose_system_hardware = expose_hardware_info
|
|
}
|
|
if let Some(expose_crypto_hardware) = self.expose_crypto_hardware {
|
|
section.expose_crypto_hardware = expose_crypto_hardware
|
|
}
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct MixnetArgs {
|
|
/// Address this node will bind to for listening for mixnet packets
|
|
/// default: `[::]:1789`
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_MIXNET_BIND_ADDRESS_ARG
|
|
)]
|
|
pub(crate) mixnet_bind_address: Option<SocketAddr>,
|
|
|
|
/// If applicable, custom port announced in the self-described API that other clients and nodes
|
|
/// will use.
|
|
/// Useful when the node is behind a proxy.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_MIXNET_ANNOUNCE_PORT_ARG
|
|
)]
|
|
pub(crate) mixnet_announce_port: Option<u16>,
|
|
|
|
/// Addresses to nym APIs from which the node gets the view of the network.
|
|
#[clap(
|
|
long,
|
|
value_delimiter = ',',
|
|
env = NYMNODE_NYM_APIS_ARG
|
|
)]
|
|
pub(crate) nym_api_urls: Option<Vec<Url>>,
|
|
|
|
/// Addresses to nyxd chain endpoint which the node will use for chain interactions.
|
|
#[clap(
|
|
long,
|
|
value_delimiter = ',',
|
|
env = NYMNODE_NYXD_URLS_ARG
|
|
)]
|
|
pub(crate) nyxd_urls: Option<Vec<Url>>,
|
|
|
|
/// Specifies whether this node should **NOT** use noise protocol in the connections (currently not implemented)
|
|
#[clap(
|
|
hide = true,
|
|
long,
|
|
env = NYMNODE_UNSAFE_DISABLE_NOISE
|
|
)]
|
|
pub(crate) unsafe_disable_noise: bool,
|
|
|
|
/// Specifies whether this node should **NOT** be using replay protection
|
|
#[clap(
|
|
hide = true,
|
|
long,
|
|
env = NYMNODE_UNSAFE_DISABLE_REPLAY_PROTECTION
|
|
)]
|
|
pub(crate) unsafe_disable_replay_protection: bool,
|
|
}
|
|
|
|
impl MixnetArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section<P: AsRef<Path>>(self, data_dir: P) -> config::Mixnet {
|
|
self.override_config_section(config::Mixnet::new_default(data_dir))
|
|
}
|
|
|
|
pub(crate) fn override_config_section(self, mut section: config::Mixnet) -> config::Mixnet {
|
|
if let Some(bind_address) = self.mixnet_bind_address {
|
|
section.bind_address = bind_address
|
|
}
|
|
if let Some(mixnet_announce_port) = self.mixnet_announce_port {
|
|
section.announce_port = Some(mixnet_announce_port)
|
|
}
|
|
if let Some(nym_api_urls) = self.nym_api_urls {
|
|
section.nym_api_urls = nym_api_urls
|
|
}
|
|
if let Some(nyxd_urls) = self.nyxd_urls {
|
|
section.nyxd_urls = nyxd_urls
|
|
}
|
|
if self.unsafe_disable_noise {
|
|
section.debug.unsafe_disable_noise = true
|
|
}
|
|
if self.unsafe_disable_replay_protection {
|
|
section.replay_protection.debug.unsafe_disabled = true
|
|
}
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct WireguardArgs {
|
|
/// Specifies whether the wireguard service is enabled on this node.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_WG_ENABLED_ARG
|
|
)]
|
|
pub(crate) wireguard_enabled: Option<bool>,
|
|
|
|
/// Socket address this node will use for binding its wireguard interface.
|
|
/// default: `[::]:51822`
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_WG_BIND_ADDRESS_ARG
|
|
)]
|
|
pub(crate) wireguard_bind_address: Option<SocketAddr>,
|
|
|
|
/// Tunnel port announced to external clients wishing to connect to the wireguard interface.
|
|
/// Useful in the instances where the node is behind a proxy.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_WG_ANNOUNCED_PORT_ARG
|
|
)]
|
|
pub(crate) wireguard_tunnel_announced_port: Option<u16>,
|
|
|
|
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
|
|
/// The maximum value for IPv4 is 32 and for IPv6 is 128
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_WG_PRIVATE_NETWORK_PREFIX_ARG
|
|
)]
|
|
pub(crate) wireguard_private_network_prefix: Option<u8>,
|
|
}
|
|
|
|
impl WireguardArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section<P: AsRef<Path>>(self, data_dir: P) -> config::Wireguard {
|
|
self.override_config_section(config::Wireguard::new_default(data_dir))
|
|
}
|
|
|
|
pub(crate) fn override_config_section(
|
|
self,
|
|
mut section: config::Wireguard,
|
|
) -> config::Wireguard {
|
|
if let Some(enabled) = self.wireguard_enabled {
|
|
section.enabled = enabled
|
|
}
|
|
|
|
if let Some(bind_address) = self.wireguard_bind_address {
|
|
section.bind_address = bind_address
|
|
}
|
|
|
|
if let Some(announced_tunnel_port) = self.wireguard_tunnel_announced_port {
|
|
section.announced_tunnel_port = announced_tunnel_port
|
|
}
|
|
|
|
if let Some(private_network_prefix) = self.wireguard_private_network_prefix {
|
|
section.private_network_prefix_v4 = private_network_prefix
|
|
}
|
|
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct VerlocArgs {
|
|
/// Socket address this node will use for binding its verloc API.
|
|
/// default: `[::]:1790`
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_VERLOC_BIND_ADDRESS_ARG
|
|
)]
|
|
pub(crate) verloc_bind_address: Option<SocketAddr>,
|
|
|
|
/// If applicable, custom port announced in the self-described API that other clients and nodes
|
|
/// will use.
|
|
/// Useful when the node is behind a proxy.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_VERLOC_ANNOUNCE_PORT_ARG
|
|
)]
|
|
pub(crate) verloc_announce_port: Option<u16>,
|
|
}
|
|
|
|
impl VerlocArgs {
|
|
pub(crate) fn build_config_section(self) -> config::Verloc {
|
|
self.override_config_section(config::Verloc::default())
|
|
}
|
|
|
|
pub(crate) fn override_config_section(self, mut section: config::Verloc) -> config::Verloc {
|
|
if let Some(bind_address) = self.verloc_bind_address {
|
|
section.bind_address = bind_address
|
|
}
|
|
if let Some(announce_port) = self.verloc_announce_port {
|
|
section.announce_port = Some(announce_port)
|
|
}
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct MetricsArgs {
|
|
/// Specify whether running statistics of this node should be logged to the console.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_ENABLE_CONSOLE_LOGGING
|
|
)]
|
|
enable_console_logging: Option<bool>,
|
|
}
|
|
|
|
impl MetricsArgs {
|
|
pub(crate) fn build_config_section(self) -> config::MetricsConfig {
|
|
self.override_config_section(config::MetricsConfig::default())
|
|
}
|
|
|
|
pub(crate) fn override_config_section(
|
|
self,
|
|
mut section: config::MetricsConfig,
|
|
) -> config::MetricsConfig {
|
|
if let Some(enable_console_logging) = self.enable_console_logging {
|
|
section.debug.log_stats_to_console = enable_console_logging;
|
|
}
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug, Zeroize, ZeroizeOnDrop)]
|
|
pub(crate) struct EntryGatewayArgs {
|
|
/// Socket address this node will use for binding its client websocket API.
|
|
/// default: `[::]:9000`
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_ENTRY_BIND_ADDRESS_ARG
|
|
)]
|
|
#[zeroize(skip)]
|
|
pub(crate) entry_bind_address: Option<SocketAddr>,
|
|
|
|
/// Custom announced port for listening for websocket client traffic.
|
|
/// If unspecified, the value from the `bind_address` will be used instead
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_ENTRY_ANNOUNCE_WS_PORT_ARG
|
|
)]
|
|
pub(crate) announce_ws_port: Option<u16>,
|
|
|
|
/// If applicable, announced port for listening for secure websocket client traffic.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_ENTRY_ANNOUNCE_WSS_PORT_ARG
|
|
)]
|
|
pub(crate) announce_wss_port: Option<u16>,
|
|
|
|
/// Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet
|
|
/// or if it also accepts non-paying clients
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_ENFORCE_ZK_NYMS_ARG
|
|
)]
|
|
pub(crate) enforce_zk_nyms: Option<bool>,
|
|
|
|
/// Custom cosmos wallet mnemonic used for zk-nym redemption.
|
|
/// If no value is provided, a fresh mnemonic is going to be generated.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_MNEMONIC_ARG
|
|
)]
|
|
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
|
|
|
/// Endpoint to query to retrieve current upgrade mode attestation.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_UPGRADE_MODE_ATTESTATION_URL_ARG
|
|
)]
|
|
#[zeroize(skip)]
|
|
pub(crate) upgrade_mode_attestation_url: Option<Url>,
|
|
}
|
|
|
|
impl EntryGatewayArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section<P: AsRef<Path>>(
|
|
self,
|
|
data_dir: P,
|
|
) -> Result<config::GatewayTasksConfig, NymNodeError> {
|
|
Ok(self.override_config_section(config::GatewayTasksConfig::new(data_dir)?))
|
|
}
|
|
|
|
pub(crate) fn override_config_section(
|
|
mut self,
|
|
mut section: config::GatewayTasksConfig,
|
|
) -> config::GatewayTasksConfig {
|
|
if let Some(bind_address) = self.entry_bind_address {
|
|
section.ws_bind_address = bind_address
|
|
}
|
|
if let Some(ws_port) = self.announce_ws_port {
|
|
section.announce_ws_port = Some(ws_port)
|
|
}
|
|
if let Some(wss_port) = self.announce_wss_port {
|
|
section.announce_wss_port = Some(wss_port)
|
|
}
|
|
if let Some(enforce_zk_nyms) = self.enforce_zk_nyms {
|
|
section.enforce_zk_nyms = enforce_zk_nyms
|
|
}
|
|
if let Some(upgrade_mode_attestation_url) = self.upgrade_mode_attestation_url.take() {
|
|
section.upgrade_mode.attestation_url = upgrade_mode_attestation_url
|
|
}
|
|
|
|
section
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Args, Debug)]
|
|
pub(crate) struct ExitGatewayArgs {
|
|
/// Specifies the url for an upstream source of the exit policy used by this node.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_UPSTREAM_EXIT_POLICY_ARG,
|
|
)]
|
|
pub(crate) upstream_exit_policy_url: Option<Url>,
|
|
|
|
/// Specifies whether this exit node should run in 'open-proxy' mode
|
|
/// and thus would attempt to resolve **ANY** request it receives.
|
|
#[clap(
|
|
long,
|
|
env = NYMNODE_OPEN_PROXY_ARG,
|
|
)]
|
|
pub(crate) open_proxy: Option<bool>,
|
|
}
|
|
|
|
impl ExitGatewayArgs {
|
|
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
|
pub(crate) fn build_config_section<P: AsRef<Path>>(
|
|
self,
|
|
data_dir: P,
|
|
) -> config::ServiceProvidersConfig {
|
|
self.override_config_section(config::ServiceProvidersConfig::new_default(data_dir))
|
|
}
|
|
|
|
pub(crate) fn override_config_section(
|
|
self,
|
|
mut section: config::ServiceProvidersConfig,
|
|
) -> config::ServiceProvidersConfig {
|
|
if let Some(upstream_exit_policy) = self.upstream_exit_policy_url {
|
|
section.upstream_exit_policy_url = upstream_exit_policy
|
|
}
|
|
if let Some(open_proxy) = self.open_proxy {
|
|
section.open_proxy = open_proxy
|
|
}
|
|
|
|
section
|
|
}
|
|
}
|