-
Notifications
You must be signed in to change notification settings - Fork 11
ESO-174: Harden RBAC by adding resourceNames #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
127a47e
c907acf
c4b6625
3f502a3
7545196
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -204,7 +204,7 @@ metadata: | |||||||||||||||||||||||||||||||||||||||
| categories: Security | ||||||||||||||||||||||||||||||||||||||||
| console.openshift.io/disable-operand-delete: "true" | ||||||||||||||||||||||||||||||||||||||||
| containerImage: openshift.io/external-secrets-operator:latest | ||||||||||||||||||||||||||||||||||||||||
| createdAt: "2025-08-18T11:50:12Z" | ||||||||||||||||||||||||||||||||||||||||
| createdAt: "2025-08-21T05:49:03Z" | ||||||||||||||||||||||||||||||||||||||||
| features.operators.openshift.io/cnf: "false" | ||||||||||||||||||||||||||||||||||||||||
| features.operators.openshift.io/cni: "false" | ||||||||||||||||||||||||||||||||||||||||
| features.operators.openshift.io/csi: "false" | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -379,19 +379,25 @@ spec: | |||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
| - validatingwebhookconfigurations | ||||||||||||||||||||||||||||||||||||||||
| verbs: | ||||||||||||||||||||||||||||||||||||||||
| - create | ||||||||||||||||||||||||||||||||||||||||
| - get | ||||||||||||||||||||||||||||||||||||||||
| - list | ||||||||||||||||||||||||||||||||||||||||
| - watch | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
382
to
+384
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add global “create” for ValidatingWebhookConfigurations. Otherwise the operator cannot create the webhook objects; resourceNames cannot scope create. resources:
- validatingwebhookconfigurations
verbs:
+ - create
- get
- list
- watch📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| - apiGroups: | ||||||||||||||||||||||||||||||||||||||||
| - admissionregistration.k8s.io | ||||||||||||||||||||||||||||||||||||||||
| resourceNames: | ||||||||||||||||||||||||||||||||||||||||
| - externalsecret-validate | ||||||||||||||||||||||||||||||||||||||||
| - secretstore-validate | ||||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
| - validatingwebhookconfigurations | ||||||||||||||||||||||||||||||||||||||||
| verbs: | ||||||||||||||||||||||||||||||||||||||||
| - create | ||||||||||||||||||||||||||||||||||||||||
| - patch | ||||||||||||||||||||||||||||||||||||||||
| - update | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+386
to
395
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove “create” from the resourceNames-scoped webhook rule. This does not authorize create and gives a false sense of scoping. verbs:
- - create
- patch
- update📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| - watch | ||||||||||||||||||||||||||||||||||||||||
| - apiGroups: | ||||||||||||||||||||||||||||||||||||||||
| - apiextensions.k8s.io | ||||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
| - customresourcedefinitions | ||||||||||||||||||||||||||||||||||||||||
| verbs: | ||||||||||||||||||||||||||||||||||||||||
| - create | ||||||||||||||||||||||||||||||||||||||||
| - delete | ||||||||||||||||||||||||||||||||||||||||
| - get | ||||||||||||||||||||||||||||||||||||||||
| - list | ||||||||||||||||||||||||||||||||||||||||
| - patch | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -402,11 +408,21 @@ spec: | |||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
| - deployments | ||||||||||||||||||||||||||||||||||||||||
| verbs: | ||||||||||||||||||||||||||||||||||||||||
| - list | ||||||||||||||||||||||||||||||||||||||||
| - watch | ||||||||||||||||||||||||||||||||||||||||
| - apiGroups: | ||||||||||||||||||||||||||||||||||||||||
| - apps | ||||||||||||||||||||||||||||||||||||||||
| resourceNames: | ||||||||||||||||||||||||||||||||||||||||
| - bitwarden-sdk-server | ||||||||||||||||||||||||||||||||||||||||
| - external-secrets | ||||||||||||||||||||||||||||||||||||||||
| - external-secrets-cert-controller | ||||||||||||||||||||||||||||||||||||||||
| - external-secrets-webhook | ||||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
| - deployments | ||||||||||||||||||||||||||||||||||||||||
| verbs: | ||||||||||||||||||||||||||||||||||||||||
| - create | ||||||||||||||||||||||||||||||||||||||||
| - get | ||||||||||||||||||||||||||||||||||||||||
| - list | ||||||||||||||||||||||||||||||||||||||||
| - update | ||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||
| - watch | ||||||||||||||||||||||||||||||||||||||||
| - apiGroups: | ||||||||||||||||||||||||||||||||||||||||
| - cert-manager.io | ||||||||||||||||||||||||||||||||||||||||
| resources: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,19 +41,25 @@ rules: | |
| resources: | ||
| - validatingwebhookconfigurations | ||
| verbs: | ||
| - create | ||
| - get | ||
| - list | ||
| - watch | ||
| - apiGroups: | ||
|
Comment on lines
44
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Create on ValidatingWebhookConfigurations must be global (resourceNames cannot scope create). A rule with resourceNames never matches create (name unknown at auth time). Without a global create on validatingwebhookconfigurations, the operator won’t be able to create the webhooks. Apply: resources:
- validatingwebhookconfigurations
verbs:
+ - create
- get
- list
- watch🤖 Prompt for AI Agents |
||
| - admissionregistration.k8s.io | ||
| resourceNames: | ||
| - externalsecret-validate | ||
| - secretstore-validate | ||
| resources: | ||
| - validatingwebhookconfigurations | ||
| verbs: | ||
| - create | ||
| - patch | ||
|
Comment on lines
+48
to
56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove “create” from the resourceNames-scoped webhook rule. Create cannot be name-scoped; this rule won’t authorize create anyway and is misleading. verbs:
- - create
- patch
- update
🤖 Prompt for AI Agents |
||
| - update | ||
| - watch | ||
| - apiGroups: | ||
| - apiextensions.k8s.io | ||
| resources: | ||
| - customresourcedefinitions | ||
| verbs: | ||
| - create | ||
| - delete | ||
| - get | ||
| - list | ||
| - patch | ||
|
|
@@ -64,11 +70,21 @@ rules: | |
| resources: | ||
| - deployments | ||
| verbs: | ||
| - list | ||
| - watch | ||
| - apiGroups: | ||
| - apps | ||
| resourceNames: | ||
| - bitwarden-sdk-server | ||
| - external-secrets | ||
| - external-secrets-cert-controller | ||
| - external-secrets-webhook | ||
| resources: | ||
| - deployments | ||
| verbs: | ||
| - create | ||
| - get | ||
| - list | ||
| - update | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - watch | ||
| - apiGroups: | ||
| - cert-manager.io | ||
| resources: | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,37 @@ | ||||||||||||||||||||||||||||||||||||||||||
| #!/bin/sh | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| OUTPUT_PATH=${1:-./bin/operator-sdk} | ||||||||||||||||||||||||||||||||||||||||||
| VERSION=${2:-"v1.39.0"} | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| GOOS=$(go env GOOS) | ||||||||||||||||||||||||||||||||||||||||||
| GOARCH=$(go env GOARCH) | ||||||||||||||||||||||||||||||||||||||||||
| BIN="operator-sdk" | ||||||||||||||||||||||||||||||||||||||||||
| BIN_ARCH="${BIN}_${GOOS}_${GOARCH}" | ||||||||||||||||||||||||||||||||||||||||||
| OPERATOR_SDK_DL_URL="https://github.com/operator-framework/operator-sdk/releases/download/${VERSION}" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if [[ "$GOOS" != "linux" && "$GOOS" != "darwin" ]]; then | ||||||||||||||||||||||||||||||||||||||||||
| echo "Unsupported OS $GOOS" | ||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if [[ "$GOARCH" != "amd64" && "$GOARCH" != "arm64" && "$GOARCH" != "ppc64le" && "$GOARCH" != "s390x" ]]; then | ||||||||||||||||||||||||||||||||||||||||||
| echo "Unsupported architecture $GOARCH" | ||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+14
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix bashisms under /bin/sh (will fail on dash). The script uses [[ … ]] and &> which are bash-only. With the current shebang (/bin/sh), this breaks on many systems. Apply: -if [[ "$GOOS" != "linux" && "$GOOS" != "darwin" ]]; then
- echo "Unsupported OS $GOOS"
- exit 1
-fi
+case "$GOOS" in
+ linux|darwin) ;;
+ *) echo "Unsupported OS $GOOS"; exit 1 ;;
+esac
-
-if [[ "$GOARCH" != "amd64" && "$GOARCH" != "arm64" && "$GOARCH" != "ppc64le" && "$GOARCH" != "s390x" ]]; then
- echo "Unsupported architecture $GOARCH"
- exit 1
-fi
+case "$GOOS/$GOARCH" in
+ linux/amd64|linux/arm64|linux/ppc64le|linux/s390x|darwin/amd64|darwin/arm64) ;;
+ *) echo "Unsupported architecture $GOARCH for $GOOS"; exit 1 ;;
+esac
-
-command -v curl &> /dev/null || { echo "can't find curl command" && exit 1; }
+command -v curl >/dev/null 2>&1 || { echo "can't find curl command" >&2; exit 1; }Also applies to: 24-24 🧰 Tools🪛 Shellcheck (0.10.0)[warning] 14-14: In POSIX sh, [[ ]] is undefined. (SC3010) [warning] 19-19: In POSIX sh, [[ ]] is undefined. (SC3010) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| command -v curl &> /dev/null || { echo "can't find curl command" && exit 1; } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| TEMPDIR=$(mktemp -d) | ||||||||||||||||||||||||||||||||||||||||||
| BIN_PATH="${TEMPDIR}/${BIN_ARCH}" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| echo "> downloading binary" | ||||||||||||||||||||||||||||||||||||||||||
| curl --location -o "${BIN_PATH}" "${OPERATOR_SDK_DL_URL}/operator-sdk_${GOOS}_${GOARCH}" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| echo "> installing binary" | ||||||||||||||||||||||||||||||||||||||||||
| mv "${BIN_PATH}" "${OUTPUT_PATH}" | ||||||||||||||||||||||||||||||||||||||||||
| chmod +x "${OUTPUT_PATH}" | ||||||||||||||||||||||||||||||||||||||||||
| rm -rf "${TEMPDIR}" | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Harden download/install and guarantee cleanup. Add trap for tempdir cleanup, fail on HTTP errors, ensure destination dir exists, and use install(1) atomically. TEMPDIR=$(mktemp -d)
BIN_PATH="${TEMPDIR}/${BIN_ARCH}"
+trap 'rm -rf "${TEMPDIR}"' EXIT
echo "> downloading binary"
-curl --location -o "${BIN_PATH}" "${OPERATOR_SDK_DL_URL}/operator-sdk_${GOOS}_${GOARCH}"
+curl -fSL -o "${BIN_PATH}" "${OPERATOR_SDK_DL_URL}/operator-sdk_${GOOS}_${GOARCH}"
echo "> installing binary"
-mv "${BIN_PATH}" "${OUTPUT_PATH}"
-chmod +x "${OUTPUT_PATH}"
-rm -rf "${TEMPDIR}"
+mkdir -p "$(dirname "${OUTPUT_PATH}")"
+install -m 0755 "${BIN_PATH}" "${OUTPUT_PATH}"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| echo "> operator-sdk binary available at ${OUTPUT_PATH}" | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,156 @@ | ||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||
|
|
||||||||||||||||||
| # validate-rbac-resourcenames.sh | ||||||||||||||||||
| # This script validates that the resourceNames in kubebuilder RBAC annotations | ||||||||||||||||||
| # match the actual resource names defined in the assets. | ||||||||||||||||||
|
|
||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||
|
|
||||||||||||||||||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||||||||||||||||
| PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" | ||||||||||||||||||
|
|
||||||||||||||||||
| # extract resourceNames from kubebuilder annotations | ||||||||||||||||||
| extract_kubebuilder_resourcenames() { | ||||||||||||||||||
| local resource_type="$1" | ||||||||||||||||||
| grep -E "^\s*//\s*\+kubebuilder:rbac:.*resources=${resource_type}.*resourceNames=" \ | ||||||||||||||||||
| "${PROJECT_ROOT}/pkg/controller/external_secrets/controller.go" | \ | ||||||||||||||||||
| sed -E 's/.*resourceNames=([^,]*).*/\1/' | \ | ||||||||||||||||||
| tr ';' '\n' | sort -u | ||||||||||||||||||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regex uses ‘\s’ which grep -E doesn’t support; extractor will return empty. Use POSIX classes. - grep -E "^\s*//\s*\+kubebuilder:rbac:.*resources=${resource_type}.*resourceNames=" \
+ grep -E "^[[:space:]]*//[[:space:]]*\+kubebuilder:rbac:.*resources=${resource_type}.*resourceNames=" \
"${PROJECT_ROOT}/pkg/controller/external_secrets/controller.go" | \📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| # extract actual resource names from assets | ||||||||||||||||||
| extract_asset_names() { | ||||||||||||||||||
| local pattern="$1" | ||||||||||||||||||
| find "${PROJECT_ROOT}/bindata/external-secrets/resources" "${PROJECT_ROOT}/bindata/external-secrets" -name "*.yml" -exec grep -l "kind: ${pattern}" {} \; 2>/dev/null | \ | ||||||||||||||||||
| xargs grep -h "^ name:" | \ | ||||||||||||||||||
| awk '{print $2}' | sort -u | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+24
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Handle .yaml files and filenames with spaces; avoid SC2038. Use -exec … + and include both extensions; match indentation-agnostic “name:”. -extract_asset_names() {
+extract_asset_names() {
local pattern="$1"
- find "${PROJECT_ROOT}/bindata/external-secrets/resources" "${PROJECT_ROOT}/bindata/external-secrets" -name "*.yml" -exec grep -l "kind: ${pattern}" {} \; 2>/dev/null | \
- xargs grep -h "^ name:" | \
- awk '{print $2}' | sort -u
+ find "${PROJECT_ROOT}/bindata/external-secrets/resources" "${PROJECT_ROOT}/bindata/external-secrets" \
+ -type f \( -name "*.yml" -o -name "*.yaml" \) -exec grep -l "kind: ${pattern}" {} + 2>/dev/null | \
+ xargs -r grep -hE '^[[:space:]]{2}name:' | \
+ awk '{print $2}' | sort -u
}
🧰 Tools🪛 Shellcheck (0.10.0)[warning] 24-24: Use 'find .. -print0 | xargs -0 ..' or 'find .. -exec .. +' to allow non-alphanumeric filenames. (SC2038) 🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| # extract CRD names from assets | ||||||||||||||||||
| extract_crd_names() { | ||||||||||||||||||
| # Get CRDs from config/crd/bases | ||||||||||||||||||
| local crd_names="" | ||||||||||||||||||
| if [[ -d "${PROJECT_ROOT}/config/crd/bases" ]]; then | ||||||||||||||||||
| crd_names=$(find "${PROJECT_ROOT}/config/crd/bases" -name "*.yml" -o -name "*.yaml" 2>/dev/null | \ | ||||||||||||||||||
| xargs grep -l "kind: CustomResourceDefinition" 2>/dev/null | \ | ||||||||||||||||||
| xargs grep -h "^ name:" 2>/dev/null | \ | ||||||||||||||||||
| awk '{print $2}') | ||||||||||||||||||
|
Comment on lines
+34
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Same robustness fix for CRD discovery; avoid xargs on unsanitized filenames. - crd_names=$(find "${PROJECT_ROOT}/config/crd/bases" -name "*.yml" -o -name "*.yaml" 2>/dev/null | \
- xargs grep -l "kind: CustomResourceDefinition" 2>/dev/null | \
- xargs grep -h "^ name:" 2>/dev/null | \
- awk '{print $2}')
+ crd_names=$(find "${PROJECT_ROOT}/config/crd/bases" -type f \( -name "*.yml" -o -name "*.yaml" \) \
+ -exec grep -l "kind: CustomResourceDefinition" {} + 2>/dev/null | \
+ xargs -r grep -hE '^[[:space:]]{2}name:' 2>/dev/null | \
+ awk '{print $2}')📝 Committable suggestion
Suggested change
🧰 Tools🪛 Shellcheck (0.10.0)[warning] 34-34: Use 'find .. -print0 | xargs -0 ..' or 'find .. -exec .. +' to allow non-alphanumeric filenames. (SC2038) 🤖 Prompt for AI Agents |
||||||||||||||||||
| fi | ||||||||||||||||||
| echo "${crd_names}" | grep -v "^$" | sort -u | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| # compare kubebuilder resourceNames with actual resources | ||||||||||||||||||
| compare_resources() { | ||||||||||||||||||
| local resource_display_name="$1" | ||||||||||||||||||
| local kubebuilder_resources="$2" | ||||||||||||||||||
| local actual_resources="$3" | ||||||||||||||||||
|
|
||||||||||||||||||
| echo "Kubebuilder resourceNames:" | ||||||||||||||||||
| echo "${kubebuilder_resources}" | sed 's/^/ - /' | ||||||||||||||||||
| echo | ||||||||||||||||||
| echo "Actual ${resource_display_name} names:" | ||||||||||||||||||
| echo "${actual_resources}" | sed 's/^/ - /' | ||||||||||||||||||
| echo | ||||||||||||||||||
|
|
||||||||||||||||||
| # Compare - find missing and extra resources | ||||||||||||||||||
| local missing_in_kb | ||||||||||||||||||
| missing_in_kb=$(comm -23 <(echo "${actual_resources}") <(echo "${kubebuilder_resources}")) | ||||||||||||||||||
|
|
||||||||||||||||||
| local extra_in_kb | ||||||||||||||||||
| extra_in_kb=$(comm -13 <(echo "${actual_resources}") <(echo "${kubebuilder_resources}")) | ||||||||||||||||||
|
|
||||||||||||||||||
| local has_errors=false | ||||||||||||||||||
|
|
||||||||||||||||||
| if [[ -n "${missing_in_kb}" ]]; then | ||||||||||||||||||
| echo "Missing in kubebuilder annotations:" | ||||||||||||||||||
| echo "${missing_in_kb}" | sed 's/^/ /' | ||||||||||||||||||
| has_errors=true | ||||||||||||||||||
| fi | ||||||||||||||||||
|
|
||||||||||||||||||
| if [[ -n "${extra_in_kb}" ]]; then | ||||||||||||||||||
| echo "Extra in kubebuilder annotations (might be outdated):" | ||||||||||||||||||
| echo "${extra_in_kb}" | sed 's/^/ /' | ||||||||||||||||||
| fi | ||||||||||||||||||
|
|
||||||||||||||||||
| if [[ "$has_errors" == "false" ]]; then | ||||||||||||||||||
| echo "${resource_display_name} validation passed" | ||||||||||||||||||
| return 0 | ||||||||||||||||||
| else | ||||||||||||||||||
| return 1 | ||||||||||||||||||
| fi | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| # Generic validation function | ||||||||||||||||||
| validate_resource_type() { | ||||||||||||||||||
| local resource_display_name="$1" | ||||||||||||||||||
| local kubebuilder_resource_type="$2" | ||||||||||||||||||
| local asset_kind="$3" | ||||||||||||||||||
| local extract_func="$4" | ||||||||||||||||||
|
|
||||||||||||||||||
| echo "Validating ${resource_display_name}..." | ||||||||||||||||||
|
|
||||||||||||||||||
| # Extract from kubebuilder annotations | ||||||||||||||||||
| local kb_resources | ||||||||||||||||||
| kb_resources=$(extract_kubebuilder_resourcenames "${kubebuilder_resource_type}" || echo "") | ||||||||||||||||||
|
|
||||||||||||||||||
| # Extract from assets using the specified function | ||||||||||||||||||
| local actual_resources | ||||||||||||||||||
| if [[ "$extract_func" == "extract_crd_names" ]]; then | ||||||||||||||||||
| actual_resources=$(extract_crd_names) | ||||||||||||||||||
| else | ||||||||||||||||||
| actual_resources=$(extract_asset_names "${asset_kind}") | ||||||||||||||||||
| fi | ||||||||||||||||||
|
|
||||||||||||||||||
| # Compare and report | ||||||||||||||||||
| compare_resources "${resource_display_name}" "${kb_resources}" "${actual_resources}" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_deployments() { | ||||||||||||||||||
| validate_resource_type "Deployments" "deployments" "Deployment" "extract_asset_names" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_webhooks() { | ||||||||||||||||||
| validate_resource_type "ValidatingWebhookConfigurations" "validatingwebhookconfigurations" "ValidatingWebhookConfiguration" "extract_asset_names" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_crds() { | ||||||||||||||||||
| validate_resource_type "CustomResourceDefinitions" "customresourcedefinitions" "" "extract_crd_names" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_roles() { | ||||||||||||||||||
| validate_resource_type "Roles" "roles" "Role" "extract_asset_names" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_rolebindings() { | ||||||||||||||||||
| validate_resource_type "RoleBindings" "rolebindings" "RoleBinding" "extract_asset_names" | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| main() { | ||||||||||||||||||
| local exit_code=0 | ||||||||||||||||||
|
|
||||||||||||||||||
| echo "Validating RBAC resourceNames consistency for external-secrets-operator" | ||||||||||||||||||
| echo "==================================================================================" | ||||||||||||||||||
|
|
||||||||||||||||||
| validate_deployments || exit_code=1 | ||||||||||||||||||
| echo | ||||||||||||||||||
| validate_webhooks || exit_code=1 | ||||||||||||||||||
| echo | ||||||||||||||||||
| validate_crds || exit_code=1 | ||||||||||||||||||
| echo | ||||||||||||||||||
| validate_roles || exit_code=1 | ||||||||||||||||||
| echo | ||||||||||||||||||
| validate_rolebindings || exit_code=1 | ||||||||||||||||||
| echo | ||||||||||||||||||
|
|
||||||||||||||||||
| if [[ $exit_code -eq 0 ]]; then | ||||||||||||||||||
| echo "All RBAC resourceNames validations passed!" | ||||||||||||||||||
| echo "The kubebuilder annotations are consistent with the actual resources." | ||||||||||||||||||
| else | ||||||||||||||||||
| echo "RBAC validation failed!" | ||||||||||||||||||
| echo "Please update the kubebuilder annotations in pkg/controller/external_secrets/controller.go" | ||||||||||||||||||
| fi | ||||||||||||||||||
|
|
||||||||||||||||||
| return $exit_code | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| main "$@" | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -97,16 +97,18 @@ type Reconciler struct { | |||||||||||||
| // +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;create;update;patch | ||||||||||||||
|
|
||||||||||||||
| // +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles;rolebindings;clusterroles;clusterrolebindings,verbs=get;list;watch;create;update;patch;delete | ||||||||||||||
| // +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=get;list;watch;create;update;patch | ||||||||||||||
| // +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=get;list;watch | ||||||||||||||
| // +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=create;update;patch,resourceNames=externalsecret-validate;secretstore-validate | ||||||||||||||
| // +kubebuilder:rbac:groups="",resources=events;secrets;services;serviceaccounts,verbs=get;list;watch;create;update;delete;patch | ||||||||||||||
|
Comment on lines
+100
to
102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Webhook RBAC: add global create; remove create from name-scoped rule. Create cannot be authorized with resourceNames. Without a global create, webhook creation will fail and escalate checks will also fail. -// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=get;list;watch
-// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=create;update;patch,resourceNames=externalsecret-validate;secretstore-validate
+// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=create;get;list;watch
+// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=update;patch,resourceNames=externalsecret-validate;secretstore-validate🤖 Prompt for AI Agents |
||||||||||||||
| // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update | ||||||||||||||
| // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=list;watch | ||||||||||||||
| // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;create;update,resourceNames=external-secrets;external-secrets-cert-controller;external-secrets-webhook;bitwarden-sdk-server | ||||||||||||||
| // +kubebuilder:rbac:groups=cert-manager.io,resources=certificates;clusterissuers;issuers,verbs=get;list;watch;create;update | ||||||||||||||
|
Comment on lines
+103
to
105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deployments RBAC: create cannot be name-scoped; add global create or move to a namespaced Role. As-is, operator won't be able to create its Deployments. Quick fix below; longer-term consider moving create to a namespaced Role bound to the operator SA. -// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=list;watch
-// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;create;update,resourceNames=external-secrets;external-secrets-cert-controller;external-secrets-webhook;bitwarden-sdk-server
+// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=create;list;watch
+// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;update,resourceNames=external-secrets;external-secrets-cert-controller;external-secrets-webhook;bitwarden-sdk-serverAlternative (recommended hardening): move create/get/update for these resourceNames into a namespaced Role (CSV permissions) instead of ClusterRole. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| // +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch;create | ||||||||||||||
|
|
||||||||||||||
| // +kubebuilder:rbac:groups="",resources=endpoints,verbs=get;list;watch;create | ||||||||||||||
| // +kubebuilder:rbac:groups="",resources=serviceaccounts/token,verbs=create | ||||||||||||||
| // +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete | ||||||||||||||
| // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch;create;update;patch;delete | ||||||||||||||
| // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch;update;patch | ||||||||||||||
| // +kubebuilder:rbac:groups=external-secrets.io,resources=clusterexternalsecrets;clustersecretstores;clusterpushsecrets;externalsecrets;secretstores;pushsecrets,verbs=get;list;watch;create;update;patch;delete;deletecollection | ||||||||||||||
| // +kubebuilder:rbac:groups=external-secrets.io,resources=clusterexternalsecrets/finalizers;clustersecretstores/finalizers;externalsecrets/finalizers;pushsecrets/finalizers;secretstores/finalizers;clusterpushsecrets/finalizers,verbs=get;update;patch | ||||||||||||||
| // +kubebuilder:rbac:groups=external-secrets.io,resources=clusterexternalsecrets/status;clustersecretstores/status;externalsecrets/status;pushsecrets/status;secretstores/status;clusterpushsecrets/status,verbs=get;update;patch | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the
resourceNamesmight not help as expected with ClusterRole, because of limitations withcreate,list, andwatchverbs.xref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/