Forum Discussion
Client Certificate Auth x509x3 parsing irule for APM
I've been running this code for over a year with no issues. It's the second iteration of my x509x3 cert parsing irule that I call from within APM. I'm looking to add an enhancement. The regex looks for 10 or 16 digit patterns of numbers and only grabs 10 or 16. I need to add functionality that ensures only 10 digits are used for the temppiv. If a string of 10 numbers is matched - use that. If 16 numbers are matched - use only the first 10 numbers for the temppiv. The "else" is just a fallback looking for othername:UPN in the event that the first routine fails, but to be honest this is never called anymore. I just keep the code around as a catch-all. Any help or pointers is appreciated.
when ACCESS_POLICY_AGENT_EVENT {
switch [ACCESS::policy agent_id] {
"CERTPROCESSING" {
if { ([regexp {([0-9]{16}|[0-9]{10})} [ACCESS::session data get session.ssl.cert.subject] temppiv ] == 1) and ([ACCESS::session data get session.ssl.cert.issuer] contains "OU=COMPANY") } {
set tempupn "$temppiv@com"
ACCESS::session data set session.custom.certupn $tempupn }
else { if { [ACCESS::session data get session.ssl.cert.x509extension] contains "othername:UPN<" } {
set tempupn [findstr [ACCESS::session data get session.ssl.cert.x509extension] "othername:UPN<" 14 ">"]
ACCESS::session data set session.custom.certupn $tempupn }
}
}
}
}
- Kevin_Stewart
Employee
Something like this maybe,
set str1 "foo.bar.1234567890" set str2 "foo.bar.1234567890123456" if { ( [regexp {([0-9]{16}|[0-9]{10})} $str2 temppiv] == 1 ) and ( [set temppiv [string range $temppiv 0 9]] ne "" ) } { log local0. "TEST: temppiv = $temppiv" }
- Stanislas_Piro2
Cumulonimbus
Can you explain exactly what is the subject format? does it contain some other characters than digits?
The regular expression provided by kevin will match every string with at least 10 digits.
set str "foo." set str_end ".bar" for {set i 1 } { $i<20} {incr i} { append str [expr {int(rand()*10)}] echo "result for string $str$str_end is [lindex {false true} [regexp {([0-9]{16}|[0-9]{10})} $str$str_end temppiv]]" } foo. % .bar % result for string foo.7.bar is false result for string foo.71.bar is false result for string foo.712.bar is false result for string foo.7129.bar is false result for string foo.71293.bar is false result for string foo.712939.bar is false result for string foo.7129391.bar is false result for string foo.71293917.bar is false result for string foo.712939174.bar is false result for string foo.7129391740.bar is true result for string foo.71293917401.bar is true result for string foo.712939174010.bar is true result for string foo.7129391740102.bar is true result for string foo.71293917401029.bar is true result for string foo.712939174010292.bar is true result for string foo.7129391740102928.bar is true result for string foo.71293917401029287.bar is true result for string foo.712939174010292879.bar is true result for string foo.7129391740102928792.bar is true
the result is the same as if you only check for a 10 digits string..
% set str "foo." set str_end ".bar" for {set i 1 } { $i<20} {incr i} { append str [expr {int(rand()*10)}] echo "result for string $str$str_end is [lindex {false true} [regexp {([0-9]{10})} $str$str_end temppiv]]" } foo. % .bar % result for string foo.4.bar is false result for string foo.41.bar is false result for string foo.419.bar is false result for string foo.4199.bar is false result for string foo.41991.bar is false result for string foo.419918.bar is false result for string foo.4199182.bar is false result for string foo.41991829.bar is false result for string foo.419918296.bar is false result for string foo.4199182963.bar is true result for string foo.41991829630.bar is true result for string foo.419918296309.bar is true result for string foo.4199182963098.bar is true result for string foo.41991829630985.bar is true result for string foo.419918296309854.bar is true result for string foo.4199182963098543.bar is true result for string foo.41991829630985439.bar is true result for string foo.419918296309854391.bar is true result for string foo.4199182963098543916.bar is true
You can check that there is no digit before and after the searched string
set str "foo." set str_end ".bar" for {set i 1 } { $i<20} {incr i} { append str [expr {int(rand()*10)}] echo "result for string $str$str_end is [lindex {false true} [regexp {^[^\d]*(\d{16}|\d{10})[^\d]*$} $str$str_end temppiv]]" }foo. % .bar % result for string foo.4.bar is false result for string foo.43.bar is false result for string foo.430.bar is false result for string foo.4304.bar is false result for string foo.43048.bar is false result for string foo.430483.bar is false result for string foo.4304835.bar is false result for string foo.43048355.bar is false result for string foo.430483554.bar is false result for string foo.4304835549.bar is true result for string foo.43048355498.bar is false result for string foo.430483554980.bar is false result for string foo.4304835549809.bar is false result for string foo.43048355498095.bar is false result for string foo.430483554980954.bar is false result for string foo.4304835549809545.bar is true result for string foo.43048355498095452.bar is false result for string foo.430483554980954520.bar is false result for string foo.4304835549809545206.bar is false %
instead of the irule event, create a variable assign for variable session.custom.certupn with expression:
if {[regexp {^[^\d]*(\d{16}|\d{10})[^\d]*$} [mcget {session.ssl.cert.subject}] temppiv]] == 1} { return [string range $temppiv 0 9] } elseif { [mcget {session.ssl.cert.x509extension}] contains "othername:UPN<" } { set extension [mcget {session.ssl.cert.x509extension}]; return [string range $extension [expr {[string first "othername:UPN<" $extension] +14}] [expr {[string last ">" $extension] -1}] ]; }
- eric_haupt1
Nimbostratus
Here is my current version - Pulls digits from subject and builds UPN, grabs UPN from x509, or pulls email from x509. Been using this a long time.
` when ACCESS_POLICY_AGENT_EVENT { switch [ACCESS::policy agent_id] { "CACPROCESSING" { if { ([regexp {([0-9]{16}|[0-9]{10})} [ACCESS::session data get session.ssl.cert.subject] var_temp_piv ] == 1) and ([ACCESS::session data get session.ssl.cert.issuer] contains "COMPANY") } { set var_temp_upn "$var_temp_piv@COMPANY" set var_session_start [clock format [clock seconds] -format {%d %b %Y %T %Z}] ACCESS::session data set session.custom.cert.upn $var_temp_upn ACCESS::session data set session.custom.start.time $var_session_start } else { if { [ACCESS::session data get session.ssl.cert.x509extension] contains "othername:UPN<" } { set var_temp_upn [findstr [ACCESS::session data get session.ssl.cert.x509extension] "othername:UPN<" 14 ">"] set var_session_start [clock format [clock seconds] -format {%d %b %Y %T %Z}] ACCESS::session data set session.custom.cert.upn $var_temp_upn ACCESS::session data set session.custom.start.time $var_session_start } else { if { [ACCESS::session data get session.ssl.cert.x509extension] contains "email:" } { set var_temp_x509extension ([string map -nocase {" " "" \n "" \r ""} [ACCESS::session data get session.ssl.cert.x509extension]]) set var_temp_email [findstr $var_temp_x509extension "email:" 6 "X509"] set var_session_start [clock format [clock seconds] -format {%d %b %Y %T %Z}] ACCESS::session data set session.custom.cert.email $var_temp_email ACCESS::session data set session.custom.start.time $var_session_start }
}}}}}`
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com