519 lines
16 KiB
Bash
519 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
# TLS/HTTPS Setup Script for BotServer
|
|
# This script sets up a complete TLS infrastructure with internal CA and certificates for all services
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
CERT_DIR="./certs"
|
|
CA_DIR="$CERT_DIR/ca"
|
|
VALIDITY_DAYS=365
|
|
COUNTRY="BR"
|
|
STATE="SP"
|
|
LOCALITY="São Paulo"
|
|
ORGANIZATION="BotServer"
|
|
COMMON_NAME_SUFFIX="botserver.local"
|
|
|
|
# Services that need certificates
|
|
SERVICES=(
|
|
"api:8443:localhost,api.botserver.local,127.0.0.1"
|
|
"llm:8444:localhost,llm.botserver.local,127.0.0.1"
|
|
"embedding:8445:localhost,embedding.botserver.local,127.0.0.1"
|
|
"qdrant:6334:localhost,qdrant.botserver.local,127.0.0.1"
|
|
"redis:6380:localhost,redis.botserver.local,127.0.0.1"
|
|
"postgres:5433:localhost,postgres.botserver.local,127.0.0.1"
|
|
"minio:9001:localhost,minio.botserver.local,127.0.0.1"
|
|
"directory:8446:localhost,directory.botserver.local,127.0.0.1"
|
|
"email:465:localhost,email.botserver.local,127.0.0.1"
|
|
"meet:7881:localhost,meet.botserver.local,127.0.0.1"
|
|
)
|
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE}BotServer TLS/HTTPS Setup${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
|
# Function to check if OpenSSL is installed
|
|
check_openssl() {
|
|
if ! command -v openssl &> /dev/null; then
|
|
echo -e "${RED}OpenSSL is not installed. Please install it first.${NC}"
|
|
exit 1
|
|
fi
|
|
echo -e "${GREEN}✓ OpenSSL found${NC}"
|
|
}
|
|
|
|
# Function to create directory structure
|
|
create_directories() {
|
|
echo -e "${YELLOW}Creating certificate directories...${NC}"
|
|
|
|
mkdir -p "$CA_DIR"
|
|
mkdir -p "$CA_DIR/private"
|
|
mkdir -p "$CA_DIR/certs"
|
|
mkdir -p "$CA_DIR/crl"
|
|
mkdir -p "$CA_DIR/newcerts"
|
|
|
|
# Create directories for each service
|
|
for service_config in "${SERVICES[@]}"; do
|
|
IFS=':' read -r service port sans <<< "$service_config"
|
|
mkdir -p "$CERT_DIR/$service"
|
|
done
|
|
|
|
# Create CA database files
|
|
touch "$CA_DIR/index.txt"
|
|
echo "1000" > "$CA_DIR/serial"
|
|
echo "1000" > "$CA_DIR/crlnumber"
|
|
|
|
echo -e "${GREEN}✓ Directories created${NC}"
|
|
}
|
|
|
|
# Function to create CA configuration
|
|
create_ca_config() {
|
|
echo -e "${YELLOW}Creating CA configuration...${NC}"
|
|
|
|
cat > "$CA_DIR/ca.conf" << EOF
|
|
[ ca ]
|
|
default_ca = CA_default
|
|
|
|
[ CA_default ]
|
|
dir = $CA_DIR
|
|
certs = \$dir/certs
|
|
crl_dir = \$dir/crl
|
|
new_certs_dir = \$dir/newcerts
|
|
database = \$dir/index.txt
|
|
serial = \$dir/serial
|
|
crlnumber = \$dir/crlnumber
|
|
crl = \$dir/crl.pem
|
|
certificate = \$dir/ca.crt
|
|
private_key = \$dir/private/ca.key
|
|
RANDFILE = \$dir/private/.rand
|
|
x509_extensions = usr_cert
|
|
name_opt = ca_default
|
|
cert_opt = ca_default
|
|
default_days = $VALIDITY_DAYS
|
|
default_crl_days = 30
|
|
default_md = sha256
|
|
preserve = no
|
|
policy = policy_loose
|
|
|
|
[ policy_loose ]
|
|
countryName = optional
|
|
stateOrProvinceName = optional
|
|
localityName = optional
|
|
organizationName = optional
|
|
organizationalUnitName = optional
|
|
commonName = supplied
|
|
emailAddress = optional
|
|
|
|
[ req ]
|
|
default_bits = 4096
|
|
default_keyfile = privkey.pem
|
|
distinguished_name = req_distinguished_name
|
|
attributes = req_attributes
|
|
x509_extensions = v3_ca
|
|
string_mask = utf8only
|
|
default_md = sha256
|
|
|
|
[ req_distinguished_name ]
|
|
countryName = Country Name (2 letter code)
|
|
countryName_default = $COUNTRY
|
|
stateOrProvinceName = State or Province Name (full name)
|
|
stateOrProvinceName_default = $STATE
|
|
localityName = Locality Name (eg, city)
|
|
localityName_default = $LOCALITY
|
|
organizationName = Organization Name (eg, company)
|
|
organizationName_default = $ORGANIZATION
|
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
|
commonName = Common Name (e.g. server FQDN or YOUR name)
|
|
emailAddress = Email Address
|
|
|
|
[ req_attributes ]
|
|
challengePassword = A challenge password
|
|
challengePassword_min = 4
|
|
challengePassword_max = 20
|
|
unstructuredName = An optional company name
|
|
|
|
[ v3_ca ]
|
|
subjectKeyIdentifier = hash
|
|
authorityKeyIdentifier = keyid:always,issuer
|
|
basicConstraints = critical,CA:true
|
|
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
|
|
[ v3_intermediate_ca ]
|
|
subjectKeyIdentifier = hash
|
|
authorityKeyIdentifier = keyid:always,issuer
|
|
basicConstraints = critical, CA:true, pathlen:0
|
|
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
|
|
[ usr_cert ]
|
|
basicConstraints = CA:FALSE
|
|
nsCertType = client, email
|
|
nsComment = "OpenSSL Generated Client Certificate"
|
|
subjectKeyIdentifier = hash
|
|
authorityKeyIdentifier = keyid,issuer
|
|
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
|
|
extendedKeyUsage = clientAuth, emailProtection
|
|
|
|
[ server_cert ]
|
|
basicConstraints = CA:FALSE
|
|
nsCertType = server
|
|
nsComment = "OpenSSL Generated Server Certificate"
|
|
subjectKeyIdentifier = hash
|
|
authorityKeyIdentifier = keyid,issuer:always
|
|
keyUsage = critical, digitalSignature, keyEncipherment
|
|
extendedKeyUsage = serverAuth
|
|
EOF
|
|
|
|
echo -e "${GREEN}✓ CA configuration created${NC}"
|
|
}
|
|
|
|
# Function to generate Root CA
|
|
generate_root_ca() {
|
|
echo -e "${YELLOW}Generating Root CA...${NC}"
|
|
|
|
if [ -f "$CA_DIR/ca.crt" ] && [ -f "$CA_DIR/private/ca.key" ]; then
|
|
echo -e "${YELLOW}Root CA already exists, skipping...${NC}"
|
|
return
|
|
fi
|
|
|
|
# Generate Root CA private key
|
|
openssl genrsa -out "$CA_DIR/private/ca.key" 4096
|
|
chmod 400 "$CA_DIR/private/ca.key"
|
|
|
|
# Generate Root CA certificate
|
|
openssl req -config "$CA_DIR/ca.conf" \
|
|
-key "$CA_DIR/private/ca.key" \
|
|
-new -x509 -days 7300 -sha256 -extensions v3_ca \
|
|
-out "$CA_DIR/ca.crt" \
|
|
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/CN=BotServer Root CA"
|
|
|
|
# Copy CA cert to main cert directory for easy access
|
|
cp "$CA_DIR/ca.crt" "$CERT_DIR/ca.crt"
|
|
|
|
echo -e "${GREEN}✓ Root CA generated${NC}"
|
|
}
|
|
|
|
# Function to generate Intermediate CA
|
|
generate_intermediate_ca() {
|
|
echo -e "${YELLOW}Generating Intermediate CA...${NC}"
|
|
|
|
if [ -f "$CA_DIR/intermediate.crt" ] && [ -f "$CA_DIR/private/intermediate.key" ]; then
|
|
echo -e "${YELLOW}Intermediate CA already exists, skipping...${NC}"
|
|
return
|
|
fi
|
|
|
|
# Generate Intermediate CA private key
|
|
openssl genrsa -out "$CA_DIR/private/intermediate.key" 4096
|
|
chmod 400 "$CA_DIR/private/intermediate.key"
|
|
|
|
# Generate Intermediate CA CSR
|
|
openssl req -config "$CA_DIR/ca.conf" \
|
|
-new -sha256 \
|
|
-key "$CA_DIR/private/intermediate.key" \
|
|
-out "$CA_DIR/intermediate.csr" \
|
|
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/CN=BotServer Intermediate CA"
|
|
|
|
# Sign Intermediate CA certificate with Root CA
|
|
openssl ca -config "$CA_DIR/ca.conf" \
|
|
-extensions v3_intermediate_ca \
|
|
-days 3650 -notext -md sha256 \
|
|
-in "$CA_DIR/intermediate.csr" \
|
|
-out "$CA_DIR/intermediate.crt" \
|
|
-batch
|
|
|
|
chmod 444 "$CA_DIR/intermediate.crt"
|
|
|
|
# Create certificate chain
|
|
cat "$CA_DIR/intermediate.crt" "$CA_DIR/ca.crt" > "$CA_DIR/ca-chain.crt"
|
|
|
|
echo -e "${GREEN}✓ Intermediate CA generated${NC}"
|
|
}
|
|
|
|
# Function to generate service certificate
|
|
generate_service_cert() {
|
|
local service=$1
|
|
local port=$2
|
|
local sans=$3
|
|
|
|
echo -e "${YELLOW}Generating certificates for $service...${NC}"
|
|
|
|
local cert_dir="$CERT_DIR/$service"
|
|
|
|
# Create SAN configuration
|
|
cat > "$cert_dir/san.conf" << EOF
|
|
[req]
|
|
distinguished_name = req_distinguished_name
|
|
req_extensions = v3_req
|
|
|
|
[req_distinguished_name]
|
|
|
|
[v3_req]
|
|
basicConstraints = CA:FALSE
|
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
|
subjectAltName = @alt_names
|
|
|
|
[alt_names]
|
|
EOF
|
|
|
|
# Add SANs
|
|
IFS=',' read -ra SAN_ARRAY <<< "$sans"
|
|
local san_index=1
|
|
for san in "${SAN_ARRAY[@]}"; do
|
|
if [[ $san =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echo "IP.$san_index = $san" >> "$cert_dir/san.conf"
|
|
else
|
|
echo "DNS.$san_index = $san" >> "$cert_dir/san.conf"
|
|
fi
|
|
((san_index++))
|
|
done
|
|
|
|
# Generate server private key
|
|
openssl genrsa -out "$cert_dir/server.key" 2048
|
|
chmod 400 "$cert_dir/server.key"
|
|
|
|
# Generate server CSR
|
|
openssl req -new -sha256 \
|
|
-key "$cert_dir/server.key" \
|
|
-out "$cert_dir/server.csr" \
|
|
-config "$cert_dir/san.conf" \
|
|
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/CN=$service.$COMMON_NAME_SUFFIX"
|
|
|
|
# Sign server certificate with CA
|
|
openssl x509 -req -in "$cert_dir/server.csr" \
|
|
-CA "$CA_DIR/ca.crt" \
|
|
-CAkey "$CA_DIR/private/ca.key" \
|
|
-CAcreateserial \
|
|
-out "$cert_dir/server.crt" \
|
|
-days $VALIDITY_DAYS \
|
|
-sha256 \
|
|
-extensions v3_req \
|
|
-extfile "$cert_dir/san.conf"
|
|
|
|
# Generate client certificate for mTLS
|
|
openssl genrsa -out "$cert_dir/client.key" 2048
|
|
chmod 400 "$cert_dir/client.key"
|
|
|
|
openssl req -new -sha256 \
|
|
-key "$cert_dir/client.key" \
|
|
-out "$cert_dir/client.csr" \
|
|
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/CN=$service-client.$COMMON_NAME_SUFFIX"
|
|
|
|
openssl x509 -req -in "$cert_dir/client.csr" \
|
|
-CA "$CA_DIR/ca.crt" \
|
|
-CAkey "$CA_DIR/private/ca.key" \
|
|
-CAcreateserial \
|
|
-out "$cert_dir/client.crt" \
|
|
-days $VALIDITY_DAYS \
|
|
-sha256
|
|
|
|
# Copy CA certificate to service directory
|
|
cp "$CA_DIR/ca.crt" "$cert_dir/ca.crt"
|
|
|
|
# Create full chain certificate
|
|
cat "$cert_dir/server.crt" "$CA_DIR/ca.crt" > "$cert_dir/fullchain.crt"
|
|
|
|
# Clean up CSR files
|
|
rm -f "$cert_dir/server.csr" "$cert_dir/client.csr" "$cert_dir/san.conf"
|
|
|
|
echo -e "${GREEN}✓ Certificates generated for $service (port $port)${NC}"
|
|
}
|
|
|
|
# Function to generate all service certificates
|
|
generate_all_service_certs() {
|
|
echo -e "${BLUE}Generating certificates for all services...${NC}"
|
|
|
|
for service_config in "${SERVICES[@]}"; do
|
|
IFS=':' read -r service port sans <<< "$service_config"
|
|
generate_service_cert "$service" "$port" "$sans"
|
|
done
|
|
|
|
echo -e "${GREEN}✓ All service certificates generated${NC}"
|
|
}
|
|
|
|
# Function to create TLS configuration file
|
|
create_tls_config() {
|
|
echo -e "${YELLOW}Creating TLS configuration file...${NC}"
|
|
|
|
cat > "$CERT_DIR/tls-config.toml" << EOF
|
|
# TLS Configuration for BotServer
|
|
# Generated on $(date)
|
|
|
|
[tls]
|
|
enabled = true
|
|
mtls_enabled = true
|
|
auto_generate_certs = true
|
|
renewal_threshold_days = 30
|
|
|
|
[ca]
|
|
ca_cert_path = "$CA_DIR/ca.crt"
|
|
ca_key_path = "$CA_DIR/private/ca.key"
|
|
intermediate_cert_path = "$CA_DIR/intermediate.crt"
|
|
intermediate_key_path = "$CA_DIR/private/intermediate.key"
|
|
validity_days = $VALIDITY_DAYS
|
|
organization = "$ORGANIZATION"
|
|
country = "$COUNTRY"
|
|
state = "$STATE"
|
|
locality = "$LOCALITY"
|
|
|
|
# Service configurations
|
|
EOF
|
|
|
|
for service_config in "${SERVICES[@]}"; do
|
|
IFS=':' read -r service port sans <<< "$service_config"
|
|
cat >> "$CERT_DIR/tls-config.toml" << EOF
|
|
|
|
[[services]]
|
|
name = "$service"
|
|
port = $port
|
|
cert_path = "$CERT_DIR/$service/server.crt"
|
|
key_path = "$CERT_DIR/$service/server.key"
|
|
client_cert_path = "$CERT_DIR/$service/client.crt"
|
|
client_key_path = "$CERT_DIR/$service/client.key"
|
|
ca_cert_path = "$CERT_DIR/$service/ca.crt"
|
|
sans = "$sans"
|
|
EOF
|
|
done
|
|
|
|
echo -e "${GREEN}✓ TLS configuration file created${NC}"
|
|
}
|
|
|
|
# Function to display certificate information
|
|
display_cert_info() {
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE}Certificate Information${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
|
|
echo -e "${YELLOW}Root CA:${NC}"
|
|
openssl x509 -in "$CA_DIR/ca.crt" -noout -subject -dates
|
|
|
|
echo ""
|
|
echo -e "${YELLOW}Service Certificates:${NC}"
|
|
for service_config in "${SERVICES[@]}"; do
|
|
IFS=':' read -r service port sans <<< "$service_config"
|
|
echo -e "${GREEN}$service (port $port):${NC}"
|
|
openssl x509 -in "$CERT_DIR/$service/server.crt" -noout -subject -dates
|
|
done
|
|
}
|
|
|
|
# Function to create environment variables file
|
|
create_env_vars() {
|
|
echo -e "${YELLOW}Creating environment variables file...${NC}"
|
|
|
|
cat > "$CERT_DIR/tls.env" << EOF
|
|
# TLS Environment Variables for BotServer
|
|
# Source this file to set TLS environment variables
|
|
|
|
export TLS_ENABLED=true
|
|
export MTLS_ENABLED=true
|
|
export CA_CERT_PATH="$CA_DIR/ca.crt"
|
|
export CA_KEY_PATH="$CA_DIR/private/ca.key"
|
|
|
|
# Service-specific TLS settings
|
|
export API_TLS_PORT=8443
|
|
export API_CERT_PATH="$CERT_DIR/api/server.crt"
|
|
export API_KEY_PATH="$CERT_DIR/api/server.key"
|
|
|
|
export LLM_TLS_PORT=8444
|
|
export LLM_CERT_PATH="$CERT_DIR/llm/server.crt"
|
|
export LLM_KEY_PATH="$CERT_DIR/llm/server.key"
|
|
|
|
export EMBEDDING_TLS_PORT=8445
|
|
export EMBEDDING_CERT_PATH="$CERT_DIR/embedding/server.crt"
|
|
export EMBEDDING_KEY_PATH="$CERT_DIR/embedding/server.key"
|
|
|
|
export QDRANT_TLS_PORT=6334
|
|
export QDRANT_CERT_PATH="$CERT_DIR/qdrant/server.crt"
|
|
export QDRANT_KEY_PATH="$CERT_DIR/qdrant/server.key"
|
|
|
|
export REDIS_TLS_PORT=6380
|
|
export REDIS_CERT_PATH="$CERT_DIR/redis/server.crt"
|
|
export REDIS_KEY_PATH="$CERT_DIR/redis/server.key"
|
|
|
|
export POSTGRES_TLS_PORT=5433
|
|
export POSTGRES_CERT_PATH="$CERT_DIR/postgres/server.crt"
|
|
export POSTGRES_KEY_PATH="$CERT_DIR/postgres/server.key"
|
|
|
|
export MINIO_TLS_PORT=9001
|
|
export MINIO_CERT_PATH="$CERT_DIR/minio/server.crt"
|
|
export MINIO_KEY_PATH="$CERT_DIR/minio/server.key"
|
|
EOF
|
|
|
|
echo -e "${GREEN}✓ Environment variables file created${NC}"
|
|
}
|
|
|
|
# Function to test certificate validity
|
|
test_certificates() {
|
|
echo -e "${BLUE}Testing certificate validity...${NC}"
|
|
|
|
local all_valid=true
|
|
|
|
for service_config in "${SERVICES[@]}"; do
|
|
IFS=':' read -r service port sans <<< "$service_config"
|
|
|
|
# Verify certificate chain
|
|
if openssl verify -CAfile "$CA_DIR/ca.crt" "$CERT_DIR/$service/server.crt" > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ $service server certificate is valid${NC}"
|
|
else
|
|
echo -e "${RED}✗ $service server certificate is invalid${NC}"
|
|
all_valid=false
|
|
fi
|
|
|
|
if openssl verify -CAfile "$CA_DIR/ca.crt" "$CERT_DIR/$service/client.crt" > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ $service client certificate is valid${NC}"
|
|
else
|
|
echo -e "${RED}✗ $service client certificate is invalid${NC}"
|
|
all_valid=false
|
|
fi
|
|
done
|
|
|
|
if $all_valid; then
|
|
echo -e "${GREEN}✓ All certificates are valid${NC}"
|
|
else
|
|
echo -e "${RED}Some certificates failed validation${NC}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
check_openssl
|
|
create_directories
|
|
create_ca_config
|
|
generate_root_ca
|
|
# Intermediate CA is optional but recommended
|
|
# generate_intermediate_ca
|
|
generate_all_service_certs
|
|
create_tls_config
|
|
create_env_vars
|
|
test_certificates
|
|
display_cert_info
|
|
|
|
echo ""
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo -e "${GREEN}TLS Setup Complete!${NC}"
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}Next steps:${NC}"
|
|
echo "1. Source the environment variables: source $CERT_DIR/tls.env"
|
|
echo "2. Update your service configurations to use HTTPS/TLS"
|
|
echo "3. Restart all services with TLS enabled"
|
|
echo ""
|
|
echo -e "${YELLOW}Important files:${NC}"
|
|
echo " CA Certificate: $CA_DIR/ca.crt"
|
|
echo " TLS Config: $CERT_DIR/tls-config.toml"
|
|
echo " Environment Variables: $CERT_DIR/tls.env"
|
|
echo ""
|
|
echo -e "${YELLOW}To trust the CA certificate on your system:${NC}"
|
|
echo " Ubuntu/Debian: sudo cp $CA_DIR/ca.crt /usr/local/share/ca-certificates/botserver-ca.crt && sudo update-ca-certificates"
|
|
echo " RHEL/CentOS: sudo cp $CA_DIR/ca.crt /etc/pki/ca-trust/source/anchors/ && sudo update-ca-trust"
|
|
echo " macOS: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $CA_DIR/ca.crt"
|
|
}
|
|
|
|
# Run main function
|
|
main
|