Script File to Validate Network Setup

You must create a script file to validate if the existing WebLogic Server subnet and the database subnets meet the prerequisites to provision the WebLogic instance in Oracle WebLogic Server for OCI.

You can copy the following scripts in Cloud Shell to perform the validation. For example, copy the scripts and save the file as validate.sh.

# ##################################################
# Script to validate existing WebLogic and DB subnets meet the pre-requisite for
# provisioning and proper functioning of WebLogic Server for Oracle Cloud Infrastructure.
#
 
# Set Flags
# -----------------------------------
# Flags which can be overridden by user input.
# Default values are below
# -----------------------------------
DB_PORT=1521
ATP_DB_PORT=1522
SSH_PORT=22
T3_PORT=9071
WLS_LB_PORT=7003
LB_PORT=443
NETWORK_COMPARTMENT_OCID=""
WLS_SUBNET_OCID=""
DB_SUBNET_OCID=""
APP_DB_SUBNET_OCID=""
BASTION_SUBNET_OCID=""
BASTION_HOST_IP_CIDR=""
LB_SUBNET_OCID=""
FSS_SUBNET_OCID=""
 
debug=false
args=()
 
function ip_to_int() {
  local ip_addr="${1}"
  local ip_1 ip_2 ip_3 ip_4
 
  ip_1=$(echo "${ip_addr}" | cut -d'.' -f1)
  ip_2=$(echo "${ip_addr}" | cut -d'.' -f2)
  ip_3=$(echo "${ip_addr}" | cut -d'.' -f3)
  ip_4=$(echo "${ip_addr}" | cut -d'.' -f4)
 
  echo $(( ip_1 * 256**3 + ip_2 * 256**2 + ip_3 * 256 + ip_4 ))
}
 
####################################################
# Determine whether IP address is in the specified subnet.
#
# Args:
#   cidr_subnet: Subnet, in CIDR notation.
#   ip_addr: IP address to check.
#
# Returns:
#   0|1
####################################################
function in_cidr_range() {
  local cidr_subnet="${1}"
  local ip_addr="${2}"
  local subnet_ip cidr_mask netmask ip_addr_subnet subnet rval
 
  subnet_ip=$(echo "${cidr_subnet}" | cut -d'/' -f1)
  cidr_mask=$(echo "${cidr_subnet}" | cut -d'/' -f2)
 
  netmask=$(( 0xFFFFFFFF << $(( 32 - ${cidr_mask} )) ))
 
  # Apply netmask to both the subnet IP and the given IP address
  ip_addr_subnet=$(( netmask & $(ip_to_int ${ip_addr}) ))
  subnet=$(( netmask & $(ip_to_int ${subnet_ip}) ))
 
  # Subnet IPs will match if given IP address is in CIDR subnet
  [ "${ip_addr_subnet}" == "${subnet}" ] && rval=0 || rval=1
 
  return $rval
}
 
