UiPath Documentation
automation-suite
2023.10
false
Automation Suite unter Linux – Installationsanleitung
Wichtig :
Es kann 1–2 Wochen dauern, bis die Lokalisierung neu veröffentlichter Inhalte verfügbar ist.

Manuelle Schadensbegrenzung bei ArgoCD NetworkPolicy (GHSA-47m3-95c7-g2g8)

Lösungen für den nicht authentifizierten Netzwerkzugriff auf den ArgoCD-Repository-Server und Redis in Automation Suite mit einem manuellen Verfahren zur Schadensbegrenzung bei der Netzwerkrichtlinie.

Beschreibung

Eine Sicherheitslücke, welche die ArgoCD-Komponente repo-server betrifft, wurde kürzlich veröffentlicht und wird derzeit von ArgoCD noch nicht behoben.

ArgoCD repo-server (Port 8081) und ArgoCD Redis sind von jedem Pod im Clusternetzwerk aus erreichbar, da keine Netzwerkrichtlinie den Ingress standardmäßig auf diese Komponenten beschränkt. Infolgedessen kann jeder Pod innerhalb des Clusternetzwerks eine direkte Verbindung zu ihnen herstellen, da ArgoCD keine Authentifizierung für diese internen Komponenten erfordert. Weitere Informationen finden Sie unter GHSA-47m3-95c7-g2g8.

Um das Problem zu verringern, müssen Sie die Netzwerkrichtlinie manuell anwenden, die im Abschnitt „Lösung“ auf dieser Seite beschrieben ist.

Voraussetzungen

  • Führen Sie dieses Verfahren von einem Host aus, der kubectl -Zugriff auf den Cluster hat.
  • Das Verfahren geht von dem standardmäßigen Automation Suite Namespace argocd aus. Wenn ArgoCD einen anderen Namespace verwendet, legen Sie ARGOCD_NS fest, bevor Sie das Skript ausführen.
  • Diese Schadensbegrenzung basiert auf der Durchsetzung der Kubernetes-Netzwerkrichtlinie. Von der Automation Suite unterstützte Cluster verwenden eine kompatible CNI-Konfiguration (Container Network Interface).

