1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-09 04:22:45 +03:00
Files
authentication-service/crates/cli/src/main.rs
reivilibre fbc360d1a9 Backend work to support minimum password complexity (#2965)
* config: Add minimum password complexity option

* PasswordManager: add function for checking if complexity is sufficient

* Enforce password complexity on registration, change and recovery

* cli: Use exit code 1 for weak passwords

This seems preferable to exit code 0, but ideally we should choose one
and document it.

* Expose minimum password complexity score over GraphQL
2024-07-11 10:17:39 +01:00

141 lines
4.8 KiB
Rust

// Copyright 2021, 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(clippy::module_name_repetitions)]
use std::{io::IsTerminal, process::ExitCode, sync::Arc};
use anyhow::Context;
use clap::Parser;
use mas_config::{ConfigurationSection, TelemetryConfig};
use sentry_tracing::EventFilter;
use tracing_subscriber::{
filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, Registry,
};
use crate::sentry_transport::HyperTransportFactory;
mod app_state;
mod commands;
mod sentry_transport;
mod server;
mod sync;
mod telemetry;
mod util;
#[tokio::main]
async fn main() -> anyhow::Result<ExitCode> {
// We're splitting the "fallible" part of main in another function to have a
// chance to shutdown the telemetry exporters regardless of if there was an
// error or not
let res = try_main().await;
self::telemetry::shutdown();
res
}
async fn try_main() -> anyhow::Result<ExitCode> {
// Load environment variables from .env files
// We keep the path to log it afterwards
let dotenv_path: Result<Option<_>, _> = dotenvy::dotenv()
.map(Some)
// Display the error if it is something other than the .env file not existing
.or_else(|e| if e.not_found() { Ok(None) } else { Err(e) });
// Setup logging
// This writes logs to stderr
let output = std::io::stderr();
let with_ansi = output.is_terminal();
let (log_writer, _guard) = tracing_appender::non_blocking(output);
let fmt_layer = tracing_subscriber::fmt::layer()
.with_writer(log_writer)
.with_file(true)
.with_line_number(true)
.with_ansi(with_ansi);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.context("could not setup logging filter")?;
// Setup the rustls crypto provider
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.map_err(|_| anyhow::anyhow!("could not install the AWS LC crypto provider"))?;
// Parse the CLI arguments
let opts = self::commands::Options::parse();
// Load the base configuration files
let figment = opts.figment();
// Telemetry config could fail to load, but that's probably OK, since the whole
// config will be loaded afterwards, and crash if there is a problem.
// Falling back to default.
let telemetry_config = TelemetryConfig::extract(&figment).unwrap_or_default();
// Setup Sentry
let sentry = sentry::init((
telemetry_config.sentry.dsn.as_deref(),
sentry::ClientOptions {
transport: Some(Arc::new(HyperTransportFactory::new(
mas_http::make_untraced_client(),
))),
traces_sample_rate: 1.0,
auto_session_tracking: true,
session_mode: sentry::SessionMode::Request,
..Default::default()
},
));
let sentry_layer = sentry.is_enabled().then(|| {
sentry_tracing::layer().event_filter(|md| {
// All the spans in the handlers module send their data to Sentry themselves, so
// we only create breadcrumbs for them, instead of full events
if md.target().starts_with("mas_handlers::") {
EventFilter::Breadcrumb
} else {
sentry_tracing::default_event_filter(md)
}
})
});
// Setup OpenTelemetry tracing and metrics
let tracer = telemetry::setup(&telemetry_config).context("failed to setup OpenTelemetry")?;
let telemetry_layer = tracer.map(|tracer| {
tracing_opentelemetry::layer()
.with_tracer(tracer)
.with_tracked_inactivity(false)
.with_filter(LevelFilter::INFO)
});
let subscriber = Registry::default()
.with(sentry_layer)
.with(telemetry_layer)
.with(filter_layer)
.with(fmt_layer);
subscriber
.try_init()
.context("could not initialize logging")?;
// Log about the .env loading
match dotenv_path {
Ok(Some(path)) => tracing::info!(?path, "Loaded environment variables from .env file"),
Ok(None) => {}
Err(e) => tracing::warn!(?e, "Failed to load .env file"),
}
// And run the command
tracing::trace!(?opts, "Running command");
opts.run(&figment).await
}