####################################################
# Validates if one of service or nat gateways exist in the specified private subnet.
#
# Returns:
#   0|1
####################################################
function validate_service_or_nat_gw_exist() {
  local vcn_ocid=""
  local vcn_compartment_ocid=""
 
  is_private_subnet=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["prohibit-public-ip-on-vnic"]')
 
  if [[ $is_private_subnet = true ]]
  then
    vcn_ocid=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["vcn-id"]')
    vcn_compartment_ocid=$(oci network vcn get --vcn-id ${vcn_ocid} | jq -r '.data["compartment-id"]')
    # Check if NAT gateway exists in the VCN
    res=$(oci network nat-gateway list --compartment-id ${vcn_compartment_ocid} --vcn-id ${vcn_ocid})
    nat_gw_found=$(if [[ -n $res ]]; then echo 0; else echo 1; fi)
 
    # Check if Service gateway exists in the VCN
    res=$(oci network service-gateway list --compartment-id ${vcn_compartment_ocid} --vcn-id ${vcn_ocid})
    svc_gw_found=$(if [[ -n $res ]]; then echo 0; else echo 1; fi)
 
    # One of NAT or Service Gateway must exist
    if [[ $nat_gw_found -ne 0 ]] && [[ $svc_gw_found -ne 0 ]]
    then
      echo 1
      return
    fi
 
    # WLS subnet should be using either NAT or service gateway or both in its routetable
    rt_ocid=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["route-table-id"]')
    rt_rules=$(oci network route-table get --rt-id ${rt_ocid} | jq -r '.data["route-rules"]')
    rt_rules_count=$(echo $rt_rules | jq '.|length')
 
    nat=""
    svc=""
    nat_gw_id=""
    svc_gw_id=""
 
    for ((i = 0 ; i < $rt_rules_count ; i++))
    do
      network_entity_ocid=$(echo $rt_rules | jq -r --arg i "$i" '.[$i|tonumber]["network-entity-id"]')
      nat_id=$(echo $network_entity_ocid | grep natgateway)
      if [[ -n $nat_id ]]; then nat_gw_id=$nat_id; fi
      svc_id=$(echo $network_entity_ocid | grep servicegateway)
      if [[ -n $svc_id ]]; then svc_gw_id=$svc_id; fi
    done
 
    if [[ (-z $nat_gw_id  && -z $svc_gw_id) ]]; then
      echo 2
      return
    fi
 
    # If WLS subnet route table has a rule to use service gateway then it should be using
    # all-<region-code>-services-in-oracle-services-network destination
    if [[ -n $svc_gw_id ]]
    then
      is_all_services_name=$(oci network service-gateway get --service-gateway-id $svc_gw_id | jq -r '.data.services[0]["service-name"]' | grep -i "all.*services in oracle services network")
      if [[ -z $is_all_services_name ]]
      then
        echo 3
        return
      fi
      for ((i = 0 ; i < $rt_rules_count ; i++))
      do
        network_entity_ocid=$(echo $rt_rules | jq -r --arg i "$i" '.[$i|tonumber]["network-entity-id"]')
        res=$(echo $network_entity_ocid | grep servicegateway)
        if [[ -n $res ]]
        then
          all_services_destination=$(echo $rt_rules | jq -r --arg i "$i" '.[$i|tonumber].destination'  | grep -i "all-.*-services-in-oracle-services-network")
          if [[ -z $all_services_destination ]]
          then
            echo 4
            return
          fi
        fi
      done
    fi
  fi
  echo 0
}
 
####################################################
# Validates if the internet gateway exists in the VCN of WLS subnet.
# Without Internet gateway in WLS VCN, SSH access from ORM will not work.
# When using terraform CLI from within private network, internet gateway is not required.
# Hence this check will give a warning and not an error.
#
# Returns:
#   0|1
####################################################
function validate_internet_gw_exist() {
  local vcn_ocid=""
  local vcn_compartment_ocid=""
 
  vcn_ocid=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["vcn-id"]')
  vcn_compartment_ocid=$(oci network vcn get --vcn-id ${vcn_ocid} | jq -r '.data["compartment-id"]')
 
  # Check if Service gateway exists in the VCN
  res=$(oci network internet-gateway list --compartment-id ${vcn_compartment_ocid} --vcn-id ${vcn_ocid})
 
  if [[ -n $res ]]; then
    echo 0
  else
    echo 1
  fi
}
 
