Hi Everyone,
I think this needs a bit of clarification. I have managed to make the F5 APM work like a web services API, so that other external systems can utilise the built in OTP generation/verficiation. I will show the code and how it works below. I would like some feedback as to how i could improve it (if it can be improved).
HOW IT WORKS
GENERATE OTP CODE
External System --> (calls) F5 APM (using a HTTPS POST) and passing a header variable "otpmode", that is used to select if the ext system wants to generate or verify the otp code.
POST https://fqdn.com/otp HTTP/1.1
User-Agent: Fiddler
Host: fqdn.com
Content-Length: 0
otpmode: generate
A response is then received as follows, with a header variable "otp" which is the OTP code generated in the F5 APM and also gets returned the cookie for the APM session. This OTP code can then be used by the external system (send via email or SMS for user/other to use)
HTTP/1.0 200 OK
OTP: 623177
SID: xxxxx
Server: BigIP
Connection: Close
Set-Cookie: LastMRH_Session=xxxxx;path=/;secure
Set-Cookie: MRHSession=xxxxx;path=/;secure
Content-Length: 0
VERIFY OTP CODE
External System --> (calls) F5 APM (using a HTTPS POST) and passing a header variable "otpmode", that is used to select if the ext system wants to generate or verify the otp code (in this case verify) and the OTP code that needs to be verified. It also passes the cookie so the system rejoins to the APM session it created in the generation activity.
POST https://fqdn.com/otp HTTP/1.1
User-Agent: Fiddler
Host: fqdn.com
Content-Length: 0
otpmode: verify
otp: 536484
Cookie: MRHSession=xxxxx;path=/;secure
A response is then received telling the ext system if the code sent for verification is correct.
HTTP/1.0 200 OK
OTP_status: success
Server: BigIP
Connection: Close
Set-Cookie: LastMRH_Session=xxxxx;path=/;secure
Set-Cookie: MRHSession=xxxxx;path=/;secure
Content-Length: 0
CODE TO MAKE THIS WORK
iRULE
when HTTP_REQUEST {
HTTP::header insert "clientless-mode" 1
set otp_generated [ACCESS::session data get "session.otp.assigned.val"]
set otp_to_verify [HTTP::header otp]
set otp_status "failed"
if { ($otp_to_verify) equals ($otp_generated) }
{ set otp_status "success" }
if { ([HTTP::header otpmode] equals "generate") }{}
if { ([HTTP::header otpmode] equals "verify") }
{ HTTP::respond 200 otp_status $otp_status Connection Close }}
when ACCESS_SESSION_STARTED {
ACCESS::session data set "session.custom.otpmode" [string trim [HTTP::header otpmode]]
}
when ACCESS_POLICY_COMPLETED {
ACCESS::respond 200 OTP [ACCESS::session data get "session.otp.assigned.val"] SID [ACCESS::session data get "session.user.sessionid"] Connection Close
}
}
}
APM POLICY
The APM policy is basically as follows:
-> Blank Box, which looks at "optmode" and selects branch as either "generate" or "verify"
-> "Generate" branch then goes to "OTP Generate" -> faallback -> Allow
-> "Verify" branch then goes to "OTP verify" -> Success or Fallback -> Allow