189 lines
5.5 KiB
Bash
189 lines
5.5 KiB
Bash
#!/usr/bin/env bash
|
||
set -e
|
||
|
||
if [ $# -ne 3 ]; then
|
||
echo "Usage: $0 <controller-url> <api-token> <inventory-name>"
|
||
exit 1
|
||
fi
|
||
|
||
CONTROLLER_URL="$1"
|
||
API_TOKEN="$2"
|
||
INVENTORY_NAME="$3"
|
||
|
||
# -----------------------------
|
||
# Detect OS + environment
|
||
# -----------------------------
|
||
echo "[INFO] Detecting OS and environment..."
|
||
|
||
if [ -f /etc/os-release ]; then
|
||
. /etc/os-release
|
||
DISTRO=$ID
|
||
DISTRO_PRETTY=$PRETTY_NAME
|
||
else
|
||
DISTRO="unknown"
|
||
DISTRO_PRETTY="Unknown OS"
|
||
fi
|
||
|
||
ARCH=$(uname -m)
|
||
|
||
# -----------------------------
|
||
# Detect virtualization (with hardware detection)
|
||
# -----------------------------
|
||
RAW_VIRT=$(systemd-detect-virt 2>/dev/null || echo "unknown")
|
||
|
||
case "$RAW_VIRT" in
|
||
none)
|
||
VIRT_TYPE="hardware"
|
||
;;
|
||
docker|podman|lxc|container)
|
||
VIRT_TYPE="container"
|
||
;;
|
||
kvm|qemu|vmware|xen|microsoft|oracle|hyperv)
|
||
VIRT_TYPE="$RAW_VIRT"
|
||
;;
|
||
*)
|
||
VIRT_TYPE="unknown"
|
||
;;
|
||
esac
|
||
|
||
# -----------------------------
|
||
# Detect cloud provider
|
||
# -----------------------------
|
||
if curl -s --connect-timeout 1 http://169.254.169.254/latest/meta-data/ >/dev/null; then
|
||
CLOUD="aws"
|
||
elif curl -s --connect-timeout 1 -H Metadata:true http://169.254.169.254/metadata/instance?api-version=2021-02-01 >/dev/null; then
|
||
CLOUD="azure"
|
||
elif curl -s --connect-timeout 1 http://metadata.google.internal >/dev/null; then
|
||
CLOUD="gcp"
|
||
else
|
||
CLOUD="none"
|
||
fi
|
||
|
||
IPA_HOSTNAME=$(hostname -f)
|
||
|
||
echo "[INFO] Hostname: $IPA_HOSTNAME"
|
||
echo "[INFO] OS: $DISTRO_PRETTY"
|
||
echo "[INFO] Architecture: $ARCH"
|
||
echo "[INFO] Virtualization: $VIRT_TYPE"
|
||
echo "[INFO] Cloud provider: $CLOUD"
|
||
|
||
# -----------------------------
|
||
# Install Python
|
||
# -----------------------------
|
||
install_python() {
|
||
case "$DISTRO" in
|
||
arch)
|
||
sudo pacman -Sy --noconfirm python
|
||
;;
|
||
debian|ubuntu)
|
||
sudo apt update && sudo apt install -y python3
|
||
;;
|
||
rhel|centos|rocky|almalinux)
|
||
sudo yum install -y python3 || sudo dnf install -y python3
|
||
;;
|
||
fedora)
|
||
sudo dnf install -y python3
|
||
;;
|
||
opensuse*|sles)
|
||
sudo zypper install -y python3
|
||
;;
|
||
*)
|
||
echo "[WARN] Unknown distro, trying generic python3 install..."
|
||
sudo bash -c "apt install -y python3 || yum install -y python3 || dnf install -y python3 || pacman -Sy --noconfirm python"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
if ! command -v python3 >/dev/null 2>&1; then
|
||
echo "[INFO] Installing Python..."
|
||
install_python
|
||
fi
|
||
|
||
# -----------------------------
|
||
# Ensure SSH + GSSAPI
|
||
# -----------------------------
|
||
echo "[INFO] Ensuring SSH is running..."
|
||
sudo systemctl enable sshd --now 2>/dev/null || sudo systemctl enable ssh --now || true
|
||
|
||
if ! grep -q "GSSAPIAuthentication yes" /etc/ssh/sshd_config; then
|
||
echo "GSSAPIAuthentication yes" | sudo tee -a /etc/ssh/sshd_config
|
||
sudo systemctl restart sshd || sudo systemctl restart ssh
|
||
fi
|
||
|
||
# -----------------------------
|
||
# Helper: API GET
|
||
# -----------------------------
|
||
api_get() {
|
||
curl -s -H "Authorization: Bearer $API_TOKEN" "$CONTROLLER_URL$1"
|
||
}
|
||
|
||
# -----------------------------
|
||
# Helper: API POST
|
||
# -----------------------------
|
||
api_post() {
|
||
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d "$2" "$CONTROLLER_URL$1"
|
||
}
|
||
|
||
# -----------------------------
|
||
# Ensure inventory exists
|
||
# -----------------------------
|
||
echo "[INFO] Checking inventory '$INVENTORY_NAME'..."
|
||
|
||
INVENTORY_ID=$(api_get "/api/v2/inventories/?name=$INVENTORY_NAME" \
|
||
| python3 -c "import sys, json; d=json.load(sys.stdin); print(d['results'][0]['id'] if d['count'] else '')")
|
||
|
||
if [ -z "$INVENTORY_ID" ]; then
|
||
echo "[INFO] Inventory not found. Creating..."
|
||
INVENTORY_ID=$(api_post "/api/v2/inventories/" \
|
||
"{\"name\": \"$INVENTORY_NAME\", \"organization\": 1}" \
|
||
| python3 -c "import sys, json; print(json.load(sys.stdin)['id'])")
|
||
else
|
||
echo "[INFO] Inventory exists with ID $INVENTORY_ID"
|
||
fi
|
||
|
||
# -----------------------------
|
||
# Ensure groups exist
|
||
# -----------------------------
|
||
create_group_if_missing() {
|
||
local GROUP="$1"
|
||
local GROUP_ID=$(api_get "/api/v2/groups/?name=$GROUP&inventory=$INVENTORY_ID" \
|
||
| python3 -c "import sys, json; d=json.load(sys.stdin); print(d['results'][0]['id'] if d['count'] else '')")
|
||
|
||
if [ -z "$GROUP_ID" ]; then
|
||
echo "[INFO] Creating group: $GROUP"
|
||
GROUP_ID=$(api_post "/api/v2/groups/" \
|
||
"{\"name\": \"$GROUP\", \"inventory\": $INVENTORY_ID}" \
|
||
| python3 -c "import sys, json; print(json.load(sys.stdin)['id'])")
|
||
fi
|
||
|
||
echo "$GROUP_ID"
|
||
}
|
||
|
||
GROUP_OS=$(create_group_if_missing "$DISTRO")
|
||
GROUP_ARCH=$(create_group_if_missing "arch-$ARCH")
|
||
GROUP_VIRT=$(create_group_if_missing "virt-$VIRT_TYPE")
|
||
GROUP_CLOUD=$(create_group_if_missing "cloud-$CLOUD")
|
||
|
||
# -----------------------------
|
||
# Register host
|
||
# -----------------------------
|
||
echo "[INFO] Registering host..."
|
||
|
||
HOST_ID=$(api_post "/api/v2/hosts/" \
|
||
"{\"name\": \"$IPA_HOSTNAME\", \"inventory\": $INVENTORY_ID, \"enabled\": true}" \
|
||
| python3 -c "import sys, json; print(json.load(sys.stdin)['id'])")
|
||
|
||
echo "[INFO] Host ID: $HOST_ID"
|
||
|
||
# -----------------------------
|
||
# Add host to groups
|
||
# -----------------------------
|
||
for G in $GROUP_OS $GROUP_ARCH $GROUP_VIRT $GROUP_CLOUD; do
|
||
echo "[INFO] Adding host to group ID $G"
|
||
api_post "/api/v2/groups/$G/hosts/" "{\"id\": $HOST_ID}" >/dev/null
|
||
done
|
||
|
||
echo "[SUCCESS] Host fully enrolled and auto‑classified."
|