From 69e3cecb40fdd2b8e6a84136298c983b2442db9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CGiems=E2=80=9D?= <“hubert.wabia@gmail.com”> Date: Mon, 12 Aug 2024 15:35:48 +0200 Subject: [PATCH] grafana read only user --- infra/.env | 4 ++ infra/scripts/clean_start.sh | 41 +++++++++++++++++++ .../setup_database_datasource.rs | 4 +- server/src/infra_env.rs | 14 +++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/infra/.env b/infra/.env index 3d8d9b83..c738af77 100755 --- a/infra/.env +++ b/infra/.env @@ -12,6 +12,10 @@ POSTGRES_PASSWORD=password12345 POSTGRES_DB=connect_db PG_DATA=/home/postgres/pgdata +# Grafana read only database user +GRAFANA_DB_USERNAME=grafanaaccess +GRAFANA_DB_PASSWORD=very-stronk-password + # Images # https://github.com/timescale/timescaledb-docker-ha TIMESCALEDB_IMAGE=timescale/timescaledb-ha:pg15-ts2.10 diff --git a/infra/scripts/clean_start.sh b/infra/scripts/clean_start.sh index 4d39ec51..0b98b0fa 100755 --- a/infra/scripts/clean_start.sh +++ b/infra/scripts/clean_start.sh @@ -227,6 +227,47 @@ if wait_for_db_ready; then # echo "Not a CI, displaying the container logs..." # docker logs -f $CONTAINER_ID # fi + + echo "Creating a restricted user for Grafana in the database..." + + # Verify the variables are set + if [ -z "$GRAFANA_DB_USERNAME" ] || [ -z "$GRAFANA_DB_PASSWORD" ]; then + echo "Error: GRAFANA_DB_USERNAME or GRAFANA_DB_PASSWORD is not set. Please set these variables." + exit 1 + fi + printf "DATABASE NAME: $POSTGRES_DB\n" + + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "CREATE USER $GRAFANA_DB_USERNAME WITH PASSWORD '$GRAFANA_DB_PASSWORD';" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "GRANT CONNECT ON DATABASE $POSTGRES_DB TO $GRAFANA_DB_USERNAME;" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "GRANT USAGE ON SCHEMA public TO $GRAFANA_DB_USERNAME;" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO $GRAFANA_DB_USERNAME;" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO $GRAFANA_DB_USERNAME;" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "REVOKE DELETE ON ALL TABLES IN SCHEMA public FROM $GRAFANA_DB_USERNAME;" + docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE DELETE ON TABLES FROM $GRAFANA_DB_USERNAME;" + + echo "Restricted user for Grafana has been created with SELECT privileges only." + + # Check if the user was created successfully + echo "Verifying the user creation and connection..." + # This query will return a row if the user exists + user_exists=$(docker exec -u postgres $CONTAINER_ID psql -d "$POSTGRES_DB" -tAc "SELECT 1 FROM pg_roles WHERE rolname = '$GRAFANA_DB_USERNAME';") + + if [[ "$user_exists" == "1" ]]; then + echo "User $GRAFANA_DB_USERNAME exists in the database." + else + echo "User $GRAFANA_DB_USERNAME does not exist. Please check the creation process." + exit 1 + fi + + # Check if the new user can connect and run a query + docker exec -u postgres $CONTAINER_ID psql -U "$GRAFANA_DB_USERNAME" -d "$POSTGRES_DB" -c "SELECT 1;" &>/dev/null + + if [ $? -eq 0 ]; then + echo "User $GRAFANA_DB_USERNAME created and verified successfully." + else + echo "Failed to verify user $GRAFANA_DB_USERNAME. Please check the PostgreSQL logs." + exit 1 + fi else echo "Failed to confirm TimescaleDB readiness after restart. Check logs for more details." exit 1 diff --git a/server/src/http/cloud/grafana_utils/setup_database_datasource.rs b/server/src/http/cloud/grafana_utils/setup_database_datasource.rs index 220c4239..e0639bd0 100644 --- a/server/src/http/cloud/grafana_utils/setup_database_datasource.rs +++ b/server/src/http/cloud/grafana_utils/setup_database_datasource.rs @@ -1,6 +1,6 @@ use crate::{ env::DATABASE_ADDRESS, - infra_env::{POSTGRES_DB, POSTGRES_USER}, + infra_env::{GRAFANA_DB_USERNAME, POSTGRES_DB}, statics::POSTGRES_DATASOURCE_UID, structs::cloud::grafana_error::handle_grafana_error, }; @@ -26,7 +26,7 @@ pub async fn setup_database_datasource( // DATABASE ADDRESS from main env file url: Some(DATABASE_ADDRESS().to_string()), database: Some(POSTGRES_DB().to_string()), - user: Some(POSTGRES_USER().to_string()), + user: Some(GRAFANA_DB_USERNAME().to_string()), basic_auth: None, with_credentials: Some(false), is_default: Some(true), diff --git a/server/src/infra_env.rs b/server/src/infra_env.rs index deb74985..27970b51 100644 --- a/server/src/infra_env.rs +++ b/server/src/infra_env.rs @@ -11,6 +11,8 @@ pub struct INFRA_ENV { pub POSTGRES_PASSWORD: String, pub POSTGRES_DB: String, pub PG_DATA: String, + pub GRAFANA_DB_USERNAME: String, + pub GRAFANA_DB_PASSWORD: String, pub TIMESCALEDB_IMAGE: String, pub OFELIA_IMAGE: String, pub TIMESCALEDB_DATA: String, @@ -47,6 +49,10 @@ pub fn get_env() -> &'static INFRA_ENV { .expect("Failed to get POSTGRES_PASSWORD env"), POSTGRES_DB: std::env::var("POSTGRES_DB").expect("Failed to get POSTGRES_DB env"), PG_DATA: std::env::var("PG_DATA").expect("Failed to get PG_DATA env"), + GRAFANA_DB_USERNAME: std::env::var("GRAFANA_DB_USERNAME") + .expect("Failed to get GRAFANA_DB_USERNAME env"), + GRAFANA_DB_PASSWORD: std::env::var("GRAFANA_DB_PASSWORD") + .expect("Failed to get GRAFANA_DB_PASSWORD env"), TIMESCALEDB_IMAGE: std::env::var("TIMESCALEDB_IMAGE") .expect("Failed to get TIMESCALEDB_IMAGE env"), OFELIA_IMAGE: std::env::var("OFELIA_IMAGE").expect("Failed to get OFELIA_IMAGE env"), @@ -166,3 +172,11 @@ pub fn OFELIA_EMAIL_FROM() -> &'static str { pub fn OFELIA_EMAIL_TO() -> &'static str { get_env().OFELIA_EMAIL_TO.as_str() } + +pub fn GRAFANA_DB_USERNAME() -> &'static str { + get_env().GRAFANA_DB_USERNAME.as_str() +} + +pub fn GRAFANA_DB_PASSWORD() -> &'static str { + get_env().GRAFANA_DB_PASSWORD.as_str() +}