File: //bigscoots/wpo/cloudflare/cloudflare_init_wpoapi.sh
#!/bin/bash
source /bigscoots/includes/common.sh
source /root/.bigscoots/.cf
# Initialize a default JSON response
init_json_response
# Usage information
usage() {
echo "Usage: $0 --domain DOMAIN --ip IP [--email EMAIL] [--apikey APIKEY] [--zoneid ZONEID]"
echo "Mandatory options:"
echo " --domain DOMAIN Domain name to update DNS records for"
echo " --ip IP IP address to set for the DNS records"
echo "Optional options:"
echo " --email EMAIL Cloudflare email address"
echo " --apikey APIKEY Cloudflare API key"
echo " --zoneid ZONEID Cloudflare zone ID"
exit 0
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--domain)
DOMAIN="$2"
shift
shift
;;
--ip)
IP="$2"
shift
shift
;;
--email)
DOMAIN_CF_EMAIL="$2"
shift
shift
;;
--apikey)
DOMAIN_CF_APIKEY="$2"
shift
shift
;;
--zoneid)
DOMAIN_CF_ZONEID="$2"
shift
shift
;;
*)
usage
;;
esac
done
ENTZONE=c2d79b78db1f915729e6a48f8bd6b0c3
CFAPIURL=https://api.cloudflare.com/client/v4
# Check that mandatory options are present
if [ -z "$DOMAIN" ] || [ -z "$IP" ]
then
usage
fi
# ---------------------------
# Function: GEN_PKEY
# ---------------------------
GEN_PKEY() {
# ---------------------------
# Argument Handling
# ---------------------------
if [[ $# -ne 3 ]]; then
echo "Usage: GEN_PKEY <DOMAIN> <ZONE_ID> <IP>"
return 1
fi
local DOMAIN="$1"
local IP="$2"
local INFO_FILE="/root/cfplugin/${DOMAIN}.info"
echo "Starting GEN_PKEY for Domain: ${DOMAIN}, Zone ID: ${ENTZONE}, IP: ${IP}"
# ---------------------------
# Execute SSH Command
# ---------------------------
if ssh "${SSH_OPTIONS[@]}" -p 2222 [email protected] \
"bash /var/www/main.bigscoots.com/create_master.sh ${DOMAIN} ${ENTZONE} ${IP}" > "${INFO_FILE}"
then
echo "Successfully populated ${INFO_FILE} with data from the master server."
else
add_json_error "Failed to execute SSH command to populate ${INFO_FILE}."
return 1
fi
# ---------------------------
# Validate JSON File
# ---------------------------
if [[ -s "${INFO_FILE}" ]]; then
echo "INFO_FILE ${INFO_FILE} exists and is not empty."
else
add_json_error "The info file ${INFO_FILE} does not exist or is empty."
return 1
fi
# ---------------------------
# Optional: Validate JSON Syntax
# ---------------------------
if ! jq empty "${INFO_FILE}" 2>/dev/null; then
add_json_error "Invalid JSON format in ${INFO_FILE}."
return 1
fi
echo "JSON format in ${INFO_FILE} is valid."
# ---------------------------
# Send JSON Payload to Webhook
# ---------------------------
local webhook_url="https://n8n.bigscoots.dev/webhook-test/bigscoots-cache/record-keeper"
# Read the JSON content
local json_payload
json_payload=$(cat "${INFO_FILE}")
# Send the POST request
local response
response=$(curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST \
"${webhook_url}" \
-H "Content-Type: application/json" \
-d "${json_payload}")
# ---------------------------
# Parse Response
# ---------------------------
local http_body
http_body=$(echo "${response}" | sed -e '/HTTP_STATUS:/,$d')
local http_status
http_status=$(echo "${response}" | tr -d '\n' | sed -e 's/.*HTTP_STATUS://')
# ---------------------------
# Handle Response
# ---------------------------
if [[ "${http_status}" =~ ^2 ]]; then
echo "JSON payload successfully posted to N8N API. HTTP Status: ${http_status}"
else
add_json_error "Failed to POST JSON payload to N8N API. HTTP Status: ${http_status}. Response: ${http_body}"
return 1
fi
}
# ---------------------------
# Example Usage
# ---------------------------
# Uncomment the following line to test the function with sample arguments
# GEN_PKEY "parentfromheart.com" "exampleZone" "192.168.1.100"
function DEPLOY_PKEY () {
# echo "Creating the pkey and configuring wp-config.php on ${IP}"
RUNCOMMAND=$(grep bash /root/cfplugin/"${DOMAIN}".info)
ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "cd /bigscoots/ ; git pull ; /bigscoots/wpo_update.sh" >/dev/null 2>&1
ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "$RUNCOMMAND"
}
function GATHERCFAPI () {
if grep -q CFAPI /root/cfplugin/"${DOMAIN}".info
then
send_slack_alert "#cloudflare" ":warning:" "Function: \`GATHERCFAPI\`" "$hostname" "CFAPI already exists in /root/cfplugin/"${DOMAIN}".info\nIf this info is incorrect or incomplete then remove CFAPI lines and rerun this command."
else
# echo "Generating and adding to /root/cfplugin/"${DOMAIN}".info"
ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "bash /bigscoots/wpo/cloudflare/fujames.sh ${DOMAIN} CFAPI" >> /root/cfplugin/"${DOMAIN}".info
fi
CFAPI_DOMAIN=$(grep 'CFAPI Domain' /root/cfplugin/"${DOMAIN}".info | awk '{print $3}')
CFAPI_SERVERIP=$(grep 'CFAPI Server IP' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
CFAPI_CANONICALDOMAIN=$(grep 'CFAPI Canonical Domain' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
CFAPI_CUSTOMHOSTNAME=$(grep 'CFAPI Custom Hostname' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
}
function ADDDNSCFAPI () {
curl -s -X POST "${CFAPIURL}/zones/${ENTZONE}/dns_records" \
-H "X-Auth-Email: ${CFUSER}" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"'"$CFAPI_DOMAIN"'","content":"'"$CFAPI_SERVERIP"'","ttl":120,"priority":10,"proxied":true}' \
-o /root/cfplugin/${DOMAIN}.step1.api
}
function ADDCHNAMECFAPI () {
curl -s -X POST "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames" \
-H "X-Auth-Email: ${CFUSER}" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"hostname":"'"$CFAPI_CANONICALDOMAIN"'", "ssl": { "bundle_method": "ubiquitous", "certificate_authority": "lets_encrypt", "method": "txt", "settings": { "early_hints": "on", "http2": "on", "http3": "on", "min_tls_version": "1.2", "tls_1_3": "on" }, "type": "dv", "wildcard": false }}' \
-o /root/cfplugin/${DOMAIN}.step2.api
if grep -q '"success": true' /root/cfplugin/${DOMAIN}.step2.api
then
CFAPICHNAMEID=$(jq -r '.result.id' < /root/cfplugin/${DOMAIN}.step2.api)
elif grep -q '"success": false' /root/cfplugin/${DOMAIN}.step2.api
then
grep '"code":\|"message":' /root/cfplugin/${DOMAIN}.step2.api
fi
}
function MDFYCHNAMECFAPI () {
curl -s -X PATCH "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames/${CFAPICHNAMEID}" \
-H "X-Auth-Email: ${CFUSER}" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"custom_origin_server":"'"$CFAPI_CUSTOMHOSTNAME"'"}' \
-o /root/cfplugin/${DOMAIN}.step3.api
}
function VRFYCFAPI () {
sleep 30
SSL_TXT_NAME=$(jq -r '.result.ssl.validation_records[0].txt_name' < /root/cfplugin/${DOMAIN}.step3.api)
SSL_TXT_VALUE=$(jq -r '.result.ssl.validation_records[0].txt_value' < /root/cfplugin/${DOMAIN}.step3.api)
OWNERTXT=$(jq -r '.result.ownership_verification.value' < /root/cfplugin/${DOMAIN}.step3.api)
if [ -z "$SSL_TXT_VALUE" ] || [ "$SSL_TXT_VALUE" == "null" ]
then
# echo "Failed to pull the TXT record for SSL verification, waiting 30 seconds then trying again."
sleep 30
MDFYCHNAMECFAPI
SSL_TXT_NAME=$(jq -r '.result.ssl.validation_records[0].txt_name' < /root/cfplugin/${DOMAIN}.step3.api)
SSL_TXT_VALUE=$(jq -r '.result.ssl.validation_records[0].txt_value' < /root/cfplugin/${DOMAIN}.step3.api)
fi
if [[ ${CFAPI_CANONICALDOMAIN} = www* ]]
then
CANONICAL=www
else
CANONICAL=nonwww
fi
bash /bigscoots/general/slack.sh "#cloudflare" "\n \n \n \
:zap:*Cloudflare Enterprise Setup*:zap: \
\n \
Domain: \`${DOMAIN}\` on server IP: \`${IP}\` \n \
\n \
In WPO Admin, set Cloudflare Plan to purchased *Tier 1,2,3*.\n \
\n
Remove the ORANGE CLOUD from record: \`${CFAPI_CANONICALDOMAIN}\` \n \
Ensure the NON Canonical Domain is pointed with an A Record, Orange Cloud. Sometimes its a CNAME which will cause it to fail. \n \
\n \
Add the following DNS records to \`${DOMAIN}\` \n \
Verify Domain Ownership: \n \
\`\`\`TXT Record: _cf-custom-hostname.${CFAPI_CANONICALDOMAIN}\n\
TXT Value: ${OWNERTXT}\`\`\`
\n
SSL Verification \n \
\`\`\`TXT Record: ${SSL_TXT_NAME}\n\
TXT Value: ${SSL_TXT_VALUE}\`\`\` \
\n \
SSH into \`${IP}\` and force non Canonical Domain to \`${CFAPI_CANONICALDOMAIN}\` \n \
\`\`\`bash /bigscoots/wpo/manage/set.sh canonical ${DOMAIN} ${CANONICAL}\`\`\`
Wait 15 minutes then you can change the \`${CFAPI_CANONICALDOMAIN}\` record to a CNAME and point to \`enterprise.tier1.bigscoots.com.\` with a GREY cloud."
}
# Function to add TXT record
ADD_TXT_RECORD() {
local NAME=$1
local CONTENT=$2
local RECORD_TYPE=TXT
# echo "Adding TXT record with value: $NAME $CONTENT"
curl -s -X POST "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--data "{\"type\":\"$RECORD_TYPE\",\"name\":\"$NAME\",\"content\":\"$CONTENT\",\"ttl\":1,\"proxied\":false}" \
| jq '{success: .success, errors: .errors, messages: .messages}'
}
GRAY_CLOUD_DOMAIN() {
# echo "Gray clouding domain"
DNS_RECORD_ID=$(GET_DNS_RECORD_ID)
curl --SILENT --location --request PUT "https://api.cloudflare.com/client/v4/zones/$DOMAIN_CF_ZONEID/dns_records/$DNS_RECORD_ID" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--data "{\"content\":\"$IP\",\"name\":\"$CFAPI_CANONICALDOMAIN\",\"proxied\":false,\"type\":\"A\"}" \
| jq '{success: .success, errors: .errors, messages: .messages}'
# echo "Gray clouding done"
}
GET_ZONE_ID() {
curl -s -X GET "${CFAPIURL}/zones?name=$DOMAIN" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "Content-Type: application/json" | jq -r '.result[0].id'
}
function UPDATE_DNS_RECORD() {
# echo "Checking to see if $CFAPI_CANONICALDOMAIN is an A Record"
response=$(curl --silent --location "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records?name=$CFAPI_CANONICALDOMAIN" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json')
record_id=$(echo "$response" | jq -r '.result[0].id')
record_type=$(echo "$response" | jq -r '.result[0].type')
if [ "$record_type" == "CNAME" ]
then
# echo "$CFAPI_CANONICALDOMAIN was a CNAME record, so well delete it now."
# Delete the CNAME record
curl --silent --location --request DELETE "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records/$record_id" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json'
# echo "Recreating $CFAPI_CANONICALDOMAIN with an A Record"
# Add a new A record with the IP from the $IP variable
curl --silent --location --request POST "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json' \
--data '{
"type": "A",
"name": "'"$CFAPI_CANONICALDOMAIN"'",
"content": "'"$IP"'",
"ttl": 120,
"proxied": false
}'
# echo "$CFAPI_CANONICALDOMAIN A record has been created."
fi
}
function GET_DNS_RECORD_ID() {
curl --silent --location "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records?name=$CFAPI_CANONICALDOMAIN" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" | jq -r '.result[0].id'
}
function FINALSTEPS () {
ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "bash /bigscoots/wpo/cloudflare/fujames.sh ${DOMAIN}"
}
enable_performance_plan() {
local api_url="https://main.bigscoots.com/bscache-usage-log/api/"
local content_type="Content-Type: application/json"
local security_header="x-bigscoots-user: webmaster"
local server_ip="$serverip"
local hostname="$CFAPI_CANONICALDOMAIN"
local server_hostname="$(hostname)"
local data='{
"action": "enable_plan",
"hostname": "'"$hostname"'",
"server_ip": "'"$server_ip"'",
"server_hostname": "'"$server_hostname"'",
"plan": "performance+"
}'
local response=$(curl -s --header "$content_type" --header "$security_header" --data "$data" "$api_url")
if [[ $response == *"\"success\": false"* ]]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`enable_standard_plan\`" "$hostname" "$response"
fi
}
update_master_db() {
local api_url="https://main.bigscoots.com/cf-custom-hostnames/"
local content_type="Content-Type: application/json"
local security_header="x-bigscoots-user: webmaster"
local hostname="$CFAPI_CANONICALDOMAIN"
local step3_file_path="/root/cfplugin/${DOMAIN}.step3.api"
local custom_host_name_id
if [ ! -f "$step3_file_path" ]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "File does not exist. \`\`\`file: $step3_file_path\`\`\`"
return 1
fi
custom_host_name_id=$(cat "$step3_file_path" | jq -r ".result.id")
if [ -z "$custom_host_name_id" ] || [ "$custom_host_name_id" == "null" ]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "Custom Hostname ID is empty. \`\`\`file: $step3_file_path\`\`\`"
return 1
fi
local data='{
"action": "add_record",
"hostname": "'"$hostname"'",
"hostname_id": "'"$custom_host_name_id"'"
}'
local response=$(curl -s --header "$content_type" --header "$security_header" -X POST --data "$data" "$api_url")
if [[ $response == *"\"success\": false"* ]]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "$response"
fi
}
if [[ -z "$DOMAIN_CF_ZONEID" && -n "$DOMAIN_CF_EMAIL" && -n "$DOMAIN_CF_APIKEY" ]]
then
DOMAIN_CF_ZONEID=$(GET_ZONE_ID)
fi
if [ -f /root/cfplugin/"${DOMAIN}".info ]
then
# echo "We've aleady created a master file for ${DOMAIN} will check to see if pkey data is already there."
if grep -q 'bash /bigscoots/wpo/cloudflare/create_pkey.sh' /root/cfplugin/"${DOMAIN}".info
then
## All the Cloudflare Enterprise related functions ##
# echo "pkey data already available, will run the the /bigscoots/wpo/cloudflare/create_pkey.sh script on ${IP}"
DEPLOY_PKEY
FINALSTEPS
GATHERCFAPI
ADDDNSCFAPI
ADDCHNAMECFAPI
MDFYCHNAMECFAPI
VRFYCFAPI
## Now changes to the free Cloudflare account
UPDATE_DNS_RECORD
GET_DNS_RECORD_ID
GRAY_CLOUD_DOMAIN
if [[ -n "$SSL_TXT_NAME" && -n "$SSL_TXT_VALUE" ]]; then
ADD_TXT_RECORD ${SSL_TXT_NAME} ${SSL_TXT_VALUE}
fi
if [[ -n "$CFAPI_CANONICALDOMAIN" && -n "$OWNERTXT" ]]; then
ADD_TXT_RECORD _cf-custom-hostname.${CFAPI_CANONICALDOMAIN} ${OWNERTXT}
fi
enable_performance_plan
update_master_db
else
## All the Cloudflare Enterprise related functions ##
# echo "pkey data does not exist, will generate it now."
GEN_PKEY
DEPLOY_PKEY
FINALSTEPS
GATHERCFAPI
ADDDNSCFAPI
ADDCHNAMECFAPI
MDFYCHNAMECFAPI
VRFYCFAPI
## Now changes to the free Cloudflare account
UPDATE_DNS_RECORD
GET_DNS_RECORD_ID
GRAY_CLOUD_DOMAIN
if [[ -n "$SSL_TXT_NAME" && -n "$SSL_TXT_VALUE" ]]; then
ADD_TXT_RECORD ${SSL_TXT_NAME} ${SSL_TXT_VALUE}
fi
if [[ -n "$CFAPI_CANONICALDOMAIN" && -n "$OWNERTXT" ]]; then
ADD_TXT_RECORD _cf-custom-hostname.${CFAPI_CANONICALDOMAIN} ${OWNERTXT}
fi
enable_performance_plan
update_master_db
fi
else
## All the Cloudflare Enterprise related functions ##
GEN_PKEY
DEPLOY_PKEY
FINALSTEPS
GATHERCFAPI
ADDDNSCFAPI
ADDCHNAMECFAPI
MDFYCHNAMECFAPI
VRFYCFAPI
## Now changes to the free Cloudflare account
UPDATE_DNS_RECORD
GET_DNS_RECORD_ID
GRAY_CLOUD_DOMAIN
if [[ -n "$SSL_TXT_NAME" && -n "$SSL_TXT_VALUE" ]]; then
ADD_TXT_RECORD ${SSL_TXT_NAME} ${SSL_TXT_VALUE}
fi
if [[ -n "$CFAPI_CANONICALDOMAIN" && -n "$OWNERTXT" ]]; then
ADD_TXT_RECORD _cf-custom-hostname.${CFAPI_CANONICALDOMAIN} ${OWNERTXT}
fi
enable_performance_plan
update_master_db
fi