From 8efdcbf186eff69c80de3b27598970f83d1ba300 Mon Sep 17 00:00:00 2001 From: Ross Simpson Date: Tue, 27 Jun 2023 13:03:35 +1200 Subject: [PATCH] Script to generate permission policies This script enumerates permission policies from Cloudflare's API and then writes them to a format that can be copy & pasted into `add.go` in this project. It's a bit ugly, it has a bunch of duplication and could be done better, but it gets the job done. In future, it might be nice for the policies to be externalized into their own files (toml or whatever) that can easily be updated, rather than having to copy/paste sections into a file. --- script/generate-permission-policies | 156 ++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100755 script/generate-permission-policies diff --git a/script/generate-permission-policies b/script/generate-permission-policies new file mode 100755 index 0000000..43fd715 --- /dev/null +++ b/script/generate-permission-policies @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +# Pull permission groups from Cloudflare's API +# Generate policy output for pasting into generatePolicy() + + +if [[ ! -z "${CLOUDFLARE_API_TOKEN}" ]]; then + auth_headers=( -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" ) + +elif [[ ! -z "${CLOUDFLARE_EMAIL}" && ! -z "${CLOUDFLARE_API_KEY}" ]]; then + auth_headers=( -H "X-Auth-Email: $CF_EMAIL" + -H "X-Auth-Key: $CF_API_KEY" ) + +else + >&2 echo -e "ERROR: CLOUDFLARE_API_TOKEN or (CLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY) should be set in the environment.\n " + exit 1 +fi + +groups=$(curl -s "https://api.cloudflare.com/client/v4/user/tokens/permission_groups" \ + "${auth_headers[@]}") + +if [[ "$(echo "${groups}" | jq -r '.success')" != "true" ]]; then + echo "Error fetching permission groups:" + echo "${groups}" | jq + exit 1 +fi + +declare -A account_read zone_read user_read +declare -A account_write zone_write user_write + +# account +while IFS=\| read id name; do + if [[ "${name}" =~ (^|[^[:alnum:]_])Read([^[:alnum:]_]|$) ]]; then + account_read+=([${id}]=${name}) + else + account_write+=([${id}]=${name}) + fi +done < <(echo "${groups}" | jq -r '.result[] | select(.scopes[] | contains("com.cloudflare.api.account")) | "\(.id)|\(.name)"') + +# zone +while IFS=\| read id name; do + if [[ "${name}" =~ (^|[^[:alnum:]_])Read([^[:alnum:]_]|$) ]]; then + zone_read+=([${id}]=${name}) + else + zone_write+=([${id}]=${name}) + fi +done < <(echo "${groups}" | jq -r '.result[] | select(.scopes[] | contains("com.cloudflare.api.account.zone")) | "\(.id)|\(.name)"') + +# user +while IFS=\| read id name; do + if [[ "${name}" =~ (^|[^[:alnum:]_])Read([^[:alnum:]_]|$) ]]; then + user_read+=([${id}]=${name}) + elif [[ "${name}" == "API Tokens Write" ]]; then + # Tokens can't have this permission + : + else + user_write+=([${id}]=${name}) + fi +done < <(echo "${groups}" | jq -r '.result[] | select(.scopes[] | contains("com.cloudflare.api.user")) | "\(.id)|\(.name)"') + + +# +# Read-only +# +cat <<"EOF" + readOnlyPolicy := []policy{ + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.account.*": "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!account_read[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${account_read[$key]}" +done | sort + +cat <<"EOF" + }, + }, + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.account.zone.*": "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!zone_read[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${zone_read[$key]}" +done | sort + +cat <<"EOF" + }, + }, + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.user." + userID: "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!user_read[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${user_read[$key]}" +done | sort + +cat <<"EOF" + }, + }, + } +EOF + + +# +# Write everything +# +cat <<"EOF" + + writeEverythingPolicy := []policy{ + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.account.*": "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!account_write[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${account_write[$key]}" +done | sort + +cat <<"EOF" + }, + }, + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.account.zone.*": "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!zone_write[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${zone_write[$key]}" +done | sort + +cat <<"EOF" + }, + }, + { + Effect: "allow", + Resources: map[string]interface{}{"com.cloudflare.api.user." + userID: "*"}, + PermissionGroups: []permissionGroup{ +EOF + +for key in "${!user_write[@]}"; do + echo -e "\t\t\t\t{ID: \"${key}\"}, // ${user_write[$key]}" +done | sort + +cat <<"EOF" + }, + }, + } +EOF