Convert ASA access-list rules to a parseable YAML format.
by deaves
This script spun out of a string of firewall migrations off the legacy ASA platform, I need the ability to convert access-lists to a parseable format. There are multiple reasons for needing this script. First is for human readability and auditing purposes. Second is to have a parseable rule base for duplication or migration to other firewall types.
ASA_acls.sh: Bourne-Again shell script text executable, ASCII text
#!/bin/bash
## Convert ASA access-list rules to a parseable YAML format.
## 2018 (v.01) - Script from www.davideaves.com
### VARIABLES ###
asa_config_file="${1}"
search_string="${2}"
### MAIN SCRIPT ###
[ -z "${asa_config_file}" ] && { echo -e "${0} - ERROR: missing ASA config"; exit 0; }
for ACCESSGROUP in `awk '/^access-group /{print $2}' "${asa_config_file}" | sort --ignore-case`
do
echo "${ACCESSGROUP}:"
awk 'BEGIN{ REMARK=""; ACTION=""; SERVICE=""; SOURCE=""; DESTINATION=""; PORT=""; LOG=""; DISABLED=""; previous="" }
# convert number to bits
function bits(N){
c = 0
for(i=0; i<8; ++i) if(and(2**i, N)) ++c
return c
}
# convert ipv4 to prefix
function to_prefix(mask) {
split(mask, octet, ".")
return bits(octet[1]) + bits(octet[2]) + bits(octet[3]) + bits(octet[4])
}
# test if a string is an ipv4 address
function is_v4(address) {
split(address, octet, ".")
if ( octet[1] <= 255 && octet[2] <= 255 && octet[3] <= 255 && octet[4] <= 255 )
return address
}
# Only look at access-lists lines
/^access-list '''${ACCESSGROUP}''' .*'''${search_string}'''/{
# If line is a remark store it else continue
if ( $3 == "remark" ) { $1=$2=$3=""; REMARK=substr($0,4) }
else { $1=$2=$3=""; gsub("^ ", "")
# Itterate through columns
for(col = 1; col <= NF; col++) {
# Append prefix to SOURCE & DESTINATION
if ( is_v4(previous) && is_v4($col) ) {
if ( DESTINATION != "" ) { DESTINATION=DESTINATION"/"to_prefix($col); previous="" }
else if ( SOURCE != "" ) { SOURCE=SOURCE"/"to_prefix($col); previous="" }
} else {
# Determine col variable
if ( col == "1" ) { ACTION=$col; SERVICE=""; SOURCE=""; DESTINATION=""; PORT=""; LOG=""; DISABLED=""; previous="" }
else if ( $col ~ /^(eq|interface|object|object-group)$/ ) { previous=$col }
else if ( SERVICE == "" && $col !~ /^(host|object|object-group)$/ ) { SERVICE=$col; PORT=""; previous="" }
else if ( SOURCE == "" && $col !~ /^(host|object|object-group)$/ ) {
if ( previous == "interface" ) { SOURCE=previous"/"$col }
else { SOURCE=$col }; PORT=""; previous=to_prefix($col) }
else if ( DESTINATION == "" && $col !~ /^(host|object|object-group)$/ ) {
if ( previous == "interface" ) { DESTINATION=previous"/"$col }
else { DESTINATION=$col }; PORT=""; previous=to_prefix($col) }
else if ( previous ~ /^(eq|object-group)$/ ) { PORT=$col; previous="" }
else if ( $col == "log" ) { LOG=$col; previous="" }
else if ( $col == "inactive" ) { DISABLED=$col; previous="" }
else { LAST=$col; previous="" }
}
}}
# Display the output
if ( DESTINATION != "" ) { count++
print " - name: '''${ACCESSGROUP}''' rule",count,"line",NR
print " debug:",$0
if ( REMARK != "" ) { print " description:",REMARK }
print " action:",ACTION
print " source:",SOURCE
print " destination:",DESTINATION
if ( PORT == "" ) { print " service:",SERVICE }
else { print " service:",SERVICE"/"PORT }
if ( LOG != "" ) { print " log: true" }
if ( DISABLED != "" ) { print " disabled: true" }
REMARK=""; ACTION=""; SERVICE=""; SOURCE=""; DESTINATION=""; PORT=""; LOG=""; DISABLED=""; previous=""
}
}' "${asa_config_file}"
done