From a535597b1df9252c3adb0473fa017dbe0ecc1aba Mon Sep 17 00:00:00 2001 From: Shea Stewart Date: Mon, 29 Jan 2024 09:14:16 -0500 Subject: [PATCH] remove cb --- .../k8s-deployment-gitops-gh-remediate.yaml | 36 ---- ...8s-deployment-gitops-gh-remediate-slx.yaml | 23 -- ...eployment-gitops-gh-remediate-taskset.yaml | 34 --- .../README.md | 21 -- .../meta.yaml | 1 - .../runbook.robot | 103 --------- .../update_github_manifests.sh | 196 ------------------ .../validate_all_probes.sh | 164 --------------- 8 files changed, 578 deletions(-) delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/generation-rules/k8s-deployment-gitops-gh-remediate.yaml delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-slx.yaml delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-taskset.yaml delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/README.md delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/meta.yaml delete mode 100644 codebundles/k8s-deployment-gitops-gh-remediate/runbook.robot delete mode 100755 codebundles/k8s-deployment-gitops-gh-remediate/update_github_manifests.sh delete mode 100755 codebundles/k8s-deployment-gitops-gh-remediate/validate_all_probes.sh diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/generation-rules/k8s-deployment-gitops-gh-remediate.yaml b/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/generation-rules/k8s-deployment-gitops-gh-remediate.yaml deleted file mode 100644 index f4f2e51b..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/generation-rules/k8s-deployment-gitops-gh-remediate.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: runwhen.com/v1 -kind: GenerationRules -spec: - generationRules: - - resourceTypes: - - deployment - matchRules: - - type: and - matches: - - type: pattern - pattern: ".+" - properties: [name] - mode: substring - - type: pattern - pattern: "kustomize.toolkit.fluxcd.io/name" - properties: [labels] - mode: substring - - resourceType: variables - type: pattern - pattern: "github" - properties: [custom/gitops_provider] - mode: substring - - resourceType: variables - type: pattern - pattern: ".+" - properties: [custom/github_token_secret_name] - mode: substring - slxs: - - baseName: depl-gh-fix - levelOfDetail: detailed - qualifiers: ["namespace", "cluster"] - baseTemplateName: k8s-deployment-gitops-gh-remediate - outputItems: - - type: slx - - type: runbook - templateName: k8s-deployment-gitops-gh-remediate-taskset.yaml diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-slx.yaml b/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-slx.yaml deleted file mode 100644 index da2b2ceb..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-slx.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: runwhen.com/v1 -kind: ServiceLevelX -metadata: - name: {{slx_name}} - labels: - {% include "common-labels.yaml" %} - annotations: - {% include "common-annotations.yaml" %} -spec: - imageURL: https://storage.googleapis.com/runwhen-nonprod-shared-images/icons/github-mark.svg - alias: {{match_resource.resource.metadata.namespace}} Deployment GitOps Configuration Remediations - asMeasuredBy: "" - configProvided: - - name: OBJECT_NAME - value: {{match_resource.resource.metadata.name}} - owners: - - {{workspace.owner_email}} - statement: Remediate deployments in Namespace {{match_resource.resource.metadata.namespace}} managed in GitHub repositories. - additionalContext: - namespace: "{{match_resource.resource.metadata.namespace}}" - labelMap: "{{match_resource.resource.metadata.labels}}" - cluster: "{{ cluster.name }}" - context: "{{ cluster.context }}" \ No newline at end of file diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-taskset.yaml b/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-taskset.yaml deleted file mode 100644 index 60fe3139..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/.runwhen/templates/k8s-deployment-gitops-gh-remediate-taskset.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: runwhen.com/v1 -kind: Runbook -metadata: - name: {{slx_name}} - labels: - {% include "common-labels.yaml" %} - annotations: - {% include "common-annotations.yaml" %} -spec: - location: {{default_location}} - codeBundle: - {% if repo_url %} - repoUrl: {{repo_url}} - {% else %} - repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git - {% endif %} - {% if ref %} - ref: {{ref}} - {% else %} - ref: main - {% endif %} - pathToRobot: codebundles/k8s-deployment-gitops-gh-remediate/runbook.robot - configProvided: - - name: NAMESPACE - value: {{match_resource.resource.metadata.namespace}} - - name: CONTEXT - value: {{context}} - - name: KUBERNETES_DISTRIBUTION_BINARY - value: {{custom.kubernetes_distribution_binary}} - secretsProvided: - - name: kubeconfig - workspaceKey: {{custom.kubeconfig_secret_name}} - - name: github_token - workspaceKey: {{custom.github_token_secret_name}} diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/README.md b/codebundles/k8s-deployment-gitops-gh-remediate/README.md deleted file mode 100644 index 2b12ee87..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Kubernetes Deployment Triage - -This codebundle provides a suite of tasks aimed at remediating configuration issues related to Kubernetes deployments managed in github repositories. - -## Tasks -`Remediate Readiness and Liveness Probe GitOps Manifests for Deployments in Namespace` - -## Configuration -The TaskSet requires initialization to import necessary secrets, services, and user variables. The following variables should be set: - -- `kubeconfig`: The kubeconfig secret containing access info for the cluster. -- `KUBERNETES_DISTRIBUTION_BINARY`: Which binary to use for Kubernetes CLI commands. Default value is `kubectl`. -- `CONTEXT`: The Kubernetes context to operate within. -- `NAMESPACE`: The name of the namespace to search. Leave it blank to search in all namespaces. - -## Requirements -- A kubeconfig with appropriate RBAC permissions to perform the desired command. - -## TODO -- [ ] Add additional documentation. - diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/meta.yaml b/codebundles/k8s-deployment-gitops-gh-remediate/meta.yaml deleted file mode 100644 index 649b2866..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/meta.yaml +++ /dev/null @@ -1 +0,0 @@ -commands: [] diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/runbook.robot b/codebundles/k8s-deployment-gitops-gh-remediate/runbook.robot deleted file mode 100644 index 5c534067..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/runbook.robot +++ /dev/null @@ -1,103 +0,0 @@ -*** Settings *** -Documentation Provides a list of tasks that can remediate configuraiton issues with deployment manifests in GitHub based gitops repositories. -Metadata Author stewartshea -Metadata Display Name Kubernetes GitOps GitHub Remediation -Metadata Supports Kubernetes,AKS,EKS,GKE,OpenShift,FluxCD,ArgoCD - -Library BuiltIn -Library RW.Core -Library RW.CLI -Library RW.platform -Library RW.NextSteps -Library OperatingSystem -Library String - -Suite Setup Suite Initialization - - -*** Tasks *** -Remediate Readiness and Liveness Probe GitOps Manifests Namespace `${NAMESPACE}` - [Documentation] Fixes misconfigured readiness or liveness probe configurations for deployments in a namespace - [Tags] readiness liveness probe deployment remediate gitops ${NAMESPACE} - ${probe_health}= RW.CLI.Run Bash File - ... bash_file=validate_all_probes.sh - ... cmd_override=./validate_all_probes.sh deployment ${NAMESPACE} - ... env=${env} - ... include_in_history=False - ... secret_file__kubeconfig=${kubeconfig} - ... timeout_seconds=180 - ${remediation_list}= RW.CLI.Run Cli - ... cmd=awk "/Remediation Steps:/ {start=1; getline} start" <<< '''${probe_health.stdout}''' - ... env=${env} - ... include_in_history=false - ${gh_updates}= RW.CLI.Run Bash File - ... bash_file=update_github_manifests.sh - ... cmd_override=./update_github_manifests.sh '${remediation_list.stdout}' - ... env=${env} - ... include_in_history=False - ... secret_file__kubeconfig=${kubeconfig} - ${recommendations}= RW.CLI.Run Cli - ... cmd=echo '${gh_updates.stdout}' | awk '/Recommended Next Steps:/ {flag=1; next} flag' - ... env=${env} - ... include_in_history=false - IF len($recommendations.stdout) > 0 - RW.Core.Add Issue - ... severity=3 - ... expected=Pull Requests for manifest changes are reviewed for namespace `${NAMESPACE}` - ... actual=Pull Requests for manifest changes are open and in need of review for namespace `${NAMESPACE}` - ... title=Pull Requests for manifest changes are open and in need of review for namespace `${NAMESPACE}` - ... reproduce_hint=Check Pull Request details for more information. - ... details=${remediation_list.stdout} - ... next_steps=${recommendations.stdout} - END - ${history}= RW.CLI.Pop Shell History - RW.Core.Add Pre To Report Readiness probe testing results:\n\n${probe_health.stdout} - RW.Core.Add Pre To Report Commands Used: ${probe_health.cmd} - - -*** Keywords *** -Suite Initialization - ${kubeconfig}= RW.Core.Import Secret - ... kubeconfig - ... type=string - ... description=The kubernetes kubeconfig yaml containing connection configuration used to connect to cluster(s). - ... pattern=\w* - ... example=For examples, start here https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/ - ${github_token}= RW.Core.Import Secret - ... github_token - ... type=string - ... description=The GitHub Personal Access token used to create commits and open PRs against the GitOps repo. - ... pattern=\w* - ${NAMESPACE}= RW.Core.Import User Variable NAMESPACE - ... type=string - ... description=The name of the Kubernetes namespace to scope actions and searching to. - ... pattern=\w* - ... example=my-namespace - ${CONTEXT}= RW.Core.Import User Variable CONTEXT - ... type=string - ... description=Which Kubernetes context to operate within. - ... pattern=\w* - ... example=my-main-cluster - ${KUBERNETES_DISTRIBUTION_BINARY}= RW.Core.Import User Variable KUBERNETES_DISTRIBUTION_BINARY - ... type=string - ... description=Which binary to use for Kubernetes CLI commands. - ... enum=[kubectl,oc] - ... example=kubectl - ... default=kubectl - ${HOME}= RW.Core.Import User Variable HOME - ${RW_TASK_TITLES}= Get Environment Variable RW_TASK_TITLES "[]" - ${RW_TASK_STRING}= Evaluate ${RW_TASK_TITLES} json - ${RW_TASK_STRING}= Evaluate ', '.join(${RW_TASK_STRING}) json - ${RW_FRONTEND_URL}= Get Environment Variable RW_FRONTEND_URL none - ${RW_SESSION_ID}= Get Environment Variable RW_SESSION_ID none - ${RW_USERNAME}= Get Environment Variable RW_USERNAME none - ${RW_WORKSPACE}= Get Environment Variable RW_WORKSPACE none - - Set Suite Variable ${kubeconfig} ${kubeconfig} - Set Suite Variable ${KUBERNETES_DISTRIBUTION_BINARY} ${KUBERNETES_DISTRIBUTION_BINARY} - Set Suite Variable ${CONTEXT} ${CONTEXT} - Set Suite Variable ${NAMESPACE} ${NAMESPACE} - Set Suite Variable ${HOME} ${HOME} - Set Suite Variable - ... ${env} - ... {"KUBECONFIG":"./${kubeconfig.key}", "KUBERNETES_DISTRIBUTION_BINARY":"${KUBERNETES_DISTRIBUTION_BINARY}", "CONTEXT":"${CONTEXT}", "NAMESPACE":"${NAMESPACE}", "HOME":"${HOME}", "GITHUB_TOKEN":"${github_token.value}", "RW_TASK_TITLES":"${RW_TASK_STRING}", "RW_FRONTEND_URL":"${RW_FRONTEND_URL}", "RW_SESSION_ID":"${RW_SESSION_ID}", "RW_USERNAME": "${RW_USERNAME}", "RW_WORKSPACE":"${RW_WORKSPACE}"} diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/update_github_manifests.sh b/codebundles/k8s-deployment-gitops-gh-remediate/update_github_manifests.sh deleted file mode 100755 index 1e45fd73..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/update_github_manifests.sh +++ /dev/null @@ -1,196 +0,0 @@ -#!/bin/bash - - -declare -a next_steps=() - - -# Define labels or annotations for identifying gitops resources -# Flux -declare -A flux_type_map -# TODO - add additional flux resource types like helmrelease -flux_type_map["kustomize"]="kustomization" -flux_label="toolkit.fluxcd.io" - -# Argo (placeholder) - -# Function to find GitOps owner and Git manifest location -find_gitops_info() { - local objectType="$1" - local objectName="$2" - echo "Finding GitOps info for $objectType $objectName..." - object_json=$(${KUBERNETES_DISTRIBUTION_BINARY} get "$objectType" "$objectName" -n "$NAMESPACE" --context "$CONTEXT" -o json) - - # Check if the object is from Flux - flux_match=$(echo "$object_json" | grep "$flux_label") - if [[ -n $flux_match ]]; then - fetch_flux_owner_details "$object_json" - else - echo "No label containing '$flux_label' found in $objectType $objectName" - fi - -} - -fetch_flux_owner_details() { - local object_json="$1" - echo "Processing Flux owner details..." - # Get flux type - flux_type=$(echo $object_json | jq -r '.metadata.labels | to_entries[] | select(.key | test("^[^.]+\\.toolkit\\.fluxcd\\.io/")) | .key | split(".")[0]' | uniq ) - flux_type_count=$(echo "$flux_type" | wc -l | awk '{print $1}') - if [[ $flux_type_count -gt 1 ]]; then - echo "Error: More than one flux type found" >&2 - exit 1 - fi - flux_name=$(echo "$object_json" | jq -r --arg flux_type "$flux_type" '.metadata.labels[$flux_type + ".toolkit.fluxcd.io/name"]') - flux_namespace=$(echo "$object_json" | jq -r --arg flux_type "$flux_type" '.metadata.labels[$flux_type + ".toolkit.fluxcd.io/namespace"]') - flux_object_json=$(${KUBERNETES_DISTRIBUTION_BINARY} get ${flux_type_map[$flux_type]} $flux_name -n $NAMESPACE --context $CONTEXT -o json) - flux_source=$(echo "$flux_object_json" | jq -r .spec.sourceRef ) - flux_source_kind=$(echo "$flux_source" | jq -r .kind ) - flux_source_name=$(echo "$flux_source" | jq -r .name ) - flux_source_namespace=$(echo "$flux_source" | jq -r .namespace ) - flux_source_object=$(${KUBERNETES_DISTRIBUTION_BINARY} get $flux_source_kind $flux_source_name -n $flux_source_namespace --context $CONTEXT -o json) - git_url=$(echo "$flux_source_object" | jq -r .spec.url ) - git_path=$(echo "$flux_object_json" | jq -r .spec.path) -} - -## Argo placeholder -# fetch_argo_owner_details() { - -# } - -update_github_manifests () { - DATETIME=$(date '+%Y%m%d-%H%M%S') - local git_url_no_suffix="${git_url%.git}" - local git_owner=$(echo "$git_url_no_suffix" | awk -F '[/:]' '{print $(NF-1)}') - local git_repo=$(echo "$git_url_no_suffix" | awk -F '[/:]' '{print $NF}') - git config --global user.email "runsessions@runwhen.com" 2>&1 - git config --global user.name "RunWhen Runsession Bot" 2>&1 - git config --global pull.rebase false 2>&1 - - workdir=$(pwd) - git clone $git_url 2>&1 - cd $workdir/$git_repo - git remote set-url origin https://x-access-token:$GITHUB_TOKEN@github.com/$git_owner/$git_repo - git checkout -b "runwhen/manifest-update-$DATETIME" 2>&1 - git branch - # Search for YAML files and process them - find $git_path -type f -name '*.yaml' -o -name '*.yml' | while read yaml_file; do - echo "object name: $object_name" - echo "old string: $old_string" - echo "new string: $new_string" - $substitution_function - done - - # Test if any git changes are made. If not, bail out and send instruction. If so, commit and PR. - cd $workdir/$git_repo - if git diff-index --quiet HEAD --; then - echo "No git changes detected" - exit 0 - else - echo "Changes detected. Pushing..." - git add . 2>&1 - git commit -m "Manifest updates" 2>&1 - git status 2>&1 - git push -f -v --set-upstream origin "runwhen/manifest-update-$DATETIME" - generate_pull_request_body_content - PR_DATA=$(jq -n \ - --arg title "[RunWhen] - GitOps Manifest Updates for $object_type $object_name" \ - --arg body "$PR_BODY" \ - --arg head "runwhen/manifest-update-$DATETIME" \ - --arg base "main" \ - '{title: $title, body: $body, head: $head, base: $base}') - pr_output=$(curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/$git_owner/$git_repo/pulls" \ - -d "$PR_DATA") - pr_html_url=$(jq -r '.html_url // empty' <<< "$pr_output") - next_steps+=("View proposed Github changes in [Pull Request]($pr_html_url)") - fi -} - -probe_exec_substitution () { - # Convert the old and new strings into array elements - IFS=' ' read -ra old_string_array <<< "$old_string" - IFS=' ' read -ra new_string_array <<< "$new_string" - - # Use yq to iterate over each element in the command array and replace it if it matches - for i in "${!old_string_array[@]}"; do - yq e "(select(.kind == \"Deployment\" and .metadata.name == \"$object_name\").spec.template.spec.containers[] | select(.name == \"$container\").$probe_type.exec.command[] | select(. == \"${old_string_array[$i]}\") ) |= \"${new_string_array[$i]}\"" -i "$yaml_file" - done - -} - -generate_pull_request_body_content () { -runsession_url=$RW_FRONTEND_URL/map/$RW_WORKSPACE#selectedRunSessions=$RW_SESSION_ID - -read -r -d '' PR_BODY << EOF -### RunSession Details - -A RunSession (started by $RW_USERNAME) with the following tasks has produced this Pull Request: - -- $RW_TASK_TITLES - -To view the RunSession, click [this link]($runsession_url) - -### Change Details -$change_summary - -The following details prompted this change: -\`\`\` -$json_pretty -\`\`\` - ---- -[RunWhen Workspace]($RW_FRONTEND_URL/map/$RW_WORKSPACE) -EOF - -} - - -# Main script starts here -json_input="$1" - -# Check if input is provided -if [[ -z "$json_input" ]]; then - echo "No JSON input provided" - exit 1 -fi - -# Process the JSON -while read -r json_object; do - json_pretty=$(echo $json_object | jq .) - object_type=$(jq -r '.object_type' <<< "$json_object") - object_name=$(jq -r '.object_name' <<< "$json_object") - remediation_type=$(jq -r '.remediation_type' <<< "$json_object") - probe_type=$(jq -r '.probe_type' <<< "$json_object") - exec=$(jq -r '.exec' <<< "$json_object") - invalid_command=$(jq -r '.invalid_command // empty' <<< "$json_object") - valid_command=$(jq -r '.valid_command // empty' <<< "$json_object") - invalid_ports=$(jq -r '.invalid_ports // empty' <<< "$json_object") - valid_ports=$(jq -r '.valid_ports // empty' <<< "$json_object") - container=$(jq -r '.container // empty' <<< "$json_object") - - # Logic to prefer invalid_command over invalid_oorts - if [[ "$remediation_type" == "probe_update" ]]; then - if [[ "$exec" == "true" && -n "$invalid_command" ]]; then - echo "Processing $object_type $object_name with invalidCommand" - find_gitops_info "$object_type" "$object_name" - old_string=$invalid_command - new_string=$valid_command - substitution_function=probe_exec_substitution - change_summary="Container \`$container\` in $object_type \`$object_name\` had an invalid exec command for $probe_type. The updated command is \`$valid_command\`" - update_github_manifests - - elif [[ "$exec" == "true" && -n "$invalid_ports" ]]; then - echo "Processing $object_type $object_name with invalidPorts" - find_gitops_info "$object_type" "$object_name" - ## Placeholder for GitOps Update Details - fi - fi -done < <(jq -c '.[]' <<< "$json_input") - - -# Display all unique recommendations that can be shown as Next Steps -if [[ ${#next_steps[@]} -ne 0 ]]; then - printf "\nRecommended Next Steps: \n" - printf "%s\n" "${next_steps[@]}" | sort -u -fi diff --git a/codebundles/k8s-deployment-gitops-gh-remediate/validate_all_probes.sh b/codebundles/k8s-deployment-gitops-gh-remediate/validate_all_probes.sh deleted file mode 100755 index 8bf860d7..00000000 --- a/codebundles/k8s-deployment-gitops-gh-remediate/validate_all_probes.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash -# ----------------------------------------------------------------------------- -# Script Information and Metadata -# ----------------------------------------------------------------------------- -# Author: @stewartshea -# Description: This script takes in a namespace and object type, and tries to determine -# if readiness and liveness probes are accurate. -# ----------------------------------------------------------------------------- - - -# Set the type of Kubernetes object (e.g., deployment) and namespace -OBJECT_TYPE="${1:-deployment}" -NAMESPACE="${2}" - -declare -a remediation_steps=() - -# Function to extract data using jq -extract_data() { - echo "$1" | jq -r "$2" 2>/dev/null -} - -extract_port_from_command() { - echo "$1" | grep -oE ':[0-9]+' | grep -oE '[0-9]+' | head -n 1 -} - -# Get all objects of the specified type in the specified namespace -OBJECTS=$(${KUBERNETES_DISTRIBUTION_BINARY} get "$OBJECT_TYPE" -n "$NAMESPACE" --context "$CONTEXT" -o json) -if [ $? -ne 0 ]; then - echo "Error fetching $OBJECT_TYPE details: $OBJECTS" - exit 1 -fi - -# Get number of objects -NUM_OBJECTS=$(extract_data "$OBJECTS" '.items | length') -if [ -z "$NUM_OBJECTS" ]; then - echo "No $OBJECT_TYPE found in namespace $NAMESPACE." - exit 1 -fi - -# Loop through each object -for ((o=0; o/dev/null; then - PROBE_PORT=$(extract_data "$PROBE" '.httpGet.port // .tcpSocket.port') - CONTAINER_PORTS=$(extract_data "$MANIFEST" ".spec.template.spec.containers[$i].ports[].containerPort") - - if [[ ! " $CONTAINER_PORTS " == *"$PROBE_PORT"* ]]; then - echo "Container \`$CONTAINER_NAME\`: Port $PROBE_PORT used in $PROBE_TYPE is not exposed by the container." - next_steps+=("Update $PROBE_TYPE For ${OBJECT_TYPE} \`${OBJECT_NAME}\` to use one of the following ports: $CONTAINER_PORTS") - remediation_steps+=("{\"remediation_type\":\"probe_update\", \"object\": \"$OBJECT_TYPE}\\$OBJECT_NAME\", \"probe_type\": \"$PROBE_TYPE\", \"exec\":\"false\", \"invalid_port\":\"$PROBE_PORT\",\"valid_ports\":\"$CONTAINER_PORTS\", \"container\":\"$CONTAINER_NAME\"}") - else - echo "Container \`$CONTAINER_NAME\`: ${PROBE_TYPE} port $PROBE_PORT is valid." - fi - fi - - # Check if exec permissions are available (for exec type probes) - if echo "$PROBE" | jq -e '.exec' >/dev/null; then - IFS=$'\n' read -r -d '' -a EXEC_COMMAND_ARRAY < <(echo "$PROBE" | jq -r '.exec.command[]' && printf '\0') - PORT_IN_COMMAND=$(extract_port_from_command "${EXEC_COMMAND_ARRAY[*]}") - - # Check if we see the port in the exec command, and if so, if it's defined in the manifest - if [ -n "$PORT_IN_COMMAND" ]; then - CONTAINER_PORTS=$(extract_data "$MANIFEST" ".spec.template.spec.containers[$i].ports[].containerPort") - if [[ ! " $CONTAINER_PORTS " == *"$PORT_IN_COMMAND"* ]]; then - echo "Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND used in ${PROBE_TYPE} exec command is not exposed by the container. The following ports are exposed: $CONTAINER_PORTS" - next_steps+=("Get $OBJECT_TYPE Details For $OBJECT_TYPE \`${OBJECT_NAME}\`") - remediation_steps+=("{\"remediation_type\":\"probe_update\", \"object_type\":\"$OBJECT_TYPE\",\"object_name\":\"$OBJECT_NAME\",\"probe_type\": \"$PROBE_TYPE\", \"exec\":\"true\", \"invalid_ports\":\"$PORT_IN_COMMAND\",\"valid_ports\":\"$CONTAINER_PORTS\", \"container\":\"$CONTAINER_NAME\"}") - else - echo "Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND in ${PROBE_TYPE} exec command appears valid." - fi - fi - - # Check exec permission and execute command - if ${KUBERNETES_DISTRIBUTION_BINARY} auth can-i create pods/exec -n "$NAMESPACE" >/dev/null 2>&1; then - - # Execute command - echo "" - echo "+++ START Exec Test as configured +++" - echo "Executing command in $OBJECT_TYPE $OBJECT_NAME: ${EXEC_COMMAND_ARRAY[*]}" - EXEC_OUTPUT=$(${KUBERNETES_DISTRIBUTION_BINARY} exec $OBJECT_TYPE/$OBJECT_NAME -n "$NAMESPACE" -- ${EXEC_COMMAND_ARRAY[*]} 2>&1) - EXEC_EXIT_CODE=$? - echo "Command Output: $EXEC_OUTPUT" - echo "Exit Code: $EXEC_EXIT_CODE" - echo "+++ END Exec Test+++" - echo "" - - # Simple exec test to try substituting ports found in manifest - if [[ -n "$CONTAINER_PORTS" && "$EXEC_EXIT_CODE" != 0 ]]; then - for PORT in $CONTAINER_PORTS; do - MODIFIED_EXEC_COMMAND_ARRAY=("${EXEC_COMMAND_ARRAY[@]}") - for j in "${!MODIFIED_EXEC_COMMAND_ARRAY[@]}"; do - MODIFIED_EXEC_COMMAND_ARRAY[$j]=$(echo "${MODIFIED_EXEC_COMMAND_ARRAY[$j]}" | sed -r "s/:[0-9]+/:$PORT/") - done - # Execute modified command - echo "+++ START Exec Test with port $PORT +++" - echo "Executing modified command in $OBJECT_TYPE $OBJECT_NAME with port $PORT: ${MODIFIED_EXEC_COMMAND_ARRAY[*]}" - EXEC_OUTPUT=$(${KUBERNETES_DISTRIBUTION_BINARY} exec $OBJECT_TYPE/$OBJECT_NAME -n "$NAMESPACE" -- "${MODIFIED_EXEC_COMMAND_ARRAY[@]}" 2>&1) - EXEC_EXIT_CODE=$? - echo "Command Output: $EXEC_OUTPUT" - echo "Exit Code: $EXEC_EXIT_CODE" - if [ $EXEC_EXIT_CODE == 0 ]; then - next_steps+=("Update $PROBE_TYPE For $OBJECT_TYPE \`${OBJECT_NAME}\` to use port $PORT") - remediation_steps+=("{\"remediation_type\":\"probe_update\",\"object_type\":\"$OBJECT_TYPE\",\"object_name\":\"$OBJECT_NAME\",\"probe_type\": \"$PROBE_TYPE\", \"exec\":\"true\", \"invalid_command\":\"${EXEC_COMMAND_ARRAY[*]}\",\"valid_command\":\"${MODIFIED_EXEC_COMMAND_ARRAY[*]}\", \"container\":\"$CONTAINER_NAME\"}") - fi - echo "+++ END Exec Test+++" - echo "" - done - fi - else - echo "Exec permission is not available." - fi - fi - echo "------- END Validation -------" - echo "" - done - done -done - -# Display all unique recommendations that can be shown as Next Steps -if [[ ${#next_steps[@]} -ne 0 ]]; then - printf "\nRecommended Next Steps: \n" - printf "%s\n" "${next_steps[@]}" | sort -u -fi - -REMEDIATION_STEPS_JSON=$(printf '%s\n' "${remediation_steps[@]}" | jq -s .) -echo "" -echo "Remediation Steps:" -echo "$REMEDIATION_STEPS_JSON" -