chagitqskjdlqskdmslkqdj chatjkqsdjlqskdjqslkdjkslqd azekzkjeqksldjlqsjdlsqd xqlqkzdjlqsdklqsdkslqd ?? GreenFile

?? GreenFile — File Browser

Current path: opt/sh/



?? Go up: /opt

?? Viewing: wp_cli.sh

#!/bin/bash

# ============================================================
# WP-CLI実行スクリプト
#
# [使用方法]
# /opt/sh/wp_cli/wp_cli.sh "PHP_VERSION" "WP_PATH" "WP_COMMAND"
#
# [引数]
# - PHP_VERSION: PHPのバージョン(例: 8.2)
# - WP_PATH: WordPressのディレクトリパス(例: /home/user001/example.com/public_html/)
# - WP_COMMAND: WP-CLIのコマンド(例: core install)
#
# [補足]
# - cpadmin(WebAPI)がsudoでユーザー権限で実行します(ユーザーが直接実行することはできません)
# - ホワイトリスト(ALLOWED_COMMANDS)で許可されていないコマンドは実行できません
# ============================================================

# ============================================================
# 事前準備(引数取得、エラーハンドリング)
# ============================================================

# エラーハンドリングの強化
set -euo pipefail

# 許可されたWP-CLIコマンドのリスト
ALLOWED_COMMANDS=(
    "core"
    "plugin"
    "theme"
    "user"
    "db"
    "export"
    "import"
    "maintenance-mode"
    "config"
    "rewrite"
    "cache"
    "cron"
    "search-replace"
    "option"
    "site"
    "network"
    "role"
    "widget"
    "sidebar"
    "taxonomy"
    "term"
    "comment-meta"
    "post-meta"
    "user-meta"
    "rest"
    "scaffold"
    "package"
    "doctor"
    "post"
    "comment"
    "eval-file" # 当社管理の定型スクリプト実行のみなので許可
    "transient"
    "media"
    "i18n"
    "cldsec-wp-security" # CloudSecure WP Security
    "super-cache" # WP Super Cache
    "w3-total-cache" # W3 Total Cache
    "litespeed-purge" # LiteSpeed Cache
    "rocket" # WP Rocket
    "wc" # WooCommerce
    "yoast" # Yoast SEO
    "rankmath" # Rank Math
)

# wp-cliバイナリのパス設定
## /usr/bin/wp-cliが存在しない場合は/usr/bin/wpを実行
if [[ -f "/usr/bin/wp-cli" ]]; then
  WP_CLI_PATH="/usr/bin/wp-cli"
else
  WP_CLI_PATH="/usr/bin/wp"
fi

