install-ca.sh
· 6.3 KiB · Bash
原始文件
#!/usr/bin/env bash
set -euo pipefail
# ==========================================
# Root CA bootstrap + install script
# For Linux/macOS/WSL/Git Bash
# ==========================================
# Defaults can be overridden with env vars or CLI args
CA_URL="${CA_URL:-https://ca.insmw.internal}"
CA_FINGERPRINT="${CA_FINGERPRINT:-}"
STEP_VERSION="${STEP_VERSION:-0.28.7}"
STEP_BIN_DIR="${STEP_BIN_DIR:-/usr/local/bin}"
STEP_CONFIG_DIR="${STEP_CONFIG_DIR:-$HOME/.step}"
FORCE="${FORCE:-0}"
usage() {
cat <<EOF
Usage:
$0 --ca-url <url> --fingerprint <fingerprint> [--force]
Examples:
curl -fsSL https://your-opengist/raw/install-ca.sh | bash -s -- \\
--ca-url https://ca.insmw.internal \\
--fingerprint abcdef1234567890...
Environment variables:
CA_URL
CA_FINGERPRINT
STEP_VERSION
STEP_BIN_DIR
STEP_CONFIG_DIR
FORCE=1
EOF
}
log() {
printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}
fail() {
echo "ERROR: $*" >&2
exit 1
}
need_cmd() {
command -v "$1" >/dev/null 2>&1
}
download_file() {
local url="$1"
local out="$2"
if need_cmd curl; then
curl -fsSL "$url" -o "$out"
elif need_cmd wget; then
wget -qO "$out" "$url"
else
fail "Neither curl nor wget is installed"
fi
}
detect_os() {
local uname_s
uname_s="$(uname -s 2>/dev/null || true)"
case "$uname_s" in
Linux*) echo "linux" ;;
Darwin*) echo "darwin" ;;
MINGW*|MSYS*|CYGWIN*) echo "windows_bash" ;;
*) echo "unknown" ;;
esac
}
detect_arch() {
local uname_m
uname_m="$(uname -m 2>/dev/null || true)"
case "$uname_m" in
x86_64|amd64) echo "amd64" ;;
aarch64|arm64) echo "arm64" ;;
armv7l) echo "armv7" ;;
*) echo "$uname_m" ;;
esac
}
install_step_linux() {
local arch="$1"
local tmpdir pkg_ext pkg_name url
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' RETURN
if need_cmd apk; then
pkg_ext="apk"
case "$arch" in
amd64) pkg_name="step-cli_${STEP_VERSION}_amd64.apk" ;;
arm64) pkg_name="step-cli_${STEP_VERSION}_arm64.apk" ;;
*) fail "Unsupported architecture for Alpine: $arch" ;;
esac
url="https://github.com/smallstep/cli/releases/download/v${STEP_VERSION}/${pkg_name}"
log "Downloading step-cli from $url"
download_file "$url" "$tmpdir/$pkg_name"
sudo apk add --allow-untrusted "$tmpdir/$pkg_name"
return
fi
if need_cmd dpkg; then
pkg_ext="deb"
case "$arch" in
amd64) pkg_name="step-cli_${STEP_VERSION}_amd64.deb" ;;
arm64) pkg_name="step-cli_${STEP_VERSION}_arm64.deb" ;;
*) fail "Unsupported architecture for Debian/Ubuntu: $arch" ;;
esac
url="https://github.com/smallstep/cli/releases/download/v${STEP_VERSION}/${pkg_name}"
log "Downloading step-cli from $url"
download_file "$url" "$tmpdir/$pkg_name"
sudo dpkg -i "$tmpdir/$pkg_name" || sudo apt-get update && sudo apt-get install -f -y
return
fi
fail "Unsupported Linux distribution. Supported: Debian/Ubuntu, Alpine"
}
install_step_darwin() {
if need_cmd brew; then
log "Installing step via Homebrew"
brew install step
return
fi
fail "Homebrew is required on macOS to install step automatically"
}
ensure_step() {
local os arch
if need_cmd step; then
log "step CLI already installed"
return
fi
os="$(detect_os)"
arch="$(detect_arch)"
log "step CLI not found, installing for $os/$arch"
case "$os" in
linux) install_step_linux "$arch" ;;
darwin) install_step_darwin ;;
windows_bash)
fail "For native Windows, use the PowerShell installer instead of the bash script"
;;
*)
fail "Unsupported OS: $os"
;;
esac
need_cmd step || fail "step CLI installation failed"
}
bootstrap_step() {
[ -n "$CA_FINGERPRINT" ] || fail "CA fingerprint is required"
if [ "$FORCE" = "1" ]; then
log "Removing previous step configuration because FORCE=1"
rm -rf "$STEP_CONFIG_DIR"
fi
mkdir -p "$STEP_CONFIG_DIR"
log "Bootstrapping step against $CA_URL"
step ca bootstrap \
--ca-url "$CA_URL" \
--fingerprint "$CA_FINGERPRINT" \
--install \
--force
}
install_linux_trust() {
local root_cert
root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt"
[ -f "$root_cert" ] || fail "Root certificate not found at $root_cert"
if need_cmd update-ca-certificates; then
log "Installing root CA into system trust store using update-ca-certificates"
sudo mkdir -p /usr/local/share/ca-certificates
sudo cp "$root_cert" /usr/local/share/ca-certificates/insmw-root-ca.crt
sudo update-ca-certificates
return
fi
if need_cmd trust; then
log "Installing root CA into system trust store using p11-kit trust"
sudo trust anchor "$root_cert"
return
fi
if [ -d /etc/ssl/certs ]; then
log "Copying certificate to /etc/ssl/certs as fallback"
sudo cp "$root_cert" /etc/ssl/certs/insmw-root-ca.crt
return
fi
fail "Could not determine how to install the CA into the Linux trust store"
}
install_macos_trust() {
local root_cert
root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt"
[ -f "$root_cert" ] || fail "Root certificate not found at $root_cert"
log "Installing root CA into macOS System keychain"
sudo security add-trusted-cert \
-d \
-r trustRoot \
-k /Library/Keychains/System.keychain \
"$root_cert"
}
install_trust_store() {
local os
os="$(detect_os)"
case "$os" in
linux) install_linux_trust ;;
darwin) install_macos_trust ;;
*)
fail "Unsupported OS for trust installation: $os"
;;
esac
}
verify_install() {
local root_cert
root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt"
log "Installed root CA at: $root_cert"
log "Certificate subject:"
step certificate inspect "$root_cert" --short || true
echo
echo "Done."
echo "You may need to restart applications that cache trust settings, such as browsers or Docker."
}
parse_args() {
while [ $# -gt 0 ]; do
case "$1" in
--ca-url)
CA_URL="$2"
shift 2
;;
--fingerprint)
CA_FINGERPRINT="$2"
shift 2
;;
--force)
FORCE=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
fail "Unknown argument: $1"
;;
esac
done
}
main() {
parse_args "$@"
[ -n "$CA_URL" ] || fail "CA URL is required"
[ -n "$CA_FINGERPRINT" ] || fail "CA fingerprint is required"
ensure_step
bootstrap_step
install_trust_store
verify_install
}
main "$@"
| 1 | #!/usr/bin/env bash |
| 2 | set -euo pipefail |
| 3 | |
| 4 | # ========================================== |
| 5 | # Root CA bootstrap + install script |
| 6 | # For Linux/macOS/WSL/Git Bash |
| 7 | # ========================================== |
| 8 | |
| 9 | # Defaults can be overridden with env vars or CLI args |
| 10 | CA_URL="${CA_URL:-https://ca.insmw.internal}" |
| 11 | CA_FINGERPRINT="${CA_FINGERPRINT:-}" |
| 12 | STEP_VERSION="${STEP_VERSION:-0.28.7}" |
| 13 | STEP_BIN_DIR="${STEP_BIN_DIR:-/usr/local/bin}" |
| 14 | STEP_CONFIG_DIR="${STEP_CONFIG_DIR:-$HOME/.step}" |
| 15 | FORCE="${FORCE:-0}" |
| 16 | |
| 17 | usage() { |
| 18 | cat <<EOF |
| 19 | Usage: |
| 20 | $0 --ca-url <url> --fingerprint <fingerprint> [--force] |
| 21 | |
| 22 | Examples: |
| 23 | curl -fsSL https://your-opengist/raw/install-ca.sh | bash -s -- \\ |
| 24 | --ca-url https://ca.insmw.internal \\ |
| 25 | --fingerprint abcdef1234567890... |
| 26 | |
| 27 | Environment variables: |
| 28 | CA_URL |
| 29 | CA_FINGERPRINT |
| 30 | STEP_VERSION |
| 31 | STEP_BIN_DIR |
| 32 | STEP_CONFIG_DIR |
| 33 | FORCE=1 |
| 34 | |
| 35 | EOF |
| 36 | } |
| 37 | |
| 38 | log() { |
| 39 | printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" |
| 40 | } |
| 41 | |
| 42 | fail() { |
| 43 | echo "ERROR: $*" >&2 |
| 44 | exit 1 |
| 45 | } |
| 46 | |
| 47 | need_cmd() { |
| 48 | command -v "$1" >/dev/null 2>&1 |
| 49 | } |
| 50 | |
| 51 | download_file() { |
| 52 | local url="$1" |
| 53 | local out="$2" |
| 54 | |
| 55 | if need_cmd curl; then |
| 56 | curl -fsSL "$url" -o "$out" |
| 57 | elif need_cmd wget; then |
| 58 | wget -qO "$out" "$url" |
| 59 | else |
| 60 | fail "Neither curl nor wget is installed" |
| 61 | fi |
| 62 | } |
| 63 | |
| 64 | detect_os() { |
| 65 | local uname_s |
| 66 | uname_s="$(uname -s 2>/dev/null || true)" |
| 67 | |
| 68 | case "$uname_s" in |
| 69 | Linux*) echo "linux" ;; |
| 70 | Darwin*) echo "darwin" ;; |
| 71 | MINGW*|MSYS*|CYGWIN*) echo "windows_bash" ;; |
| 72 | *) echo "unknown" ;; |
| 73 | esac |
| 74 | } |
| 75 | |
| 76 | detect_arch() { |
| 77 | local uname_m |
| 78 | uname_m="$(uname -m 2>/dev/null || true)" |
| 79 | |
| 80 | case "$uname_m" in |
| 81 | x86_64|amd64) echo "amd64" ;; |
| 82 | aarch64|arm64) echo "arm64" ;; |
| 83 | armv7l) echo "armv7" ;; |
| 84 | *) echo "$uname_m" ;; |
| 85 | esac |
| 86 | } |
| 87 | |
| 88 | install_step_linux() { |
| 89 | local arch="$1" |
| 90 | local tmpdir pkg_ext pkg_name url |
| 91 | |
| 92 | tmpdir="$(mktemp -d)" |
| 93 | trap 'rm -rf "$tmpdir"' RETURN |
| 94 | |
| 95 | if need_cmd apk; then |
| 96 | pkg_ext="apk" |
| 97 | case "$arch" in |
| 98 | amd64) pkg_name="step-cli_${STEP_VERSION}_amd64.apk" ;; |
| 99 | arm64) pkg_name="step-cli_${STEP_VERSION}_arm64.apk" ;; |
| 100 | *) fail "Unsupported architecture for Alpine: $arch" ;; |
| 101 | esac |
| 102 | |
| 103 | url="https://github.com/smallstep/cli/releases/download/v${STEP_VERSION}/${pkg_name}" |
| 104 | log "Downloading step-cli from $url" |
| 105 | download_file "$url" "$tmpdir/$pkg_name" |
| 106 | sudo apk add --allow-untrusted "$tmpdir/$pkg_name" |
| 107 | return |
| 108 | fi |
| 109 | |
| 110 | if need_cmd dpkg; then |
| 111 | pkg_ext="deb" |
| 112 | case "$arch" in |
| 113 | amd64) pkg_name="step-cli_${STEP_VERSION}_amd64.deb" ;; |
| 114 | arm64) pkg_name="step-cli_${STEP_VERSION}_arm64.deb" ;; |
| 115 | *) fail "Unsupported architecture for Debian/Ubuntu: $arch" ;; |
| 116 | esac |
| 117 | |
| 118 | url="https://github.com/smallstep/cli/releases/download/v${STEP_VERSION}/${pkg_name}" |
| 119 | log "Downloading step-cli from $url" |
| 120 | download_file "$url" "$tmpdir/$pkg_name" |
| 121 | sudo dpkg -i "$tmpdir/$pkg_name" || sudo apt-get update && sudo apt-get install -f -y |
| 122 | return |
| 123 | fi |
| 124 | |
| 125 | fail "Unsupported Linux distribution. Supported: Debian/Ubuntu, Alpine" |
| 126 | } |
| 127 | |
| 128 | install_step_darwin() { |
| 129 | if need_cmd brew; then |
| 130 | log "Installing step via Homebrew" |
| 131 | brew install step |
| 132 | return |
| 133 | fi |
| 134 | |
| 135 | fail "Homebrew is required on macOS to install step automatically" |
| 136 | } |
| 137 | |
| 138 | ensure_step() { |
| 139 | local os arch |
| 140 | if need_cmd step; then |
| 141 | log "step CLI already installed" |
| 142 | return |
| 143 | fi |
| 144 | |
| 145 | os="$(detect_os)" |
| 146 | arch="$(detect_arch)" |
| 147 | |
| 148 | log "step CLI not found, installing for $os/$arch" |
| 149 | |
| 150 | case "$os" in |
| 151 | linux) install_step_linux "$arch" ;; |
| 152 | darwin) install_step_darwin ;; |
| 153 | windows_bash) |
| 154 | fail "For native Windows, use the PowerShell installer instead of the bash script" |
| 155 | ;; |
| 156 | *) |
| 157 | fail "Unsupported OS: $os" |
| 158 | ;; |
| 159 | esac |
| 160 | |
| 161 | need_cmd step || fail "step CLI installation failed" |
| 162 | } |
| 163 | |
| 164 | bootstrap_step() { |
| 165 | [ -n "$CA_FINGERPRINT" ] || fail "CA fingerprint is required" |
| 166 | |
| 167 | if [ "$FORCE" = "1" ]; then |
| 168 | log "Removing previous step configuration because FORCE=1" |
| 169 | rm -rf "$STEP_CONFIG_DIR" |
| 170 | fi |
| 171 | |
| 172 | mkdir -p "$STEP_CONFIG_DIR" |
| 173 | |
| 174 | log "Bootstrapping step against $CA_URL" |
| 175 | step ca bootstrap \ |
| 176 | --ca-url "$CA_URL" \ |
| 177 | --fingerprint "$CA_FINGERPRINT" \ |
| 178 | --install \ |
| 179 | --force |
| 180 | } |
| 181 | |
| 182 | install_linux_trust() { |
| 183 | local root_cert |
| 184 | root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt" |
| 185 | |
| 186 | [ -f "$root_cert" ] || fail "Root certificate not found at $root_cert" |
| 187 | |
| 188 | if need_cmd update-ca-certificates; then |
| 189 | log "Installing root CA into system trust store using update-ca-certificates" |
| 190 | sudo mkdir -p /usr/local/share/ca-certificates |
| 191 | sudo cp "$root_cert" /usr/local/share/ca-certificates/insmw-root-ca.crt |
| 192 | sudo update-ca-certificates |
| 193 | return |
| 194 | fi |
| 195 | |
| 196 | if need_cmd trust; then |
| 197 | log "Installing root CA into system trust store using p11-kit trust" |
| 198 | sudo trust anchor "$root_cert" |
| 199 | return |
| 200 | fi |
| 201 | |
| 202 | if [ -d /etc/ssl/certs ]; then |
| 203 | log "Copying certificate to /etc/ssl/certs as fallback" |
| 204 | sudo cp "$root_cert" /etc/ssl/certs/insmw-root-ca.crt |
| 205 | return |
| 206 | fi |
| 207 | |
| 208 | fail "Could not determine how to install the CA into the Linux trust store" |
| 209 | } |
| 210 | |
| 211 | install_macos_trust() { |
| 212 | local root_cert |
| 213 | root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt" |
| 214 | |
| 215 | [ -f "$root_cert" ] || fail "Root certificate not found at $root_cert" |
| 216 | |
| 217 | log "Installing root CA into macOS System keychain" |
| 218 | sudo security add-trusted-cert \ |
| 219 | -d \ |
| 220 | -r trustRoot \ |
| 221 | -k /Library/Keychains/System.keychain \ |
| 222 | "$root_cert" |
| 223 | } |
| 224 | |
| 225 | install_trust_store() { |
| 226 | local os |
| 227 | os="$(detect_os)" |
| 228 | |
| 229 | case "$os" in |
| 230 | linux) install_linux_trust ;; |
| 231 | darwin) install_macos_trust ;; |
| 232 | *) |
| 233 | fail "Unsupported OS for trust installation: $os" |
| 234 | ;; |
| 235 | esac |
| 236 | } |
| 237 | |
| 238 | verify_install() { |
| 239 | local root_cert |
| 240 | root_cert="$STEP_CONFIG_DIR/certs/root_ca.crt" |
| 241 | |
| 242 | log "Installed root CA at: $root_cert" |
| 243 | log "Certificate subject:" |
| 244 | step certificate inspect "$root_cert" --short || true |
| 245 | |
| 246 | echo |
| 247 | echo "Done." |
| 248 | echo "You may need to restart applications that cache trust settings, such as browsers or Docker." |
| 249 | } |
| 250 | |
| 251 | parse_args() { |
| 252 | while [ $# -gt 0 ]; do |
| 253 | case "$1" in |
| 254 | --ca-url) |
| 255 | CA_URL="$2" |
| 256 | shift 2 |
| 257 | ;; |
| 258 | --fingerprint) |
| 259 | CA_FINGERPRINT="$2" |
| 260 | shift 2 |
| 261 | ;; |
| 262 | --force) |
| 263 | FORCE=1 |
| 264 | shift |
| 265 | ;; |
| 266 | -h|--help) |
| 267 | usage |
| 268 | exit 0 |
| 269 | ;; |
| 270 | *) |
| 271 | fail "Unknown argument: $1" |
| 272 | ;; |
| 273 | esac |
| 274 | done |
| 275 | } |
| 276 | |
| 277 | main() { |
| 278 | parse_args "$@" |
| 279 | |
| 280 | [ -n "$CA_URL" ] || fail "CA URL is required" |
| 281 | [ -n "$CA_FINGERPRINT" ] || fail "CA fingerprint is required" |
| 282 | |
| 283 | ensure_step |
| 284 | bootstrap_step |
| 285 | install_trust_store |
| 286 | verify_install |
| 287 | } |
| 288 | |
| 289 | main "$@" |