- Created docs/00-meta/ for documentation meta files (11 files) - Created docs/archive/reports/ for reports (5 files) - Created docs/archive/issues/ for issue tracking (2 files) - Created docs/bridge/contracts/ for Solidity contracts (3 files) - Created docs/04-configuration/metamask/ for Metamask configs (3 files) - Created docs/scripts/ for documentation scripts (2 files) - Root directory now contains only 3 essential files (89.3% reduction) All recommended actions from docs directory review complete.
267 lines
9.1 KiB
Bash
Executable File
267 lines
9.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Setup Keycloak for Sankofa on r630-01
|
|
# VMID: 7802, IP: 10.160.0.12
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/.env.r630-01" 2>/dev/null || true
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Configuration
|
|
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.11}"
|
|
VMID="${VMID_SANKOFA_KEYCLOAK:-7802}"
|
|
CONTAINER_IP="${SANKOFA_KEYCLOAK_IP:-10.160.0.12}"
|
|
KEYCLOAK_ADMIN_USERNAME="${KEYCLOAK_ADMIN_USERNAME:-admin}"
|
|
KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-24)}"
|
|
KEYCLOAK_REALM="${KEYCLOAK_REALM:-master}"
|
|
KEYCLOAK_CLIENT_ID_API="${KEYCLOAK_CLIENT_ID_API:-sankofa-api}"
|
|
KEYCLOAK_CLIENT_ID_PORTAL="${KEYCLOAK_CLIENT_ID_PORTAL:-portal-client}"
|
|
KEYCLOAK_CLIENT_SECRET_API="${KEYCLOAK_CLIENT_SECRET_API:-$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)}"
|
|
KEYCLOAK_CLIENT_SECRET_PORTAL="${KEYCLOAK_CLIENT_SECRET_PORTAL:-$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)}"
|
|
DB_HOST="${SANKOFA_POSTGRES_IP:-10.160.0.13}"
|
|
DB_NAME="${DB_NAME:-keycloak}"
|
|
DB_USER="${DB_USER:-keycloak}"
|
|
DB_PASSWORD="${DB_PASSWORD:-$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-24)}"
|
|
|
|
# SSH function
|
|
ssh_r630_01() {
|
|
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$PROXMOX_HOST" "$@"
|
|
}
|
|
|
|
# Execute command in container
|
|
exec_container() {
|
|
ssh_r630_01 "pct exec $VMID -- $*"
|
|
}
|
|
|
|
main() {
|
|
echo ""
|
|
log_info "========================================="
|
|
log_info "Keycloak Setup for Sankofa"
|
|
log_info "========================================="
|
|
echo ""
|
|
log_info "Container VMID: $VMID"
|
|
log_info "Container IP: $CONTAINER_IP"
|
|
log_info "Realm: $KEYCLOAK_REALM"
|
|
echo ""
|
|
|
|
# Check if container exists and is running
|
|
log_info "Checking container status..."
|
|
if ! ssh_r630_01 "pct status $VMID >/dev/null 2>&1"; then
|
|
log_error "Container $VMID does not exist or is not running"
|
|
exit 1
|
|
fi
|
|
|
|
local status=$(ssh_r630_01 "pct status $VMID" 2>/dev/null | awk '{print $2}' || echo "stopped")
|
|
if [[ "$status" != "running" ]]; then
|
|
log_info "Starting container $VMID..."
|
|
ssh_r630_01 "pct start $VMID"
|
|
sleep 5
|
|
fi
|
|
log_success "Container is running"
|
|
echo ""
|
|
|
|
# Install Java and PostgreSQL client
|
|
log_info "Installing Java and dependencies..."
|
|
exec_container bash -c "export DEBIAN_FRONTEND=noninteractive && \
|
|
apt-get update -qq && \
|
|
apt-get install -y -qq openjdk-21-jdk wget curl unzip"
|
|
|
|
# Set JAVA_HOME
|
|
exec_container bash -c "echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' >> /etc/profile"
|
|
|
|
log_success "Java installed"
|
|
echo ""
|
|
|
|
# Create Keycloak database on PostgreSQL
|
|
log_info "Creating Keycloak database on PostgreSQL..."
|
|
ssh_r630_01 "pct exec ${VMID_SANKOFA_POSTGRES:-7803} -- bash -c \"sudo -u postgres psql << 'EOF'
|
|
CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
|
|
CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8';
|
|
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
|
|
EOF\""
|
|
|
|
log_success "Keycloak database created"
|
|
echo ""
|
|
|
|
# Download and install Keycloak
|
|
log_info "Downloading Keycloak..."
|
|
exec_container bash -c "cd /opt && \
|
|
wget -q https://github.com/keycloak/keycloak/releases/download/24.0.0/keycloak-24.0.0.tar.gz && \
|
|
tar -xzf keycloak-24.0.0.tar.gz && \
|
|
mv keycloak-24.0.0 keycloak && \
|
|
rm keycloak-24.0.0.tar.gz && \
|
|
chmod +x keycloak/bin/kc.sh"
|
|
|
|
log_success "Keycloak downloaded"
|
|
echo ""
|
|
|
|
# Build Keycloak
|
|
log_info "Building Keycloak (this may take a few minutes)..."
|
|
exec_container bash -c "cd /opt/keycloak && \
|
|
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 && \
|
|
./bin/kc.sh build --db postgres"
|
|
|
|
log_success "Keycloak built"
|
|
echo ""
|
|
|
|
# Create systemd service
|
|
log_info "Creating Keycloak systemd service..."
|
|
exec_container bash -c "cat > /etc/systemd/system/keycloak.service << 'EOF'
|
|
[Unit]
|
|
Description=Keycloak Authorization Server
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=idle
|
|
User=root
|
|
WorkingDirectory=/opt/keycloak
|
|
Environment=\"JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64\"
|
|
Environment=\"KC_DB=postgres\"
|
|
Environment=\"KC_DB_URL_HOST=$DB_HOST\"
|
|
Environment=\"KC_DB_URL_DATABASE=$DB_NAME\"
|
|
Environment=\"KC_DB_USERNAME=$DB_USER\"
|
|
Environment=\"KC_DB_PASSWORD=$DB_PASSWORD\"
|
|
Environment=\"KC_HTTP_ENABLED=true\"
|
|
Environment=\"KC_HOSTNAME_STRICT=false\"
|
|
Environment=\"KC_HOSTNAME_PORT=8080\"
|
|
ExecStart=/opt/keycloak/bin/kc.sh start --optimized
|
|
ExecStop=/bin/kill -TERM \$MAINPID
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF"
|
|
|
|
# Start Keycloak
|
|
log_info "Starting Keycloak service..."
|
|
exec_container bash -c "systemctl daemon-reload && \
|
|
systemctl enable keycloak && \
|
|
systemctl start keycloak"
|
|
|
|
log_info "Waiting for Keycloak to start (this may take 1-2 minutes)..."
|
|
sleep 30
|
|
|
|
# Wait for Keycloak to be ready
|
|
local max_attempts=30
|
|
local attempt=0
|
|
while [ $attempt -lt $max_attempts ]; do
|
|
if exec_container bash -c "curl -s -f http://localhost:8080/health/ready >/dev/null 2>&1"; then
|
|
log_success "Keycloak is ready"
|
|
break
|
|
fi
|
|
attempt=$((attempt + 1))
|
|
log_info "Waiting for Keycloak... ($attempt/$max_attempts)"
|
|
sleep 5
|
|
done
|
|
|
|
if [ $attempt -eq $max_attempts ]; then
|
|
log_error "Keycloak failed to start"
|
|
exit 1
|
|
fi
|
|
echo ""
|
|
|
|
# Create admin user
|
|
log_info "Creating admin user..."
|
|
exec_container bash -c "cd /opt/keycloak && \
|
|
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 && \
|
|
./bin/kc.sh config credentials --server http://localhost:8080 --realm master --user admin --password admin 2>/dev/null || \
|
|
./bin/kc.sh config credentials --server http://localhost:8080 --realm master --user $KEYCLOAK_ADMIN_USERNAME --password $KEYCLOAK_ADMIN_PASSWORD"
|
|
|
|
# Get admin token and create clients
|
|
log_info "Creating API and Portal clients..."
|
|
|
|
# Note: This requires Keycloak Admin REST API
|
|
# We'll create a script that can be run after Keycloak is fully started
|
|
exec_container bash -c "cat > /root/create-clients.sh << 'SCRIPT'
|
|
#!/bin/bash
|
|
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
|
|
cd /opt/keycloak
|
|
|
|
# Get admin token
|
|
TOKEN=\$(curl -s -X POST \"http://localhost:8080/realms/master/protocol/openid-connect/token\" \\
|
|
-H \"Content-Type: application/x-www-form-urlencoded\" \\
|
|
-d \"username=$KEYCLOAK_ADMIN_USERNAME\" \\
|
|
-d \"password=$KEYCLOAK_ADMIN_PASSWORD\" \\
|
|
-d \"grant_type=password\" \\
|
|
-d \"client_id=admin-cli\" | jq -r '.access_token')
|
|
|
|
# Create sankofa-api client
|
|
curl -s -X POST \"http://localhost:8080/admin/realms/master/clients\" \\
|
|
-H \"Authorization: Bearer \$TOKEN\" \\
|
|
-H \"Content-Type: application/json\" \\
|
|
-d '{
|
|
\"clientId\": \"$KEYCLOAK_CLIENT_ID_API\",
|
|
\"enabled\": true,
|
|
\"clientAuthenticatorType\": \"client-secret\",
|
|
\"secret\": \"$KEYCLOAK_CLIENT_SECRET_API\",
|
|
\"protocol\": \"openid-connect\",
|
|
\"publicClient\": false,
|
|
\"standardFlowEnabled\": true,
|
|
\"directAccessGrantsEnabled\": true,
|
|
\"serviceAccountsEnabled\": true
|
|
}' > /dev/null
|
|
|
|
# Create portal-client
|
|
curl -s -X POST \"http://localhost:8080/admin/realms/master/clients\" \\
|
|
-H \"Authorization: Bearer \$TOKEN\" \\
|
|
-H \"Content-Type: application/json\" \\
|
|
-d '{
|
|
\"clientId\": \"$KEYCLOAK_CLIENT_ID_PORTAL\",
|
|
\"enabled\": true,
|
|
\"clientAuthenticatorType\": \"client-secret\",
|
|
\"secret\": \"$KEYCLOAK_CLIENT_SECRET_PORTAL\",
|
|
\"protocol\": \"openid-connect\",
|
|
\"publicClient\": false,
|
|
\"standardFlowEnabled\": true,
|
|
\"directAccessGrantsEnabled\": true
|
|
}' > /dev/null
|
|
|
|
echo \"Clients created successfully\"
|
|
SCRIPT
|
|
chmod +x /root/create-clients.sh"
|
|
|
|
# Wait a bit more and create clients
|
|
sleep 10
|
|
exec_container bash -c "/root/create-clients.sh" || log_warn "Client creation may need to be done manually via web UI"
|
|
|
|
log_success "Keycloak setup complete"
|
|
echo ""
|
|
|
|
# Summary
|
|
log_success "========================================="
|
|
log_success "Keycloak Setup Complete"
|
|
log_success "========================================="
|
|
echo ""
|
|
log_info "Keycloak Configuration:"
|
|
echo " URL: http://$CONTAINER_IP:8080"
|
|
echo " Admin URL: http://$CONTAINER_IP:8080/admin"
|
|
echo " Admin Username: $KEYCLOAK_ADMIN_USERNAME"
|
|
echo " Admin Password: $KEYCLOAK_ADMIN_PASSWORD"
|
|
echo " Realm: $KEYCLOAK_REALM"
|
|
echo ""
|
|
log_info "Client Secrets:"
|
|
echo " API Client Secret: $KEYCLOAK_CLIENT_SECRET_API"
|
|
echo " Portal Client Secret: $KEYCLOAK_CLIENT_SECRET_PORTAL"
|
|
echo ""
|
|
log_info "Next steps:"
|
|
echo " 1. Update .env.r630-01 with Keycloak credentials"
|
|
echo " 2. Verify clients in Keycloak admin console"
|
|
echo " 3. Run: ./scripts/deploy-api-r630-01.sh"
|
|
echo ""
|
|
}
|
|
|
|
main "$@"
|