I am using the re library in Python 3.12 to capture multiple items from a F5 BIG-IP LTM configuration file to associate pools and members to wildcard certificates and store the data into a dictionary variable using .finditer()
and .groupdict()
since I want the key/value relationship to be maintained for later use in the script. I am having issues with one of the regular expressions not capturing all of the data that I need, but instead capturing only a single value.
Here is the regular expression that I am using:
ltmspools(?P<ltm_pool_name>/Common/.+)s{(?:s{n){0,}(?:n.+){1,2}memberss{(?:(?:n.+){0,1}/Common/(?P<ltm_pool_node_ipaddr>[0-9.]+):(?P<ltm_pool_node_port>[0-9]+)s{n.+n.+}){0,}
The sample data that this is being used against is stored in a file that is accessed by the with open(filenamehere.txt,"r")
, but here is a block from that file that is giving me issues:
ltm pool /Common/pool_put-something.domain.here {
members {
/Common/10.20.30.1:443 {
address 10.20.30.1
}
/Common/10.20.40.2:80 {
address 10.20.40.2
}
/Common/10.20.50.3:8443 {
address 10.20.50.3
}
/Common/10.20.60.4:8080 {
address 10.20.60.4
}
}
When I run my Python script to grab the data using the regular expression mentioned earlier, it will capture only the last member:
/Common/10.20.60.4:8080
And not the rest of the members prior to it. If I modify the very last quantifier to be {0,1}, {0,2}, {0,3}, etc. it will then grab the associated member as the capture group but it will not grab each member otherwise.
When I use the following regular expression:
(?:n.+){0,1}/Common/(?P<ltm_pool_node_ipaddr>[0-9.]+):(?P<ltm_pool_node_port>[0-9]+)s{n.+n.+}
That will capture each of the members in that configuration block but then I am unable to grab the ltm pool /Common/pool_put-something.domain.here
portion that I would like to relate this to. I need both of them to complete the last part of my script.
Below is the script itself:
import re
#
user_input = input("Enter the hostname of the F5 LTM device here: ")
print("-----")
#
hostname = r"A:FilePathHere" + user_input + ".txt"
sys_cert_regex = re.compile(r"syssfilesssl-certs(?P<ssl_cert_name>.+)s{(?:n.+){0,12}expiration-strings"(?P<cert_exp>.+)"(?:n.+){0,10}serial-numbers(?P<cert_serial>.+)(?:n.+){0,3}subjects"(?P<cert_dn>.+)"(?:n.+){0,1}subject-alternative-names(?P<cert_san>.+)")
ltm_profile_clientssl_regex = re.compile(r"ltmsprofilesclient-ssls(?P<ltm_ssl_name>.+)s{(?:n.+){1,4}app-service(?:.+n.+){1,3}certs(?P<ltm_profile_cert>.+)n")
ltm_virtual_regex = re.compile(r"ltmsvirtuals(?P<ltm_virtual_name>.+)s{(?:n.+){1,2}destinations(?P<ltm_destination_name>.+)(?:n.+){1,9}pools(?P<ltm_pool_name>.+)n.+profiless{(?:n.+){0,7}/(?P<cert>.+)s{n.+contextsclientsiden")
ltm_pool_regex = re.compile(r"ltmspools(?P<ltm_pool_name>/Common/.+)s{(?:s{n){0,}(?:n.+){1,2}memberss{(?:(?:n.+){0,1}/Common/(?P<ltm_pool_node_ipaddr>[0-9.]+):(?P<ltm_pool_node_port>[0-9]+)s{n.+n.+}){0,}")
with open(hostname,"r") as file_obj:
for sys_cert_match in sys_cert_regex.finditer(file_obj.read()):
sys_cert = sys_cert_match.groupdict()
if "*" in sys_cert["cert_dn"]:
file_obj.seek(0)
for ltm_profile_clientssl_match in ltm_profile_clientssl_regex.finditer(file_obj.read()):
ltm_profile = ltm_profile_clientssl_match.groupdict()
if sys_cert["ssl_cert_name"] in ltm_profile["ltm_profile_cert"]:
file_obj.seek(0)
for ltm_virtual_match in ltm_virtual_regex.finditer(file_obj.read()):
ltm_virtual = ltm_virtual_match.groupdict()
if ltm_virtual["cert"] in ltm_profile["ltm_ssl_name"]:
file_obj.seek(0)
for ltm_pool_match in ltm_pool_regex.finditer(file_obj.read()):
ltm_pool = ltm_pool_match.groupdict()
if ltm_pool["ltm_pool_name"] in ltm_virtual["ltm_pool_name"]:
file_obj.seek(0)
print("Certificate subject string: ", sys_cert["cert_dn"])
print("Certificate subject alternative names: ", sys_cert["cert_san"])
print("Certificate expiration: ", sys_cert["cert_exp"])
print("Name of the virtual pool using the certificate: ", ltm_pool["ltm_pool_name"])
print("IP address and associated port of a member in that pool: ", ltm_pool["ltm_pool_node_ipaddr"], ":", ltm_pool["ltm_pool_node_port"])
print("***")
continue
else:
continue
I expect the print("IP address and associated port of a member in that pool: ", ltm_pool["ltm_pool_node_ipaddr"], ":", ltm_pool["ltm_pool_node_port"])
portion to print out every member, not just the first or last member, of every pool. Right now, it will only do the first or last member.
Is there a way to get both of these to work as a singular regular expression so that when I use the .finditer()
and .groupdict()
that it will store that into a single dictionary? If not, then is my next best way to achieve this is by putting each member into an array and then potentially taking that array and appending it as a value to a specific key?
aa44414c is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.