cf-cli-tools/cf-ssl
feibisi 1be3d8ef8d 初始提交:Cloudflare CLI 工具集
debian 开发,modiqi 修复 cf_load_profile 缺失问题。
9 个命令:cf-api/cf-zone/cf-dns/cf-cache/cf-ssl/cf-fw/cf-pagerule/cf-analytics/cf-hostname
支持多账号、域名自动解析 zone_id。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-24 02:39:31 +08:00

182 lines
6.9 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -euo pipefail
# cf-ssl — Cloudflare SSL/TLS 管理
# 用法: cf-ssl status <domain> SSL 设置和证书状态
# cf-ssl mode <domain> [mode] 查看/设置 SSL 模式
# cf-ssl certs <domain> 列出自定义证书
# cf-ssl edge-certs <domain> Edge 证书状态
# cf-ssl origin <domain> Origin CA 证书列表
# cf-ssl verify <domain> 验证 SSL 配置
# cf-ssl hsts <domain> [on|off] HSTS 开关
# cf-ssl tls-version <domain> [ver] 最低 TLS 版本
# cf-ssl always-https <domain> [on|off] 始终 HTTPS
# 选项: -p <profile> 指定 profile
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/cf-lib.sh"
cf_parse_profile "$@"
set -- "${CF_REMAINING_ARGS[@]}"
cf_load_profile
usage() {
cat >&2 <<'EOF'
用法: cf-ssl <command> <domain> [args...]
命令:
status <domain> SSL 概览(模式+证书+HSTS
mode <domain> [mode] SSL 模式off/flexible/full/strict
certs <domain> 自定义 SSL 证书列表
edge-certs <domain> Edge 证书Universal SSL状态
origin <domain> Origin CA 证书
hsts <domain> [on|off] HSTS 开关
tls-version <domain> [ver] 最低 TLS 版本1.0/1.1/1.2/1.3
always-https <domain> [on|off] 始终使用 HTTPS
EOF
exit 1
}
[[ $# -lt 1 ]] && usage
CMD="$1"; shift
case "$CMD" in
status)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl status <domain>" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
echo "=== $DOMAIN SSL 状态 ==="
# SSL 模式
resp=$(cf_call GET "/zones/$ZONE_ID/settings/ssl")
mode=$(echo "$resp" | jq -r '.result.value')
echo "SSL 模式: $mode"
# TLS 最低版本
resp=$(cf_call GET "/zones/$ZONE_ID/settings/min_tls_version")
tls=$(echo "$resp" | jq -r '.result.value')
echo "最低 TLS: $tls"
# Always HTTPS
resp=$(cf_call GET "/zones/$ZONE_ID/settings/always_use_https")
https=$(echo "$resp" | jq -r '.result.value')
echo "始终 HTTPS: $https"
# HSTS
resp=$(cf_call GET "/zones/$ZONE_ID/settings/security_header")
echo -n "HSTS: "
echo "$resp" | jq -r '.result.value.strict_transport_security | "enabled=\(.enabled) max_age=\(.max_age) include_subdomains=\(.include_subdomains)"'
# Universal SSL
resp=$(cf_call GET "/zones/$ZONE_ID/ssl/universal/settings" 2>/dev/null || echo '{}')
enabled=$(echo "$resp" | jq -r '.result.enabled // "unknown"')
echo "Universal SSL: $enabled"
;;
mode)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl mode <domain> [off|flexible|full|strict]" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
if [[ $# -lt 2 ]]; then
resp=$(cf_call GET "/zones/$ZONE_ID/settings/ssl")
echo "$resp" | jq -r '.result.value'
else
MODE="$2"
resp=$(cf_call PATCH "/zones/$ZONE_ID/settings/ssl" -d "{\"value\":\"$MODE\"}")
cf_check_error "$resp"
echo "SSL 模式已设为: $MODE"
fi
;;
certs)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl certs <domain>" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
resp=$(cf_call GET "/zones/$ZONE_ID/custom_certificates")
cf_check_error "$resp"
count=$(echo "$resp" | jq '.result | length')
if [[ "$count" == "0" ]]; then
echo "无自定义 SSL 证书"
else
echo "$resp" | jq -r '
["主机名", "颁发者", "到期", "状态", "ID"],
(.result[] | [(.hosts | join(",")), .issuer, .expires_on[:10], .status, .id]) |
@tsv' | column -t -s $'\t'
fi
;;
edge-certs)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl edge-certs <domain>" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
resp=$(cf_call GET "/zones/$ZONE_ID/ssl/certificate_packs?status=all")
cf_check_error "$resp"
echo "$resp" | jq '.result[] | {
id, type, status,
hosts,
validity_days,
certificate_authority,
validation_method
}'
;;
origin)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl origin <domain>" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
resp=$(cf_call GET "/zones/$ZONE_ID/origin_tls_client_auth")
cf_check_error "$resp"
count=$(echo "$resp" | jq '.result | length')
if [[ "$count" == "0" ]]; then
echo "无 Origin CA 证书"
else
echo "$resp" | jq -r '
["ID", "状态", "到期", "颁发者"],
(.result[] | [.id[:12], .status, .expires_on[:10], .issuer]) |
@tsv' | column -t -s $'\t'
fi
;;
hsts)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl hsts <domain> [on|off]" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
if [[ $# -lt 2 ]]; then
resp=$(cf_call GET "/zones/$ZONE_ID/settings/security_header")
echo "$resp" | jq '.result.value.strict_transport_security'
else
if [[ "$2" == "on" ]]; then
DATA='{"value":{"strict_transport_security":{"enabled":true,"max_age":31536000,"include_subdomains":true,"nosniff":true}}}'
else
DATA='{"value":{"strict_transport_security":{"enabled":false,"max_age":0}}}'
fi
resp=$(cf_call PATCH "/zones/$ZONE_ID/settings/security_header" -d "$DATA")
cf_check_error "$resp"
echo "HSTS 已设为: $2"
fi
;;
tls-version)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl tls-version <domain> [1.0|1.1|1.2|1.3]" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
if [[ $# -lt 2 ]]; then
resp=$(cf_call GET "/zones/$ZONE_ID/settings/min_tls_version")
echo "$resp" | jq -r '.result.value'
else
resp=$(cf_call PATCH "/zones/$ZONE_ID/settings/min_tls_version" -d "{\"value\":\"$2\"}")
cf_check_error "$resp"
echo "最低 TLS 版本已设为: $2"
fi
;;
always-https)
[[ $# -lt 1 ]] && { echo "用法: cf-ssl always-https <domain> [on|off]" >&2; exit 1; }
DOMAIN="$1"
ZONE_ID=$(cf_resolve_zone "$DOMAIN")
if [[ $# -lt 2 ]]; then
resp=$(cf_call GET "/zones/$ZONE_ID/settings/always_use_https")
echo "$resp" | jq -r '.result.value'
else
resp=$(cf_call PATCH "/zones/$ZONE_ID/settings/always_use_https" -d "{\"value\":\"$2\"}")
cf_check_error "$resp"
echo "始终 HTTPS 已设为: $2"
fi
;;
*) usage ;;
esac