# 引数チェック
if [ $# -ne 3 ]; then
    echo "エラー: 引数が正しくありません。"
    echo "使用方法: $0 \"PHPバージョン\" \"WordPressディレクトリパス\" \"WP-CLIコマンド\""
    exit 1
fi

PHP_VERSION="$1"
WP_PATH="$2"
WP_COMMAND="$3"

# ============================================================
# 入力値サニタイゼーション関数
# ============================================================

# パスの安全性チェック関数
validate_path() {
    local path="$1"

    # 異常に長いパスの拒否
    if [ ${#path} -gt 4096 ]; then
        echo "エラー: パスが長すぎます(最大4096文字)"
        return 1
    fi

    # 危険な文字をチェック
    if [[ "$path" =~ [\;\|\&\$\`\\\(\)\{\}\[\]\<\>] ]]; then
        echo "エラー: パスに危険な文字が含まれています: $path" >&2
        return 1
    fi

    # その他NG文字列チェック
    local dangerous_patterns=(
        ".."           # ディレクトリトラバーサル
        "\0"           # ヌル文字
        "%2e%2e"       # URLエンコードされた..
        "%00"          # URLエンコードされたヌル文字
        "//"           # ダブルスラッシュ
        "%2f%2e%2e"    # URLエンコードされた/..
        "%2e%2e%2f"    # URLエンコードされた../
        "%252e%252e"   # 二重URLエンコードされた..
        "%c0%ae"       # UTF-8オーバーロング.
        "%c1%9c"       # UTF-8オーバーロング\
        "~"            # ホームディレクトリ参照
    )
    for pattern in "${dangerous_patterns[@]}"; do
        if [[ "$path" == *"$pattern"* ]]; then
            echo "エラー: パスに危険なパターンが検出されました: $pattern"
            return 1
        fi
    done

    return 0
}

# ============================================================
# PHPバージョンの検証・PHPバイナリのパス構築
# ============================================================

# PHPバージョンの検証
if [[ ! "$PHP_VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
    echo "エラー: PHPバージョンの形式が正しくありません。(例: 8.2)"
    exit 1
fi

# PHPバイナリのパス構築
PHP_BINARY="/opt/php-${PHP_VERSION}/bin/php"

# PHPバイナリの存在確認
if [ ! -f "$PHP_BINARY" ]; then
    echo "エラー: PHPバイナリが見つかりません: $PHP_BINARY"
    exit 1
fi

# ============================================================
# WP_PATHの正規化・チェック
# ============================================================

# パスの安全性チェック
if ! validate_path "$WP_PATH"; then
    exit 1
fi

# realpath を使用してパスを正規化
WP_PATH_REAL=$(realpath "$WP_PATH" 2>/dev/null) || {
    echo "エラー: パスの解決に失敗しました。"
    exit 1
}
WP_PATH="$WP_PATH_REAL"

# シンボリックリンクチェック
if [ -e "$WP_PATH" ] && [ -L "$WP_PATH" ]; then
    echo "エラー: シンボリックリンクが指定されています: $WP_PATH"
    exit 1
fi

# WordPressディレクトリの存在確認
if [ ! -d "$WP_PATH" ]; then
    echo "エラー: WordPressディレクトリが見つかりません: $WP_PATH"
    exit 1
fi

# ディレクトリの読み書き権限確認
if [ ! -r "$WP_PATH" ] || [ ! -w "$WP_PATH" ]; then
    echo "エラー: WordPressディレクトリへの適切な権限がありません。"
    exit 1
fi

# ============================================================
# 実行ユーザーの検証
# ============================================================

# パスからサーバーIDとドメイン名を抽出
SERVER_ID=$(echo "$WP_PATH" | sed -n 's|^/home/\([^/]*\)/.*|\1|p')
DOMAIN_NAME=$(echo "$WP_PATH" | sed -n 's|^/home/[^/]*/\([^/]*\)/.*|\1|p')

if [ -z "$SERVER_ID" ] || [ -z "$DOMAIN_NAME" ]; then
    echo "エラー: サーバーIDまたはドメイン名を抽出できませんでした。"
    exit 1
fi

# cpadminからのsudo実行のみ許可
if [ "${SUDO_USER:-}" != "cpadmin" ]; then
    echo "エラー: このスクリプトは実行できません。"
    exit 1
fi

# SERVER_IDと実行ユーザーが一致するかチェック
if [ "$SERVER_ID" != "$USER" ]; then
    echo "エラー: 実行ユーザー($USER)とパスのサーバーID($SERVER_ID)が一致しません。"
    echo "指定されたパスは別のユーザーのサイトです。"
    exit 1
fi

# システムユーザーかどうかを判定
check_system_user() {
    local username="$1"

    if [ -z "$username" ]; then
        return 0  # システムユーザー(true)
    fi

    # UIDとGIDを取得
    local uid=$(id -u "$username" 2>/dev/null || echo "")
    local gid=$(id -g "$username" 2>/dev/null || echo "")

    # id コマンドが失敗した場合はシステムユーザーとして扱う
    if [ -z "$uid" ] || [ -z "$gid" ]; then
        return 0  # システムユーザー(true)
    fi

    # uidが2000以上の場合、システムユーザではない
    if [ "$uid" -ge 2000 ]; then
        return 1  # 非システムユーザー(false)
    fi

    # uidが1000-2000かつgidが1000の場合
    if [ "$uid" -ge 1000 ] && [ "$uid" -lt 2000 ] && [ "$gid" -eq 1000 ]; then
        # 除外対象のユーザー名リスト
        local system_users=("phpmyadmin" "phpmyadmin2" "phpmyadmin4a" "phpmyadmin4b" "webftp" "webmail" "analyzer")

        # 除外対象のユーザー名以外の場合はシステムユーザではない
        for sys_user in "${system_users[@]}"; do
            if [ "$username" = "$sys_user" ]; then
                return 0  # システムユーザー(true)
            fi
        done

        return 1  # 非システムユーザー(false)
    fi

    return 0  # その他の場合はシステムユーザー(true)
}

if check_system_user "$USER"; then
    echo "エラー: システムユーザーでは実行できません。"
    exit 1
fi

# ============================================================
# WP-CLIコマンドの検証
# ============================================================

# まず「wp」で始まるかチェック
if [[ ! "$WP_COMMAND" =~ ^wp[[:space:]] ]]; then
    echo "エラー: コマンドは'wp'で始まる必要があります。"
    exit 1
fi

# コマンドの安全性チェック
check_command_safety() {
    local cmd="$1"

    # NULLバイトチェック
    if printf '%s' "$cmd" | od -An -tx1 | grep -q " 00"; then
        echo "エラー: コマンドにNULLバイトが含まれています。"
        return 1
    fi

    # 引用符で囲まれていないバッククォートのみを危険として検出
    # 単純なパーサーで引用符の状態を追跡
    local in_single_quote=false
    local in_double_quote=false
    local escaped=false
    local i=0

    while [ $i -lt ${#cmd} ]; do
        local char="${cmd:$i:1}"

        if [ "$escaped" = true ]; then
            escaped=false
        elif [ "$char" = "\\" ]; then
            escaped=true
        elif [ "$char" = "'" ] && [ "$in_double_quote" = false ]; then
            in_single_quote=$( [ "$in_single_quote" = true ] && echo false || echo true )
        elif [ "$char" = '"' ] && [ "$in_single_quote" = false ]; then
            in_double_quote=$( [ "$in_double_quote" = true ] && echo false || echo true )
        elif [ "$char" = '`' ] && [ "$in_single_quote" = false ] && [ "$in_double_quote" = false ]; then
            echo "エラー: 引用符で囲まれていないバッククォート(\`)は使用できません。"
            return 1
        fi

        i=$((i + 1))
    done

    # 引用符で囲まれた部分を除去して危険文字をチェック
    local temp_cmd="$cmd"
    # 引用符で囲まれた部分を一時的に置換
    temp_cmd=$(echo "$temp_cmd" | sed 's/"[^"]*"/__QUOTED__/g' | sed "s/'[^']*'/__QUOTED__/g")

    if [[ "$temp_cmd" =~ [\|\&\;\<\>] ]]; then
        echo "エラー: 危険文字は引用符で囲んでください: | & ; < >"
        echo "例: --title=\"含む&文字\""
        return 1
    fi

    return 0
}

# 安全性チェック実行
if ! check_command_safety "$WP_COMMAND"; then
    exit 1
fi

# コマンドからwpプレフィックスを除去してコマンド部分を抽出
COMMAND_PART=$(echo "$WP_COMMAND" | sed 's/^wp[[:space:]]*//')
MAIN_COMMAND=$(echo "$COMMAND_PART" | awk '{print $1}')

# 許可されたコマンドかチェック
COMMAND_ALLOWED=false
for allowed in "${ALLOWED_COMMANDS[@]}"; do
    if [ "$MAIN_COMMAND" = "$allowed" ]; then
        COMMAND_ALLOWED=true
        break
    fi
done

if [ "$COMMAND_ALLOWED" = false ]; then
    echo "エラー: 許可されていないコマンドです: $MAIN_COMMAND"
    echo "許可されているコマンド: ${ALLOWED_COMMANDS[*]}"
    exit 1
fi

# wp-cliの存在確認
if [ ! -f "$WP_CLI_PATH" ]; then
    echo "エラー: WP-CLIが見つかりません: $WP_CLI_PATH"
    exit 1
fi

# ============================================================
# WP-CLIコマンドの実行
# ============================================================

# WP-CLIコマンドの実行
cd "$WP_PATH" || {
    echo "エラー: WordPressディレクトリに移動できません: $WP_PATH"
    exit 1
}

# wp cli実行
eval "$PHP_BINARY" "$WP_CLI_PATH" --path="$WP_PATH" $COMMAND_PART

# 終了
exit $?


??

??