Script
#!/bin/bash
RULE_SERVICE_URL=https://rules.app.gomboc.ai
if ! which curl > /dev/null; then
echo "curl is not installed"
exit 1
fi
if ! which yq > /dev/null;
then
echo "yq is not installed"
exit 1
fi
if [[ -z "$RULE_SERVICE_TOKEN" ]]; then
echo "RULE_SERVICE_TOKEN is not set"
exit 1
fi
list_classifications() {
echo "Listing classifications $@"
local page=1
while true; do
local response=$(curl -s "$RULE_SERVICE_URL/api/v1/classifications/search" \
-G \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "query=(not%20(eq%20%24.name%20%22%22))&page=$page")
echo "$response" | jq -r '.data'
local classifications=$(echo "$response" | jq -r '.data.classifications')
if [[ "$classifications" == "[]" ]]; then
break
fi
page=$((page + 1))
done
}
list_channels() {
echo "Listing channels"
local page=1
while true; do
local response=$(curl -s "$RULE_SERVICE_URL/api/v1/channels/search" \
-G \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "query=(not%20(eq%20%24.name%20%22%22))&page=$page")
echo "$response" | jq -r '.'
local channels=$(echo "$response" | jq -r '.data.channels')
if [[ "$channels" == "[]" ]]; then
break
fi
page=$((page + 1))
done
}
list_rules() {
echo "Listing rules"
local page=1
while true; do
local response=$(curl -s "$RULE_SERVICE_URL/api/v1/rules/search" \
-G \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "query=(not%20(eq%20%24.name%20%22%22))&page=$page")
echo "$response" | jq -r '.data'
local rules=$(echo "$response" | jq -r '.data.rules')
if [[ "$rules" == "[]" ]]; then
break
fi
page=$((page + 1))
done
}
# upsert_raw <type> <directory>
# can only upsert raw rules service object from yaml files
upsert_raw() {
local type=$1
shift 1
# List all yaml files in the provided directory, 1 level deep
local files=$(find "$1" -maxdepth 1 -type f -name '*.yaml' | sort)
# Loop through each file
for file in $files; do
echo "Upserting $file"
# if rule contains "delete-after" annotation then check the date and if it is in the past and ignore the rule
if yq -e '.annotations["delete-after"]' "$file" > /dev/null 2>&1; then
delete_after=$(yq -e '.annotations["delete-after"]' "$file")
if [[ "$(date +%Y-%m-%d)" > "$delete_after" ]]; then
echo -e "\tIgnoring $file because it is in the past ($delete_after)"
continue
fi
fi
# convert to json
json=$(yq -o=json "$file")
# Because updates are more common we try to update first, then fall back to create
local response=$(curl -w "%{http_code}" -X PUT "$RULE_SERVICE_URL/api/v1/$type/update" \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "$json" -o /dev/null 2>/dev/null)
if [[ "$response" -ne 200 ]]; then
echo -e "\tcouldn't update, trying create (response: $response)"
response=$(curl -w "%{http_code}" -X POST "$RULE_SERVICE_URL/api/v1/$type/create" \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "$json" -o /dev/null 2>/dev/null)
if [[ "$response" -ne 200 ]]; then
echo -e "\tFailed to create (response: $response)"
exit 1
fi
fi
echo -e "\tSuccessfully upserted $type $file"
done
# recurse
local dirs=$(find "$1" -mindepth 1 -maxdepth 1 -type d | sort)
for dir in $dirs; do
upsert_raw "$type" "$dir"
done
}
# delete_raw <type> <directory>
# can only delete raw rules service object from yaml files
# if the `delete-after` annotation is in the past
delete_raw() {
local type=$1
shift 1
echo "Deleting $type"
local glob="*.yaml"
if [[ "$type" == "rules" ]]; then
glob="*.orl"
fi
local files=$(find "$1" -mindepth 1 -maxdepth 1 -type f,l -name "$glob" | sort)
# Loop through each file
for file in $files; do
echo "Processing $file"
# if rule contains "delete-after" annotation then check the date and if it is in the past and ignore the rule
delete_after=$(yq -e '.metadata.annotations["delete-after"]' "$file" 2>/dev/null)
if [[ "$delete_after" == "null" || "$delete_after" == "" ]]; then
echo "No delete-after annotation found in $file, skipping"
continue
fi
if [[ "$delete_after" > "$(date +%Y-%m-%d)" ]]; then
echo "Ignoring $file because it should not be deleted until $delete_after"
continue
fi
local name=$(yq -e '.metadata.name' "$file" 2>/dev/null)
echo "Name: '$name'"
local response=$(curl -w "%{http_code}" "$RULE_SERVICE_URL/api/v1/$type/delete" \
-X DELETE \
-G \
-H "Authorization: Bearer $RULE_SERVICE_TOKEN" \
--data-urlencode "name=$name" -o /dev/null 2>/dev/null)
if [[ "$response" -ne 200 && "$response" -ne 404 ]]; then
echo -e "\tFailed to delete $name in $file ($response)"
exit 1
fi
echo -e "\tSuccessfully deleted $type $name in $file"
done
}
main() {
local command=$1
local type=$2
shift 2
case "${command} ${type}" in
"delete channels")
delete_raw "channels" "$@"
;;
"delete classifications")
delete_raw "classifications" "$@"
;;
"delete rules")
delete_raw "rules" "$@"
;;
"list classifications")
list_classifications "$@"
;;
"list channels")
list_channels "$@"
;;
"list rules")
list_rules "$@"
;;
"upsert channels")
upsert_raw "channels" "$@"
;;
"upsert classifications")
upsert_raw "classifications" "$@"
;;
*)
echo "Invalid command: ${command} ${type}"
echo "Usage: $0 <command> <type> [<args>...]"
echo "Valid commands:"
echo " delete channels <path of channel yamls>"
echo " delete classifications <path of classification yamls>"
echo " delete rules <path of rule yamls>"
echo " list classifications"
echo " list channels"
echo " list rules"
echo " upsert channels <path of channel yamls>"
echo " upsert classifications <path of classification yamls>"
echo
echo "NOTE: delete and upsert check for the delete-after annotation in the yaml file"
echo "upsert will not update an item past the delete-after date"
echo "delete will only delete items if the delete-after date is in the past"
exit 1
;;
esac
}
main "$@"Last updated