Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make TLS to NB Infra to be optional #71

Merged
merged 2 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,20 @@ CGW_DB_HOST - IP or hostname of remote database server to connect to
CGW_DB_PORT - PORT of remote database server to connect to
CGW_DB_USER - PSQL DB username (credentials) to use upon connect to DB
CGW_DB_PASS - PSQL DB password (credentials) to use upon connect to DB
CGW_DB_TLS - Utilize TLS connection with DB server
CGW_REDIS_HOST - IP or hostname of remote redis-db server to connect to
CGW_REDIS_PORT - PORT of remote redis-db server to connect to
CGW_REDIS_USERNAME - REDIS username (credentials) to use upon connect to
CGW_REDIS_PASSWORD - REDIS password (credentials) to use upon connect to
CGW_REDIS_TLS - Utilize TLS connection with REDIS server
CGW_LOG_LEVEL - Log level to start CGW application with (debug, info)
CGW_METRICS_PORT - PORT of metrics to connect to
CGW_CERTS_PATH - Path to certificates located on host machine
CGW_ALLOW_CERT_MISMATCH - Allow client certificate CN and device MAC address mismatch (used for OWLS)
CGW_NB_INFRA_CERTS_DIR - Path to NB infrastructure (Redis, PostgreSQL)certificates located on host machine
CGW_NB_INFRA_CERTS_DIR - Path to NB infrastructure (Redis, PostgreSQL) certificates located on host machine
CGW_NB_INFRA_TLS - Utilize TLS connection with NB infrastructure (Redis, PostgreSQL)
If set enabled - the CGW_DB_TLS and CGW_REDIS_TLS values will be ignored and
the TLS connection will be used for Redis and PostgreSQL connection
```

Example of properly configured list of env variables to start CGW:
Expand All @@ -90,6 +95,7 @@ declare -x CGW_DB_HOST="localhost" # PSQL server is locate
declare -x CGW_DB_PORT="5432"
declare -x CGW_DB_USERNAME="cgw" # PSQL login credentials (username) default 'cgw' will be used
declare -x CGW_DB_PASS="123" # PSQL login credentials (password) default '123' will be used
declare -x CGW_DB_TLS="no"
declare -x CGW_GRPC_LISTENING_IP="127.0.0.1" # Local default subnet is 127.0.0.1/24
declare -x CGW_GRPC_LISTENING_PORT="50051"
declare -x CGW_GRPC_PUBLIC_HOST="localhost"
Expand All @@ -102,6 +108,7 @@ declare -x CGW_REDIS_HOST="localhost" # Redis server can be f
declare -x CGW_REDIS_PORT="6379"
declare -x CGW_REDIS_USERNAME="cgw" # REDIS login credentials (username) - optional
declare -x CGW_REDIS_PASSWORD="123" # REDIS login credentials (password) - optional
declare -x CGW_REDIS_TLS="no"
declare -x CGW_METRICS_PORT="8080"
declare -x CGW_WSS_IP="0.0.0.0" # Accept WSS connections at all interfaces / subnets
declare -x CGW_WSS_PORT="15002"
Expand All @@ -111,6 +118,7 @@ declare -x CGW_WSS_KEY="key.pem"
declare -x CGW_CERTS_PATH="/etc/ssl/certs" # Path to certificates located on host machine
declare -x CGW_ALLOW_CERT_MISMATCH="no" # Allow client certificate CN and device MAC address mismatch
declare -x CGW_NB_INFRA_CERTS_PATH="/etc/nb_infra_certs"
declare -x CGW_NB_INFRA_TLS="no"
```
# Certificates
The CGW uses two different sets of certificate configuration:
Expand Down
12 changes: 12 additions & 0 deletions run_cgw.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ DEFAULT_DB_PORT=5432
DEFAULT_DB_NAME="cgw"
DEFAULT_DB_USER="cgw"
DEFAULT_DB_PASW="123"
DEFAULT_DB_TLS="no"

DEFAULT_REDIS_HOST="localhost"
DEFAULT_REDIS_PORT=6379
DEFAULT_REDIS_TLS="no"

DEFAULT_METRICS_PORT=8080

CONTAINTER_CERTS_VOLUME="/etc/cgw/certs"
CONTAINTER_NB_INFRA_CERTS_VOLUME="/etc/cgw/nb_infra/certs"
DEFAULT_NB_INFRA_TLS="no"

DEFAULT_ALLOW_CERT_MISMATCH="no"