####################################################
# Checks if specified port is open to specified source CIDR in the ingress rules of specified seclist or nsg.
#
# Args:
#     seclist_or_nsg_ocid:  OCID for the security list or nsg.
#     port: destination port to check
#     source: Source CIDR (either block/range of IPs or single IP (with /32 suffix)
#     ocid_type: Valid values: "nsg" for Network Security Group OCID, "seclist" for Security List OCID (default)
#
# Returns:
#   0|1
####################################################
function check_tcp_port_open_in_seclist_or_nsg() {
  local seclist_or_nsg_ocid=$1
  local port=$2
  local source=$3
  local ocid_type=$4
  local port_is_open=false
  local tcp_protocol="6"
 
  if [[ $ocid_type = "nsg" ]]; then
      ingress_rules=$(oci network nsg rules list --nsg-id $seclist_or_nsg_ocid | jq -r '.data')
  else
      ingress_rules=$(oci network security-list get --security-list-id $seclist_or_nsg_ocid | jq -r '.data["ingress-security-rules"]')
  fi

  ingress_rules_count=$(echo $ingress_rules | jq '.|length')
 
  for ((i = 0 ; i < $ingress_rules_count ; i++))
  do
    ingress_protocol=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber].protocol')
    ingress_source=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber].source')
    tcp_options=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["tcp-options"]')
    port_min=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["tcp-options"]["destination-port-range"].min')
    port_max=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["tcp-options"]["destination-port-range"].max')
 
    source_in_cidr_range=1
    if [[ $source = "0.0.0.0/0" ]]
    then
      if [[ $ingress_source = $source ]]
      then
        source_in_cidr_range=0
      else
        source_in_cidr_range=1
      fi
    else
      source_in_cidr_range=$(in_cidr_range $ingress_source $source ; echo $?)
    fi
 
    if [[ ($ingress_protocol = "all" || $ingress_protocol = $tcp_protocol ) && ( $tcp_options = "null" || ( $port -ge $port_min && $port -le $port_max ) ) && $source_in_cidr_range -eq 0 ]]
    then
       port_is_open=true
       echo 0
       return
    fi
  done
  echo 1
}

