#!/bin/bash ################# FUNCTION TO DISPLAY HELP show_help() { echo "Usage: oci.sh [OPTION]" echo "Options:" echo " -lu List all users in the tenancy" echo " -lc List all compartments in the tenancy" echo " -lr List all running instances in the tenancy" echo " -la List and parse audit events for a specific user (filtered by email)///ONLY WORKS FOR OWN DATA" echo " --usage Display usage and cost summary for the current month" echo " -h Show this help message" } SEP="echo -------------------------------" activate_venv() { $SEP echo "Activating oci-cli venv..." source $HOME/oci-cli/oci/bin/activate sleep 0.5 $SEP } test_connection() { echo "Testing Oci Connection...." $SEP oci iam region list > /dev/null STATUS=$? if [[ $STATUS -eq 0 ]]; then echo "Test connection to oci completed succesfully!" else echo "Something went wrong, check oci-cli config file" exit 1 fi } ################# LIST ALL USERS IN TENANCY list_users_lite() { TENANCY_ID=$(oci iam compartment list --query 'data[0]."compartment-id"' --raw-output) echo "Listing users in tenancy: $TENANCY_ID" $SEP oci iam user list --compartment-id $TENANCY_ID | grep email | awk -F '"' '{print $4}' | grep -v '^$' | paste -sd ',' - $SEP } ################# LIST ALL COMPARTMENTS IN TENANCY list_compartments() { echo "Listing all compartments in the tenancy" $SEP #////////////////TABLE HEADER\\\\\\\\\\\\\\\######### printf " %-25s | %-12s | %-25s | %-s\n" "Name" "State" "Created By" "Description" echo "$(printf '%.0s-' {1..130})" #////////////FETCH AND JQ PARSE\\\\\\\\\\\\\\\# oci iam compartment list --all --compartment-id-in-subtree true 2>/dev/null | \ jq -r '.data[] | [ (.name // ""), (.["lifecycle-state"] // ""), (.["defined-tags"]["Oracle-Tags"]["CreatedBy"] // "" | split("/")[1] // ""), (.description // "") ] | @tsv' | \ awk -F'\t' '{printf " %-25s | %-12s | %-25s | %s\n", $1, $2, $3, $4}' $SEP } ################# LIST ALL RUNNING INSTANCES IN TENANCY list_running_instances() { echo "Listing all running instances in the tenancy" $SEP #////////////FETCH ROOT TENANCY ID FROM CONFIG\\\\\\\\\\\\\\\# TENANCY_ID=$(grep "^tenancy=" "$HOME/.oci/config" | cut -d'=' -f2) #////////////LIST INSTANCES FROM ROOT TENANCY\\\\\\\\\\\\\\\# echo "[ROOT TENANCY]" oci compute instance list --compartment-id "$TENANCY_ID" --lifecycle-state RUNNING \ --query "data[*].{Name:\"display-name\", State:\"lifecycle-state\", Shape:shape, CreatedBy:\"defined-tags\".\"Oracle-Tags\".\"CreatedBy\", CreatedOn:\"defined-tags\".\"Oracle-Tags\".\"CreatedOn\", OCID:id}" \ --output table 2>/dev/null #////////////FETCH ALL COMPARTMENTS AND LIST INSTANCES\\\\\\\\\\\\\\\# oci iam compartment list --all --compartment-id-in-subtree true 2>/dev/null | \ jq -r '.data[] | "\(.id)|\(.name)|\(.description // "")|\(.["defined-tags"]["Oracle-Tags"]["CreatedBy"] // "")|\(.["defined-tags"]["Oracle-Tags"]["CreatedOn"] // "")"' | while IFS='|' read -r COMPARTMENT_ID COMPARTMENT_NAME DESCRIPTION CREATEDBY CREATEDON; do echo "" printf "┌─ [%s]\n" "$COMPARTMENT_NAME" printf "│ ID: %s\n" "$COMPARTMENT_ID" printf "│ Description: %s\n" "$DESCRIPTION" printf "│ Created By: %s | Created On: %s\n" "$CREATEDBY" "$CREATEDON" printf "└─ Instances:\n" oci compute instance list --compartment-id "$COMPARTMENT_ID" --lifecycle-state RUNNING \ --query "data[*].{Name:\"display-name\", State:\"lifecycle-state\", Shape:shape, CreatedBy:\"defined-tags\".\"Oracle-Tags\".\"CreatedBy\", CreatedOn:\"defined-tags\".\"Oracle-Tags\".\"CreatedOn\", OCID:id}" \ --output table 2>/dev/null done $SEP } ################# LIST AUDIT EVENTS FOR USER list_audit_events() { TENANCY_ID=$(oci iam compartment list --query 'data[0]."compartment-id"' --raw-output) echo "Enter email to search audit events:" read -p "Email: " USER_EMAIL ##### SELECT TIME RANGE echo "Select time range:" echo "1) This day" echo "2) Last 3 days" echo "3) Last 10 days" echo "4) Last month" echo "5) Last 90 days" read -p "Option (1-5): " TIME_OPTION ##### SET TIME RANGE BASED ON SELECTION case "$TIME_OPTION" in 1) START_TIME=$(date -u -d '1 day ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; 2) START_TIME=$(date -u -d '3 days ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; 3) START_TIME=$(date -u -d '10 days ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; 4) START_TIME=$(date -u -d '1 month ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; 5) START_TIME=$(date -u -d '90 days ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; *) echo "Invalid option. Using last 90 days." START_TIME=$(date -u -d '90 days ago' +"%Y-%m-%dT%H:%M:%S.000Z") ;; esac END_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") echo "Listing audit events for user: $USER_EMAIL" $SEP echo "Fetching audit events (this may take a moment)..." ################## FETCH AND PARSE AUDIT EVENTS //// WILL ONLY DISPLAY DATA OF USER MATCHING THE FINGERPRINT IN OCI-CLI CONFIG FILE (OWN DATA) echo " Timestamp | Event | Service | Action | Status | Description | User | IP Address " echo "$(printf '%.0s-' {1..130})" timeout 120 oci audit event list \ --compartment-id $TENANCY_ID \ --start-time "$START_TIME" \ --end-time "$END_TIME" \ --all 2>/dev/null | \ jq --arg email "$USER_EMAIL" \ '.data | map(select( ((.data."defined-tags"."Oracle-Tags"."CreatedBy" // "") | contains($email)) or ((.data.identity."principal-name" // "") | contains($email)) or ((.data."compartment-name" // "") | contains($email)) )) | .[] | { "Time": (."event-time" | split("+")[0] | split(".")[0]), "Event": .data."event-name", "Source": .source, "Action": .data.request.action, "Status": .data.response.status, "Message": .data.response.message, "Principal": .data.identity."principal-name", "IP": .data.identity."ip-address" }' \ 2>/dev/null | \ jq -r '[.Time, .Event, .Source, .Action, .Status, .Message, .Principal, .IP] | @tsv' | \ column -t -s $'\t' || echo "No audit events found for: $USER_EMAIL" $SEP echo "Audit events retrieval completed for: $USER_EMAIL" } ################# DISPLAY USAGE AND COST SUMMARY list_usage_summary() { echo "Select time window for usage report:" echo "1) Last 7 days" echo "2) Last month (30 days)" echo "3) Last 3 months (90 days)" echo "4) Last 6 months (180 days)" echo "5) Last 9 months (270 days)" echo "6) Custom date range" read -p "Option (1-6): " TIME_OPTION $SEP echo "Select grouping:" echo "1) By compartment only" echo "2) By compartment and service" read -p "Option (1-2): " GROUP_OPTION $SEP echo "Displaying usage and cost summary" $SEP #////////////FETCH TENANCY ID FROM CONFIG\\\\\\\\\\\\\\\# TENANCY_ID=$(grep "^tenancy=" "$HOME/.oci/config" | cut -d'=' -f2) #////////////CALCULATE TIME RANGE BASED ON SELECTION\\\\\\\\\\\\\\\# case "$TIME_OPTION" in 1) TIME_STARTED=$(date -u -d '7 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; 2) TIME_STARTED=$(date -u -d '30 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; 3) TIME_STARTED=$(date -u -d '90 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; 4) TIME_STARTED=$(date -u -d '180 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; 5) TIME_STARTED=$(date -u -d '270 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; 6) read -p "Start date (YYYY-MM-DD): " START_DATE read -p "End date (YYYY-MM-DD): " END_DATE TIME_STARTED="${START_DATE}T00:00:00Z" TIME_ENDED="${END_DATE}T00:00:00Z" ;; *) echo "Invalid option. Using last 7 days." TIME_STARTED=$(date -u -d '7 days ago' '+%Y-%m-%dT00:00:00Z') TIME_ENDED=$(date -u '+%Y-%m-%dT00:00:00Z') ;; esac #////////////SET GROUP-BY PARAMETER BASED ON SELECTION\\\\\\\\\\\\\\\# TEMP_FILE=$(mktemp) if [[ "$GROUP_OPTION" == "2" ]]; then GROUP_BY='["compartmentName","service"]' printf "%-25s | %-15s | %-25s | %-20s | %-s\n" "Compartment" "Date" "Service" "Cost (EUR)" "Usage" echo "$(printf '%.0s-' {1..110})" oci usage-api usage-summary request-summarized-usages \ --tenant-id "$TENANCY_ID" \ --time-usage-started "$TIME_STARTED" \ --time-usage-ended "$TIME_ENDED" \ --granularity DAILY \ --query-type COST \ --group-by "$GROUP_BY" \ --compartment-depth 7 \ --output json 2>/dev/null | \ jq -r '.data.items[] | [."compartment-name", ."time-usage-started"[0:10], (."service" // "N/A"), (."computed-amount" | tostring | split(".")[0] + "." + (split(".")[1][0:2] // "00")), ."computed-quantity"] | @tsv' | \ sort -k2 -rn | \ while IFS=$'\t' read -r COMP DATE SERVICE COST USAGE; do printf "%-25s | %-15s | %-25s | %-20s | %-s\n" "$COMP" "$DATE" "$SERVICE" "$COST" "$USAGE" echo "$COMP|$SERVICE|$COST" >> "$TEMP_FILE" done echo "" printf "%-25s | %-25s | %-s\n" "Compartment" "Service" "Total Cost (EUR)" echo "$(printf '%.0s-' {1..60})" awk -F'|' '{key=$1"|"$2; comp_service[key]+=$3} END {for (k in comp_service) {split(k, arr, "|"); printf "%-25s | %-25s | %.2f\n", arr[1], arr[2], comp_service[k]}}' "$TEMP_FILE" | sort else GROUP_BY='["compartmentName"]' printf "%-25s | %-15s | %-20s | %-20s | %-s\n" "Compartment" "Date" "Cost (EUR)" "Service" "Usage" echo "$(printf '%.0s-' {1..100})" oci usage-api usage-summary request-summarized-usages \ --tenant-id "$TENANCY_ID" \ --time-usage-started "$TIME_STARTED" \ --time-usage-ended "$TIME_ENDED" \ --granularity DAILY \ --query-type COST \ --group-by "$GROUP_BY" \ --compartment-depth 7 \ --output json 2>/dev/null | \ jq -r '.data.items[] | [."compartment-name", ."time-usage-started"[0:10], (."computed-amount" | tostring | split(".")[0] + "." + (split(".")[1][0:2] // "00")), (."service" // "N/A"), ."computed-quantity"] | @tsv' | \ sort -k2 -rn | \ while IFS=$'\t' read -r COMP DATE COST SERVICE USAGE; do printf "%-25s | %-15s | %-20s | %-20s | %-s\n" "$COMP" "$DATE" "$COST" "$SERVICE" "$USAGE" echo "$COMP|$COST" >> "$TEMP_FILE" done echo "" printf "%-25s | %-s\n" "Compartment" "Total Cost (EUR)" echo "$(printf '%.0s-' {1..42})" awk -F'|' '{comp[$1]+=$2} END {for (c in comp) printf "%-25s | %.2f\n", c, comp[c]}' "$TEMP_FILE" | sort fi rm -f "$TEMP_FILE" $SEP } ################# MAIN FUNC if [[ $# -eq 0 ]]; then #####ALWAYS ACTIVATE VENV AND TEST CONNECTION TO OCI activate_venv test_connection else case "$1" in -lu) activate_venv test_connection list_users_lite ;; -lc) activate_venv test_connection list_compartments ;; -lr) activate_venv test_connection list_running_instances ;; -la) activate_venv test_connection list_audit_events ;; --usage) activate_venv test_connection list_usage_summary ;; -h|--help) show_help ;; *) echo "Unknown option: $1" show_help exit 1 ;; esac fi