Lösung

  1. Führen Sie das folgende Skript aus. Sie erkennt Ihre ArgoCD-Version und Ihren Redis-Modus (eigenständig oder Hochverfügbarkeit, HA) und wendet die passende Netzwerkrichtlinie automatisch an:

    export ARGOCD_NS="${ARGOCD_NS:-argocd}"
    export ARGOCD_RELEASE="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.labels.app\.kubernetes\.io/instance}')"
    
    test -n "$ARGOCD_RELEASE" || { echo "Cannot detect Argo CD Helm release"; exit 1; }
    
    if kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" --no-headers 2>/dev/null | grep -q .; then
      REDIS_MODE=ha
    else
      REDIS_MODE=standalone
    fi
    
    echo "Argo CD namespace: $ARGOCD_NS"
    echo "Argo CD release: $ARGOCD_RELEASE"
    echo "Redis mode: $REDIS_MODE"
    
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-repo-server-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-repo-server
          app.kubernetes.io/instance: ${ARGOCD_RELEASE}
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-applicationset-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-notifications-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 8081
        - from:
            - namespaceSelector: {}
          ports:
            - protocol: TCP
              port: 8084
    EOF
    
    if [ "$REDIS_MODE" = "ha" ]; then
      cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-ha-server-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          release: ${ARGOCD_RELEASE}
          app: redis-ha
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  release: ${ARGOCD_RELEASE}
                  app: redis-ha
            - podSelector:
                matchLabels:
                  release: ${ARGOCD_RELEASE}
                  app: redis-ha-haproxy
          ports:
            - protocol: TCP
              port: 6379
            - protocol: TCP
              port: 26379
    ---
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-ha-haproxy-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          release: ${ARGOCD_RELEASE}
          app: redis-ha-haproxy
          app.kubernetes.io/name: argocd-redis-ha-haproxy
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-repo-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 6379
    EOF
    else
      cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-redis
          app.kubernetes.io/instance: ${ARGOCD_RELEASE}
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-repo-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 6379
        - from:
            - namespaceSelector: {}
          ports:
            - protocol: TCP
              port: 9121
    EOF
    fi
    export ARGOCD_NS="${ARGOCD_NS:-argocd}"
    export ARGOCD_RELEASE="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.labels.app\.kubernetes\.io/instance}')"
    
    test -n "$ARGOCD_RELEASE" || { echo "Cannot detect Argo CD Helm release"; exit 1; }
    
    if kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" --no-headers 2>/dev/null | grep -q .; then
      REDIS_MODE=ha
    else
      REDIS_MODE=standalone
    fi
    
    echo "Argo CD namespace: $ARGOCD_NS"
    echo "Argo CD release: $ARGOCD_RELEASE"
    echo "Redis mode: $REDIS_MODE"
    
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-repo-server-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-repo-server
          app.kubernetes.io/instance: ${ARGOCD_RELEASE}
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-applicationset-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-notifications-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 8081
        - from:
            - namespaceSelector: {}
          ports:
            - protocol: TCP
              port: 8084
    EOF
    
    if [ "$REDIS_MODE" = "ha" ]; then
      cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-ha-server-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          release: ${ARGOCD_RELEASE}
          app: redis-ha
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  release: ${ARGOCD_RELEASE}
                  app: redis-ha
            - podSelector:
                matchLabels:
                  release: ${ARGOCD_RELEASE}
                  app: redis-ha-haproxy
          ports:
            - protocol: TCP
              port: 6379
            - protocol: TCP
              port: 26379
    ---
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-ha-haproxy-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          release: ${ARGOCD_RELEASE}
          app: redis-ha-haproxy
          app.kubernetes.io/name: argocd-redis-ha-haproxy
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-repo-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 6379
    EOF
    else
      cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: argocd-redis-manual-mitigation
      namespace: ${ARGOCD_NS}
    spec:
      podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-redis
          app.kubernetes.io/instance: ${ARGOCD_RELEASE}
      policyTypes:
        - Ingress
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-repo-server
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-application-controller
                  app.kubernetes.io/instance: ${ARGOCD_RELEASE}
          ports:
            - protocol: TCP
              port: 6379
        - from:
            - namespaceSelector: {}
          ports:
            - protocol: TCP
              port: 9121
    EOF
    fi
    

überprüfen

Führen Sie die folgenden Befehle aus, um zu bestätigen, dass die Schadensbegrenzung erfolgreich angewendet wurde:

kubectl -n "$ARGOCD_NS" get networkpolicy
kubectl -n "$ARGOCD_NS" get pods
kubectl get applications.argoproj.io -A
kubectl -n "$ARGOCD_NS" get networkpolicy
kubectl -n "$ARGOCD_NS" get pods
kubectl get applications.argoproj.io -A

Bestätigen Sie Folgendes:

  • argocd-repo-server-manual-mitigation ist vorhanden.
  • Für Redis HA sind argocd-redis-ha-server-manual-mitigation und argocd-redis-ha-haproxy-manual-mitigation vorhanden.
  • Für eigenständiges Redis ist argocd-redis-manual-mitigation vorhanden.
  • ArgoCD-Pods sind Running oder Completed.
  • ArgoCD-Anwendungen bleiben Synced und Healthy.

Bestätigen Sie die Schadensbegrenzung

