diff --git a/.gitignore b/.gitignore index 020d6ca..94c1de1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Configuration files with sensitive data -rbk_api.conf +rsc.json # Log files *.log diff --git a/README.md b/README.md index 58ac24d..d05ea15 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,22 @@ The `rsc_clone.sh` script performs Oracle database clone operations using the Ru - Source Oracle database protected by Rubrik - Target Oracle host configured and registered in RSC - Required configuration files: - - `rbk_api.conf` - RSC API credentials + - `rsc.json` - RSC API credentials - Oracle cloning options file ## Configuration -### RSC API Configuration (`rbk_api.conf`) +### RSC API Configuration (`rsc.json`) -Create a configuration file with your RSC credentials: +Download the JSON configuration file from RSC: -```bash -# Rubrik Security Cloud (RSC) Configuration -RSC_HOST=your-organization.my.rubrik.com -RSC_ID="client|your-client-id-here" -RSC_SECRET=your-secret-key-here +```json +{ + "client_id": "client|your-client-id-here", + "client_secret": "your-client-secret-here", + "name": "Your RSC Service Account Name", + "access_token_uri": "https://your-organization.my.rubrik.com/api/client_token" +} ``` ### Oracle Cloning Options File @@ -179,7 +181,7 @@ The script includes comprehensive error handling for: ## Dependencies - `rsc_ops.sh` - RSC API operations and utility functions -- `rbk_api.conf` - RSC credentials configuration +- `rsc.json` - RSC credentials configuration - `jq` - JSON processing - `curl` - HTTP requests - `date`/`gdate` - Date/time operations diff --git a/oracle_funcs.sh b/oracle_funcs.sh deleted file mode 100755 index 0b3468e..0000000 --- a/oracle_funcs.sh +++ /dev/null @@ -1,247 +0,0 @@ -#!/bin/bash -# -#-------------------------------------------------------------------------------------------------------- -# Oracle shell script support functions -# v0.2 - James Pattinson - August 2021 -# v0.3 - U701053 - 30.03.2022 - if database not found, try to search with the ENDPOINT datagurad -# v0.4 - James Pattinson 25/01/23 - Adding support for Service Accounts -#-------------------------------------------------------------------------------------------------------- - -MYDIR="$(dirname "$(realpath "$0")")" -source $MYDIR/rbk_api.conf - -# -- Mobi config --------- -#RBK_ENV=$OUTI/shell/rubrik/conf/rbk_env -# -- End Mobi config ---- - -# -- Mobi config ----------- -#if [ -f "${RBK_ENV}" ] ; then -# source ${RBK_ENV} -#else -# echo "The ${RBK_ENV} file is not found ...." -# exit_with_error -#fi -# -- End Mobi config ------- - -nowait=0 - -if [[ "$OSTYPE" == "darwin"* ]]; then - DATE=gdate -else - DATE=date -fi - -exit_with_error () { - rm -f /tmp/rbkresponse.$$ - echo Aborting Script! - exit 1 -} - -# for canceled status -exit_with_cancel () { - rm -f /tmp/rbkresponse.$$ - echo Canceling Script! - exit 1 -} - -# for undoing status -exit_with_undoing () { - rm -f /tmp/rbkresponse.$$ - echo undoing Script! - exit 1 -} - -check_http_error () { - # All good responses start with a 2 - if [ ${http_response:0:1} != "2" ]; then - echo FATAL: HTTP error from API call: $http_response. The server responded with: - cat /tmp/rbkresponse.$$ ; echo ; exit_with_error - fi -} - -# Given RBK_SID return $db_id of matching database -find_database () { - - # First get IDs of all the mounted DBs for this SID - ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount" - rest_api_get - - cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.mountedDatabaseId!=null and .mountedDatabaseName==$SID) | .mountedDatabaseId' > /tmp/mountedDBs.$$ - - # Now get a list of Oracle DBs - ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID" - rest_api_get - - # If no dtaabse is found, try with dataguard - if [ `cat /tmp/rbkresponse.$$ | grep "id\":" | wc -l` -eq 0 ]; then - echo " DB not found, try with dataguard..." - ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?is_data_guard_group=true&is_relic=false&name=$RBK_SID" - rest_api_get - fi - -#echo "=================================" -#cat /tmp/rbkresponse.$$ | jq -r '.data[]' | tee /tmp/titi -#echo "=================================" -#echo "cat /tmp/rbkresponse.$$ | jq -r '.data[]'" - - - # If no host is specified then just look for the DB with the right SID - if [ -z $RBK_HOST ]; then - - # get list of DB IDs in scope (sid matches and not a relic) - myDBs=$(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .id' ; cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .dataGuardGroupId' | sort | uniq) - - for db in $myDBs; do - id=$(echo $db | cut -d: -f 4) - if grep -q $id /tmp/mountedDBs.$$; then - continue - else - break - fi - done - - # Get the details for the specific DB ID - read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) - - # Host was specified - else - read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" --arg HOST "$RBK_HOST" '.data[] | select(.sid==$SID and .infraPath[0].name==$HOST and .isRelic==false) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) - fi - - if [ "$dg_type" == "DataGuardMember" ]; then - db_id=$dg_id - # Now find SLA of the DG GROUP not just the DB (which will be unprotected) - ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" - rest_api_get - sla_id=$(cat /tmp/rbkresponse.$$ | jq -r '.effectiveSlaDomainId') - fi - - if [ -z "$db_id" ]; then - echo FATAL: No DB found with SID $RBK_SID on host $RBK_HOST - if [ "${SCRIPT}" = "check_recoverable_range.sh" ] ; then - export ret=11 - else - exit_with_error - fi - else - echo " db_id is: $db_id" - fi -} - -check_get_token () { - - if [ -z "${AUTH_TOKEN}" ]; then - - if [[ "${ID}" =~ ^client ]]; then - # Looks like an RSC service account - id_string=$(echo $ID | cut -d\| -f 2) - else - # Not an RSC service account - id_string=$(echo $ID | cut -d: -f 4) - fi - - # If there is a cached credential file, use it - if [ -f ~/.rbksession.$id_string ]; then - read expiration token < <(echo $(cat ~/.rbksession.$id_string)) - # If token expires within 30 min, get a new one - if [ $($DATE +%s -d $expiration) -lt $(( $($DATE +%s) + 1800 )) ]; then - get_token - else - AUTH_TOKEN=$token - fi - else - get_token - fi - fi -} - -get_token () { - - MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session" - MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}" - - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d $MYPAYLOAD) - check_http_error - - AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.token') - SESSION=$(cat /tmp/rbkresponse.$$ | jq -r '.sessionId') - EXPIRATION=$(cat /tmp/rbkresponse.$$ | jq -r '.expirationTime') - echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string - -} - -# HTTP GET: Given $ENDPOINT write output to file -rest_api_get () { - check_get_token - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") - check_http_error -} - -# HTTP POST: Given $ENDPOINT and $PAYLOAD write output to file -rest_api_post () { - check_get_token - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) - check_http_error -} - -rest_api_post_empty () { - check_get_token - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json") - check_http_error -} - -rest_api_patch () { - check_get_token - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X PATCH $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) - check_http_error -} - -rest_api_delete () { - check_get_token - http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X DELETE $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") - check_http_error -} - -get_cluster_uuid () { - ENDPOINT="https://$RUBRIK_IP/api/v1/cluster/me" - rest_api_get - cluster_uuid=$(cat /tmp/rbkresponse.$$ | jq -r .id) -} - -# Given an ENDPOINT of an async job, monitor it -check_status () { - if [ $nowait -ne 1 ]; then - # Check the status in a loop - while true; do - rest_api_get - status=$(cat /tmp/rbkresponse.$$ | jq -r '.status') - if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ] && [ $status != "CANCELED" ] && [ $status != "UNDOING" ]; then - echo Status is $status, checking in 30 seconds - else - if [ $status != "SUCCEEDED" ]; then - - if [ $status = "CANCELED" ] ; then - echo OPERATION FAILED WITH STATUS $status - exit_with_cancel - elif [ $status = "UNDOING" ] ; then - echo OPERATION FAILED WITH STATUS $status - exit_with_undoing - else - echo OPERATION FAILED WITH STATUS $status - exit_with_error - fi - else - echo OPERATION SUCCEEDED - exit 0 - fi - fi - sleep 30 - done - fi -} - -cleanup () { - rm -f /tmp/mountedDBs.$$ - rm -f /tmp/rbkresponse.$$ - rm -f /tmp/payload.$$ -} diff --git a/rbk_api.conf b/rbk_api.conf old mode 100755 new mode 100644 index 883d2d6..0c87c57 --- a/rbk_api.conf +++ b/rbk_api.conf @@ -1,5 +1,3 @@ -# IP Address (or DNS name) of Rubrik CDM -RUBRIK_IP=192.168.10.76 RSC_HOST=rubrik-rbkpso20.my.rubrik.com RSC_ID="client|673af632-150d-47e0-908e-66a6d71fe621" diff --git a/rbk_api.conf.example b/rbk_api.conf.example deleted file mode 100644 index a60e39f..0000000 --- a/rbk_api.conf.example +++ /dev/null @@ -1,7 +0,0 @@ -# Example Rubrik API Configuration File -# Copy this file to rbk_api.conf and fill in your actual values - -# Rubrik Security Cloud (RSC) Configuration -RSC_HOST=your-organization.my.rubrik.com -RSC_ID="client|your-client-id-here" -RSC_SECRET=your-secret-key-here \ No newline at end of file diff --git a/rsc.json.example b/rsc.json.example new file mode 100644 index 0000000..a6a639a --- /dev/null +++ b/rsc.json.example @@ -0,0 +1,6 @@ +{ + "client_id": "client|your-client-id-here", + "client_secret": "your-client-secret-here", + "name": "Your RSC Service Account Name", + "access_token_uri": "https://your-organization.my.rubrik.com/api/client_token" +} \ No newline at end of file diff --git a/rsc_ops.sh b/rsc_ops.sh index c981ff6..0c66814 100755 --- a/rsc_ops.sh +++ b/rsc_ops.sh @@ -8,7 +8,16 @@ #-------------------------------------------------------------------------------------------------------- MYDIR="$(dirname "$(realpath "$0")")" -source $MYDIR/rbk_api.conf + +# Load RSC configuration from rsc.json +if [ -f "$MYDIR/rsc.json" ]; then + RSC_ID=$(jq -r '.client_id' "$MYDIR/rsc.json") + RSC_SECRET=$(jq -r '.client_secret' "$MYDIR/rsc.json") + RSC_HOST=$(jq -r '.access_token_uri' "$MYDIR/rsc.json" | sed 's|https://||' | sed 's|/api/client_token||') +else + echo "ERROR: rsc.json configuration file not found" + exit 1 +fi # Set DATE command based on OS if [[ "$OSTYPE" == "darwin"* ]]; then