postgre-tls/entrypoint.sh

260 lines
10 KiB
Bash
Executable File

#!/bin/bash
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}[Postgre-TLS] Starting PostgreSQL with encryption...${NC}"
# Function to setup SSL certificates from Docker Swarm secrets
setup_ssl_certificates() {
echo -e "${YELLOW}[Postgre-TLS] Setting up SSL certificates from Docker Swarm secrets...${NC}"
# Debug: list contents of /run/secrets
echo -e "${YELLOW}[Postgre-TLS] Listing contents of /run/secrets:${NC}"
ls -la /run/secrets/ || echo "No /run/secrets directory found"
# Check if running in Docker Swarm mode
if [ -f "/run/secrets/server_crt" ] || [ -f "/run/secrets/server.crt" ]; then
echo -e "${YELLOW}[Postgre-TLS] Using SSL certificates from Docker Swarm secrets...${NC}"
# Copy certificates from Docker secrets to expected locations
if [ -f "/run/secrets/ca_crt" ]; then
cp /run/secrets/ca_crt /var/lib/postgresql/ssl/ca.crt
elif [ -f "/run/secrets/ca.crt" ]; then
cp /run/secrets/ca.crt /var/lib/postgresql/ssl/ca.crt
fi
if [ -f "/run/secrets/server_crt" ]; then
cp /run/secrets/server_crt /var/lib/postgresql/ssl/server.crt
elif [ -f "/run/secrets/server.crt" ]; then
cp /run/secrets/server.crt /var/lib/postgresql/ssl/server.crt
fi
if [ -f "/run/secrets/server_key" ]; then
cp /run/secrets/server_key /var/lib/postgresql/ssl/server.key
elif [ -f "/run/secrets/server.key" ]; then
cp /run/secrets/server.key /var/lib/postgresql/ssl/server.key
fi
# Set proper permissions
chmod 600 /var/lib/postgresql/ssl/server.key
chmod 644 /var/lib/postgresql/ssl/server.crt
chmod 644 /var/lib/postgresql/ssl/ca.crt
# Set ownership to postgres user
chown postgres:postgres /var/lib/postgresql/ssl/*
echo -e "${GREEN}[Postgre-TLS] SSL certificates from Docker Swarm configured successfully${NC}"
elif [ "$ENABLE_FALLBACK_SSL" = "true" ]; then
echo -e "${YELLOW}[Postgre-TLS] Generating fallback SSL certificates for local development...${NC}"
# Generate CA private key
openssl genrsa -out /var/lib/postgresql/ssl/ca.key 2048
# Generate CA certificate
openssl req -new -x509 -key /var/lib/postgresql/ssl/ca.key \
-out /var/lib/postgresql/ssl/ca.crt -days 365 \
-subj "/C=US/ST=State/L=City/O=Postgre-TLS/CN=Postgre-TLS-CA"
# Generate server private key
openssl genrsa -out /var/lib/postgresql/ssl/server.key 2048
# Generate server certificate signing request
openssl req -new -key /var/lib/postgresql/ssl/server.key \
-out /var/lib/postgresql/ssl/server.csr \
-subj "/C=US/ST=State/L=City/O=Postgre-TLS/CN=localhost"
# Generate server certificate signed by CA
openssl x509 -req -in /var/lib/postgresql/ssl/server.csr \
-CA /var/lib/postgresql/ssl/ca.crt \
-CAkey /var/lib/postgresql/ssl/ca.key \
-CAcreateserial -out /var/lib/postgresql/ssl/server.crt \
-days 365
# Clean up CSR
rm /var/lib/postgresql/ssl/server.csr
# Set proper permissions
chmod 600 /var/lib/postgresql/ssl/server.key
chmod 644 /var/lib/postgresql/ssl/server.crt
chmod 644 /var/lib/postgresql/ssl/ca.crt
# Set ownership to postgres user
chown postgres:postgres /var/lib/postgresql/ssl/*
echo -e "${GREEN}[Postgre-TLS] Fallback SSL certificates generated successfully${NC}"
else
echo -e "${RED}[Postgre-TLS] Error: SSL certificates must be provided via Docker Swarm secrets. Fallback generation is not supported.${NC}"
exit 1
fi
}
# Function to check if database needs initialization
needs_initialization() {
if [ ! -s "$PGDATA/PG_VERSION" ]; then
return 0 # true - needs initialization
else
return 1 # false - already initialized
fi
}
# Function to load secrets from Docker Swarm or environment
load_secrets() {
echo -e "${YELLOW}[Postgre-TLS] Loading secrets...${NC}"
# Check if secrets are available
if [ -f "/run/secrets/postgres_password" ]; then
echo -e "${YELLOW}[Postgre-TLS] Loading secrets from /run/secrets...${NC}"
export POSTGRES_PASSWORD=$(cat /run/secrets/postgres_password)
export BACKUP_ENCRYPTION_KEY=$(cat /run/secrets/backup_encryption_key 2>/dev/null || echo "")
export JWT_SECRET=$(cat /run/secrets/jwt_secret 2>/dev/null || echo "")
export APP_SECRET_KEY=$(cat /run/secrets/app_secret_key 2>/dev/null || echo "")
echo -e "${GREEN}[Postgre-TLS] Secrets loaded from /run/secrets${NC}"
echo "Loaded POSTGRES_PASSWORD: $POSTGRES_PASSWORD"
else
echo -e "${YELLOW}[Postgre-TLS] Using environment variables for secrets${NC}"
export POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-change_me_in_production}"
fi
# Set default values for other variables
export POSTGRES_DB="${POSTGRES_DB:-postgre_tls}"
export POSTGRES_USER="${POSTGRES_USER:-postgre_tls_user}"
}
# Function to initialize database with encryption
initialize_database() {
echo -e "${YELLOW}[Postgre-TLS] Initializing database...${NC}"
# Create a temporary password file with proper ownership
su-exec postgres sh -c "echo '$POSTGRES_PASSWORD' > /tmp/pgpass"
su-exec postgres chmod 600 /tmp/pgpass
# Initialize the database with proper encoding and authentication
# Create the main database during initdb
export POSTGRES_DB="${POSTGRES_DB:-postgre_tls}"
su-exec postgres initdb \
--pgdata="$PGDATA" \
--username="$POSTGRES_USER" \
--pwfile=/tmp/pgpass \
--auth-local=scram-sha-256 \
--auth-host=scram-sha-256 \
--encoding=UTF8 \
--locale=C.UTF-8 \
--data-checksums
# Clean up password file
rm -f /tmp/pgpass
echo -e "${GREEN}[Postgre-TLS] Database initialized successfully${NC}"
}
# Function to start PostgreSQL
start_postgresql() {
echo -e "${YELLOW}[Postgre-TLS] Starting PostgreSQL server...${NC}"
# Start PostgreSQL with custom configuration
exec su-exec postgres postgres \
-c config_file=/etc/postgresql/postgresql.conf \
-c ssl=on \
-c ssl_cert_file=/var/lib/postgresql/ssl/server.crt \
-c ssl_key_file=/var/lib/postgresql/ssl/server.key \
-c ssl_ca_file=/var/lib/postgresql/ssl/ca.crt \
-c shared_preload_libraries=pg_stat_statements \
-c log_statement=ddl \
-c log_destination=stderr \
-c logging_collector=on \
-c log_directory=/var/log/postgresql \
-c log_filename=postgresql.log
}
# Main execution
main() {
# Set PGDATA if not set
export PGDATA="${PGDATA:-/var/lib/postgresql/data}"
# Ensure data directory exists and has proper permissions
# mkdir -p "$PGDATA"
# chown postgres:postgres "$PGDATA"
# chmod 700 "$PGDATA"
# Load secrets from Docker Swarm or environment
load_secrets
# Setup SSL certificates
setup_ssl_certificates
# Initialize database if needed
if needs_initialization; then
echo -e "${YELLOW}[Postgre-TLS] Database not found, initializing...${NC}"
initialize_database
# Create temporary pg_hba.conf for trust authentication during init
echo 'local all all trust' > /tmp/pg_hba.conf
echo 'host all all 127.0.0.1/32 trust' >> /tmp/pg_hba.conf
echo 'host all all ::1/128 trust' >> /tmp/pg_hba.conf
# Start PostgreSQL temporarily with temporary hba for initialization
echo -e "${YELLOW}[Postgre-TLS] Starting PostgreSQL temporarily for initialization...${NC}"
su-exec postgres postgres \
-c config_file=/etc/postgresql/postgresql.conf \
-c ssl=off \
-c listen_addresses=localhost \
-c port=5432 \
-c hba_file=/tmp/pg_hba.conf &
# Wait for PostgreSQL to start
until su-exec postgres pg_isready -h localhost -p 5432; do
echo -e "${YELLOW}[Postgre-TLS] Waiting for PostgreSQL to start...${NC}"
sleep 1
done
# Create the application database if it doesn't exist
echo -e "${YELLOW}[Postgre-TLS] Creating database: $POSTGRES_DB${NC}"
su-exec postgres createdb -h localhost -p 5432 -U "$POSTGRES_USER" "$POSTGRES_DB" 2>/dev/null || echo -e "${GREEN}[Postgre-TLS] Database $POSTGRES_DB already exists${NC}"
# Run initialization scripts
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh)
echo -e "${YELLOW}[Postgre-TLS] Running $f${NC}"
bash "$f"
;;
*.sql)
echo -e "${YELLOW}[Postgre-TLS] Running $f${NC}"
su-exec postgres psql -v ON_ERROR_STOP=1 -h localhost -p 5432 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$f"
;;
*)
echo -e "${YELLOW}[Postgre-TLS] Ignoring $f${NC}"
;;
esac
done
# Stop the temporary PostgreSQL instance
su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop
# Configure final pg_hba.conf for SSL connections
echo -e "${YELLOW}[Postgre-TLS] Configuring pg_hba.conf for SSL...${NC}"
cat > "$PGDATA/pg_hba.conf" <<EOF
# TYPE DATABASE USER ADDRESS METHOD
local all all scram-sha-256
hostssl all all 0.0.0.0/0 scram-sha-256
hostssl all all ::/0 scram-sha-256
EOF
chown postgres:postgres "$PGDATA/pg_hba.conf"
chmod 600 "$PGDATA/pg_hba.conf"
echo -e "${GREEN}[Postgre-TLS] Database initialization completed${NC}"
else
echo -e "${GREEN}[Postgre-TLS] Database already initialized${NC}"
fi
# Start PostgreSQL with full configuration
start_postgresql
}
# Run main function
main "$@"