Expand All @@ -61,12 +64,15 @@ export CGW_DB_PORT="${CGW_DB_PORT:-$DEFAULT_DB_PORT}"
export CGW_DB_NAME="${CGW_DB_NAME:-$DEFAULT_DB_NAME}"
export CGW_DB_USERNAME="${CGW_DB_USER:-$DEFAULT_DB_USER}"
export CGW_DB_PASSWORD="${CGW_DB_PASS:-$DEFAULT_DB_PASW}"
export CGW_DB_TLS="${CGW_DB_TLS:-$DEFAULT_DB_TLS}"
export CGW_REDIS_HOST="${CGW_REDIS_HOST:-$DEFAULT_REDIS_HOST}"
export CGW_REDIS_PORT="${CGW_REDIS_PORT:-$DEFAULT_REDIS_PORT}"
export CGW_REDIS_TLS="${CGW_REDIS_TLS:-$DEFAULT_REDIS_TLS}"
export CGW_METRICS_PORT="${CGW_METRICS_PORT:-$DEFAULT_METRICS_PORT}"
export CGW_CERTS_PATH="${CGW_CERTS_PATH:-$DEFAULT_CERTS_PATH}"
export CGW_ALLOW_CERT_MISMATCH="${CGW_ALLOW_CERT_MISMATCH:-$DEFAULT_ALLOW_CERT_MISMATCH}"
export CGW_NB_INFRA_CERTS_PATH="${CGW_NB_INFRA_CERTS_PATH:-$DEFAULT_CERTS_PATH}"
export CGW_NB_INFRA_TLS="${CGW_NB_INFRA_TLS:-$DEFAULT_NB_INFRA_TLS}"

if [ -z "${!CGW_REDIS_USERNAME}" ]; then
export CGW_REDIS_USERNAME="${CGW_REDIS_USERNAME}"
Expand All @@ -90,11 +96,14 @@ echo "CGW KAFKA HOST/PORT : $CGW_KAFKA_HOST:$CGW_KAFKA_PORT"
echo "CGW KAFKA TOPIC : $CGW_KAFKA_CONSUME_TOPIC:$CGW_KAFKA_PRODUCE_TOPIC"
echo "CGW DB NAME : $CGW_DB_NAME"
echo "CGW DB HOST/PORT : $CGW_DB_HOST:$CGW_DB_PORT"
echo "CGW DB TLS : $CGW_DB_TLS"
echo "CGW REDIS HOST/PORT : $CGW_REDIS_HOST:$CGW_REDIS_PORT"
echo "CGW REDIS TLS : $CGW_REDIS_TLS"
echo "CGW METRICS PORT : $CGW_METRICS_PORT"
echo "CGW CERTS PATH : $CGW_CERTS_PATH"
echo "CGW ALLOW CERT MISMATCH : $CGW_ALLOW_CERT_MISMATCH"
echo "CGW NB INFRA CERTS PATH : $CGW_NB_INFRA_CERTS_PATH"
echo "CGW NB INFRA TLS : $CGW_NB_INFRA_TLS"

docker run \
--cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
Expand All @@ -121,11 +130,14 @@ docker run \
-e CGW_DB_PORT \
-e CGW_DB_USERNAME \
-e CGW_DB_PASSWORD \
-e CGW_DB_TLS \
-e CGW_REDIS_HOST \
-e CGW_REDIS_PORT \
-e CGW_REDIS_USERNAME \
-e CGW_REDIS_PASSWORD \
-e CGW_REDIS_TLS \
-e CGW_FEATURE_TOPOMAP_ENABLE \
-e CGW_METRICS_PORT \
-e CGW_ALLOW_CERT_MISMATCH \
-e CGW_NB_INFRA_TLS \
-d -t --network=host --name $2 $1 ucentral-cgw
33 changes: 31 additions & 2 deletions src/cgw_app_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ const CGW_DEFAULT_DB_PORT: u16 = 6379;
const CGW_DEFAULT_DB_NAME: &str = "cgw";
const CGW_DEFAULT_DB_USERNAME: &str = "cgw";
const CGW_DEFAULT_DB_PASSWORD: &str = "123";
const CGW_DEFAULT_DB_TLS: &str = "no";
const CGW_DEFAULT_REDIS_HOST: &str = "localhost";
const CGW_DEFAULT_REDIS_PORT: u16 = 6379;
const CGW_DEFAULT_REDIS_TLS: &str = "no";
const CGW_DEFAULT_ALLOW_CERT_MISMATCH: &str = "no";
const CGW_DEFAULT_METRICS_PORT: u16 = 8080;
const CGW_DEFAULT_TOPOMAP_STATE: bool = false;
const CGW_DEFAULT_NB_INFRA_TLS: &str = "no";

