diff --git a/services/backup/src/config.rs b/services/backup/src/config.rs index 3f2ba5068..d7dbabd29 100644 --- a/services/backup/src/config.rs +++ b/services/backup/src/config.rs @@ -1,48 +1,49 @@ +use aws_config::BehaviorVersion; use clap::Parser; use once_cell::sync::Lazy; use tracing::info; use crate::constants::{DEFAULT_BLOB_SERVICE_URL, DEFAULT_HTTP_PORT}; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// HTTP server listening port #[arg(long, default_value_t = DEFAULT_HTTP_PORT)] pub http_port: u16, /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, /// Blob service URL #[arg(env = "BLOB_SERVICE_URL")] #[arg(long, default_value = DEFAULT_BLOB_SERVICE_URL)] pub blob_service_url: reqwest::Url, /// Identity service endpoint #[arg(env = "IDENTITY_SERVICE_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() { // force evaluation of the lazy initialized config Lazy::force(&CONFIG); } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws_config::SdkConfig { - let mut config_builder = aws_config::from_env(); + let mut config_builder = aws_config::defaults(BehaviorVersion::v2024_03_28()); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } diff --git a/services/blob/src/config.rs b/services/blob/src/config.rs index 8e164ea0a..164af483f 100644 --- a/services/blob/src/config.rs +++ b/services/blob/src/config.rs @@ -1,78 +1,79 @@ use anyhow::Result; +use aws_config::BehaviorVersion; use clap::{ArgAction, Parser}; use once_cell::sync::Lazy; use std::collections::HashSet; use tracing::info; use crate::constants::{ DEFAULT_HTTP_PORT, DEFAULT_S3_BUCKET_NAME, S3_BUCKET_ENV_VAR, }; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// HTTP server listening port #[arg(long, default_value_t = DEFAULT_HTTP_PORT, global = true)] pub http_port: u16, /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, #[arg(env = S3_BUCKET_ENV_VAR)] #[arg(long, default_value_t = DEFAULT_S3_BUCKET_NAME.to_string())] pub s3_bucket_name: String, /// Identity service endpoint #[arg(env = "IDENTITY_SERVICE_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, /// If set, blobs will be deleted instantly after revoking last holder #[arg(long, global = true, action = ArgAction::SetTrue)] pub instant_delete: bool, #[clap(subcommand)] pub command: Option, } #[derive(clap::Subcommand)] pub enum Command { Server, Cleanup, } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> { // force evaluation of the lazy initialized config let cfg = Lazy::force(&CONFIG); if cfg.s3_bucket_name != DEFAULT_S3_BUCKET_NAME { info!("Using custom S3 bucket: {}", &cfg.s3_bucket_name); } Ok(cfg) } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws_config::SdkConfig { - let mut config_builder = aws_config::from_env(); + let mut config_builder = aws_config::defaults(BehaviorVersion::v2024_03_28()); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } fn get_all_offensive_invite_links() -> HashSet { let contents = include_str!("../third-party/bad-words/words.json"); let reserved_usernames: Vec = serde_json::from_str(contents).unwrap(); reserved_usernames.into_iter().collect() } pub static OFFENSIVE_INVITE_LINKS: Lazy> = Lazy::new(get_all_offensive_invite_links); diff --git a/services/feature-flags/src/config.rs b/services/feature-flags/src/config.rs index 8faeba3b8..65f6d41a8 100644 --- a/services/feature-flags/src/config.rs +++ b/services/feature-flags/src/config.rs @@ -1,33 +1,34 @@ +use aws_config::BehaviorVersion; use clap::Parser; use once_cell::sync::Lazy; use tracing::info; use crate::constants::HTTP_SERVER_DEFAULT_PORT; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, #[arg(long, default_value_t = HTTP_SERVER_DEFAULT_PORT)] pub http_port: u16, } pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); pub fn parse_cmdline_args() { Lazy::force(&CONFIG); } pub async fn load_aws_config() -> aws_config::SdkConfig { - let mut config_builder = aws_config::from_env(); + let mut config_builder = aws_config::defaults(BehaviorVersion::v2024_03_28()); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } diff --git a/services/identity/src/main.rs b/services/identity/src/main.rs index 6b5781c9b..e494e44f7 100644 --- a/services/identity/src/main.rs +++ b/services/identity/src/main.rs @@ -1,133 +1,137 @@ use comm_lib::aws; use comm_lib::aws::config::timeout::TimeoutConfig; +use comm_lib::aws::config::BehaviorVersion; use config::Command; use database::DatabaseClient; use tonic::transport::Server; use tonic_web::GrpcWebLayer; mod client_service; mod config; pub mod constants; mod cors; mod database; pub mod ddb_utils; mod device_list; pub mod error; mod grpc_services; mod grpc_utils; mod http; mod id; mod keygen; mod log; mod nonce; mod olm; mod regex; mod reserved_users; mod siwe; mod sync_identity_search; mod token; mod tunnelbroker; mod websockets; use constants::{COMM_SERVICES_USE_JSON_LOGS, IDENTITY_SERVICE_SOCKET_ADDR}; use cors::cors_layer; use keygen::generate_and_persist_keypair; use std::env; use sync_identity_search::sync_index; use tokio::time::Duration; use tracing::{self, info, Level}; use tracing_subscriber::EnvFilter; use client_service::{ClientService, IdentityClientServiceServer}; use grpc_services::authenticated::AuthenticatedService; use grpc_services::protos::auth::identity_client_service_server::IdentityClientServiceServer as AuthServer; use websockets::errors::BoxedError; #[tokio::main] async fn main() -> Result<(), BoxedError> { let filter = EnvFilter::builder() .with_default_directive(Level::INFO.into()) .with_env_var(EnvFilter::DEFAULT_ENV) .from_env_lossy(); let use_json_logs: bool = env::var(COMM_SERVICES_USE_JSON_LOGS) .unwrap_or("false".to_string()) .parse() .unwrap_or_default(); if use_json_logs { let subscriber = tracing_subscriber::fmt() .json() .with_env_filter(filter) .finish(); tracing::subscriber::set_global_default(subscriber)?; } else { let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish(); tracing::subscriber::set_global_default(subscriber)?; } match config::parse_cli_command() { Command::Keygen { dir } => { generate_and_persist_keypair(dir)?; } Command::Server => { config::load_server_config(); let addr = IDENTITY_SERVICE_SOCKET_ADDR.parse()?; - let aws_config = aws::config::from_env() + let aws_config = aws::config::defaults(BehaviorVersion::v2024_03_28()) .timeout_config( TimeoutConfig::builder() .connect_timeout(Duration::from_secs(60)) .build(), ) .region("us-east-2") .load() .await; let database_client = DatabaseClient::new(&aws_config); let inner_client_service = ClientService::new(database_client.clone()); let client_service = IdentityClientServiceServer::with_interceptor( inner_client_service, grpc_services::shared::version_interceptor, ); let inner_auth_service = AuthenticatedService::new(database_client.clone()); let db_client = database_client.clone(); let auth_service = AuthServer::with_interceptor(inner_auth_service, move |req| { grpc_services::authenticated::auth_interceptor(req, &db_client) .and_then(grpc_services::shared::version_interceptor) }); info!("Listening to gRPC traffic on {}", addr); let grpc_server = Server::builder() .accept_http1(true) .layer(cors_layer()) .layer(GrpcWebLayer::new()) .trace_fn(|_| { tracing::info_span!( "grpc_request", request_id = uuid::Uuid::new_v4().to_string() ) }) .add_service(client_service) .add_service(auth_service) .serve(addr); let websocket_server = websockets::run_server(database_client); return tokio::select! { websocket_result = websocket_server => websocket_result, grpc_result = grpc_server => { grpc_result.map_err(|e| e.into()) }, }; } Command::SyncIdentitySearch => { - let aws_config = aws::config::from_env().region("us-east-2").load().await; + let aws_config = aws::config::defaults(BehaviorVersion::v2024_03_28()) + .region("us-east-2") + .load() + .await; let database_client = DatabaseClient::new(&aws_config); let sync_result = sync_index(&database_client).await; error::consume_error(sync_result); } } Ok(()) } diff --git a/services/reports/src/config.rs b/services/reports/src/config.rs index 6e66a4f76..b16eab3a8 100644 --- a/services/reports/src/config.rs +++ b/services/reports/src/config.rs @@ -1,104 +1,105 @@ use anyhow::Result; +use aws_config::BehaviorVersion; use clap::{ArgAction, Parser}; use comm_lib::blob::client::Url; use once_cell::sync::Lazy; use tracing::{info, warn}; use crate::email::config::{EmailArgs, EmailConfig}; // environment variable names const ENV_LOCALSTACK_ENDPOINT: &str = "LOCALSTACK_ENDPOINT"; const ENV_BLOB_SERVICE_URL: &str = "BLOB_SERVICE_URL"; const ENV_PUBLIC_URL: &str = "PUBLIC_URL"; /// Base URL on which Reports service is accessible. /// Used for sending e-mail links. pub static SERVICE_PUBLIC_URL: Lazy = Lazy::new(|| { std::env::var(ENV_PUBLIC_URL) .ok() .filter(|s| !s.is_empty()) .unwrap_or_else(|| "http://localhost:50056".to_string()) }); #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// HTTP server listening port #[arg(long, default_value_t = 50056)] pub http_port: u16, #[arg(env = ENV_BLOB_SERVICE_URL)] #[arg(long, default_value = "http://localhost:50053")] pub blob_service_url: Url, /// Identity service endpoint #[arg(env = "IDENTITY_SERVICE_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, /// Should reports be encrypted? Note that this flag disables encryption /// which is enabled by default. #[arg(long = "no-encrypt", action = ArgAction::SetFalse)] pub encrypt_reports: bool, /// AWS Localstack service URL #[arg(env = ENV_LOCALSTACK_ENDPOINT)] #[arg(long)] localstack_endpoint: Option, /// This config shouldn't be used directly. It's used for parsing purposes /// only. Use [`AppConfig::email_config()`] instead. #[command(flatten)] email_args: EmailArgs, } impl AppConfig { pub fn is_dev(&self) -> bool { self.localstack_endpoint.is_some() } pub fn email_config(&self) -> Option { // we return None in case of error because this should've already been // checked by parse_cmdline_args() self.email_args.parse().ok().flatten() } } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> { // force evaluation of the lazy initialized config let cfg = Lazy::force(&CONFIG); // initialize e-mail config to check for errors match cfg.email_args.parse()? { Some(_) => { info!("E-mail config found. E-mail notifications are enabled."); } None => { warn!("E-mail config is disabled or missing! E-mails will not be sent."); } } if !cfg.encrypt_reports { warn!("Encryption disabled. Reports will be stored in plaintext!"); } Ok(cfg) } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws_config::SdkConfig { - let mut config_builder = aws_config::from_env(); + let mut config_builder = aws_config::defaults(BehaviorVersion::v2024_03_28()); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS Endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } diff --git a/services/tunnelbroker/src/config.rs b/services/tunnelbroker/src/config.rs index cd1b7b451..2e666b1eb 100644 --- a/services/tunnelbroker/src/config.rs +++ b/services/tunnelbroker/src/config.rs @@ -1,76 +1,78 @@ use crate::constants; use crate::constants::{ENV_APNS_CONFIG, ENV_FCM_CONFIG, ENV_WEB_PUSH_CONFIG}; use crate::notifs::apns::config::APNsConfig; use crate::notifs::fcm::config::FCMConfig; use crate::notifs::web_push::config::WebPushConfig; use anyhow::{ensure, Result}; use clap::Parser; use comm_lib::aws; +use comm_lib::aws::config::BehaviorVersion; use once_cell::sync::Lazy; use tracing::info; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// gRPC server listening port #[arg(long, default_value_t = constants::GRPC_SERVER_PORT)] pub grpc_port: u16, /// HTTP server listening port #[arg(long, default_value_t = 51001)] pub http_port: u16, /// AMQP server URI #[arg(env = "AMQP_URI")] #[arg(long, default_value = "amqp://comm:comm@localhost:5672")] pub amqp_uri: String, /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, /// Comm Identity service URL #[arg(env = "COMM_TUNNELBROKER_IDENTITY_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, /// APNs secrets #[arg(env = ENV_APNS_CONFIG)] #[arg(long)] pub apns_config: Option, /// FCM secrets #[arg(env = ENV_FCM_CONFIG)] #[arg(long)] pub fcm_config: Option, /// Web Push secrets #[arg(env = ENV_WEB_PUSH_CONFIG)] #[arg(long)] pub web_push_config: Option, } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<()> { // force evaluation of the lazy initialized config let cfg = Lazy::force(&CONFIG); // Perform some additional validation for CLI args ensure!( cfg.grpc_port != cfg.http_port, "gRPC and HTTP ports cannot be the same: {}", cfg.grpc_port ); Ok(()) } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws::AwsConfig { - let mut config_builder = aws::config::from_env(); + let mut config_builder = + aws::config::defaults(BehaviorVersion::v2024_03_28()); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using localstack URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await }