####################################################
# Checks if specified UDP port is open to specified source CIDR in the specified seclist's ingress rules.
#
# Args:
#     seclist_ocid: Security list OCID for the security list to check ingress rules for.
#     port: destination port to check
#     source: Source CIDR (either block/range of IPs or single IP (with /32 suffix)
#
# Returns:
#   0|1
####################################################
function check_udp_port_open_in_seclist() {
  local seclist_ocid=$1
  local port=$2
  local source=$3
  local port_is_open=false
  local udp_protocol="17"

  ingress_rules=$(oci network security-list get --security-list-id $seclist_ocid | jq -r '.data["ingress-security-rules"]')
  ingress_rules_count=$(echo $ingress_rules | jq '.|length')

  for ((i = 0 ; i < $ingress_rules_count ; i++))
  do
    ingress_protocol=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber].protocol')
    ingress_source=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber].source')
    udp_options=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["udp-options"]')
    port_min=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["udp-options"]["destination-port-range"].min')
    port_max=$(echo $ingress_rules | jq -r --arg i "$i" '.[$i|tonumber]["udp-options"]["destination-port-range"].max')

    source_in_cidr_range=1
    if [[ $source = "0.0.0.0/0" ]]
    then
      if [[ $ingress_source = $source ]]
      then
        source_in_cidr_range=0
      else
        source_in_cidr_range=1
      fi
    else
      source_in_cidr_range=$(in_cidr_range $ingress_source $source ; echo $?)
    fi

    if [[ ($ingress_protocol = "all" || $ingress_protocol = $udp_protocol ) && ( $udp_options = "null" || ( $port -ge $port_min && $port -le $port_max ) ) && $source_in_cidr_range -eq 0 ]]
    then
       port_is_open=true
       echo 0
       return
    fi
  done
  echo 1
}

 
####################################################
# Validates if the specified TCP port is open for the WLS subnet CIDR.
#
# Args:
#     port:         Destination port
#     source_cidr:  Source CIDR
#
# Returns:
#   0|1
####################################################
function validate_subnet_port_access() {
  local port_found_open=1
  local subnet=$1
  local port=$2
  local source_cidr=$3
  local protocol=$4 # Default protocol is TCP, if it is UDP then need to pass this param

  sec_lists=$(oci network subnet get --subnet-id ${subnet} | jq -c '.data["security-list-ids"]')
 
  # Convert to bash array
  declare -A seclists_array
 
  while IFS="=" read -r key value
  do
      seclists_array[$key]="$value"
  done < <(jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' <<< "$sec_lists")
 
  # Check the ingress rules for specified destination port is open for access by source CIDR
  for seclist_ocid in "${seclists_array[@]}"
  do
    if [[ $port_found_open -ne 0 ]]; then
      if [[ -z $protocol ]]; then # default is TCP
          port_found_open=$(check_tcp_port_open_in_seclist_or_nsg $seclist_ocid "${port}" "$source_cidr" "seclist")
      else # protocol param is non empty then udp
          port_found_open=$(check_udp_port_open_in_seclist $seclist_ocid "${port}" "$source_cidr")
      fi
    fi
  done
  echo $port_found_open
}

####################################################
# Validates if the ATP_PORT is open for the WLS subnet CIDR.
# This is applicable for ATP with private endpoint only.
# Args:
#     subnet: ATP private endpoint subnet
#     atp_id: ATP OCID to check port access
#     source_cidr: WLS subnet CIDR
#
# Returns:
#   0|1
####################################################
function validate_atp_port_access() {
  local port_found_open=1
  local subnet=$1
  local atp_id=$2
  local source_cidr=$3

  nsg_list=$(oci db autonomous-database get --autonomous-database-id ${atp_id} | jq -c '.data["nsg-ids"]')

  if [[ $nsg_list = "null" ]]; then
      #skip validation if nsg is not present (ATP has no private endpoint)
      port_found_open=0
  else
      # Convert to bash array
      declare -A nsg_list_array

      while IFS="=" read -r key value
      do
          nsg_list_array[$key]="$value"
      done < <(jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' <<< "$nsg_list")

      # Check the NSG ingress rules for specified destination port is open for access by source CIDR
      for nsg_ocid in "${nsg_list_array[@]}"
      do
        if [[ $port_found_open -ne 0 ]]; then
          port_found_open=$(check_tcp_port_open_in_seclist_or_nsg $nsg_ocid "${ATP_DB_PORT}" "$source_cidr" "nsg")
        fi
      done

      if [[ port_found_open -ne 0 ]]; then
          # If ATP port is not opened by NSG ingress rules, check subnet security list
          # doc: "if you choose a subnet with a security list, the security rules for the database
          # will be a union of the rules in the security list and the NSGs."
          port_found_open=$(validate_subnet_port_access ${subnet} ${ATP_DB_PORT} ${source_cidr})
      fi
  fi

  echo $port_found_open
} 

####################################################
# Validates if custom resolver has 169.254.169.254 dns entry for WLS subnet.
# Args:
#     subnet_id:    Subnet Id
#
# Returns:
#   0|1
####################################################
function validate_dhcp_options() {
  local subnet_id=$1
  dhcp_id=$(oci network subnet get --subnet-id ${subnet_id} | jq -r '.data["dhcp-options-id"]')
  resolver_type=$(oci network dhcp-options get --dhcp-id ${dhcp_id} | jq -r '.data["options"][0]["server-type"]')

  if [[ $resolver_type == "CustomDnsServer" ]]; then
    dhcp_options=$(oci network dhcp-options get --dhcp-id ${dhcp_id})
    dns_servers=($(jq -r '.data["options"][0]["custom-dns-servers"]|.[]' <<< "$dhcp_options"))
    for dns_server in "${dns_servers[@]}"
    do
      if [[ $dns_server == '169.254.169.254' ]];then
        echo 0
        return
      fi
    done
  else
    echo 0
    return
  fi
  echo 1
}
 
####################################################
# Validates if CIDR is a valid single host IP (must end with /32 suffix).
#
# Args:
#     ip_cidr: Single host IPv4 Address in CIDR format
#
# Returns:
#   0|1
####################################################
function is_valid_ip_cidr() {
  local ip_cidr=$1
 
  is_valid=$(echo ${ip_cidr} | grep -E '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(32))$')
  if [[ -n $is_valid ]]; then
    echo 0
  else
    echo 1
  fi
}
 
############## Begin Options and Usage ###################
 
# Print usage
usage() {
  echo -n "$0 [OPTIONS]...
 
This script is used to validate existing WebLogic subnet (and optionally DB Subnet) are setup correctly.
 ${bold}Options:${reset}
  -w, --wlssubnet     WebLogic Subnet OCID (Required)
  -d, --ocidbsubnet   OCI Database System Subnet OCID
  -a, --appdbsubnet   Application Database Subnet OCID
  -t, --atpid         ATP DB OCID
  -b, --bastionsubnet Bastion Subnet OCID
  -i, --bastionipcidr Bastion Host IP CIDR (should be suffixed with /32)
  -l, --lbsubnet      LB Subnet OCID
  -f, --fsssubnet     FSS Subnet OCID
      --debug         Runs script in BASH debug mode (set -x)
  -h, --help          Display this help and exit
      --version       Output version information and exit
  "
}
 
# Iterate over options breaking -ab into -a -b when needed and --foo=bar into
# --foo bar
optstring=h
unset options
while (($#)); do
  case $1 in
    # If option is of type -ab
    -[!-]?*)
      # Loop over each character starting with the second
      for ((i=1; i < ${#1}; i++)); do
        c=${1:i:1}
 
        # Add current char to options
        options+=("-$c")
 
        # If option takes a required argument, and it's not the last char make
        # the rest of the string its argument
        if [[ $optstring = *"$c:"* && ${1:i+1} ]]; then
          options+=("${1:i+1}")
          break
        fi
      done
      ;;
 
    # If option is of type --foo=bar
    --?*=*) options+=("${1%%=*}" "${1#*=}") ;;
    # add --endopts for --
    --) options+=(--endopts) ;;
    # Otherwise, nothing special
    *) options+=("$1") ;;
  esac
  shift
done
set -- "${options[@]}"
unset options
 
# Print help if no arguments were passed.
[[ $# -eq 0 ]] && set -- "--help"
 
# Read the options and set stuff
while [[ $1 = -?* ]]; do
  case $1 in
    -h|--help) usage >&2; exit 0 ;;
    --version) echo "$(basename $0) ${version}"; exit 0 ;;
    -w|--wlssubnet) shift; WLS_SUBNET_OCID=${1} ;;
    -d|--ocidbsubnet) shift; DB_SUBNET_OCID=${1} ;;
    -a|--appdbsubnet) shift; APP_DB_SUBNET_OCID=${1} ;;
    -t|--atpid) shift; ATP_OCID=${1} ;;
    -b|--bastionsubnet) shift; BASTION_SUBNET_OCID=${1} ;;
    -i|--bastionipcidr) shift; BASTION_HOST_IP_CIDR=${1} ;;
    -l|--lbsubnet) shift; LB_SUBNET_OCID=${1} ;;
    -f|--fsssubnet) shift; FSS_SUBNET_OCID=${1} ;;
    --debug) debug=true;;
    --endopts) shift; break ;;
    *) "invalid option: '$1'." ; usage >&2; exit 1 ;;
  esac
  shift
