Skip to content

Commit

Permalink
Utilize TLS connection for Redis & PostgeSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
SviatoslavBoichuk committed Jul 17, 2024
1 parent b8f5747 commit ab718d2
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 44 deletions.
95 changes: 95 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 21 additions & 20 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,42 @@ edition = "2021"

[dependencies]
serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.85"
env_logger = "0.11.3"
log = "0.4.20"
serde_json = { version = "1.0.85" }
env_logger = { version = "0.11.3" }
log = { version = "0.4.20" }
tokio = { version = "1.34.0", features = ["full"] }
tokio-stream = { version = "0.1.15", features = ["full"] }
tokio-tungstenite = { version = "0.23.0" }
tokio-rustls = "0.26.0"
tokio-rustls = { version = "0.26.0" }
tokio-postgres = { version = "0.7.10", features = ["with-eui48-1"] }
tokio-pg-mapper = "0.2.0"
tokio-postgres-rustls = { version = "0.12.0" }
tokio-pg-mapper = { version = "0.2.0" }
tungstenite = { version = "0.23.0" }
futures-util = { version = "0.3.0", default-features = false }
futures-channel = "0.3.0"
futures-channel = { version = "0.3.0" }
futures-executor = { version = "0.3.0", optional = true }
futures = "0.3.0"
rlimit = "0.10.1"
tonic = "0.11.0"
prost = "0.12"
rdkafka = "0.36.2"
futures = { version = "0.3.0" }
rlimit = { version = "0.10.1" }
tonic = { version = "0.11.0" }
prost = { version = "0.12" }
rdkafka = { version = "0.36.2" }
eui48 = { version = "1.1.0", features = ["serde"] }
uuid = { version = "1.6.1", features = ["serde"] }
redis = { version = "0.25.3", features = [
"tokio-rustls-comp",
"tls-rustls-insecure",
] }
warp = "0.3.7"
warp = { version = "0.3.7" }
prometheus = { version = "0.13.4", features = ["process"] }
lazy_static = "1.4.0"
lazy_static = { version = "1.4.0" }
petgraph = { version = "0.6.4", features = ["stable_graph"] }
flate2 = "1.0.28"
base64 = "0.22.0"
rustls-pemfile = "2.1.2"
rustls-pki-types = "1.7.0"
x509-parser = "0.16.0"
chrono = "0.4.38"
derive_more = "0.99.17"
flate2 = { version = "1.0.28" }
base64 = { version = "0.22.0" }
rustls-pemfile = { version = "2.1.2" }
rustls-pki-types = { version = "1.7.0" }
x509-parser = { version = "0.16.0" }
chrono = { version = "0.4.38" }
derive_more = { version = "0.99.17" }

