joshua-cogliati-inl commented on issue #70251:
URL: https://github.com/apache/airflow/issues/70251#issuecomment-5052402250
Workaround for the other Op issue (from Claude):
```bash
#!/usr/bin/env bash
set -euo pipefail
# fix-op-team-dag-resource.sh
#
# Workaround for environments running a keycloak provider version whose
# `_attach_team_permissions` omits DAG:{team} from the Op-{team}
# resource-based permission (see commands.py fix, tracked in [issue link]).
#
# Once every environment is on a provider version with the commands.py
# fix, this script is no longer needed and can be deleted.
#
# IMPORTANT: the Keycloak "update permission resources" endpoint REPLACES
# the resource list rather than merging (confirmed empirically). This
# script does explicit read -> merge -> write to avoid dropping the
# existing Connection/Variable/Pool resources already attached to
# Op-{team}.
#
# NOTE: deliberately avoids jq (not present in the stock Keycloak image).
# Uses `kcadm ... --format csv --noquotes` to get one ID/name per line
# instead, same pattern the rest of this repo's kcadm scripts already use.
#
# Usage:
# KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=... \
# ./fix-op-team-dag-resource.sh team-analytics ...
#
# Safe to re-run: if DAG:{team} is already attached, the script detects
# this and skips the write for that team.
kcadm=/opt/keycloak/bin/kcadm.sh
server=http://keycloak:8080
realm=airflow
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <team-name> [<team-name> ...]"
exit 1
fi
"$kcadm" config credentials --server "$server" --realm master \
--user "$KEYCLOAK_ADMIN" --password "$KEYCLOAK_ADMIN_PASSWORD"
airflow_client_id=$("$kcadm" get clients -r "$realm" -q clientId=airflow \
--fields id --format csv --noquotes | head -n 1)
test -n "$airflow_client_id" || { echo "ERROR: could not resolve airflow
client id"; exit 1; }
echo "airflow client id: $airflow_client_id"
echo
# Join an array of quoted strings with commas, e.g.:
# join_csv_json "a" "b" "c" -> "a","b","c"
join_csv_json() {
local IFS=,
echo "$*"
}
fix_op_dag_resource() {
local team=$1
local perm_name="Op-${team}"
# NOTE: resource is named "Dag:{team}" (confirmed casing from live
# kcadm output), not "DAG:{team}".
local dag_resource_name="Dag:${team}"
echo "=== $team ==="
local perm_id
perm_id=$("$kcadm" get
"clients/$airflow_client_id/authz/resource-server/permission" -r "$realm" \
-q "name=$perm_name" --fields id --format csv --noquotes | head -n 1)
if [[ -z "$perm_id" ]]; then
echo " Skipping: permission '$perm_name' not found (team may not exist
yet)"
echo
return
fi
local dag_resource_id
dag_resource_id=$("$kcadm" get
"clients/$airflow_client_id/authz/resource-server/resource" -r "$realm" \
-q "name=$dag_resource_name" --fields _id --format csv --noquotes | head
-n 1)
if [[ -z "$dag_resource_id" ]]; then
echo " Skipping: resource '$dag_resource_name' not found"
echo
return
fi
# Read current resources attached to the permission, one "id,name" pair
# per line via CSV (no jq). --fields order below matches the header-less
# csv output order.
local current_csv
current_csv=$("$kcadm" get
"clients/$airflow_client_id/authz/resource-server/permission/$perm_id/resources"
\
-r "$realm" --fields _id,name --format csv --noquotes)
local current_ids=()
local current_names=()
while IFS=, read -r id name; do
[[ -z "$id" ]] && continue
current_ids+=("$id")
current_names+=("$name")
done <<< "$current_csv"
echo " Current resources: ${current_names[*]:-(none)}"
# Check whether DAG is already present.
local id
for id in "${current_ids[@]}"; do
if [[ "$id" == "$dag_resource_id" ]]; then
echo " Already has $dag_resource_name attached. Skipping."
echo
return
fi
done
# Build merged ID list (existing + new), each quoted for the JSON array
# kcadm expects in -s 'resources=[...]'.
local quoted_ids=()
for id in "${current_ids[@]}"; do
quoted_ids+=("\"$id\"")
done
quoted_ids+=("\"$dag_resource_id\"")
local merged_json
merged_json="[$(join_csv_json "${quoted_ids[@]}")]"
echo " Adding: $dag_resource_name"
local before_count=${#current_ids[@]}
"$kcadm" update
"clients/$airflow_client_id/authz/resource-server/permission/resource/$perm_id"
\
-r "$realm" -s "resources=$merged_json"
# Verify: re-read and confirm count is exactly +1 and DAG is present.
local after_csv
after_csv=$("$kcadm" get
"clients/$airflow_client_id/authz/resource-server/permission/$perm_id/resources"
\
-r "$realm" --fields _id,name --format csv --noquotes)
local after_ids=()
local after_names=()
local found_dag=false
while IFS=, read -r id name; do
[[ -z "$id" ]] && continue
after_ids+=("$id")
after_names+=("$name")
[[ "$id" == "$dag_resource_id" ]] && found_dag=true
done <<< "$after_csv"
echo " After: ${after_names[*]:-(none)}"
local after_count=${#after_ids[@]}
if [[ "$after_count" -ne $((before_count + 1)) ]]; then
echo " WARNING: expected $((before_count + 1)) resources after update,
got $after_count."
echo " Please inspect manually -- the merge may not have applied as
expected."
elif [[ "$found_dag" != "true" ]]; then
echo " WARNING: resource count looks right but $dag_resource_name was
not found in the after list."
echo " Please inspect manually."
else
echo " OK: $dag_resource_name added, existing resources preserved."
fi
echo
}
for team in "$@"; do
fix_op_dag_resource "$team"
done
echo "Done."
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]