Implement secure random password generation and fix permission issues

This commit is contained in:
Andreas Düren 2025-03-16 17:49:00 +01:00
parent e538faa594
commit 153eaab1c0
3 changed files with 83 additions and 11 deletions

View File

@ -5,7 +5,7 @@
"description": "Elasticsearch is a distributed, open source search and analytics engine for all types of data. This package is designed for internal use only.",
"tagline": "Distributed search and analytics engine",
"version": "1.0.0",
"healthCheckPath": "/",
"healthCheckPath": "/_cluster/health?pretty",
"httpPort": 9200,
"manifestVersion": 2,
"website": "https://www.elastic.co/elasticsearch/",
@ -24,13 +24,13 @@
"database"
],
"minBoxVersion": "7.0.0",
"memoryLimit": 1073741824,
"postInstallMessage": "Elasticsearch is now installed and available for internal use only. You can access it using http://localhost:9200 from within other Cloudron apps.",
"memoryLimit": 4294967296,
"postInstallMessage": "Elasticsearch is now installed and available for internal use only. You can access it using http://localhost:9200 from within other Cloudron apps.\n\nUsername: elastic\nPassword: A secure random password has been generated and stored in /app/data/credentials.txt. You can check it in the app logs or by accessing the app container.",
"multiDomain": false,
"tcpPorts": {
"9300": {
"title": "Transport Port",
"description": "Elasticsearch transport port"
"description": "Elasticsearch transport port for node-to-node communication"
}
}
}

View File

@ -46,6 +46,6 @@ RUN chmod +x /app/start.sh /app/stop.sh
# Add healthcheck
HEALTHCHECK --interval=15s --timeout=10s --start-period=120s --retries=5 \
CMD curl -fs -u elastic:$(cat /app/data/secrets/elastic_password 2>/dev/null || echo "cloudron") http://localhost:9200/_cluster/health?pretty || exit 1
CMD curl -fs -u elastic:$(cat /app/data/secrets/elastic_password) http://localhost:9200/_cluster/health?pretty || exit 1
CMD ["/app/start.sh"]

View File