Führen Sie diese Prüfungen nach dem Anwenden der Richtlinien durch. Sie stellen sicher, dass der erforderliche ArgoCD-Datenverkehr weiterhin funktioniert und der unzulässige Datenverkehr blockiert ist.

  1. Führen Sie das folgende Skript aus:

    export ARGOCD_NS="${ARGOCD_NS:-argocd}"
    export ARGOCD_RELEASE="${ARGOCD_RELEASE:-$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.labels.app\.kubernetes\.io/instance}')}"
    
    if kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" --no-headers 2>/dev/null | grep -q .; then
      REDIS_MODE=ha
    else
      REDIS_MODE=standalone
    fi
    
    SERVER_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.name}')"
    APPSET_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-applicationset-controller -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)"
    FAILED_CHECKS=""
    
    tcp_check() {
      pod="$1"
      host="$2"
      port="$3"
      expected="$4"
      name="$5"
    
      code="$(kubectl -n "$ARGOCD_NS" exec "$pod" -- sh -c '
        host="$1"
        port="$2"
        if command -v nc >/dev/null 2>&1; then
          timeout 5 nc -z -w 3 "$host" "$port" >/dev/null 2>&1
          printf "%s\n" "$?"
        elif command -v bash >/dev/null 2>&1; then
          timeout 5 bash -c "</dev/tcp/${host}/${port}" >/dev/null 2>&1
          printf "%s\n" "$?"
        else
          printf "%s\n" "NO_TCP_TOOL"
        fi
      ' sh "$host" "$port" 2>/dev/null | tail -n 1)"
    
      if [ "$expected" = "allow" ] && [ "$code" = "0" ]; then
        return
      elif [ "$expected" = "deny" ] && [ "$code" != "0" ] && [ "$code" != "NO_TCP_TOOL" ] && [ -n "$code" ]; then
        return
      else
        FAILED_CHECKS="${FAILED_CHECKS}
    - ${name}: expected ${expected}, got exit code ${code}"
      fi
    }
    
    tcp_check "$SERVER_POD" argocd-repo-server 8081 allow "argocd-server to repo-server:8081"
    
    if [ "$REDIS_MODE" = "ha" ]; then
      HAPROXY_POD="$(kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" -o jsonpath='{.items[0].metadata.name}')"
    
      tcp_check "$SERVER_POD" argocd-redis-ha-haproxy 6379 allow "argocd-server to redis-ha-haproxy:6379"
      tcp_check "$HAPROXY_POD" argocd-redis-ha 6379 allow "redis-ha-haproxy to redis-ha:6379"
      tcp_check "$HAPROXY_POD" argocd-repo-server 8081 deny "redis-ha-haproxy to repo-server:8081"
    
      if [ -n "$APPSET_POD" ]; then
        tcp_check "$APPSET_POD" argocd-redis-ha-haproxy 6379 deny "applicationset-controller to redis-ha-haproxy:6379"
      fi
    else
      REDIS_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-redis -o jsonpath='{.items[0].metadata.name}')"
    
      tcp_check "$SERVER_POD" argocd-redis 6379 allow "argocd-server to redis:6379"
      tcp_check "$REDIS_POD" argocd-repo-server 8081 deny "redis to repo-server:8081"
    
      if [ -n "$APPSET_POD" ]; then
        tcp_check "$APPSET_POD" argocd-redis 6379 deny "applicationset-controller to redis:6379"
      fi
    fi
    
    if [ -z "$FAILED_CHECKS" ]; then
      echo "MITIGATION CHECK: PASS"
    else
      echo "MITIGATION CHECK: FAIL"
      echo "$FAILED_CHECKS"
      exit 1
    fi
    export ARGOCD_NS="${ARGOCD_NS:-argocd}"
    export ARGOCD_RELEASE="${ARGOCD_RELEASE:-$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.labels.app\.kubernetes\.io/instance}')}"
    
    if kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" --no-headers 2>/dev/null | grep -q .; then
      REDIS_MODE=ha
    else
      REDIS_MODE=standalone
    fi
    
    SERVER_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.name}')"
    APPSET_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-applicationset-controller -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)"
    FAILED_CHECKS=""
    
    tcp_check() {
      pod="$1"
      host="$2"
      port="$3"
      expected="$4"
      name="$5"
    
      code="$(kubectl -n "$ARGOCD_NS" exec "$pod" -- sh -c '
        host="$1"
        port="$2"
        if command -v nc >/dev/null 2>&1; then
          timeout 5 nc -z -w 3 "$host" "$port" >/dev/null 2>&1
          printf "%s\n" "$?"
        elif command -v bash >/dev/null 2>&1; then
          timeout 5 bash -c "</dev/tcp/${host}/${port}" >/dev/null 2>&1
          printf "%s\n" "$?"
        else
          printf "%s\n" "NO_TCP_TOOL"
        fi
      ' sh "$host" "$port" 2>/dev/null | tail -n 1)"
    
      if [ "$expected" = "allow" ] && [ "$code" = "0" ]; then
        return
      elif [ "$expected" = "deny" ] && [ "$code" != "0" ] && [ "$code" != "NO_TCP_TOOL" ] && [ -n "$code" ]; then
        return
      else
        FAILED_CHECKS="${FAILED_CHECKS}
    - ${name}: expected ${expected}, got exit code ${code}"
      fi
    }
    
    tcp_check "$SERVER_POD" argocd-repo-server 8081 allow "argocd-server to repo-server:8081"
    
    if [ "$REDIS_MODE" = "ha" ]; then
      HAPROXY_POD="$(kubectl -n "$ARGOCD_NS" get pod -l "release=${ARGOCD_RELEASE},app=redis-ha-haproxy" -o jsonpath='{.items[0].metadata.name}')"
    
      tcp_check "$SERVER_POD" argocd-redis-ha-haproxy 6379 allow "argocd-server to redis-ha-haproxy:6379"
      tcp_check "$HAPROXY_POD" argocd-redis-ha 6379 allow "redis-ha-haproxy to redis-ha:6379"
      tcp_check "$HAPROXY_POD" argocd-repo-server 8081 deny "redis-ha-haproxy to repo-server:8081"
    
      if [ -n "$APPSET_POD" ]; then
        tcp_check "$APPSET_POD" argocd-redis-ha-haproxy 6379 deny "applicationset-controller to redis-ha-haproxy:6379"
      fi
    else
      REDIS_POD="$(kubectl -n "$ARGOCD_NS" get pod -l app.kubernetes.io/name=argocd-redis -o jsonpath='{.items[0].metadata.name}')"
    
      tcp_check "$SERVER_POD" argocd-redis 6379 allow "argocd-server to redis:6379"
      tcp_check "$REDIS_POD" argocd-repo-server 8081 deny "redis to repo-server:8081"
    
      if [ -n "$APPSET_POD" ]; then
        tcp_check "$APPSET_POD" argocd-redis 6379 deny "applicationset-controller to redis:6379"
      fi
    fi
    
    if [ -z "$FAILED_CHECKS" ]; then
      echo "MITIGATION CHECK: PASS"
    else
      echo "MITIGATION CHECK: FAIL"
      echo "$FAILED_CHECKS"
      exit 1
    fi
    

    Erwartetes Ergebnis: MITIGATION CHECK: PASS

