From 7da4eff745b0823cb4b60ccb2a1fb20a91811dce Mon Sep 17 00:00:00 2001 From: cclohmar Date: Mon, 16 Mar 2026 15:28:32 +0000 Subject: [PATCH] chore: auto-commit 2026-03-16 15:28 --- install.sh | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++ uninstall.sh | 73 +++++++++ 2 files changed, 507 insertions(+) create mode 100644 install.sh create mode 100644 uninstall.sh diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..75ef153 --- /dev/null +++ b/install.sh @@ -0,0 +1,434 @@ +#!/bin/bash + +# Mock API Installation Script +# This script installs the Mock API application as a systemd service + +set -e # Exit on error + +# 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 +APP_NAME="mockapi" +APP_DIR="/opt/mockapi" +SERVICE_NAME="mockapi" +SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" +VENV_DIR="${APP_DIR}/venv" +PORT="8000" +RUN_USER="www-data" # Default user, can be changed below + +print_status() { + echo -e "${GREEN}[+]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[!]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[i]${NC} $1" +} + +check_root() { + if [[ $EUID -eq 0 ]]; then + print_warning "Running as root. It's recommended to run this script as a regular user." + read -p "Continue anyway? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi +} + +check_prerequisites() { + print_status "Checking prerequisites..." + + # Check Python + if ! command -v python3 &> /dev/null; then + print_error "Python3 is not installed. Please install it first." + print_info "On Ubuntu/Debian: sudo apt-get install python3" + exit 1 + fi + + # Check pip + if ! command -v pip3 &> /dev/null; then + print_warning "pip3 not found. Installing..." + sudo apt-get update + sudo apt-get install -y python3-pip + fi + + # Check virtualenv + if ! python3 -m venv --help &> /dev/null; then + print_warning "venv module not available. Installing..." + sudo apt-get install -y python3-venv + fi + + print_status "Prerequisites check passed." +} + +generate_random_string() { + local length=$1 + openssl rand -base64 $((length * 3 / 4)) | tr -d '/+=' | head -c "$length" +} + +setup_environment() { + print_status "Setting up Python virtual environment..." + + # Create virtual environment + if [[ ! -d "$VENV_DIR" ]]; then + python3 -m venv "$VENV_DIR" + print_status "Virtual environment created at $VENV_DIR" + else + print_warning "Virtual environment already exists at $VENV_DIR" + read -p "Recreate virtual environment? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -rf "$VENV_DIR" + python3 -m venv "$VENV_DIR" + print_status "Virtual environment recreated." + fi + fi + + # Activate virtual environment and install dependencies + source "${VENV_DIR}/bin/activate" + pip install --upgrade pip + + print_status "Installing Python dependencies..." + pip install -r "${APP_DIR}/requirements.txt" + + deactivate + print_status "Dependencies installed." +} + +configure_application() { + print_status "Configuring application..." + + # Check if .env exists + if [[ -f "${APP_DIR}/.env" ]]; then + print_warning ".env file already exists." + read -p "Overwrite with new configuration? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_info "Using existing .env file." + return + fi + fi + + # Generate secure credentials + print_info "Generating secure credentials..." + ADMIN_PASSWORD=$(generate_random_string 16) + SECRET_KEY=$(generate_random_string 64) + + # Ask for admin username + read -p "Enter admin username [admin]: " admin_username + ADMIN_USERNAME=${admin_username:-admin} + + # Ask for database path + read -p "Enter database path [${APP_DIR}/mockapi.db]: " db_path + DB_PATH=${db_path:-${APP_DIR}/mockapi.db} + + # Create .env file with generated credentials + cat > "${APP_DIR}/.env" << EOF +# Mock API Configuration +# Generated on $(date) + +# Database Configuration +DATABASE_URL=sqlite+aiosqlite:///${DB_PATH} + +# Admin Authentication +ADMIN_USERNAME=${ADMIN_USERNAME} +ADMIN_PASSWORD=${ADMIN_PASSWORD} + +# Security +SECRET_KEY=${SECRET_KEY} + +# Application Settings +DEBUG=False +LOG_LEVEL=INFO + +# OAuth2 Settings +OAUTH2_ISSUER=http://localhost:${PORT} +OAUTH2_ACCESS_TOKEN_EXPIRE_MINUTES=30 +OAUTH2_REFRESH_TOKEN_EXPIRE_DAYS=7 +OAUTH2_SUPPORTED_SCOPES=openid profile email api:read api:write + +# Server Settings +HOST=0.0.0.0 +PORT=${PORT} +EOF + + # Set secure permissions + chmod 600 "${APP_DIR}/.env" + + print_status "Created .env file with secure credentials." + print_info "Admin username: ${ADMIN_USERNAME}" + print_info "Admin password: ${ADMIN_PASSWORD}" + print_info "Secret key: ${SECRET_KEY:0:16}..." + + echo + print_warning "IMPORTANT: Save these credentials in a secure location!" + print_warning "You will need the admin password to log in." + echo + + # Create database directory if needed + DB_DIR=$(dirname "$DB_PATH") + if [[ ! -d "$DB_DIR" ]]; then + mkdir -p "$DB_DIR" + fi +} + +setup_systemd_service() { + print_status "Setting up systemd service..." + + # Ask for run user + echo + print_warning "Choose a user to run the service:" + echo "1) www-data (recommended for web applications)" + echo "2) Current user ($USER)" + echo "3) Create new user 'mockapi'" + echo "4) Custom user" + read -p "Enter choice [1-4]: " user_choice + + case $user_choice in + 1) + RUN_USER="www-data" + ;; + 2) + RUN_USER="$USER" + ;; + 3) + RUN_USER="mockapi" + if ! id -u "$RUN_USER" &> /dev/null; then + sudo adduser --system --no-create-home --group "$RUN_USER" + print_status "Created user '$RUN_USER'" + fi + ;; + 4) + read -p "Enter username: " custom_user + if id -u "$custom_user" &> /dev/null; then + RUN_USER="$custom_user" + else + print_error "User '$custom_user' does not exist." + exit 1 + fi + ;; + *) + RUN_USER="www-data" + print_warning "Using default user: www-data" + ;; + esac + + # Ask for port + read -p "Enter port number [8000]: " custom_port + if [[ -n "$custom_port" ]]; then + PORT="$custom_port" + # Update PORT in .env if it exists + if [[ -f "${APP_DIR}/.env" ]]; then + sed -i "s/^PORT=.*/PORT=${PORT}/" "${APP_DIR}/.env" + sed -i "s|^OAUTH2_ISSUER=.*|OAUTH2_ISSUER=http://localhost:${PORT}|" "${APP_DIR}/.env" + fi + fi + + # Create systemd service file + print_status "Creating systemd service file at $SERVICE_FILE..." + + sudo tee "$SERVICE_FILE" > /dev/null << EOF +[Unit] +Description=Mock API Service +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$RUN_USER +Group=$RUN_USER +WorkingDirectory=$APP_DIR +Environment="PATH=$VENV_DIR/bin" +Environment="PYTHONPATH=$APP_DIR" +EnvironmentFile=$APP_DIR/.env +ExecStart=$VENV_DIR/bin/waitress-serve --host=\$HOST --port=\$PORT wsgi:wsgi_app +Restart=always +RestartSec=10 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=$SERVICE_NAME + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ReadWritePaths=$APP_DIR + +[Install] +WantedBy=multi-user.target +EOF + + print_status "Systemd service file created." + + # Set ownership and permissions + print_status "Setting ownership and permissions..." + + # Set ownership of app directory + sudo chown -R "$RUN_USER:$RUN_USER" "$APP_DIR" + + # Make sure install script is executable + sudo chmod +x "$APP_DIR/install.sh" + + # Reload systemd + sudo systemctl daemon-reload + + print_status "Systemd service configured." +} + +initialize_database() { + print_status "Initializing database..." + + # Activate virtual environment + source "${VENV_DIR}/bin/activate" + + # Run a simple Python script to initialize database + python3 -c " +import asyncio +import sys +sys.path.insert(0, '${APP_DIR}') +from app.core.database import engine +from app.core.config import settings +import asyncio + +async def init_db(): + from sqlalchemy.ext.asyncio import AsyncSession + from sqlalchemy.orm import sessionmaker + from app.core.database import Base + from app.modules.endpoints.models import Endpoint + from app.modules.oauth2.models import OAuthClient, OAuthToken, OAuthUser + + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + print('Database tables created successfully') + +asyncio.run(init_db()) +" + + deactivate + print_status "Database initialized." +} + +start_service() { + print_status "Starting and enabling service..." + + # Enable and start the service + sudo systemctl enable "$SERVICE_NAME" + sudo systemctl start "$SERVICE_NAME" + + # Wait a moment for service to start + sleep 5 + + # Check service status + if sudo systemctl is-active --quiet "$SERVICE_NAME"; then + print_status "Service is running successfully!" + else + print_error "Service failed to start. Checking logs..." + sudo journalctl -u "$SERVICE_NAME" -n 20 --no-pager + exit 1 + fi +} + +show_summary() { + # Read credentials from .env for summary + if [[ -f "${APP_DIR}/.env" ]]; then + ADMIN_USERNAME=$(grep "^ADMIN_USERNAME=" "${APP_DIR}/.env" | cut -d'=' -f2) + ADMIN_PASSWORD=$(grep "^ADMIN_PASSWORD=" "${APP_DIR}/.env" | cut -d'=' -f2) + fi + + echo + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN} Installation Complete! ${NC}" + echo -e "${GREEN}========================================${NC}" + echo + echo "Application Details:" + echo " Directory: $APP_DIR" + echo " Service: $SERVICE_NAME" + echo " Run User: $RUN_USER" + echo " Port: $PORT" + echo " Virtual Env: $VENV_DIR" + echo + echo "Credentials (saved in ${APP_DIR}/.env):" + echo " Admin Username: $ADMIN_USERNAME" + echo " Admin Password: $ADMIN_PASSWORD" + echo + echo "Service Management Commands:" + echo " sudo systemctl start $SERVICE_NAME" + echo " sudo systemctl stop $SERVICE_NAME" + echo " sudo systemctl restart $SERVICE_NAME" + echo " sudo systemctl status $SERVICE_NAME" + echo " sudo journalctl -u $SERVICE_NAME -f" + echo + echo "Access the application:" + echo " Admin UI: http://localhost:$PORT/admin/login" + echo " API Docs: http://localhost:$PORT/docs" + echo " Health Check: http://localhost:$PORT/health" + echo + echo "Configuration Files:" + echo " Environment: $APP_DIR/.env" + echo " Service: $SERVICE_FILE" + echo " Database: $(grep "^DATABASE_URL=" "${APP_DIR}/.env" | cut -d'/' -f4-)" + echo + print_warning "IMPORTANT: Change admin password after first login!" + print_warning "Keep the .env file secure - it contains sensitive credentials." + echo + print_info "To update configuration, edit $APP_DIR/.env and restart:" + print_info " sudo systemctl restart $SERVICE_NAME" + echo +} + +main() { + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN} Mock API Installation Script ${NC}" + echo -e "${GREEN}========================================${NC}" + echo + + # Check if running as root (warn but allow) + check_root + + # Check if app directory exists + if [[ ! -d "$APP_DIR" ]]; then + print_error "Application directory not found: $APP_DIR" + print_info "Please clone the repository first:" + print_info " cd /opt/" + print_info " sudo git clone https://git.sechpoint.app/customer-engineering/mockapi.git" + print_info " sudo chown -R \$USER:\$USER /opt/mockapi" + exit 1 + fi + + # Check prerequisites + check_prerequisites + + # Setup Python environment + setup_environment + + # Configure application + configure_application + + # Initialize database + initialize_database + + # Setup systemd service + setup_systemd_service + + # Start the service + start_service + + # Show summary + show_summary +} + +# Run main function +main \ No newline at end of file diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 0000000..f71a8a1 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Mock API Uninstallation Script + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +APP_DIR="/opt/mockapi" +SERVICE_NAME="mockapi" +SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" + +print_status() { + echo -e "${GREEN}[+]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1 +} + +print_error() { + echo -e "${RED}[!]${NC} $1" +} + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} Mock API Uninstallation Script ${NC}" +echo -e "${GREEN}========================================${NC}" +echo + +# Confirm uninstallation +read -p "Are you sure you want to uninstall Mock API? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Uninstallation cancelled." + exit 0 +fi + +# Stop and disable service +if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then + print_status "Stopping service..." + sudo systemctl stop "$SERVICE_NAME" +fi + +if systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then + print_status "Disabling service..." + sudo systemctl disable "$SERVICE_NAME" +fi + +# Remove service file +if [[ -f "$SERVICE_FILE" ]]; then + print_status "Removing service file..." + sudo rm "$SERVICE_FILE" + sudo systemctl daemon-reload +fi + +# Ask about removing application directory +if [[ -d "$APP_DIR" ]]; then + read -p "Remove application directory ($APP_DIR)? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_status "Removing application directory..." + sudo rm -rf "$APP_DIR" + else + print_status "Application directory kept at $APP_DIR" + print_warning "Note: .env file with credentials is still in $APP_DIR" + fi +fi + +print_status "Uninstallation complete!" \ No newline at end of file