@ -5,14 +5,37 @@ set -e
source /app/.env
# Set constants
ELASTIC_PASSWORD="cloudron"
ES_HOME=/usr/share/elasticsearch
ES_PATH_CONF=/app/data/config
export ES_HOME ES_PATH_CONF
# Create directory structure
mkdir -p /app/data/{elasticsearch,logs/gc,config,run,secrets,jdk/bin}
echo "$ELASTIC_PASSWORD" > /app/data/secrets/elastic_password
# Set proper permissions early
echo "Setting up directory permissions..."
chown -R elasticsearch:elasticsearch /app/data
# Handle password management
setup_password() {
# Check if password already exists
if [ -f /app/data/secrets/elastic_password ]; then
ELASTIC_PASSWORD=$(cat /app/data/secrets/elastic_password)
echo "Using existing Elasticsearch password."
else
# Generate a secure password - combination of letters, numbers, and special chars
ELASTIC_PASSWORD=$(tr -dc 'A-Za-z0-9_!@#$%^&*()' < /dev/urandom | head -c 20)
echo "Generated new secure password for Elasticsearch."
# Store password
echo "$ELASTIC_PASSWORD" > /app/data/secrets/elastic_password
chmod 600 /app/data/secrets/elastic_password
chown elasticsearch:elasticsearch /app/data/secrets/elastic_password
fi
# Make password available to other functions
export ELASTIC_PASSWORD
}
# Set up Java environment
setup_java() {
@ -45,34 +68,68 @@ setup_java() {
echo "ERROR: Failed to link Java executable"
exit 1
fi
# Ensure Java symlinks have correct ownership
chown -R elasticsearch:elasticsearch /app/data/jdk
}
# Configure Elasticsearch
configure_elasticsearch() {
cd $ES_HOME
# Handle keystore creation and password
# Double-check permissions on config directory before proceeding
echo "Verifying config directory permissions..."
ls -la $ES_PATH_CONF
chmod 755 $ES_PATH_CONF
chown -R elasticsearch:elasticsearch $ES_PATH_CONF
# Handle keystore creation and password with proper error handling
if [ ! -f $ES_PATH_CONF/elasticsearch.keystore ] || [ "$1" = "force" ]; then
echo "Creating Elasticsearch keystore..."
# Remove existing keystore if it exists to avoid permission issues
[ -f $ES_PATH_CONF/elasticsearch.keystore ] && rm -f $ES_PATH_CONF/elasticsearch.keystore
su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore create" elasticsearch
# Pre-create the tmp file with correct permissions
touch $ES_PATH_CONF/elasticsearch.keystore.tmp
chown elasticsearch:elasticsearch $ES_PATH_CONF/elasticsearch.keystore.tmp
# Try to create keystore with proper error handling
if ! su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore create" elasticsearch; then
echo "ERROR: Failed to create keystore. Checking permissions and trying again..."
find $ES_PATH_CONF -type f -exec ls -la {} \;
# Try a more aggressive approach if the first attempt failed
chmod -R 777 $ES_PATH_CONF
if ! su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore create" elasticsearch; then
echo "CRITICAL ERROR: Could not create Elasticsearch keystore after multiple attempts."
echo "Current directory permissions:"
find /app/data -type d -exec ls -ld {} \;
exit 1
fi
fi
fi
# Add bootstrap password to keystore
echo "Setting bootstrap password..."
echo "$ELASTIC_PASSWORD" | su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore add -f -x 'bootstrap.password' --stdin" elasticsearch
if ! echo "$ELASTIC_PASSWORD" | su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore add -f -x 'bootstrap.password' --stdin" elasticsearch; then
echo "ERROR: Failed to add bootstrap password to keystore."
exit 1
fi
# Copy configuration files if needed
if [ ! -f $ES_PATH_CONF/elasticsearch.yml ]; then
echo "Setting up configuration files..."
cp -r $ES_HOME/config/* $ES_PATH_CONF/ || true
cp /app/elasticsearch.yml $ES_PATH_CONF/elasticsearch.yml || true
chown -R elasticsearch:elasticsearch $ES_PATH_CONF
fi
# Update JVM options for GC logs
if [ -f $ES_PATH_CONF/jvm.options ]; then
echo "Updating JVM options..."
sed -i 's|logs/gc.log|/app/data/logs/gc/gc.log|g' $ES_PATH_CONF/jvm.options
chown elasticsearch:elasticsearch $ES_PATH_CONF/jvm.options
fi
# Generate SSL certificates if needed
@ -80,6 +137,8 @@ configure_elasticsearch() {
echo "Generating self-signed certificates..."
mkdir -p /tmp/elastic-certs
chown elasticsearch:elasticsearch /tmp/elastic-certs
ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-certutil ca \
--out /tmp/elastic-certs/elastic-stack-ca.p12 \
--pass "" \
@ -99,6 +158,8 @@ configure_elasticsearch() {
# Create users file if needed
if [ ! -f $ES_PATH_CONF/users ]; then
echo "Creating users file..."
# Note: We'll reset the password after Elasticsearch starts, so this default password
# is just for initial bootstrap
echo 'elastic:$2a$10$BtVRGAoL8AbgEKnlvYj8cewQF3QkUz1pyL.Ga3j.jFKNUk2yh7.zW' > $ES_PATH_CONF/users
echo 'kibana_system:$2a$10$BtVRGAoL8AbgEKnlvYj8cewQF3QkUz1pyL.Ga3j.jFKNUk2yh7.zW' >> $ES_PATH_CONF/users
@ -114,6 +175,11 @@ configure_elasticsearch() {
echo "$setting" >> $ES_PATH_CONF/elasticsearch.yml
fi
done
# Final permission check
echo "Final permission check on all data directories..."
chown -R elasticsearch:elasticsearch /app/data
chmod 755 /app/data /app/data/config
}
# Set system limits
@ -191,22 +257,28 @@ URL: http://localhost:9200
User: elastic
Password: $ELASTIC_PASSWORD
EOL
chmod 600 /app/data/credentials.txt
echo "-----------------------------"
echo "Elasticsearch is ready to use!"
echo "URL: http://localhost:9200"
echo "User: elastic"
echo "Password: $ELASTIC_PASSWORD"
echo "Password is stored in: /app/data/credentials.txt"
echo "-----------------------------"
}
# Main execution flow
setup_password
setup_java
configure_elasticsearch
[ ! -f /app/data/.initialized ] && touch /app/data/.initialized
# Ensure correct permissions
# Final permission check
echo "Performing final permission check on all directories..."
chown -R elasticsearch:elasticsearch /app/data/{elasticsearch,logs,config,jdk,run,secrets}
chmod -R 755 /app/data
chmod 600 /app/data/secrets/elastic_password
set_system_limits
configure_heap