pub struct CGWWSSArgs {
/// Number of thread in a threadpool dedicated for handling secure websocket connections
Expand Down Expand Up @@ -252,6 +255,8 @@ pub struct CGWDBArgs {
pub db_username: String,
/// DB user password use with connection to in DB (PSQL)
pub db_password: String,
/// Utilize TLS connection with DB server
pub db_tls: bool,
}

impl CGWDBArgs {
Expand Down Expand Up @@ -289,12 +294,16 @@ impl CGWDBArgs {
let db_password: String =
env::var("CGW_DB_PASSWORD").unwrap_or(CGW_DEFAULT_DB_PASSWORD.to_string());

let db_tls_var: String = env::var("CGW_DB_TLS").unwrap_or(CGW_DEFAULT_DB_TLS.to_string());
let db_tls = db_tls_var == "yes";

Ok(CGWDBArgs {
db_host,
db_port,
db_name,
db_username,
db_password,
db_tls,
})
}
}
Expand All @@ -308,6 +317,8 @@ pub struct CGWRedisArgs {
pub redis_username: Option<String>,
/// REDIS password
pub redis_password: Option<String>,
/// Utilize TLS connection with DB server
pub redis_tls: bool,
}

impl CGWRedisArgs {
Expand Down Expand Up @@ -361,11 +372,16 @@ impl CGWRedisArgs {
Err(_) => None,
};

let redis_tls_var: String =
env::var("CGW_REDIS_TLS").unwrap_or(CGW_DEFAULT_REDIS_TLS.to_string());
let redis_tls = redis_tls_var == "yes";

Ok(CGWRedisArgs {
redis_host,
redis_port,
redis_username,
redis_password,
redis_tls,
})
}
}
Expand Down Expand Up @@ -404,6 +420,9 @@ pub struct AppArgs {
/// Topomap featue status (enabled/disabled)
pub feature_topomap_enabled: bool,

/// Utilize TLS connection with NB infrastructure (Redis, PostgreSQL)
pub nb_infra_tls: bool,

pub wss_args: CGWWSSArgs,

pub grpc_args: CGWGRPCArgs,
Expand Down Expand Up @@ -450,17 +469,27 @@ impl AppArgs {
Err(_) => CGW_DEFAULT_TOPOMAP_STATE,
};

let nb_infra_tls_var: String =
env::var("CGW_NB_INFRA_TLS").unwrap_or(CGW_DEFAULT_NB_INFRA_TLS.to_string());
let nb_infra_tls = nb_infra_tls_var == "yes";

let wss_args = CGWWSSArgs::parse()?;
let grpc_args = CGWGRPCArgs::parse()?;
let kafka_args = CGWKafkaArgs::parse()?;
let db_args = CGWDBArgs::parse()?;
let redis_args = CGWRedisArgs::parse()?;
let mut db_args = CGWDBArgs::parse()?;
let mut redis_args = CGWRedisArgs::parse()?;
let metrics_args = CGWMetricsArgs::parse()?;

if nb_infra_tls {
redis_args.redis_tls = nb_infra_tls;
db_args.db_tls = nb_infra_tls;
}

Ok(AppArgs {
log_level,
cgw_id,
feature_topomap_enabled,
nb_infra_tls,
wss_args,
grpc_args,
kafka_args,
Expand Down
96 changes: 64 additions & 32 deletions src/cgw_db_accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{

use eui48::MacAddress;

use tokio_postgres::NoTls;
use tokio_postgres::{row::Row, Client};

#[derive(Clone)]
Expand Down Expand Up @@ -60,46 +61,77 @@ impl CGWDBAccessor {
user = db_args.db_username,
db = db_args.db_name,
pass = db_args.db_password,
sslmode = "require",
sslmode = match db_args.db_tls {
true => "require",
false => "disable",
}
);
debug!(
"Trying to connect to remote db ({}:{})...\nConn args {}",
db_args.db_host, db_args.db_port, conn_str
);

let tls = match cgw_tls_create_db_connect().await {
Ok(tls_connect) => tls_connect,
Err(e) => {
error!(
"Failed to build TLS connection with remote DB, reason: {}",
e.to_string()
);
return Err(Error::DbAccessor(
"Failed to build TLS connection with remote DB",
));
}
};
let client: Client;
if db_args.db_tls {
let tls = match cgw_tls_create_db_connect().await {
Ok(tls_connect) => tls_connect,
Err(e) => {
error!(
"Failed to build TLS connection with remote DB, reason: {}",
e.to_string()
);
return Err(Error::DbAccessor(
"Failed to build TLS connection with remote DB",
));
}
};

let (client, connection) = match tokio_postgres::connect(&conn_str, tls).await {
Ok((cl, conn)) => (cl, conn),
Err(e) => {
error!("Failed to establish connection with DB, reason: {:?}", e);
return Err(Error::DbAccessor("Failed to establish connection with DB"));
}
};
let (db_client, connection) = match tokio_postgres::connect(&conn_str, tls).await {
Ok((cl, conn)) => (cl, conn),
Err(e) => {
error!("Failed to establish connection with DB, reason: {:?}", e);
return Err(Error::DbAccessor("Failed to establish connection with DB"));
}
};

tokio::spawn(async move {
if let Err(e) = connection.await {
let err_msg = format!("Connection to DB broken: {}", e);
error!("{}", err_msg);
CGWMetrics::get_ref()
.change_component_health_status(
CGWMetricsHealthComponent::DBConnection,
CGWMetricsHealthComponentStatus::NotReady(err_msg),
)
.await;
}
});
tokio::spawn(async move {
if let Err(e) = connection.await {
let err_msg = format!("Connection to DB broken: {}", e);
error!("{}", err_msg);
CGWMetrics::get_ref()
.change_component_health_status(
CGWMetricsHealthComponent::DBConnection,
CGWMetricsHealthComponentStatus::NotReady(err_msg),
)
.await;
}
});

client = db_client;
} else {
let (db_client, connection) = match tokio_postgres::connect(&conn_str, NoTls).await {
Ok((cl, conn)) => (cl, conn),
Err(e) => {
error!("Failed to establish connection with DB, reason: {:?}", e);
return Err(Error::DbAccessor("Failed to establish connection with DB"));
}
};

tokio::spawn(async move {
if let Err(e) = connection.await {
let err_msg = format!("Connection to DB broken: {}", e);
error!("{}", err_msg);
CGWMetrics::get_ref()
.change_component_health_status(
CGWMetricsHealthComponent::DBConnection,
CGWMetricsHealthComponentStatus::NotReady(err_msg),
)
.await;
}
});

client = db_client;
}

tokio::spawn(async move {
CGWMetrics::get_ref()
Expand Down
40 changes: 27 additions & 13 deletions src/cgw_remote_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,29 +151,43 @@ pub struct CGWRemoteDiscovery {

async fn cgw_create_redis_client(redis_args: &CGWRedisArgs) -> Result<Client> {
let redis_client_info = ConnectionInfo {
addr: redis::ConnectionAddr::TcpTls {
host: redis_args.redis_host.clone(),
port: redis_args.redis_port,
insecure: true,
tls_params: None,
addr: match redis_args.redis_tls {
true => redis::ConnectionAddr::TcpTls {
host: redis_args.redis_host.clone(),
port: redis_args.redis_port,
insecure: true,
tls_params: None,
},
false => {
redis::ConnectionAddr::Tcp(redis_args.redis_host.clone(), redis_args.redis_port)
}
},

redis: RedisConnectionInfo {
username: redis_args.redis_username.clone(),
password: redis_args.redis_password.clone(),
..Default::default()
},
};

let root_cert = cgw_read_root_certs_dir().await.ok();
match redis_args.redis_tls {
true => {
let root_cert = cgw_read_root_certs_dir().await.ok();

let tls_certs: TlsCertificates = TlsCertificates {
client_tls: None,
root_cert,
};
let tls_certs: TlsCertificates = TlsCertificates {
client_tls: None,
root_cert,
};

match redis::Client::build_with_tls(redis_client_info, tls_certs) {
Ok(client) => Ok(client),
Err(e) => Err(Error::Redis(format!("Failed to start Redis Client: {}", e))),
match redis::Client::build_with_tls(redis_client_info, tls_certs) {
Ok(client) => Ok(client),
Err(e) => Err(Error::Redis(format!("Failed to start Redis Client: {}", e))),
}
}
false => match redis::Client::open(redis_client_info) {
Ok(client) => Ok(client),
Err(e) => Err(Error::Redis(format!("Failed to start Redis Client: {}", e))),
},
}
}

Expand Down
Loading