[build-dependencies]
tonic-build = "0.11.0"
Expand Down
34 changes: 22 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,38 +80,44 @@ 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
```

Example of properly configured list of env variables to start CGW:
```console
$ export | grep CGW
declare -x CGW_DB_HOST="localhost" # PSQL server is located at the local host
declare -x CGW_DB_HOST="localhost" # PSQL server is located at the local host
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_GRPC_LISTENING_IP="127.0.0.1" # Local default subnet is 127.0.0.1/24
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_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"
declare -x CGW_GRPC_PUBLIC_PORT="50051"
declare -x CGW_ID="0"
declare -x CGW_KAFKA_HOST="localhost" # Kafka is located at the local host
declare -x CGW_KAFKA_HOST="localhost" # Kafka is located at the local host
declare -x CGW_KAFKA_PORT="9092"
declare -x CGW_LOG_LEVEL="debug"
declare -x CGW_REDIS_HOST="localhost" # Redis server can be found at the local host
declare -x CGW_REDIS_HOST="localhost" # Redis server can be found at the local host
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_USERNAME="cgw" # REDIS login credentials (username) - optional
declare -x CGW_REDIS_PASSWORD="123" # REDIS login credentials (password) - optional
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_IP="0.0.0.0" # Accept WSS connections at all interfaces / subnets
declare -x CGW_WSS_PORT="15002"
declare -x CGW_WSS_CAS="cas.pem"
declare -x CGW_WSS_CERT="cert.pem"
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_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"
```
# Certificates
The CGW uses a number of certificates to provide security.
The CGW uses two different sets of certificate configuration:
1. AP/Switch connectivity (southbound)
2. Infrastructure connectivity (northbound)

The AP/Switch connectivity uses a number of certificates to provide security (mTLS).
There are 2 types of certificates required for a normal deployment:
1. Server certificates
2. Client certificates
Expand All @@ -123,3 +129,7 @@ There are several environment variable to configure certificates path and names
2. CGW_WSS_KEY - CGW WSS Private Key
3. CGW_WSS_CAS - Chain certificates to validate client (root/issuer)
4. CGW_CERTS_PATH - path to certificates located on host machine

The infrastructure connectivity use root certs store - the directory with trusted certificates
The environemt variable to configure certificates path:
1. CGW_NB_INFRA_CERTS_PATH - path to certificates located on host machine
8 changes: 6 additions & 2 deletions run_cgw.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ DEFAULT_REDIS_PORT=6379
DEFAULT_METRICS_PORT=8080

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

DEFAULT_ALLOW_CERT_MISMATCH="no"

Expand Down Expand Up @@ -65,6 +66,7 @@ export CGW_REDIS_PORT="${CGW_REDIS_PORT:-$DEFAULT_REDIS_PORT}"
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}"

if [ -z "${!CGW_REDIS_USERNAME}" ]; then
export CGW_REDIS_USERNAME="${CGW_REDIS_USERNAME}"
Expand Down Expand Up @@ -92,10 +94,12 @@ echo "CGW REDIS HOST/PORT : $CGW_REDIS_HOST:$CGW_REDIS_PORT"
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"

docker run \
--cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
-v $CGW_CERTS_PATH:$CONTAINTER_CERTS_VOLUME \
--cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
-v $CGW_CERTS_PATH:$CONTAINTER_CERTS_VOLUME \
-v $CGW_NB_INFRA_CERTS_PATH:$CONTAINTER_NB_INFRA_CERTS_VOLUME \
-e CGW_LOG_LEVEL \
-e CGW_ID \
-e CGW_WSS_IP \
Expand Down
23 changes: 19 additions & 4 deletions src/cgw_db_accessor.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::cgw_app_args::CGWDBArgs;

use crate::cgw_tls::cgw_tls_create_db_connect;
use crate::{
cgw_errors::{Error, Result},
cgw_metrics::{CGWMetrics, CGWMetricsHealthComponent, CGWMetricsHealthComponentStatus},
};

use eui48::MacAddress;

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

#[derive(Clone)]
pub struct CGWDBInfra {
Expand Down Expand Up @@ -53,19 +54,33 @@ pub struct CGWDBAccessor {
impl CGWDBAccessor {
pub async fn new(db_args: &CGWDBArgs) -> Result<Self> {
let conn_str = format!(
"host={host} port={port} user={user} dbname={db} password={pass} connect_timeout=10",
"sslmode={sslmode} host={host} port={port} user={user} dbname={db} password={pass} connect_timeout=10",
host = db_args.db_host,
port = db_args.db_port,
user = db_args.db_username,
db = db_args.db_name,
pass = db_args.db_password
pass = db_args.db_password,
sslmode = "require",
);
debug!(
"Trying to connect to remote db ({}:{})...\nConn args {}",
db_args.db_host, db_args.db_port, conn_str
);

let (client, connection) = match tokio_postgres::connect(&conn_str, NoTls).await {
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);
Expand Down
3 changes: 3 additions & 0 deletions src/cgw_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub enum Error {
#[from]
TokioSync(tokio::sync::TryLockError),

#[from]
Tokiofs(tokio::fs::ReadDir),

#[from]
IpAddressParse(std::net::AddrParseError),

Expand Down
Loading

0 comments on commit ab718d2

Please sign in to comment.