diff --git a/bin/freeleaps-cluster-authenticator b/bin/freeleaps-cluster-authenticator new file mode 100755 index 00000000..2c32e5f3 --- /dev/null +++ b/bin/freeleaps-cluster-authenticator @@ -0,0 +1,232 @@ +#!/bin/sh + +set -eu + +CLUSTER_API_LB_IP=${CLUSTER_API_LB_IP:-4.155.160.32} +CLUSTER_API_LB_PORT=${CLUSTER_API_LB_PORT:-6443} +MICROSOFT_ENTRA_ID_TENANT=${MICROSOFT_ENTRA_ID_TENANT:-cf151ee8-5c2c-4fe7-a1c4-809ba43c9f24} +MICROSOFT_ENTRA_ID_CLIENT_ID=${MICROSOFT_ENTRA_ID_CLIENT_ID:-7cd1df19-24ea-46d7-acd3-5336283139e0} +MICROSOFT_ENTRA_ID_CLIENT_SECRET=${MICROSOFT_ENTRA_ID_CLIENT_SECRET:-L9J8Q~kClGP-sXKS3YFgnpDu7ednUdlWGsWfQbTl} +MICROSOFT_ENTRA_ID_ISSUER=${MICROSOFT_ENTRA_ID_ISSUER:-https://login.microsoftonline.com/${MICROSOFT_ENTRA_ID_TENANT}/v2.0} +OS=${OS:-} +ARCH=${ARCH:-} +KUBECTL_VERSION=${KUBECTL_VERSION:-v1.30.3} +KUBELOGIN_VERSION=${KUBELOGIN_VERSION:-v1.31.1} + +# Options +AUTO_INSTALL_KUBECTL=${AUTO_INSTALL_KUBECTL:-true} +AUTO_INSTALL_KUBELOGIN=${AUTO_INSTALL_KUBELOGIN:-true} + +gather_os_environment() { + echo "[GATHER] Checking OS and architecture..." + + _uname_os_output="$(uname -s)" + case "${_uname_os_output}" in + Linux*) + OS='linux' + ;; + Darwin) + OS='darwin' + ;; + *) + echo "[ERROR] Unsupported OS: ${_uname_os_output}" + exit 1 + ;; + esac + + _uname_arch_output="$(uname -m)" + case "${_uname_arch_output}" in + x86_64) + ARCH='amd64' + ;; + arm64) + ARCH='arm64' + ;; + *) + echo "[ERROR] Unsupported architecture: ${_uname_arch_output}" + exit 1 + ;; + esac +} + +ensure_kubectl() { + echo "[INSTALL] Installing kubectl..." + + _ensure_kubectl_download_url="https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/${OS}/${ARCH}/kubectl" + + echo "[INSTALL] Downloading kubectl (${ARCH}-${KUBECTL_VERSION}) from ${_ensure_kubectl_download_url}" + # download to tmp folder + curl --progress-bar -o /tmp/kubectl "${_ensure_kubectl_download_url}" + chmod +x /tmp/kubectl + sudo mv /tmp/kubectl /usr/local/bin/kubectl + echo "[INSTALL] kubectl installed successfully." +} + +ensure_kubelogin() { + echo "[INSTALL] Installing kubelogin..." + + _ensure_kubelogin_download_url="https://github.com/int128/kubelogin/releases/download/${KUBELOGIN_VERSION}/kubelogin_${OS}_${ARCH}.zip" + + echo "[INSTALL] Downloading kubelogin (${ARCH}-${KUBELOGIN_VERSION}) from ${_ensure_kubelogin_download_url}" + + # download to tmp folder + curl --progress-bar -L -o /tmp/kubelogin.zip "${_ensure_kubelogin_download_url}" + + # Check if the file is a valid zip file + if ! unzip -t /tmp/kubelogin.zip > /dev/null 2>&1; then + echo "[ERROR] Downloaded file is not a valid zip file or download failed." + rm /tmp/kubelogin.zip + exit 1 + fi + + unzip /tmp/kubelogin.zip -d /tmp/kubelogin-release + chmod +x /tmp/kubelogin-release/kubelogin + sudo mv /tmp/kubelogin-release/kubelogin /usr/local/bin/kubelogin + sudo rm -rf /tmp/kubelogin-release + echo "[INSTALL] kubelogin installed successfully." +} + +gather_prerequisites() { + gather_os_environment + + echo "[PRE-PREREQUISITES] Checking for required tools..." + + if ! command -v curl > /dev/null; then + echo "[ERROR] curl is required to download kubectl and kubelogin" + exit 1 + else + echo "[PRE-PREREQUISITES] curl: ✓" + fi + + + if ! command -v unzip > /dev/null; then + echo "[ERROR] unzip is required to extract kubelogin" + exit 1 + else + echo "[PRE-PREREQUISITES] unzip: ✓" + fi + + if ! command -v uname > /dev/null; then + echo "[ERROR] uname is required to determine OS and architecture" + exit 1 + else + echo "[PRE-PREREQUISITES] uname: ✓" + fi + + if ! command -v kubectl > /dev/null; then + if [ "${AUTO_INSTALL_KUBECTL}" = "true" ]; then + echo "[PRE-PREREQUISITES] kubectl: Installing..." + ensure_kubectl + else + echo "[ERROR] kubectl is required to authenticate with the cluster" + exit 1 + fi + + else + echo "[PRE-PREREQUISITES] kubectl: ✓" + fi + + if ! command -v kubelogin > /dev/null; then + if [ "${AUTO_INSTALL_KUBECTL}" = "true" ]; then + echo "[PRE-PREREQUISITES] kubelogin: Installing..." + ensure_kubelogin + else + echo "[ERROR] kubelogin is required to authenticate with the cluster" + exit 1 + fi + + else + echo "[PRE-PREREQUISITES] kubelogin: ✓" + fi +} + +setup_kubelogin() { + echo "[SETUP] Setting up kubelogin..." + + kubelogin setup \ + --oidc-issuer-url "${MICROSOFT_ENTRA_ID_ISSUER}" \ + --oidc-client-id "${MICROSOFT_ENTRA_ID_CLIENT_ID}" \ + --oidc-client-secret "${MICROSOFT_ENTRA_ID_CLIENT_SECRET}" \ + --oidc-extra-scope "offline_access" \ + --oidc-extra-scope "profile" \ + --oidc-extra-scope "email" > /dev/null 2>&1 + + echo "[SETUP] kubelogin setup completed successfully." +} + +prompt_username() { + echo "[PROMPT] Please enter your Mathmast account name (ending with @mathmast.com, eg. jack@mathmast.com):" + read -r username + echo "[PROMPT] Username: ${username}" +} + +set_kubectl_credentials() { + echo "[KUBECTL & KUBE_LOGIN] Setting kubectl credentials for ${username}..." + + kubectl config set-credentials "$username" \ + --exec-api-version=client.authentication.k8s.io/v1beta1 \ + --exec-command=kubelogin \ + --exec-arg=get-token \ + --exec-arg="--oidc-issuer-url=${MICROSOFT_ENTRA_ID_ISSUER}" \ + --exec-arg="--oidc-client-id=${MICROSOFT_ENTRA_ID_CLIENT_ID}" \ + --exec-arg="--oidc-client-secret=${MICROSOFT_ENTRA_ID_CLIENT_SECRET}" \ + --exec-arg="--oidc-extra-scope=offline_access" \ + --exec-arg="--oidc-extra-scope=profile" \ + --exec-arg="--oidc-extra-scope=email" > /dev/null 2>&1 + + echo "[KUBECTL & KUBE_LOGIN] Credentials set successfully." +} + +add_cluster_to_kubectl() { + echo "[KUBECTL] Adding cluster (named to: freeleaps-cluster) to kubectl..." + + kubectl config set-cluster freeleaps-cluster \ + --server="https://${CLUSTER_API_LB_IP}:${CLUSTER_API_LB_PORT}" \ + --insecure-skip-tls-verify=true > /dev/null 2>&1 + + echo "[KUBECTL] Cluster added to kubectl successfully." +} + +create_kubectl_context() { + echo "[KUBECTL] Creating kubectl context..." + + kubectl config set-context "${username}@freeleaps-cluster" \ + --cluster=freeleaps-cluster \ + --user="${username}" > /dev/null 2>&1 + + echo "[KUBECTL] Context created successfully." +} + +use_kubectl_context() { + echo "[KUBECTL] Using kubectl context..." + + kubectl config use-context "${username}@freeleaps-cluster" > /dev/null 2>&1 + + echo "[KUBECTL] Context set successfully." +} + +check_whoami() { + echo "[KUBECTL] Checking whoami..." + + kubectl auth whoami +} + +main() { + gather_prerequisites + + echo "[INFO] OS: ${OS}" + echo "[INFO] Architecture: ${ARCH}" + + setup_kubelogin + prompt_username + set_kubectl_credentials + add_cluster_to_kubectl + create_kubectl_context + use_kubectl_context + check_whoami + + echo "[INFO] Your kubectl has been authenticated with your Mathmast account." + echo "[INFO] Now you can try to using kubectl to interact with the cluster." +} + +main "$@" \ No newline at end of file diff --git a/bin/freeleaps-cluster-login b/bin/freeleaps-cluster-login deleted file mode 100755 index 725688e3..00000000 --- a/bin/freeleaps-cluster-login +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -CLUSTER_API_LB_IP="4.155.160.32" - -MICROSOFT_ENTRA_TENANT_ID=cf151ee8-5c2c-4fe7-a1c4-809ba43c9f24 -MATHMAST_AD_CLIENT_ID=7cd1df19-24ea-46d7-acd3-5336283139e0 -MATHMAST_AD_CLIENT_SECRET=L9J8Q~kClGP-sXKS3YFgnpDu7ednUdlWGsWfQbTl - -MATHMAST_AD_ISSUER="https://login.microsoftonline.com/${MICROSOFT_ENTRA_TENANT_ID}/v2.0" -OS=${OS:-linux} -ARCH=${ARCH:-amd64} -KUBECTL_VERSION=${KUBECTL_VERSION:-v1.30.3} -KUBELOGIN_VERSION=${KUBELOGIN_VERSION:-v1.29.0} - -function check_os() { - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - OS=linux - elif [[ "$OSTYPE" == "darwin"* ]]; then - OS=darwin - else - echo "Unsupported OS: $OSTYPE" - exit 1 - fi -} - -function check_arch() { - if [[ "$(uname -m)" == "x86_64" ]]; then - ARCH=amd64 - elif [[ "$(uname -m)" == "arm64" ]]; then - ARCH=arm64 - else - echo "Unsupported architecture: $(uname -m)" - exit 1 - fi -} - -function ensure_kubectl () { - local version=${KUBECTL_VERSION} - local os=${OS} - local arch=${ARCH} - local download_url=https://storage.googleapis.com/kubernetes-release/release/${version}/bin/${os}/${arch}/kubectl - - echo "Downloading kubectl (${arch}-${version}) from ${download_url}" - # download to tmp folder - curl -L o /tmp/kubectl "${download_url}" - chmod +x kubectl - sudo mv kubectl /usr/local/bin/kubectl -} - -function ensure_kubelogin () { - local os=${OS} - local arch=${ARCH} - local version=${KUBELOGIN_VERSION} - local download_url=https://github.com/int128/kubelogin/releases/download/${version}/kubelogin_${os}_${arch}.zip - - echo "Downloading kubelogin (${arch}-${version}) from ${download_url}" - # download to tmp folder - curl -L -o /tmp/kubelogin.zip "${download_url}" - unzip /tmp/kubelogin.zip -d /tmp - chmod +x /tmp/kubelogin - sudo mv /tmp/kubelogin /usr/local/bin/kubelogin -} - -function main() { - # check if the kubectl not installed - if ! command -v kubectl &> /dev/null; then - ensure_kubectl - fi - - # check if the kubelogin not installed - if ! command -v kubelogin &> /dev/null; then - ensure_kubelogin - fi - - # setup with kubelogin - kubelogin setup \ - --oidc-issuer-url ${MATHMAST_AD_ISSUER} \ - --oidc-client-id ${MATHMAST_AD_CLIENT_ID} \ - --oidc-client-secret ${MATHMAST_AD_CLIENT_SECRET} \ - --oidc-extra-scope="profile,email,offline_access" \ - --log_file=/dev/null \ - - # Prompt user to input username - echo "Please enter your username: " - read username - - # Check if username is empty - if [ -z "$username" ]; then - echo "Username cannot be empty" - exit 1 - fi - - echo "Set credentials for $username..." - kubectl config set-credentials "$username" \ - --exec-api-version=client.authentication.k8s.io/v1beta1 \ - --exec-command=kubelogin \ - --exec-arg=get-token \ - --exec-arg="--oidc-issuer-url=${MATHMAST_AD_ISSUER}" \ - --exec-arg="--oidc-client-id=${MATHMAST_AD_CLIENT_ID}" \ - --exec-arg="--oidc-client-secret=${MATHMAST_AD_CLIENT_SECRET}" \ - --exec-arg="--oidc-extra-scope=offline_access" \ - --exec-arg="--oidc-extra-scope=profile" \ - --exec-arg="--oidc-extra-scope=email" \ - - echo "Set cluster..." - kubectl config set-cluster freeleaps-cluster \ - --server=https://${CLUSTER_API_LB_IP}:6443 \ - --insecure-skip-tls-verify=true - - echo "Create context..." - kubectl config set-context "$username@freeleaps-cluster" \ - --cluster=freeleaps-cluster \ - --user="$username" - - echo "Use context..." - kubectl config use-context "$username@freeleaps-cluster" - - echo "Done." -} - -main "$@" \ No newline at end of file