Technical Forum
Ask questions. Discover Answers.
cancel
Showing results for 
Search instead for 
Did you mean: 

Selective URL client cert authentication with OU check

Peter_Z
Cirrus
Cirrus

I'm trying to write an iRule which requires client cert for selected URLs - similar to this one: https://devcentral.f5.com/s/articles/selective-client-cert-authentication.

I need to add one extra check though: when client provides the certificate, only clients with specific OU in the certificate (or the ones coming from certain source IP, which isn't relevant to the problem though described below) are allowed. It doesn't work, I see errors in the log when trying to call the certificate value. Although it should be possible to use certificate commands [X509::subject [SSL::cert 0]] or call the variable holding the same info in the HTTP_REQUEST event, everytime I try to call it from within Event HTTP_REQUEST I see TCL errors, even when I remove the OU check condition and just try to log the cert info. I am able to use the cert info in HTTP_REQUEST_SEND event though.

I am migrating this functionality from existing Apache Reverse Proxy config, where they achieved that quite easily, so there must be a way to replicate it to F5.

when CLIENTSSL_CLIENTCERT {
set cert_subject [X509::subject [SSL::cert 0]]
set cert_issuer [X509::issuer [SSL::cert 0]]

# release any stored data just in case
HTTP::release
# if there is still no cert after the SSL renegotiation kill the connection by sending a reset back to the client
if { [SSL::cert count] < 1 } {
reject
}
}
 
when HTTP_REQUEST {
set uri [HTTP::uri]
 
switch -glob $uri {
"/test1/*" {
if { [SSL::cert count] <= 0 } {
HTTP::collect
SSL::authenticate always
SSL::authenticate depth 10
SSL::cert mode require
SSL::renegotiate

 
if { ($cert_subject contains "OU=Department1") || (($cert_subject contains "OU=Department2") && ($cert_subject contains "OU=PROD")) || ( [IP::addr [getfield [IP::client_addr] "%" 1] equals 192.168.20.1 ] ) } {
pool pool1
} else {
reject
}
}
 
}
}
}


1 REPLY 1

iaine
MVP
MVP

Hi

I've just re-ordered your logic slightly, hopefully it helps a little

when CLIENTSSL_CLIENTCERT {
	set cert_subject [X509::subject [SSL::cert 0]]
	set cert_issuer [X509::issuer [SSL::cert 0]]
		if { ($cert_subject contains "OU=Department1") || (($cert_subject contains "OU=Department2") && ($cert_subject contains "OU=PROD")) || ( [IP::addr [getfield [IP::client_addr] "%" 1] equals 192.168.20.1 ] ) } {
		pool localhost_http
		} else {
		reject
	}
# if there is still no cert after the SSL renegotiation kill the connection by sending a reset back to the client
	if { [SSL::cert count] < 1 } {
	reject
	}
}
 
when HTTP_REQUEST {
	switch -glob [HTTP::uri] {
		"/test1/*" {
			if { [SSL::cert count] <= 0 } {
			SSL::authenticate always
			SSL::authenticate depth 10
			SSL::cert mode require
			SSL::renegotiate
			}
		}
	}
}