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]

Reply via email to