From 73d9ae37581e44259864c83918af5ca24b74f15c Mon Sep 17 00:00:00 2001 From: "L.Dongming" Date: Sat, 26 Jul 2025 20:49:12 +0800 Subject: [PATCH 1/4] chore: add scripts to generate rbac summary --- config/rbac/role.yaml | 4 +- deploy/helm/config/rbac/role.yaml | 18 -- hack/rbac-summary.sh | 301 ++++++++++++++++++++++++++++++ 3 files changed, 303 insertions(+), 20 deletions(-) create mode 100755 hack/rbac-summary.sh diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index af83f970170..009161fcde5 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -343,7 +343,7 @@ rules: - apiGroups: - "" resources: - - configmap + - configmaps verbs: - create - delete @@ -355,7 +355,7 @@ rules: - apiGroups: - "" resources: - - configmap/finalizers + - configmaps/finalizers verbs: - update - apiGroups: diff --git a/deploy/helm/config/rbac/role.yaml b/deploy/helm/config/rbac/role.yaml index af83f970170..aabaddad15a 100644 --- a/deploy/helm/config/rbac/role.yaml +++ b/deploy/helm/config/rbac/role.yaml @@ -340,24 +340,6 @@ rules: - patch - update - watch -- apiGroups: - - "" - resources: - - configmap - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - configmap/finalizers - verbs: - - update - apiGroups: - "" resources: diff --git a/hack/rbac-summary.sh b/hack/rbac-summary.sh new file mode 100755 index 00000000000..a30ddd34a87 --- /dev/null +++ b/hack/rbac-summary.sh @@ -0,0 +1,301 @@ +#!/bin/bash + +# KubeBlocks RBAC Permissions Summary Generator +# This script generates a concise summary of all RBAC permissions required by KubeBlocks + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +HELM_DIR="$PROJECT_ROOT/deploy/helm" + +# Output file and temp file +OUTPUT_FILE="$PROJECT_ROOT/docs/rbac-summary.md" +TEMP_YAML="$PROJECT_ROOT/temp-helm-output.yaml" + +echo -e "${BLUE}KubeBlocks RBAC Permissions Summary Generator${NC}" +echo "==============================================" + +# Check dependencies +if ! command -v helm &> /dev/null; then + echo -e "${RED}Error: helm is not installed${NC}" + exit 1 +fi + +if ! command -v yq &> /dev/null; then + echo -e "${RED}Error: yq is not installed${NC}" + exit 1 +fi + +# Create output directory +mkdir -p "$(dirname "$OUTPUT_FILE")" + +# Generate summary +echo -e "${YELLOW}Generating RBAC permissions summary...${NC}" + +# Render templates once and save to temp file +echo -e "${YELLOW}Rendering Helm templates...${NC}" +cd "$HELM_DIR" +helm template kubeblocks . > "$TEMP_YAML" +cd "$PROJECT_ROOT" + +cat > "$OUTPUT_FILE" << 'EOF' +# KubeBlocks RBAC Permissions Summary + +This document provides a comprehensive summary of all RBAC permissions required by KubeBlocks. + +## Overview + +KubeBlocks requires extensive permissions across both standard Kubernetes resources and its custom resources to manage database clusters, backups, configurations, and operations. + +EOF + +echo "" >> "$OUTPUT_FILE" +echo "**Generated:** $(date)" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +# Get summary statistics using the temp file +cluster_roles=$(yq eval 'select(.kind == "ClusterRole") | .metadata.name' "$TEMP_YAML" | wc -l | tr -d ' ') +roles=$(yq eval 'select(.kind == "Role") | .metadata.name' "$TEMP_YAML" | wc -l | tr -d ' ') + +echo "**Summary:** $cluster_roles ClusterRoles, $roles Roles" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +# Function to generate resource permissions table using simpler yq operations +generate_permissions_table() { + local title="$1" + local filter="$2" + + echo "## $title" >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "| Resource | Permissions |" >> "$OUTPUT_FILE" + echo "|----------|-------------|" >> "$OUTPUT_FILE" + + # Extract resource:verb pairs and use shell to group them + local temp_data=$(yq eval "$filter" "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + + if [[ -n "$temp_data" ]]; then + echo "$temp_data" | awk -F: ' + { + if ($1 in resources) { + if (index(resources[$1], $2) == 0) { + resources[$1] = resources[$1] ", " $2 + } + } else { + resources[$1] = $2 + } + } + END { + for (resource in resources) { + if (resource != "" && resource != "null") { + print "| `" resource "` | " resources[resource] " |" + } + } + }' | sort >> "$OUTPUT_FILE" + fi + + echo "" >> "$OUTPUT_FILE" +} + +# Core Kubernetes Resources +generate_permissions_table "Core Kubernetes Resources" ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.apiGroups[]? == "" or .apiGroups[]? == "apps" or .apiGroups[]? == "batch" or .apiGroups[]? == "coordination.k8s.io" or .apiGroups[]? == "storage.k8s.io" or .apiGroups[]? == "snapshot.storage.k8s.io") | + .resources[]? as $resource | + .verbs[]? as $verb | + select($resource != null and $verb != null) | + $resource + ":" + $verb +' + +# RBAC Resources +rbac_count=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.apiGroups[]? == "rbac.authorization.k8s.io") | + .resources[]? +' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + +if [[ "$rbac_count" -gt 0 ]]; then + generate_permissions_table "RBAC Resources" ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.apiGroups[]? == "rbac.authorization.k8s.io") | + .resources[]? as $resource | + .verbs[]? as $verb | + select($resource != null and $verb != null) | + $resource + ":" + $verb + ' +fi + +# Authentication & Authorization +auth_count=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.apiGroups[]? == "authentication.k8s.io" or .apiGroups[]? == "authorization.k8s.io") | + .resources[]? +' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + +if [[ "$auth_count" -gt 0 ]]; then + echo "## Authentication & Authorization" >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "| Resource | Permissions |" >> "$OUTPUT_FILE" + echo "|----------|-------------|" >> "$OUTPUT_FILE" + + auth_data=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.apiGroups[]? == "authentication.k8s.io" or .apiGroups[]? == "authorization.k8s.io") | + (.apiGroups[]? + "/" + .resources[]?) as $resource | + .verbs[]? as $verb | + select($resource != null and $verb != null) | + $resource + ":" + $verb + ' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + + if [[ -n "$auth_data" ]]; then + echo "$auth_data" | awk -F: ' + { + if ($1 in resources) { + if (index(resources[$1], $2) == 0) { + resources[$1] = resources[$1] ", " $2 + } + } else { + resources[$1] = $2 + } + } + END { + for (resource in resources) { + if (resource != "" && resource != "null") { + print "| `" resource "` | " resources[resource] " |" + } + } + }' | sort >> "$OUTPUT_FILE" + fi + + echo "" >> "$OUTPUT_FILE" +fi + +# KubeBlocks Custom Resources +echo "## KubeBlocks Custom Resources" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +kb_api_groups=("apps.kubeblocks.io" "dataprotection.kubeblocks.io" "extensions.kubeblocks.io" "operations.kubeblocks.io" "parameters.kubeblocks.io" "workloads.kubeblocks.io" "experimental.kubeblocks.io" "trace.kubeblocks.io") + +for api_group in "${kb_api_groups[@]}"; do + # Check if this API group has any resources + resources_count=$(yq eval " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? | + select(. != null and (test(\"/status$|/finalizers$\") | not)) + " "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + + if [[ "$resources_count" -gt 0 ]]; then + echo "### $api_group" >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "| Resource | Permissions |" >> "$OUTPUT_FILE" + echo "|----------|-------------|" >> "$OUTPUT_FILE" + + group_data=$(yq eval " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? as \$resource | + .verbs[]? as \$verb | + select(\$resource != null and \$verb != null and (\$resource | test(\"/status$|/finalizers$\") | not)) | + \$resource + \":\" + \$verb + " "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + + if [[ -n "$group_data" ]]; then + echo "$group_data" | awk -F: ' + { + if ($1 in resources) { + if (index(resources[$1], $2) == 0) { + resources[$1] = resources[$1] ", " $2 + } + } else { + resources[$1] = $2 + } + } + END { + for (resource in resources) { + if (resource != "" && resource != "null") { + print "| `" resource "` | " resources[resource] " |" + } + } + }' | sort >> "$OUTPUT_FILE" + fi + + echo "" >> "$OUTPUT_FILE" + fi +done + +# Special permissions (Non-Resource URLs) +non_resource_count=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.nonResourceURLs) | + .nonResourceURLs[]? +' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + +if [[ "$non_resource_count" -gt 0 ]]; then + echo "## Special Permissions" >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "### Non-Resource URLs" >> "$OUTPUT_FILE" + echo "" >> "$OUTPUT_FILE" + echo "| URL | Permissions |" >> "$OUTPUT_FILE" + echo "|-----|-------------|" >> "$OUTPUT_FILE" + + url_data=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.nonResourceURLs) | + .nonResourceURLs[]? as $url | + .verbs[]? as $verb | + select($url != null and $verb != null) | + $url + ":" + $verb + ' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + + if [[ -n "$url_data" ]]; then + echo "$url_data" | awk -F: ' + { + if ($1 in resources) { + if (index(resources[$1], $2) == 0) { + resources[$1] = resources[$1] ", " $2 + } + } else { + resources[$1] = $2 + } + } + END { + for (resource in resources) { + if (resource != "" && resource != "null") { + print "| `" resource "` | " resources[resource] " |" + } + } + }' | sort >> "$OUTPUT_FILE" + fi + + echo "" >> "$OUTPUT_FILE" +fi + +# Cleanup temp file +rm -f "$TEMP_YAML" + +echo -e "${GREEN}RBAC permissions summary generated successfully!${NC}" +echo -e "Output file: $OUTPUT_FILE" + +# Show statistics +echo "" +echo -e "${BLUE}Summary Statistics:${NC}" +echo "ClusterRoles: $cluster_roles" +echo "Roles: $roles" \ No newline at end of file From 3a4b481140f2de0e7b30d095d17a9c9804fc6ac1 Mon Sep 17 00:00:00 2001 From: "L.Dongming" Date: Sat, 26 Jul 2025 21:03:40 +0800 Subject: [PATCH 2/4] tidy up --- hack/rbac-summary.sh | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/hack/rbac-summary.sh b/hack/rbac-summary.sh index a30ddd34a87..5463128f82d 100755 --- a/hack/rbac-summary.sh +++ b/hack/rbac-summary.sh @@ -62,13 +62,6 @@ echo "" >> "$OUTPUT_FILE" echo "**Generated:** $(date)" >> "$OUTPUT_FILE" echo "" >> "$OUTPUT_FILE" -# Get summary statistics using the temp file -cluster_roles=$(yq eval 'select(.kind == "ClusterRole") | .metadata.name' "$TEMP_YAML" | wc -l | tr -d ' ') -roles=$(yq eval 'select(.kind == "Role") | .metadata.name' "$TEMP_YAML" | wc -l | tr -d ' ') - -echo "**Summary:** $cluster_roles ClusterRoles, $roles Roles" >> "$OUTPUT_FILE" -echo "" >> "$OUTPUT_FILE" - # Function to generate resource permissions table using simpler yq operations generate_permissions_table() { local title="$1" @@ -292,10 +285,4 @@ fi rm -f "$TEMP_YAML" echo -e "${GREEN}RBAC permissions summary generated successfully!${NC}" -echo -e "Output file: $OUTPUT_FILE" - -# Show statistics -echo "" -echo -e "${BLUE}Summary Statistics:${NC}" -echo "ClusterRoles: $cluster_roles" -echo "Roles: $roles" \ No newline at end of file +echo -e "Output file: $OUTPUT_FILE" \ No newline at end of file From bb09510d0d09ce9123ef841c89f7e26311119c3e Mon Sep 17 00:00:00 2001 From: "L.Dongming" Date: Mon, 28 Jul 2025 10:53:28 +0800 Subject: [PATCH 3/4] tidy up kubebuilder rbac marker --- config/rbac/role.yaml | 18 ------------------ .../parameters/reconfigure_controller.go | 4 ++-- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 009161fcde5..aabaddad15a 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -340,24 +340,6 @@ rules: - patch - update - watch -- apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - configmaps/finalizers - verbs: - - update - apiGroups: - "" resources: diff --git a/controllers/parameters/reconfigure_controller.go b/controllers/parameters/reconfigure_controller.go index b9924fe8f18..fa091bf1d42 100644 --- a/controllers/parameters/reconfigure_controller.go +++ b/controllers/parameters/reconfigure_controller.go @@ -75,8 +75,8 @@ var reconfigureRequiredLabels = []string{ constant.CMConfigurationSpecProviderLabelKey, } -// +kubebuilder:rbac:groups=core,resources=configmap,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=core,resources=configmap/finalizers,verbs=update +// +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=configmaps/finalizers,verbs=update // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. From 39647ad75d63ed7d07feb93f0a68bfa918ee9d56 Mon Sep 17 00:00:00 2001 From: "L.Dongming" Date: Mon, 28 Jul 2025 18:20:08 +0800 Subject: [PATCH 4/4] tidy up format follow the doc https://kubeblocks.io/docs/preview/user_docs/references/kubeblocks_options --- hack/rbac-summary.sh | 447 +++++++++++++++++++++++++------------------ 1 file changed, 263 insertions(+), 184 deletions(-) diff --git a/hack/rbac-summary.sh b/hack/rbac-summary.sh index 5463128f82d..bef355e590b 100755 --- a/hack/rbac-summary.sh +++ b/hack/rbac-summary.sh @@ -1,7 +1,8 @@ #!/bin/bash # KubeBlocks RBAC Permissions Summary Generator -# This script generates a concise summary of all RBAC permissions required by KubeBlocks +# This script generates a comprehensive summary of all RBAC permissions required by KubeBlocks +# under different configuration parameters set -e @@ -17,9 +18,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" HELM_DIR="$PROJECT_ROOT/deploy/helm" -# Output file and temp file +# Output file and temp files OUTPUT_FILE="$PROJECT_ROOT/docs/rbac-summary.md" -TEMP_YAML="$PROJECT_ROOT/temp-helm-output.yaml" +TEMP_YAML_BASE="$PROJECT_ROOT/temp-helm-base.yaml" +TEMP_YAML_WEBHOOKS="$PROJECT_ROOT/temp-helm-webhooks.yaml" +TEMP_YAML_RBAC="$PROJECT_ROOT/temp-helm-rbac.yaml" +TEMP_YAML_BOTH="$PROJECT_ROOT/temp-helm-both.yaml" echo -e "${BLUE}KubeBlocks RBAC Permissions Summary Generator${NC}" echo "==============================================" @@ -39,44 +43,34 @@ fi mkdir -p "$(dirname "$OUTPUT_FILE")" # Generate summary -echo -e "${YELLOW}Generating RBAC permissions summary...${NC}" +echo -e "${YELLOW}Generating RBAC permissions summary for different configurations...${NC}" -# Render templates once and save to temp file -echo -e "${YELLOW}Rendering Helm templates...${NC}" +# Render templates for different configurations +echo -e "${YELLOW}Rendering Helm templates for base configuration...${NC}" cd "$HELM_DIR" -helm template kubeblocks . > "$TEMP_YAML" -cd "$PROJECT_ROOT" - -cat > "$OUTPUT_FILE" << 'EOF' -# KubeBlocks RBAC Permissions Summary +helm template kubeblocks . --set webhooks.conversionEnabled=false --set rbac.enabled=false > "$TEMP_YAML_BASE" -This document provides a comprehensive summary of all RBAC permissions required by KubeBlocks. +echo -e "${YELLOW}Rendering Helm templates with webhooks.conversionEnabled=true...${NC}" +helm template kubeblocks . --set webhooks.conversionEnabled=true --set rbac.enabled=false > "$TEMP_YAML_WEBHOOKS" -## Overview +echo -e "${YELLOW}Rendering Helm templates with rbac.enabled=true...${NC}" +helm template kubeblocks . --set webhooks.conversionEnabled=false --set rbac.enabled=true > "$TEMP_YAML_RBAC" -KubeBlocks requires extensive permissions across both standard Kubernetes resources and its custom resources to manage database clusters, backups, configurations, and operations. - -EOF +echo -e "${YELLOW}Rendering Helm templates with both enabled...${NC}" +helm template kubeblocks . --set webhooks.conversionEnabled=true --set rbac.enabled=true > "$TEMP_YAML_BOTH" -echo "" >> "$OUTPUT_FILE" -echo "**Generated:** $(date)" >> "$OUTPUT_FILE" -echo "" >> "$OUTPUT_FILE" +cd "$PROJECT_ROOT" -# Function to generate resource permissions table using simpler yq operations -generate_permissions_table() { - local title="$1" +# Function to extract and format permissions for a specific API group +extract_permissions() { + local api_group="$1" local filter="$2" + local temp_file="$3" - echo "## $title" >> "$OUTPUT_FILE" - echo "" >> "$OUTPUT_FILE" - echo "| Resource | Permissions |" >> "$OUTPUT_FILE" - echo "|----------|-------------|" >> "$OUTPUT_FILE" - - # Extract resource:verb pairs and use shell to group them - local temp_data=$(yq eval "$filter" "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + local permissions=$(yq eval "$filter" "$temp_file" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) - if [[ -n "$temp_data" ]]; then - echo "$temp_data" | awk -F: ' + if [[ -n "$permissions" ]]; then + echo "$permissions" | awk -F: ' { if ($1 in resources) { if (index(resources[$1], $2) == 0) { @@ -89,127 +83,112 @@ generate_permissions_table() { END { for (resource in resources) { if (resource != "" && resource != "null") { - print "| `" resource "` | " resources[resource] " |" + print "* **" resource "**: " resources[resource] } } - }' | sort >> "$OUTPUT_FILE" + }' | sort fi - - echo "" >> "$OUTPUT_FILE" } -# Core Kubernetes Resources -generate_permissions_table "Core Kubernetes Resources" ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.apiGroups[]? == "" or .apiGroups[]? == "apps" or .apiGroups[]? == "batch" or .apiGroups[]? == "coordination.k8s.io" or .apiGroups[]? == "storage.k8s.io" or .apiGroups[]? == "snapshot.storage.k8s.io") | - .resources[]? as $resource | - .verbs[]? as $verb | - select($resource != null and $verb != null) | - $resource + ":" + $verb -' - -# RBAC Resources -rbac_count=$(yq eval ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.apiGroups[]? == "rbac.authorization.k8s.io") | - .resources[]? -' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') - -if [[ "$rbac_count" -gt 0 ]]; then - generate_permissions_table "RBAC Resources" ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.apiGroups[]? == "rbac.authorization.k8s.io") | - .resources[]? as $resource | - .verbs[]? as $verb | - select($resource != null and $verb != null) | - $resource + ":" + $verb - ' -fi +# Function to get all API groups from a template +get_api_groups() { + local temp_file="$1" + local exclude_kubeblocks="$2" -# Authentication & Authorization -auth_count=$(yq eval ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.apiGroups[]? == "authentication.k8s.io" or .apiGroups[]? == "authorization.k8s.io") | - .resources[]? -' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') - -if [[ "$auth_count" -gt 0 ]]; then - echo "## Authentication & Authorization" >> "$OUTPUT_FILE" - echo "" >> "$OUTPUT_FILE" - echo "| Resource | Permissions |" >> "$OUTPUT_FILE" - echo "|----------|-------------|" >> "$OUTPUT_FILE" - - auth_data=$(yq eval ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.apiGroups[]? == "authentication.k8s.io" or .apiGroups[]? == "authorization.k8s.io") | - (.apiGroups[]? + "/" + .resources[]?) as $resource | - .verbs[]? as $verb | - select($resource != null and $verb != null) | - $resource + ":" + $verb - ' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) - - if [[ -n "$auth_data" ]]; then - echo "$auth_data" | awk -F: ' - { - if ($1 in resources) { - if (index(resources[$1], $2) == 0) { - resources[$1] = resources[$1] ", " $2 - } - } else { - resources[$1] = $2 - } - } - END { - for (resource in resources) { - if (resource != "" && resource != "null") { - print "| `" resource "` | " resources[resource] " |" - } - } - }' | sort >> "$OUTPUT_FILE" + if [[ "$exclude_kubeblocks" == "true" ]]; then + yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + .apiGroups[]? | + select(. == "" or (test("kubeblocks") | not)) + ' "$temp_file" 2>/dev/null | grep -v "^null$" | sort | uniq + else + yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + .apiGroups[]? | + select(. != null and test("kubeblocks")) + ' "$temp_file" 2>/dev/null | grep -v "^null$" | sort | uniq fi +} - echo "" >> "$OUTPUT_FILE" -fi +# Function to generate permissions for a specific configuration +generate_permissions_section() { + local temp_file="$1" + local section_title="$2" + local output_file="$3" + + echo "### $section_title" >> "$output_file" + echo "" >> "$output_file" + + # Get all unique API groups from Kubernetes (excluding KubeBlocks groups) + local all_k8s_api_groups=$(get_api_groups "$temp_file" "true") + + # Process each API group + while IFS= read -r api_group; do + # Process all API groups including empty string (core API group) + if [[ -n "$api_group" ]] || [[ "$api_group" == "" ]]; then + # Check if this API group has any resources + resources_count=$(yq eval " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? | + select(. != null) + " "$temp_file" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + + if [[ "$resources_count" -gt 0 ]]; then + # Display API group name + if [[ "$api_group" == "" ]]; then + echo "#### Core API Group" >> "$output_file" + else + echo "#### $api_group" >> "$output_file" + fi + echo "" >> "$output_file" + + # Extract permissions for this API group + api_permissions=$(extract_permissions "$api_group" " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? as \$resource | + .verbs[]? as \$verb | + select(\$resource != null and \$verb != null) | + \$resource + \":\" + \$verb + " "$temp_file") + + if [[ -n "$api_permissions" ]]; then + echo "$api_permissions" >> "$output_file" + echo "" >> "$output_file" + fi + fi + fi + done <<< "$all_k8s_api_groups" -# KubeBlocks Custom Resources -echo "## KubeBlocks Custom Resources" >> "$OUTPUT_FILE" -echo "" >> "$OUTPUT_FILE" + # Non-Resource URLs (if any) + non_resource_count=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + select(.nonResourceURLs) | + .nonResourceURLs[]? + ' "$temp_file" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') -kb_api_groups=("apps.kubeblocks.io" "dataprotection.kubeblocks.io" "extensions.kubeblocks.io" "operations.kubeblocks.io" "parameters.kubeblocks.io" "workloads.kubeblocks.io" "experimental.kubeblocks.io" "trace.kubeblocks.io") + if [[ "$non_resource_count" -gt 0 ]]; then + echo "#### Non-Resource URLs" >> "$output_file" + echo "" >> "$output_file" -for api_group in "${kb_api_groups[@]}"; do - # Check if this API group has any resources - resources_count=$(yq eval " - select(.kind == \"ClusterRole\" or .kind == \"Role\") | - .rules[]? | - select(.apiGroups[]? == \"$api_group\") | - .resources[]? | - select(. != null and (test(\"/status$|/finalizers$\") | not)) - " "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') - - if [[ "$resources_count" -gt 0 ]]; then - echo "### $api_group" >> "$OUTPUT_FILE" - echo "" >> "$OUTPUT_FILE" - echo "| Resource | Permissions |" >> "$OUTPUT_FILE" - echo "|----------|-------------|" >> "$OUTPUT_FILE" - - group_data=$(yq eval " - select(.kind == \"ClusterRole\" or .kind == \"Role\") | + non_resource_permissions=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | .rules[]? | - select(.apiGroups[]? == \"$api_group\") | - .resources[]? as \$resource | - .verbs[]? as \$verb | - select(\$resource != null and \$verb != null and (\$resource | test(\"/status$|/finalizers$\") | not)) | - \$resource + \":\" + \$verb - " "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) - - if [[ -n "$group_data" ]]; then - echo "$group_data" | awk -F: ' + select(.nonResourceURLs) | + .nonResourceURLs[]? as $url | + .verbs[]? as $verb | + select($url != null and $verb != null) | + $url + ":" + $verb + ' "$temp_file" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) + + if [[ -n "$non_resource_permissions" ]]; then + echo "$non_resource_permissions" | awk -F: ' { if ($1 in resources) { if (index(resources[$1], $2) == 0) { @@ -222,67 +201,167 @@ for api_group in "${kb_api_groups[@]}"; do END { for (resource in resources) { if (resource != "" && resource != "null") { - print "| `" resource "` | " resources[resource] " |" + print "* **" resource "**: " resources[resource] } } - }' | sort >> "$OUTPUT_FILE" + }' | sort >> "$output_file" + echo "" >> "$output_file" fi + fi + + # KubeBlocks Custom Resources + local kb_api_groups_raw=$(get_api_groups "$temp_file" "false") - echo "" >> "$OUTPUT_FILE" + # Convert to array + local kb_api_groups=() + while IFS= read -r group; do + if [[ -n "$group" ]]; then + kb_api_groups+=("$group") + fi + done <<< "$kb_api_groups_raw" + + if [[ ${#kb_api_groups[@]} -gt 0 ]]; then + echo "#### KubeBlocks Custom Resources" >> "$output_file" + echo "" >> "$output_file" + + for api_group in "${kb_api_groups[@]}"; do + # Check if this API group has any resources + resources_count=$(yq eval " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? | + select(. != null) + " "$temp_file" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') + + if [[ "$resources_count" -gt 0 ]]; then + echo "##### $api_group" >> "$output_file" + echo "" >> "$output_file" + + # Extract permissions for this API group + kb_permissions=$(extract_permissions "$api_group" " + select(.kind == \"ClusterRole\" or .kind == \"Role\") | + .rules[]? | + select(.apiGroups[]? == \"$api_group\") | + .resources[]? as \$resource | + .verbs[]? as \$verb | + select(\$resource != null and \$verb != null) | + \$resource + \":\" + \$verb + " "$temp_file") + + if [[ -n "$kb_permissions" ]]; then + echo "$kb_permissions" >> "$output_file" + echo "" >> "$output_file" + fi + fi + done fi -done - -# Special permissions (Non-Resource URLs) -non_resource_count=$(yq eval ' - select(.kind == "ClusterRole" or .kind == "Role") | - .rules[]? | - select(.nonResourceURLs) | - .nonResourceURLs[]? -' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | wc -l | tr -d ' ') - -if [[ "$non_resource_count" -gt 0 ]]; then - echo "## Special Permissions" >> "$OUTPUT_FILE" - echo "" >> "$OUTPUT_FILE" - echo "### Non-Resource URLs" >> "$OUTPUT_FILE" - echo "" >> "$OUTPUT_FILE" - echo "| URL | Permissions |" >> "$OUTPUT_FILE" - echo "|-----|-------------|" >> "$OUTPUT_FILE" - - url_data=$(yq eval ' +} + +# Function to compare permissions and show differences +compare_permissions() { + local base_file="$1" + local compare_file="$2" + local section_title="$3" + local output_file="$4" + + echo "### $section_title" >> "$output_file" + echo "" >> "$output_file" + + # Get all permissions from both files + base_permissions=$(yq eval ' select(.kind == "ClusterRole" or .kind == "Role") | .rules[]? | - select(.nonResourceURLs) | - .nonResourceURLs[]? as $url | - .verbs[]? as $verb | - select($url != null and $verb != null) | - $url + ":" + $verb - ' "$TEMP_YAML" 2>/dev/null | grep -v "^null$" | grep -v "^---$" | sort | uniq) - - if [[ -n "$url_data" ]]; then - echo "$url_data" | awk -F: ' + (.apiGroups[]? + ":" + .resources[]? + ":" + .verbs[]?) | + select(. != null) + ' "$base_file" 2>/dev/null | grep -v "^null$" | sort | uniq) + + compare_permissions=$(yq eval ' + select(.kind == "ClusterRole" or .kind == "Role") | + .rules[]? | + (.apiGroups[]? + ":" + .resources[]? + ":" + .verbs[]?) | + select(. != null) + ' "$compare_file" 2>/dev/null | grep -v "^null$" | sort | uniq) + + # Find new permissions + new_permissions=$(comm -13 <(echo "$base_permissions" | sort) <(echo "$compare_permissions" | sort)) + + if [[ -n "$new_permissions" ]]; then + echo "**Additional permissions required:**" >> "$output_file" + echo "" >> "$output_file" + + # Group by API group and sort properly + temp_output=$(mktemp) + echo "$new_permissions" | awk -F: ' { - if ($1 in resources) { - if (index(resources[$1], $2) == 0) { - resources[$1] = resources[$1] ", " $2 + api_group = $1 + resource = $2 + verb = $3 + if (api_group == "") api_group = "Core API Group" + key = api_group ":" resource + if (key in perms) { + if (index(perms[key], verb) == 0) { + perms[key] = perms[key] ", " verb } } else { - resources[$1] = $2 + perms[key] = verb } } END { - for (resource in resources) { - if (resource != "" && resource != "null") { - print "| `" resource "` | " resources[resource] " |" - } + for (key in perms) { + split(key, parts, ":") + group = parts[1] + resource = parts[2] + print group "\t" resource "\t" perms[key] + } + }' | sort | awk -F'\t' ' + { + group = $1 + resource = $2 + permissions = $3 + if (group != current_group) { + if (current_group != "") print "" + print "#### " group + print "" + current_group = group } - }' | sort >> "$OUTPUT_FILE" + print "* **" resource "**: " permissions + }' >> "$output_file" + echo "" >> "$output_file" + else + echo "**No additional permissions required.**" >> "$output_file" + echo "" >> "$output_file" fi +} - echo "" >> "$OUTPUT_FILE" -fi +# Start generating the output file +cat > "$OUTPUT_FILE" << 'EOF' +# KubeBlocks Operator RBAC Permissions + +KubeBlocks operator requires different permissions based on configuration parameters. +EOF + +echo "" >> "$OUTPUT_FILE" +echo "**Generated:** $(date)" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +# Generate base configuration +echo "## Base Configuration" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" +echo "**Configuration:** \`webhooks.conversionEnabled=false\` and \`rbac.enabled=false\`" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +generate_permissions_section "$TEMP_YAML_BASE" "Kubernetes Resource Permissions" "$OUTPUT_FILE" + +# Generate comparison sections +echo "## Additional Permissions for Different Configurations" >> "$OUTPUT_FILE" +echo "" >> "$OUTPUT_FILE" + +compare_permissions "$TEMP_YAML_BASE" "$TEMP_YAML_WEBHOOKS" "webhooks.conversionEnabled=true" "$OUTPUT_FILE" +compare_permissions "$TEMP_YAML_BASE" "$TEMP_YAML_RBAC" "rbac.enabled=true" "$OUTPUT_FILE" -# Cleanup temp file -rm -f "$TEMP_YAML" +# Cleanup temp files +rm -f "$TEMP_YAML_BASE" "$TEMP_YAML_WEBHOOKS" "$TEMP_YAML_RBAC" "$TEMP_YAML_BOTH" echo -e "${GREEN}RBAC permissions summary generated successfully!${NC}" echo -e "Output file: $OUTPUT_FILE" \ No newline at end of file