Rollback

Führen Sie bei Bedarf die folgenden Schritte aus, um die Schadensbegrenzung zu entfernen:

  1. Löschen Sie die manuellen Richtlinien zur Schadensbegrenzung:

    kubectl -n "$ARGOCD_NS" delete networkpolicy \
      argocd-repo-server-manual-mitigation \
      argocd-redis-manual-mitigation \
      argocd-redis-ha-server-manual-mitigation \
      argocd-redis-ha-haproxy-manual-mitigation \
      --ignore-not-found
    kubectl -n "$ARGOCD_NS" delete networkpolicy \
      argocd-repo-server-manual-mitigation \
      argocd-redis-manual-mitigation \
      argocd-redis-ha-server-manual-mitigation \
      argocd-redis-ha-haproxy-manual-mitigation \
      --ignore-not-found
    
  2. Bestätigen Sie, dass das Rollback erfolgreich abgeschlossen wurde:

    kubectl -n "$ARGOCD_NS" get networkpolicy
    kubectl -n "$ARGOCD_NS" get pods
    kubectl get applications.argoproj.io -A
    kubectl -n "$ARGOCD_NS" get networkpolicy
    kubectl -n "$ARGOCD_NS" get pods
    kubectl get applications.argoproj.io -A
    

    Bestätigen Sie Folgendes:

    • Die manuellen Richtlinien zur Schadensbegrenzung werden entfernt.
    • ArgoCD-Pods bleiben Running oder Completed.
    • ArgoCD-Anwendungen bleiben Synced und Healthy.

War diese Seite hilfreich?

Verbinden

Benötigen Sie Hilfe? Support

Möchten Sie lernen? UiPath Academy

Haben Sie Fragen? UiPath-Forum

Auf dem neuesten Stand bleiben