Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added functionality for Palo Alto Firewall deployments (PANOS) #4575

Merged
merged 17 commits into from
Jul 30, 2023
Merged
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 119 additions & 35 deletions deploy/panos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@
#
# Firewall admin with superuser and IP address is required.
#
# export PANOS_USER="" # required
# export PANOS_PASS="" # required
# export PANOS_HOST="" # required
# REQURED:
# export PANOS_HOST="" # required
# export PANOS_USER="" # required
#
# AND one of the two authenticiation methods:
#
# Method 1: Password (RECOMMENDED)
# export PANOS_PASS=""
#
# Method 2: API KEY
# export PANOS_KEY=""
#
#
# The Password method will automatically generate a new API key if
# no key is found, or if a saved key has expired or is invalid.
#

# This function is to parse the XML
# This function is to parse the XML response from the firewall
parse_response() {
type=$2
if [ "$type" = 'keygen' ]; then
Expand All @@ -25,23 +38,39 @@ parse_response() {
else
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g')
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g')
if [ "$type" = 'keytest' ] && [ "$status" != "success" ]; then
_debug "**** API Key has EXPIRED or is INVALID ****"
unset _panos_key
fi
fi
return 0
}

#This function is used to deploy to the firewall
deployer() {
content=""
type=$1 # Types are keygen, cert, key, commit
_debug "**** Deploying $type *****"
type=$1 # Types are keytest, keygen, cert, key, commit
panos_url="https://$_panos_host/api/"

#Test API Key by performing an empty commit.
if [ "$type" = 'keytest' ]; then
_debug "**** Testing saved API Key ****"
_H1="Content-Type: application/x-www-form-urlencoded"
content="type=commit&key=$_panos_key&action=partial&cmd=<commit><partial><admin><member>acmekeytest</member></admin></partial></commit>"
fi

# Generate API Key
if [ "$type" = 'keygen' ]; then
_debug "**** Generating new API Key ****"
_H1="Content-Type: application/x-www-form-urlencoded"
content="type=keygen&user=$_panos_user&password=$_panos_pass"
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
fi

# Deploy Cert or Key
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
#Generate DEIM
_debug "**** Deploying $type ****"
#Generate DELIM
delim="-----MultipartDelimiter$(date "+%s%N")"
nl="\015\012"
#Set Header
Expand All @@ -61,19 +90,27 @@ deployer() {
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cdomain.key")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
fi
#Close multipart
content="$content${nl}--$delim--${nl}${nl}"
#Convert CRLF
content=$(printf %b "$content")
fi

# Commit changes
if [ "$type" = 'commit' ]; then
_debug "**** Committing changes ****"
export _H1="Content-Type: application/x-www-form-urlencoded"
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
#Check for force commit
if [ "$FORCE" ]; then
cmd=$(printf "%s" "<commit><partial><force></force><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
else
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
fi
content="type=commit&key=$_panos_key&cmd=$cmd"
fi

response=$(_post "$content" "$panos_url" "" "POST")
parse_response "$response" "$type"
# Saving response to variables
Expand All @@ -92,43 +129,90 @@ deployer() {

# This is the main function that will call the other functions to deploy everything.
panos_deploy() {
_cdomain="$1"
_cdomain=$(echo "$1" | sed 's/*/WILDCARD_/g') #Wildcard Safe Filename
sg1888 marked this conversation as resolved.
Show resolved Hide resolved
_ckey="$2"
_cfullchain="$5"
# PANOS ENV VAR check
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then
_debug "No ENV variables found lets check for saved variables"
_getdeployconf PANOS_USER
_getdeployconf PANOS_PASS
_getdeployconf PANOS_HOST
_panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS
_panos_host=$PANOS_HOST
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs."

# VALID ECC KEY CHECK
keysuffix=$(printf '%s' "$_ckey" | tail -c 8)
if [ "$keysuffix" = "_ecc.key" ] && [ ! -f "$_ckey" ]; then
sg1888 marked this conversation as resolved.
Show resolved Hide resolved
_debug "The ECC key $_ckey doesn't exist. Attempting to strip '_ecc' from the key name"
_ckey=$(echo "$_ckey" | sed 's/\(.*\)_ecc.key$/\1.key/g')
if [ ! -f "$_ckey" ]; then
_err "Unable to find a valid key. Try issuing the certificate using RSA (non-ECC) encryption."
return 1
else
_debug "Using saved env variables."
fi
fi

# PANOS_HOST
if [ "$PANOS_HOST" ]; then
_debug "Detected ENV variable PANOS_HOST. Saving to file."
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
else
_debug "Detected ENV variables to be saved to the deploy conf."
# Encrypt and save user
_debug "Attempting to load variable PANOS_HOST from file."
_getdeployconf PANOS_HOST
fi

# PANOS USER
if [ "$PANOS_USER" ]; then
_debug "Detected ENV variable PANOS_USER. Saving to file."
_savedeployconf PANOS_USER "$PANOS_USER" 1
else
_debug "Attempting to load variable PANOS_USER from file."
_getdeployconf PANOS_USER
fi

# PANOS_PASS
if [ "$PANOS_PASS" ]; then
_debug "Detected ENV variable PANOS_PASS. Saving to file."
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
_panos_user="$PANOS_USER"
_panos_pass="$PANOS_PASS"
_panos_host="$PANOS_HOST"
else
_debug "Attempting to load variable PANOS_PASS from file."
_getdeployconf PANOS_PASS
fi

# PANOS_KEY
if [ "$PANOS_KEY" ]; then
_debug "Detected ENV variable PANOS_KEY. Saving to file."
_savedeployconf PANOS_KEY "$PANOS_KEY" 1
else
_debug "Attempting to load variable PANOS_KEY from file."
_getdeployconf PANOS_KEY
fi

#Store variables
_panos_host=$PANOS_HOST
_panos_key=$PANOS_KEY
_panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS

#Test API Key if found. If the key is invalid, the variable panos_key will be unset.
if [ "$_panos_host" ] && [ "$_panos_key" ]; then
_debug "**** Testing API KEY ****"
deployer keytest
fi
_debug "Let's use username and pass to generate token."
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST"

# Check for valid variables
if [ -z "$_panos_host" ]; then
_err "No host found. If this is your first time deploying, please set PANOS_HOST in ENV variables. You can delete it after you have successfully deployed the certs."
return 1
elif [ -z "$_panos_user" ]; then
_err "No user found. If this is your first time deploying, please set PANOS_USER in ENV variables. You can delete it after you have successfully deployed the certs."
return 1
elif [ -z "$_panos_key" ] && { [ -z "$_panos_user" ] || [ -z "$_panos_pass" ]; }; then
_err "No pass OR valid API key found. If this is your first time deploying please set PANOS_PASS and/or PANOS_KEY in ENV variables. You can delete them after you have succesfully deployed the certs."
return 1
else
_debug "Getting PANOS KEY"
deployer keygen
# Generate a new API key if no valid API key is found
if [ -z "$_panos_key" ]; then
_debug "**** Generating new PANOS API KEY ****"
deployer keygen
_savedeployconf PANOS_KEY "$_panos_key" 1
fi

# Confirm that a valid key was generated
if [ -z "$_panos_key" ]; then
_err "Missing apikey."
_err "Unable to generate an API key. The user and pass may be invalid or not authorized to generate a new key. Please check the PANOS_USER and PANOS_PASS credentials and try again"
return 1
else
deployer cert
Expand Down