#!/bin/bash # # Version: @(#)oci-api.bash 1.0.4 29.11.2021 (c)2021 Oracle # # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or # Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. # # Origin: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/signingrequests.htm#Bash # Doku: https://docs.cloud.oracle.com/de-de/iaas/Content/API/Concepts/usingapi.htm # API Reference: https://docs.cloud.oracle.com/en-us/iaas/api/ # # Version: 1.0.4 # Usage: # oci-curl [file-to-send-as-body] [extra-curl-args] # # Preset: # # export TENANCY_ID=`browse-json oci/tenancyid --filename ~/.oci/config.json` # export API_USER_ID=`browse-json keys/userid --filename ~/.oci/config.json` # export API_USER=`browse-json keys/username --filename ~/.oci/config.json` # export KEY_FINGERPRINT=`browse-json keys/fingerprint --filename ~/.oci/config.json` # export PRIVATE_KEY_PATH=`browse-json keys/privkey --filename ~/.oci/config.json` # export PRIVATE_KEY_PATH=$(eval echo ${PRIVATE_KEY_PATH}) # # If private key is encrypted, a file "~/.oci/api-passwd" with the password in the first line is expected - # otherwise you are prompted for the passphrase. # # Examples: # # Get all instance data: curl -L -sS http://169.254.169.254/opc/v1/instance # Get all instance vnics: curl -L -sS http://169.254.169.254/opc/v1/vnics # Get all instance certificates: curl -L -sS http://169.254.169.254/opc/v1/identity # # Get instance internal ip: curl -sS http://169.254.169.254/opc/v1/vnics/0/privateIp # Get instance metadata: curl -L -sS http://169.254.169.254/opc/v1/instance/metadata # Get instance metadata: curl -L -sS http://169.254.169.254/openstack/latest/meta_data.json # # region=`curl -sS http://169.254.169.254/opc/v1/instance/region` # Get region from instance # iid=`curl -sS http://169.254.169.254/opc/v1/instance/id` # Get the instanceId from instance # cid=`curl -sS http://169.254.169.254/opc/v1/instance/compartmentId` # Get the compartmentId from instance # # Write certificates from instance to file: # curl -sS http://169.254.169.254/opc/v1/identity/cert.pem -o cert.pem # curl -sS http://169.254.169.254/opc/v1/identity/key.pem -o key.pem # curl -sS http://169.254.169.254/opc/v1/identity/intermediate.pem -o intermediate.pem # cat cert.pem intermediate.pem > chain.pem # # curl -v --insecure --cert /home/opc/bin/cert.pem --key /home/opc/bin/key.pem -X GET "https://iaas.${region}.oraclecloud.com/20160918/instances/$iid" # # List compartments # oci-api.bash identity.${HOME_REGION}.oraclecloud.com get "/20160918/compartments/?compartmentId=$TENANCY_ID" # # List all instances in compartment # oci-api iaas.eu-frankfurt-1.oraclecloud.com get "/20160918/instances?compartmentId=$cid" | convert-json --output json # # List single instance # oci-api iaas.${region}.oraclecloud.com get "/20160918/instances/$iid" | jq -M . # # List volume attachment # oci-api iaas.eu-frankfurt-1.oraclecloud.com get "/20160918/volumeAttachments?compartmentId=$cid" | jq -M . # oci-api iaas.eu-frankfurt-1.oraclecloud.com get "/20160918/volumeAttachments?compartmentId=$cid&instanceId=$iid" | jq -M . # # oci-api iaas.eu-frankfurt-1.oraclecloud.com post ./request.json "/20160918/vcns" # # Using oci cli instead: # # set -e # # if [[ -z "$COMPARTMENT_ID" ]];then # echo "COMPARTMENT_ID must be defined in the environment. " # exit 1 # fi # # USER_NAME="TestUser" # USER_DESCRIPTION="User created by raw request" # TARGET_URI='https://identity.us-phoenix-1.oraclecloud.com/20160918/users/' # HTTP_METHOD='POST' # PROFILE='ADMIN' # REQUEST_BODY="{\"compartmentId\": \"$COMPARTMENT_ID\", \"name\": \"$USER_NAME\", \"description\": \"$USER_DESCRIPTION\"}" # # echo "oci raw-request --profile ${PROFILE} --target-uri ${TARGET_URI} --http-method ${HTTP_METHOD} --request-body "${REQUEST_BODY}" | jq -r '.data.id'" # USER_OCID=$(oci raw-request --profile ${PROFILE} --target-uri ${TARGET_URI} --http-method ${HTTP_METHOD} --request-body "${REQUEST_BODY}" | jq -r '.data.id') # # echo "Created user OCID: $USER_OCID" function oci-curl { local alg=rsa-sha256 local sigVersion="1" local now="$(LC_ALL=C \date -u "+%a, %d %h %Y %H:%M:%S GMT")" local host=$1 local method=$2 local extra_args local keyId="$TENANCY_ID/$API_USER_ID/$KEY_FINGERPRINT" local sel="" local npg="" local qm="" case $method in "get" | "GET") local target=$3 extra_args=("${@: 4}") local curl_method="GET"; local request_method="get"; ;; "delete" | "DELETE") local target=$3 extra_args=("${@: 4}") local curl_method="DELETE"; local request_method="delete"; ;; "head" | "HEAD") local target=$3 extra_args=("--head" "${@: 4}") local curl_method="HEAD"; local request_method="head"; ;; "post" | "POST") local body=$3 local target=$4 extra_args=("${@: 5}") local curl_method="POST"; local request_method="post"; local content_sha256="$(openssl dgst -binary -sha256 < $body | openssl enc -e -base64)"; local content_type="application/json"; local content_length="$(wc -c < $body | xargs)"; ;; "put" | "PUT") local body=$3 local target=$4 extra_args=("${@: 5}") local curl_method="PUT" local request_method="put" local content_sha256="$(openssl dgst -binary -sha256 < $body | openssl enc -e -base64)"; local content_type="application/json"; local content_length="$(wc -c < $body | xargs)"; ;; *) echo "invalid method"; return;; esac # Append page selector to target if nescessary if [ "$np" != "" -o "$ns" != "" ]; then if [ $objects -eq 0 ]; then sel="page" npg="$np" else sel="start" npg="$ns" fi qm=`echo "$target" | grep '?'` if [ "$qm" = "" ]; then target="${target}?${sel}=$npg" else target="${target}&${sel}=$npg" fi fi # This line will url encode all special characters in the request target except "/", "?", "=", and "&", since those characters are used # in the request target to indicate path and query string structure. If you need to encode any of "/", "?", "=", or "&", such as when # used as part of a path value or query string key or value, you will need to do that yourself in the request target you pass in. local escaped_target="$(echo $( rawurlencode "$target" ))" local request_target="(request-target): $request_method $escaped_target" local date_header="date: $now" local host_header="host: $host" local content_sha256_header="x-content-sha256: $content_sha256" local content_type_header="content-type: $content_type" local content_length_header="content-length: $content_length" local signing_string="$request_target\n$date_header\n$host_header" local headers="(request-target) date host" local curl_header_args curl_header_args=(-H "$date_header") local body_arg body_arg=() if [ "$curl_method" = "PUT" -o "$curl_method" = "POST" ]; then signing_string="$signing_string\n$content_sha256_header\n$content_type_header\n$content_length_header" headers=$headers" x-content-sha256 content-type content-length" curl_header_args=("${curl_header_args[@]}" -H "$content_sha256_header" -H "$content_type_header" -H "$content_length_header") body_arg=(--data-binary @${body}) fi # Check if we need a passphrase to encrypt if [ ! -f "${HOME}/.oci/api-passwd" ]; then local sig=$(printf '%b' "$signing_string" | \ openssl dgst -sha256 -sign $PRIVATE_KEY_PATH | \ openssl enc -e -base64 | tr -d '\n') else local sig=$(printf '%b' "$signing_string" | \ openssl dgst -sha256 -passin "file:${HOME}/.oci/api-passwd" -sign $PRIVATE_KEY_PATH | \ openssl enc -e -base64 | tr -d '\n') fi # curl -sS http://169.254.169.254/opc/v1/identity/cert.pem -o cert.pem # curl -sS http://169.254.169.254/opc/v1/identity/intermediate.pem -o intermediate.pem # curl -sS http://169.254.169.254/opc/v1/identity/key.pem -o key.pem # cat cert.pem intermediate.pem > chain.pem # openssl crl2pkcs7 -nocrl -certfile chain.pem | openssl pkcs7 -print_certs -noout # # curl "${extra_args[@]}" "${body_arg[@]}" -X $curl_method -sS https://${host}${escaped_target} "${curl_header_args[@]}" \ # --insecure --cert ./cert.pem curl "${extra_args[@]}" "${body_arg[@]}" -X $curl_method -sS https://${host}${escaped_target} "${curl_header_args[@]}" \ -H "Authorization: Signature version=\"$sigVersion\",keyId=\"$keyId\",algorithm=\"$alg\",headers=\"${headers}\",signature=\"$sig\"" # -H "Authorization: Bearer " } # url encode all special characters except "/", "?", "=", and "&" function rawurlencode { local string="${1}" local strlen=${#string} local encoded="" local pos c o for (( pos=0 ; pos $scratchfile exitcode=$? # cat ${scratchfile}.head # Check if curl succeeded and output is valid JSON if [ $exitcode -eq 0 ]; then checkfiles exitcode=$? if [ $exitcode -eq 0 ]; then # We had a result if [ $objects -gt 0 ]; then cat $scratchfile | jq -M .objects > ${scratchfile}.out else mv -f $scratchfile ${scratchfile}.out fi # We have more than one page while [ "$np" != "" -o "$ns" != "" ]; do oci-curl $* --connect-timeout 10 --max-time 60 --retry 3 --retry-delay 5 -D ${scratchfile}.head | norm-json --quiet > $scratchfile exitcode=$? # cat ${scratchfile}.head if [ $exitcode -eq 0 ]; then checkfiles exitcode=$? else np="" ns="" fi if [ $exitcode -eq 0 ]; then # Concatenate both files if [ $objects -gt 0 ]; then cat $scratchfile | jq -M .objects > ${scratchfile}.pre else mv -f $scratchfile ${scratchfile}.pre fi # Concatenate both files jq --slurp add ${scratchfile}.out ${scratchfile}.pre > $scratchfile mv -f $scratchfile ${scratchfile}.out fi done # Return selected data cat ${scratchfile}.out fi fi # Cleanup filecheck -rm ${scratchfile}.head filecheck -rm ${scratchfile}.pre filecheck -rm ${scratchfile}.out filecheck -rm $scratchfile # Exit with error code exit $exitcode