Enhance Dockerfile and start.sh: add curl, openssl, and jq; update HOMESERVER_URL to use HTTPS; improve admin user registration logic and error handling
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk add --no-cache yq
|
||||
RUN apk add --no-cache yq curl openssl jq
|
||||
|
||||
COPY start.sh /start.sh
|
||||
|
||||
|
126
start.sh
126
start.sh
@@ -8,10 +8,9 @@ POSTGRES_HOST=matrixpostgres-db
|
||||
DB_PORT="5432"
|
||||
|
||||
SYNAPSE_HOST="${SYNAPSE_SERVER_NAME:-localhost}"
|
||||
SYNAPSE_PORT="${SYNAPSE_PORT:-8008}"
|
||||
ADMIN_USERNAME="${ADMIN_USERNAME:-admin}"
|
||||
ADMIN_PASSWORD="${ADMIN_PASSWORD:-changeme}"
|
||||
HOMESERVER_URL="${HOMESERVER_URL:-http://$SYNAPSE_HOST:$SYNAPSE_PORT}"
|
||||
HOMESERVER_URL="${HOMESERVER_URL:-https://$SYNAPSE_HOST}"
|
||||
|
||||
prepare_postgres () {
|
||||
if [ -f /data/homeserver.yaml ]; then
|
||||
@@ -37,6 +36,10 @@ prepare_postgres () {
|
||||
get_registration_secret() {
|
||||
if [ -f "/data/homeserver.yaml" ]; then
|
||||
SHARED_SECRET=$(yq '.registration_shared_secret' /data/homeserver.yaml 2>/dev/null)
|
||||
echo "$SHARED_SECRET"
|
||||
if [ -n "$SHARED_SECRET" ] && [ "$SHARED_SECRET" != "null" ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -47,7 +50,7 @@ wait_for_synapse() {
|
||||
local attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if curl -s "$HOMESERVER_URL/_matrix/client/versions" >/dev/null 2>&1; then
|
||||
if curl -sk "$HOMESERVER_URL/_matrix/client/versions" >/dev/null 2>&1; then
|
||||
echo "Synapse is ready!"
|
||||
return 0
|
||||
fi
|
||||
@@ -60,56 +63,58 @@ wait_for_synapse() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if any admin users exist using admin API
|
||||
check_admin_exists() {
|
||||
# Try to get a temporary admin token first
|
||||
local temp_token=$(get_admin_token)
|
||||
|
||||
if [ -n "$temp_token" ]; then
|
||||
local response=$(curl -s -X GET \
|
||||
"$HOMESERVER_URL/_synapse/admin/v2/users?deactivated=false" \
|
||||
-H "Authorization: Bearer $temp_token" 2>/dev/null || echo "")
|
||||
|
||||
if echo "$response" | grep -q '"admin": true'; then
|
||||
return 0 # Admin exists
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1 # No admin or couldn't check
|
||||
}
|
||||
|
||||
# Get admin token (this requires an existing admin user)
|
||||
get_admin_token() {
|
||||
# This function would need an existing admin to work
|
||||
# For initial setup, we'll rely on registration shared secret
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Register admin user using shared secret
|
||||
register_admin_user() {
|
||||
local SHARED_SECRET=$1
|
||||
|
||||
echo "Registering admin user: $ADMIN_USERNAME"
|
||||
|
||||
# Generate registration MAC
|
||||
local nonce=$(date +%s)
|
||||
local username_lower=$(echo "$ADMIN_USERNAME" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Calculate HMAC (simplified - in practice you'd want to use proper HMAC)
|
||||
local mac=$(echo -n "${nonce}${username_lower}${ADMIN_PASSWORD}admin" | openssl dgst -sha1 -hmac "$SHARED_SECRET" -binary | base64)
|
||||
|
||||
# Register user
|
||||
local response=$(curl -s -X POST "$HOMESERVER_URL/_synapse/admin/v1/register" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"nonce\": \"$nonce\",
|
||||
\"username\": \"$username_lower\",
|
||||
\"password\": \"$ADMIN_PASSWORD\",
|
||||
\"admin\": true,
|
||||
\"mac\": \"$mac\"
|
||||
}" 2>/dev/null)
|
||||
|
||||
if echo "$response" | grep -q "access_token"; then
|
||||
|
||||
# Derive localpart (strip leading @ and :domain) and lowercase
|
||||
local localpart
|
||||
localpart=$(printf '%s' "$ADMIN_USERNAME" | sed -e 's/^@//' -e 's/:.*$//' | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Fetch server-issued nonce
|
||||
local url nonce
|
||||
url="${HOMESERVER_URL%/}/_synapse/admin/v1/register"
|
||||
nonce=$(curl -kfsS "$url" | jq -r '.nonce')
|
||||
|
||||
if [ -z "$nonce" ] || [ "$nonce" = "null" ]; then
|
||||
echo "Failed to fetch nonce from $url"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Admin flag and user_type
|
||||
local admin_word admin_json user_type user_type_json
|
||||
user_type="${USER_TYPE:-}"
|
||||
case "${ADMIN:-true}" in
|
||||
true|1|yes|y|True|TRUE) admin_word="admin"; admin_json=true ;;
|
||||
*) admin_word="notadmin"; admin_json=false ;;
|
||||
esac
|
||||
if [ -n "$user_type" ]; then
|
||||
user_type_json=$(printf '"%s"' "$user_type")
|
||||
else
|
||||
user_type_json=null
|
||||
fi
|
||||
|
||||
# Compute MAC exactly like Python (no trailing NUL unless user_type present)
|
||||
local mac
|
||||
if [ -n "$user_type" ]; then
|
||||
mac=$(printf '%s\0%s\0%s\0%s\0%s' "$nonce" "$localpart" "$ADMIN_PASSWORD" "$admin_word" "$user_type" \
|
||||
| openssl dgst -sha1 -hmac "$SHARED_SECRET" -binary | od -An -tx1 | tr -d ' \n')
|
||||
else
|
||||
mac=$(printf '%s\0%s\0%s\0%s' "$nonce" "$localpart" "$ADMIN_PASSWORD" "$admin_word" \
|
||||
| openssl dgst -sha1 -hmac "$SHARED_SECRET" -binary | od -An -tx1 | tr -d ' \n')
|
||||
fi
|
||||
|
||||
# Build payload and register
|
||||
local payload response
|
||||
payload=$(printf '{"nonce":"%s","username":"%s","password":"%s","admin":%s,"user_type":%s,"mac":"%s"}' \
|
||||
"$nonce" "$localpart" "$ADMIN_PASSWORD" "$admin_json" "$user_type_json" "$mac")
|
||||
|
||||
response=$(curl -kfsS -X POST "$url" -H 'Content-Type: application/json' -d "$payload" || true)
|
||||
|
||||
if echo "$response" | grep -q '"user_id"\|"access_token"'; then
|
||||
echo "Admin user created successfully!"
|
||||
return 0
|
||||
else
|
||||
@@ -118,28 +123,9 @@ register_admin_user() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Alternative method using registration endpoint
|
||||
register_user_simple() {
|
||||
local SHARED_SECRET=$1
|
||||
|
||||
echo "Attempting simple registration for: $ADMIN_USERNAME"
|
||||
|
||||
# Try the simpler registration method
|
||||
local response=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/r0/admin/register" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"username\": \"$ADMIN_USERNAME\",
|
||||
\"password\": \"$ADMIN_PASSWORD\",
|
||||
\"admin\": true,
|
||||
\"shared_secret\": \"$SHARED_SECRET\"
|
||||
}" 2>/dev/null)
|
||||
|
||||
echo "Registration response: $response"
|
||||
}
|
||||
|
||||
# Check if admin exists by trying to login
|
||||
check_admin_by_login() {
|
||||
local response=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/r0/login" \
|
||||
local response=$(curl -sk -X POST "$HOMESERVER_URL/_matrix/client/r0/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"type\": \"m.login.password\",
|
||||
@@ -147,8 +133,11 @@ check_admin_by_login() {
|
||||
\"password\": \"$ADMIN_PASSWORD\"
|
||||
}" 2>/dev/null)
|
||||
|
||||
if echo "$response" | grep -q "access_token"; then
|
||||
if echo "$response" | grep -q access_token; then
|
||||
echo "Successfully logged in as admin user"
|
||||
yq eval '.registration_shared_secret = ""' /data/homeserver.yaml > /data/homeserver.yaml.tmp && mv /data/homeserver.yaml.tmp /data/homeserver.yaml
|
||||
return 0 # User exists and password is correct
|
||||
|
||||
fi
|
||||
return 1 # User doesn't exist or wrong password
|
||||
}
|
||||
@@ -182,7 +171,6 @@ main() {
|
||||
# Try to register admin user
|
||||
if ! register_admin_user "$SHARED_SECRET"; then
|
||||
echo "Primary registration method failed, trying alternative..."
|
||||
register_user_simple "$SHARED_SECRET"
|
||||
fi
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user