done
 
# Store the remaining part as arguments.
args+=("$@")
 
############## End Options and Usage ###################
 
# ############# ############# #############
# ##       MAIN SCRIPT BODY              ##
# ##                                     ##
# ##                                     ##
# ############# ############# #############
 
# Set IFS to preferred implementation
IFS=$'\n\t'
 
# Exit on error. Append '||true' when you run the script if you expect an error.
set -o errexit
 
# Run in debug mode, if set
if ${debug}; then set -x ; fi
 
# Bash will remember & return the highest exitcode in a chain of pipes.
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`, for example.
set -o pipefail
 
# Validate all required params are present
if [[ -z ${WLS_SUBNET_OCID} ]]
then
  echo "One or more required params are not specified."
  usage >&2
  exit
fi
 
# Check if service or NAT gateway exists in WLS subnet's VCN.
res=$(validate_service_or_nat_gw_exist)
 
if [[ $res -eq 1 ]]
then
  echo "ERROR: Missing Service or NAT gateway in the VCN of the private WLS subnet [$WLS_SUBNET_OCID]"
elif [[ $res -eq 2 ]]
then
  echo "ERROR: Private WLS subnet [$WLS_SUBNET_OCID] does not use NAT or Service gateway"
elif [[ $res -eq 3 ]]
then
  echo "ERROR: Service Gateway in VCN of private WLS subnet [$WLS_SUBNET_OCID] does not allow access to all services in Oracle services network"
elif [[ $res -eq 4 ]]
then
  echo "ERROR: Route Rule of private WLS subnet [$WLS_SUBNET_OCID] does not use 'ALL Services in Oracle services network' destination"
fi
 
#Check for custom resolver
res=$(validate_dhcp_options ${WLS_SUBNET_OCID})

if [[ $res -ne 0 ]]
then
  echo "WARNING: Missing OCI dns server [169.254.169.254] in the DNS Servers entries for the custom resolver"
fi

# Check if internet gateway exists in WLS subnet's VCN.
res=$(validate_internet_gw_exist)
 
if [[ $res -ne 0 ]]
then
  echo "WARNING: Missing internet gateway in the VCN of the WLS subnet [$WLS_SUBNET_OCID]"
fi
 
wls_subnet_cidr_block=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["cidr-block"]')
 
# Check if SSH port is open for access by WLS subnet CIDR
res=$(validate_subnet_port_access ${WLS_SUBNET_OCID} ${SSH_PORT} ${wls_subnet_cidr_block})
 
if [[ $res -ne 0 ]]
then
  echo "ERROR: Port ${SSH_PORT} is not open for access by WLS Subnet CIDR [$wls_subnet_cidr_block] in WLS Subnet [$WLS_SUBNET_OCID]"
fi

# Check if t3 port is open for access by WLS subnet CIDR
res=$(validate_subnet_port_access ${WLS_SUBNET_OCID} ${T3_PORT} ${wls_subnet_cidr_block})
if [[ $res -ne 0 ]]
then
  echo "ERROR: Port ${T3_PORT} is not open for access by WLS Subnet CIDR [$wls_subnet_cidr_block] in WLS Subnet [$WLS_SUBNET_OCID]"
fi
 
# Check if DB port is open for access by WLS subnet CIDR in DB subnet (only if DB subnet is provided)
if [[ -n ${DB_SUBNET_OCID} ]]
then
  res=$(validate_subnet_port_access ${DB_SUBNET_OCID} ${DB_PORT} ${wls_subnet_cidr_block})
  if [[ $res -ne 0 ]]
  then
    echo "ERROR: DB port ${DB_PORT} is not open for access by WLS Subnet CIDR [$wls_subnet_cidr_block] in DB Subnet [$DB_SUBNET_OCID]"
  fi
fi
 
# Check if DB port is open for access by WLS subnet CIDR in Application DB subnet (only if Application DB subnet is provided)
if [[ -n ${APP_DB_SUBNET_OCID} ]]
then
  res=$(validate_subnet_port_access ${APP_DB_SUBNET_OCID} ${DB_PORT} ${wls_subnet_cidr_block})
  if [[ $res -ne 0 ]]
  then
    echo "ERROR: DB port ${DB_PORT} is not open for access by WLS Subnet CIDR [$wls_subnet_cidr_block] in Application DB Subnet [$APP_DB_SUBNET_OCID]"
  fi
fi

# Check if port for ATP with private endpoint is open for access by WLS subnet CIDR. The ATP has associated NSG.
# No-op for ATP with no private endpoint (network security group is not present for ATP)
if [[ -n ${ATP_OCID} ]]
then
  atp_subnet_ocid=$(oci db autonomous-database get --autonomous-database-id ${ATP_OCID} | jq -r '.data["subnet-id"]')
  if [[ $atp_subnet_ocid != null ]]; then
    #skip validation if ATP has no private endpoint (no subnet-id)
    res=$(validate_atp_port_access ${atp_subnet_ocid} ${ATP_OCID} ${wls_subnet_cidr_block})
    if [[ $res -ne 0 ]]; then
      echo "ERROR: ATP port ${ATP_PORT} is not open for access by WLS Subnet CIDR [$wls_subnet_cidr_block] in ATP Subnet [${atp_subnet_ocid}]"
    fi
  fi
fi
 
# Check if SSH port is open for access by Bastion Subnet or Host CIDR in WLS Private Subnet
if [[ -n ${BASTION_SUBNET_OCID} || -n ${BASTION_HOST_IP_CIDR} ]]
then
  is_private_subnet=$(oci network subnet get --subnet-id ${WLS_SUBNET_OCID} | jq -r '.data["prohibit-public-ip-on-vnic"]')
 
  if [[ $is_private_subnet = true ]]
  then
    # Check if Bastion subnet has SSH port open for 0.0.0.0/0
    if [[ -n ${BASTION_SUBNET_OCID} ]]
    then
      all_ips="0.0.0.0/0"
      res=$(validate_subnet_port_access ${BASTION_SUBNET_OCID} ${SSH_PORT} ${all_ips})
      if [[ $res -ne 0 ]]
      then
        echo "ERROR: SSH port ${SSH_PORT} is not open for access by [$all_ips] in Bastion Subnet [$BASTION_SUBNET_OCID]"
      fi
    fi
 
    # Check if bastion host IP is valid CIDR
    bastion_cidr_block=""
    if [[ -n ${BASTION_HOST_IP_CIDR} ]]
    then
      is_valid_cidr=$(is_valid_ip_cidr ${BASTION_HOST_IP_CIDR})
      if [[ $is_valid_cidr -ne 0 ]]
      then
        echo "Bastion host IP CIDR is not valid: [${BASTION_HOST_IP_CIDR}]"
        usage >&2
        exit
      fi
      bastion_cidr_block=${BASTION_HOST_IP_CIDR}
    else
      bastion_cidr_block=$(oci network subnet get --subnet-id ${BASTION_SUBNET_OCID} | jq -r '.data["cidr-block"]')
    fi
 
    # Check if bastion CIDR has access to SSH port on WLS subnet
    res=$(validate_subnet_port_access ${WLS_SUBNET_OCID} ${SSH_PORT} ${bastion_cidr_block})
    if [[ $res -ne 0 ]]
    then
      echo "WARNING: SSH port ${SSH_PORT} is not open for access by Bastion Subnet CIDR [$bastion_cidr_block] in private WLS Subnet [$WLS_SUBNET_OCID]"
    fi
  fi
fi

# Check if 7003 port is open for access by LB Subnet or Host CIDR in WLS Subnet
if [[ -n ${LB_SUBNET_OCID} ]]
then
    lbsubnet_cidr_block=$(oci network subnet get --subnet-id "${LB_SUBNET_OCID}" | jq -r '.data["cidr-block"]')
    res=$(validate_subnet_port_access "${WLS_SUBNET_OCID}" ${WLS_LB_PORT} "${lbsubnet_cidr_block}")
    if [[ $res -ne 0 ]]
    then
      echo "ERROR: LB port ${WLS_LB_PORT} is not open for access by LB Subnet CIDR - [$lbsubnet_cidr_block] in WLS Subnet [$WLS_SUBNET_OCID]"
    fi
fi

# Check if LB Subnet port is open in LB Subnet - 443
if [[ -n ${LB_SUBNET_OCID} ]]
then
    all_ips="0.0.0.0/0"
    res=$(validate_subnet_port_access "${LB_SUBNET_OCID}" ${LB_PORT} "${all_ips}")
    if [[ $res -ne 0 ]]
    then
      echo "ERROR: Port [$LB_PORT] is not open for 0.0.0.0/0 in LB Subnet CIDR [${LB_SUBNET_OCID}]"
    fi
fi

# FSS subnet verification - Checking All TCP Ports are open in FSS SUBNET OCID for VCN CIDR
if [[ -n ${FSS_SUBNET_OCID} ]]
then
  vcn_ocid=$(oci network subnet get --subnet-id "${WLS_SUBNET_OCID}" | jq -r '.data["vcn-id"]')
  vcn_cidr=$(oci network vcn get --vcn-id "${vcn_ocid}" | jq -r '.data["cidr-block"]')

  for port in '111' '2048' '2049' '2050'; do
    res=$(validate_subnet_port_access "${FSS_SUBNET_OCID}" "${port}" "${vcn_cidr}")
    if [[ $res -ne 0 ]]
    then
      echo "ERROR: TCP Port [${port}] is not open in FSS Subnet for VCN CIDR"
    fi
  done

  # FSS subnet verification - UDP - '111' '2048' in FSS SUBNET OCID for VCN CIDR"
  for port in '111' '2048'; do
    res=$(validate_subnet_port_access "${FSS_SUBNET_OCID}" "${port}" "${vcn_cidr}" "UDP")
    if [[ $res -ne 0 ]]
    then
      echo "ERROR: UDP Port [${port}] is not open in FSS Subnet for VCN CIDR"
    fi
  done
fi