· 8 years ago · Feb 22, 2018, 06:06 PM
1#TMSH-VERSION: 13.1.0.2
2
3cli admin-partitions {
4 update-partition Common
5}
6cli script /Common/f5.iapp.1.5.6.cli {
7# Initialization proc for all templates.
8# Parameters "start" and "stop" or "end".
9proc iapp_template { action } {
10 switch $action {
11 start {
12 set ::clock_clicks [clock clicks]
13 puts "\nStarting iApp $tmsh::app_template_name [clock format \
14 [clock seconds] -format {%m/%d/%Y %T}]\n"
15 tmsh::log info "Starting iApp template $tmsh::app_template_name"
16 }
17 stop -
18 end {
19 if { [info exists ::substa_debug] } {
20 puts $::substa_debug
21 }
22 puts "\nEnding iApp $tmsh::app_template_name [clock format \
23 [clock seconds] -format {%m/%d/%Y %T}]\nRun time [expr \
24 { ([clock clicks] - $::clock_clicks) / 1000 }] msec\n"
25 tmsh::log info "Ending iApp template $tmsh::app_template_name"
26 }
27 }
28 set ::HTTP_CONTENT_TYPES { application/(css\|css-stylesheet\|doc\|excel\|javascript\|json\|lotus123\|mdb\|mpp\|msaccess\|msexcel\|ms-excel\|mspowerpoint\|ms-powerpoint\|msproject\|msword\|ms-word\|photoshop\|postscript\|powerpoint\|ps\|psd\|quarkexpress\|rtf\|txt\|visio\|vnd\\.excel\|vnd\\.msaccess\|vnd\\.ms-access\|vnd\\.msexcel\|vnd\\.ms-excel\|vnd\\.mspowerpoint\|vnd\\.ms-powerpoint\|vnd\\.ms-pps\|vnd\\.ms-project\|vnd\\.msword\|vnd\\.ms-word\|vnd\\.ms-works\|vnd\\.ms-works-db\|vnd\\.powerpoint\|vnd\\.visio\|vnd\\.wap\\.cmlscriptc\|vnd\\.wap\\.wmlc\|vnd\\.wap\\.xhtml\\+xml\|vnd\\.word\|vsd\|winword\|wks\|word\|x-excel\|xhtml\\+xml\|x-java-jnlp-file\|x-javascript\|x-json\|x-lotus123\|xls\|x-mdb\|xml\|x-mscardfile\|x-msclip\|x-msexcel\|x-ms-excel\|x-mspowerpoint\|x-msproject\|x-ms-project\|x-msword\|x-msworks-db\|x-msworks-wps\|x-photoshop\|x-postscript\|x-powerpoint\|x-ps\|x-quark-express\|x-rtf\|x-vermeer-rpc\|x-visio\|x-vsd\|x-wks\|x-word\|x-xls\|x-xml) image/(photoshop\|psd\|x-photoshop\|x-vsd) text/(css\|html\|javascript\|json\|plain\|postscript\|richtext\|rtf\|vnd\\.wap\\.wml\|vnd\\.wap\\.wmlscript\|wap\|wml\|x-component\|xml\|x-vcalendar\|x-vcard) }
29}
30
31proc iapp_is { args } {
32 set up_var [lindex $args 0]
33 upvar $up_var var
34 if { [info exists var] } {
35 foreach val [lrange $args 1 end] {
36 if { [subst $var] eq $val } {
37 return 1
38 }
39 }
40 }
41 return 0
42}
43
44proc iapp_substa { args } {
45 upvar substa_in argx \
46 substa_out rval
47 set argx $args
48
49 # check the explicit value first.
50 # multiple layers of variable substitution requires multiple subst.
51 # error occurs here if any of the substituted variables do not exist
52 # valid wildcard (*) array entries will fail here first.
53 uplevel {
54 append ::substa_debug "\n$substa_in"
55 if { [info exists [set substa_in]] } {
56 set substa_out [subst $$substa_in]
57 set substa_out [subst $substa_out]
58 } else {
59 # since explicit value did not exist, try a wildcard value.
60 # substitute "*" as the array key and repeat.
61 set substa_tmp [split $substa_in "()"]
62 set substa_in "[lindex $substa_tmp 0](*)"
63 append ::substa_debug "*"
64 if { [info exists [set substa_in]] } {
65 set substa_out [subst $$substa_in]
66 set substa_out [subst $substa_out]
67 } else {
68 error "substa \"$substa_in\" array value not found"
69 }
70 }
71 }
72 return $rval
73}
74
75proc iapp_conf { args } {
76
77 # Return value $object_name is set to the first word in $arg that
78 # contains an underscore, since the position of the object name in
79 # tmsh syntax is not consistent.
80 set args [join $args]
81 set object_name [lindex $args [lsearch -glob $args "*_*"]]
82
83 # Global array ::tmsh_history persists between calls to iapp_conf
84 # in order to suppress duplicate commands.
85 if { ![info exists ::tmsh_history($args)] } {
86 set ::tmsh_history($args) 1
87 iapp_debug $args
88 switch -exact -- [string range $args 0 5] {
89 create { tmsh::create [string range $args 7 end] }
90 modify { tmsh::modify [string range $args 7 end] }
91 delete { tmsh::delete [string range $args 7 end] }
92 default { error "iapp_conf illegal parameter" }
93 }
94 }
95 return $object_name
96}
97
98proc iapp_make_safe_password { password } {
99 if { [string first {'} $password] == -1 } {
100 set rval "'$password'"
101 } elseif { [string first {"} $password] == -1 } {
102 set rval "\"$password\""
103 } else {
104 set rval [string map { \' \\\' \" \\\" \{ \\\{ \} \\\} \; \\\; \| \\\| \# \\\# \ \\\ \\ \\\\ } $password]
105 }
106 return $rval
107}
108
109proc iapp_pull { loc items_list } {
110 upvar $items_list items
111 if { [set item [lindex $items $loc]] != "" } {
112 set items [lreplace $items $loc $loc]
113 }
114 return $item
115}
116
117proc iapp_process_flags { flags_array args_list } {
118 upvar $flags_array flags
119 upvar $args_list args
120
121 if { [set dubdash [lsearch $args "--"]] != -1 } {
122 set args [lreplace $args $dubdash $dubdash];
123 } else {
124 set dubdash end
125 }
126
127 foreach flag [array names flags] {
128 while { [set ptr [lsearch [lrange $args 0 $dubdash] $flag]] != -1 } {
129 set args [lreplace $args $ptr $ptr];
130
131 # we want to run the code in the flags_array at the calling
132 # proc's level so that the variables that it sets up are
133 # available there.
134 set access_var [format "$%s(%s)" $flags_array $flag]
135 set command [subst -nocommands { set ptr $ptr ; subst $access_var }]
136
137 uplevel 1 $command
138 }
139 }
140 return $args
141}
142
143proc iapp_tmos_version { args } {
144 set cversion [tmsh::version]
145 if { $cversion eq "" } {
146 tmsh::log err "unable to determine TMOS version"
147 error "unable to determine TMOS version"
148 }
149
150 # if no op+version was specified, just return the version
151 if { $args eq "" } { return $cversion }
152 if { [llength $args] > 2 } {
153 error "Too many arguments"
154 }
155
156 set op [lindex $args 0]; # operator
157 set NOTFOUND -1
158 # constrain to valid operators - adding more is fine as long as
159 # they are supported by [expr] (and makes sense)
160 if { [lsearch -exact { < > <= >= == != } $op] == $NOTFOUND } {
161 tmsh::log err "illegal operator: $op"
162 error "illegal operator: $op"
163 }
164
165 set tversion [lindex $args 1]; # target version
166 # one or two decimal digits, optionally followed by 0-2 complete groups of
167 # dots followed by one or two decimal digits with nothing before or after
168 set regex {^\d{1,2}(\.\d{1,2}){0,2}$}
169 if { ! [regexp -- $regex $tversion] } {
170 tmsh::log err "cannot parse version from: $tversion"
171 error "cannot parse version from: $tversion"
172 }
173
174 # p=>prefix, c=>current, t=>target
175 foreach p { c t } {
176 # extract major/minor/point components
177 scan [set [set p]version] "%d.%d.%d" [set p]mjr [set p]mnr [set p]pnt
178 # ensure that these are each set to at least 0
179 foreach level { mjr mnr pnt } {
180 if { ! [info exists [set p]${level}] } { set [set p]${level} 0 }
181 }
182 # turn them into one big number that we can compare
183 # leave room in-between just to be safe
184 set [set p]num [expr {
185 [set [set p]mjr]*1000000 +
186 [set [set p]mnr]*10000 +
187 [set [set p]pnt]*100
188 }]
189 }
190 # a simple numeric comparison is all that is needed at this point
191 return [eval expr $cnum $op $tnum ]
192}
193
194proc iapp_safe_display { args } {
195 # strings sent to APL must be truncated to 65535 bytes, see BZ435592
196 if { [string length [set [set args]]] > 65535 } {
197 set last_newline [string last "\n" [set [set args]] 65500]
198 return "[string range [set [set args]] 0 $last_newline]Error: Too many items for display"
199 } else {
200 return [set [set args]]
201 }
202}
203
204proc iapp_get_items { args } {
205
206 # Set default values.
207 set error_msg "iapp_get_items $args:"
208 set do_binary 0
209 set nocomplain 0
210 set items ""
211 set join_char "\n"
212 set recursive "recursive"
213 set com_dir "/Common"
214 set loc_dir "[tmsh::pwd]"
215
216 # Set up flag-related work.
217 array set flags {
218 -exists { [set do_binary 1] }
219 -nocomplain { [set nocomplain 1] }
220 -list { [set join_char " "] }
221 -norecursive { [set recursive ""] }
222 -local { [set com_dir ""] }
223 -dir { [set loc_dir [iapp_pull $ptr args]] }
224 -filter { [set filter_field [iapp_pull $ptr args]] \
225 [set filter_op [iapp_pull $ptr args]] \
226 [set filter_value [iapp_pull $ptr args]] }
227 }
228 iapp_process_flags flags args
229
230 # Get system object names in all requested directories.
231 set save_dir [tmsh::pwd]
232 foreach dir [lsort -unique "$com_dir $loc_dir"] {
233 tmsh::cd $dir
234 set tmsh_rval [catch {
235 foreach obj [tmsh::get_config $args $recursive] {
236
237 if { [info exists filter_field] } {
238 if { $filter_field eq "NAME" } {
239 set val [tmsh::get_name $obj]
240 } else {
241 # If get_field_value throws error, assume "none" value
242 if { [catch {
243 set val [tmsh::get_field_value $obj $filter_field]
244 # strip quotes per BZ442531
245 set val [string map {\" ""} $val]
246 }]} { set val none }
247 }
248 # Non-Tcl operators =~ and !~ added for extra flexibility
249 if { $filter_op eq "=~" } {
250 set filter "\[regexp \"$filter_value\" \"$val\"\]"
251 } elseif { $filter_op eq "!~" } {
252 set filter "!\[regexp \"$filter_value\" \"$val\"\]"
253 } else {
254 set filter "\\\"$val\\\" $filter_op \\\"$filter_value\\\""
255 }
256 # If filter fails, skip to next object
257 if { ![eval expr $filter] } {
258 continue
259 }
260 }
261 # string map catches /Common added by ltm profile ntlm,
262 # which is unlike all other ltm profile return values.
263 lappend items $dir/[string map {/Common/ ""} [tmsh::get_name $obj]]
264 }
265 } err ]
266 }
267 tmsh::cd $save_dir
268
269 # array keys: $do_binary,$tmsh_rval,$nocomplain. Do not insert whitespace.
270 array set rval {
271 0,0,0 {[join $items $join_char]}
272 0,0,1 {[join $items $join_char]}
273 0,1,0 {[error "$error_msg $err"]}
274 0,1,1 {}
275 1,0,0 {[llength $items]}
276 1,0,1 {[llength $items]}
277 1,1,0 {0}
278 1,1,1 {0}
279 }
280
281 return [subst $rval($do_binary,$tmsh_rval,$nocomplain)]
282}
283
284proc iapp_get_provisioned { args } {
285
286 array set lnum {
287 none 0
288 minimum 1
289 nominal 2
290 dedicated 3
291 }
292
293 # Set defaults.
294 set required minimum
295 set do_binary 1
296
297 # Set up flag-related work.
298 array set flags {
299 -is { [set required [iapp_pull $ptr args]] }
300 -level { [set do_binary 0] }
301 }
302 iapp_process_flags flags args
303 if { [llength $args] > 1 } {
304 error "Too many arguments"
305 }
306
307 # If checking for AM provisioning on TMOS < 11.4,
308 # check for WAM provisioning instead.
309 if { $args eq "am" && [iapp_tmos_version < 11.4] } {
310 set args "wam"
311 }
312
313 # Get the provisioning level. If blank, assume none.
314 # Proc only checks 1 module at a time, so only 1 object is returned.
315 if { [catch {
316 set obj [tmsh::get_config sys provision $args]
317 set level [tmsh::get_field_value [lindex $obj 0] level]
318 }]} { set level none }
319
320 if { $do_binary } {
321 return [expr { $lnum($level) >= $lnum($required) }]
322 } else {
323 return $level
324 }
325}
326
327proc iapp_get_user { args } {
328
329 # Set defaults.
330 set do_role 0
331 set do_binary 0
332
333 # Set up flag-related work.
334 array set flags {
335 -is_admin { [set do_binary 1] }
336 }
337 iapp_process_flags flags args
338 if { [llength $args] > 1 } {
339 error "Too many arguments"
340 }
341
342 # Show user auth was introduced in v11.6
343 set user "unknown"
344 catch {
345 set user [tmsh::show auth user field-fmt]
346 } err
347 if { $do_binary } {
348 return [expr { $user == "unknown"
349 || [string first "role " $user] == -1
350 || [string first "role admin" $user] != -1
351 || [string first "role resource-admin" $user] != -1 }]
352 } else {
353 return $user
354 }
355}
356
357proc iapp_destination { args } {
358 # Set defaults. Flag actions may overwrite defaults later.
359 set route_domain -1
360 set do_mask 0
361 set port 0
362
363 # Set up flag-based actions.
364 array set flags {
365 -route_domain { [set route_domain [iapp_pull $ptr args]] }
366 -mask { [set do_mask 1] }
367 -length { [set cidr_bits [iapp_pull $ptr args]] }
368 }
369
370 if { [llength [set non_switches [iapp_process_flags flags args]]] > 2 } {
371 error "Too many arguments"
372 }
373 if { [llength $non_switches] == 2 } { set port [lindex $non_switches 1] }
374 set addr [lindex $non_switches 0]
375
376
377 # Detect a CIDR mask and pull it off the addr string
378 if { [regexp {/[0-9][0-9]?[0-9]?$} $addr] == 1 } {
379 set loc [string first {/} $addr]
380 set cidr_bits [string range $addr [expr {$loc + 1}] end]
381 set addr [string range $addr 0 [expr {$loc - 1}]]
382 }
383
384 # Pull the route-domain off the addr string, but only use it as the
385 # route domain if it wasn't overridden by -route_domain flag.
386 if { [string first "%" $addr] != -1 } {
387 if { $route_domain == -1 } {
388 # route-domain is still default, so use value from addr string
389 set route_domain [lindex [split $addr "%"] 1]
390 }
391 set addr [lindex [split $addr "%"] 0]
392 }
393
394 if { $do_mask } {
395
396 # Define the delta between ipv4 and ipv6.
397 # length: ipv4 mask is 32 bits, ipv6 is 128 bits.
398 # group: ipv4 is grouped in octets, ipv6 as 16 bit words.
399 # format: ipv4 is decimal notation, ipv6 is hex.
400 # format1 also has the delimiter, format2 does not.
401 array set v {
402 0,length 32
403 0,group 8
404 0,format1 d.
405 0,format2 d
406 1,length 128
407 1,group 16
408 1,format1 .4x:
409 1,format2 .4x
410 }
411 set is_ipv6 [string match "*:*:*" $addr]
412
413 # Soften result of an illegal -length parameter.
414 if { ![info exists cidr_bits] || $cidr_bits > $v($is_ipv6,length) } {
415 set cidr_bits $v($is_ipv6,length)
416 } elseif { $cidr_bits < 0 } {
417 set cidr_bits 0
418 }
419
420 # Loop on the full length of the mask: 32 bits for ipv4, 128 for ipv6
421 for { set octet 0; set i 0 } { $i < $v($is_ipv6,length) } { incr i } {
422
423 # Take a break at intervals to save the grouping and add delimiter.
424 # Interval is 8 bits for ipv4 and 16 bits for ipv6.
425 if { $i && ![expr {$i % $v($is_ipv6,group)}] } {
426
427 # Add the grouping and delimiter to the mask, then reset.
428 append mask [format %$v($is_ipv6,format1) $octet]
429 set octet 0
430 }
431 # Shift the prior bits left by multiplying by 2.
432 # Then add the current bit, which is 1 if part of the mask, 0 if not.
433 # Current bit is part of the mask if $i < number of bits in the mask.
434 set octet [expr { 2 * $octet + ($i < $cidr_bits) }]
435 }
436 # Add the final grouping, then return the finished mask.
437 set ret_val [format $mask%$v($is_ipv6,format2) $octet]
438
439 } else {
440
441 # calculate a destination
442 # the route domain might be a name and we need a number.
443 if { ![string is integer $route_domain] } {
444 set route_domains [tmsh::get_config "/ net route-domain $route_domain"]
445 if { [llength $route_domains] != 1 } {
446 error "no such route domain: $route_domain"
447 }
448 # since we have already determined that the list is 1 long,
449 # this explicit reference to element 0 is safe
450 set route_domain [tmsh::get_field_value [lindex $route_domains 0] "id"]
451 }
452
453 set route_domain [expr { $route_domain == -1 ? "" : "%$route_domain" }]
454
455 # 0 and * represent wildcard port assignments in the GUI,
456 # but TMSH requires the string 'any' to specify a wildcard.
457 if { $port == 0 || $port == "*" } {
458 set port any
459 }
460
461 # Build the final destination. Use ":" for node names even if ipv6.
462 set is_ipv6_literal [string match "*:*:*" $addr]
463 set addr_delimiter [expr { $is_ipv6_literal ? "." : ":" }]
464 set ret_val ${addr}${route_domain}${addr_delimiter}${port}
465 }
466 return $ret_val
467}
468
469proc iapp_pool_members { args } {
470
471 # Set defaults.
472 array set fields {
473 address addr
474 port port
475 port-secure port_secure
476 connection-limit connection_limit
477 priority-group priority
478 ratio ratio
479 }
480 set route_domain ""
481 set port_override -1
482 set aaa_domain 0
483 set aaa_priority -1
484 set app_service ""
485 # Set up flag-related work.
486 array set flags {
487 -fields { [array set fields [iapp_pull $ptr args]] }
488 -route_domain { [set route_domain [iapp_pull $ptr args]] }
489 -port { [set port_override [iapp_pull $ptr args]] }
490 -aaa_domain { [set aaa_domain 1] }
491 -aaa_pool { [set aaa_priority 0] }
492 -noapp { [set app_service " app-service none"] }
493 }
494 iapp_process_flags flags args
495
496 # Identify the non-address/non-port fields. These go inside braces in tmsh.
497 set nonport_fields [lsearch -all -not -inline -regexp \
498 [array names fields] {address|port|port-secure}]
499
500 set members ""
501 foreach row [join $args] {
502
503 # Skip invalid table rows.
504 if { [llength [join $row]] %2 == 1 } {
505 continue
506 }
507
508 # Import APL table into an array for processing.
509 array unset columns
510 array set columns [join $row]
511 set addr $columns($fields(address))
512
513 # Identify the port number, either from table columns or by -port flag.
514 if { $port_override != -1 } {
515 set port $port_override
516 } elseif { [info exists columns($fields(port))] } {
517 set port $columns($fields(port))
518 } elseif { [info exists columns($fields(port-secure))] } {
519 set port $columns($fields(port-secure))
520 } else {
521 set port 80
522 }
523
524 # If specified, strip entered route domain and append the flag value.
525 if { $route_domain != "" } {
526 set addr [lindex [split $addr "%"] 0]
527 set addr "$addr%$route_domain"
528 }
529
530 # If -aaa_domain, use domain controller format, otherwise use pool format
531 if { $aaa_domain } {
532 append members " $columns($fields(host)) \{ ip $addr $app_service \}"
533 } else {
534 append members " [iapp_destination $addr $port] \{"
535
536 # Transfer non-port fields from the table to the tmsh string.
537 foreach name $nonport_fields {
538 if { [info exists columns($fields($name))] } {
539 append members " $name $columns($fields($name))"
540 }
541 }
542
543 # If -aaa_pool, add priority field with incrementing value.
544 # This is required by APM.
545 if { $aaa_priority >= 0 } {
546 append members " priority-group [incr aaa_priority]$app_service"
547 }
548 append members " \}"
549 }
550 }
551
552 return "[expr { $aaa_domain ? "" : "members " }][expr { $members eq "" \
553 ? "none" : "replace-all-with \{ $members \}" }]"
554}
555
556proc iapp_debug { args } {
557
558 # Passwords should be obscured in all logs. Fields shown here are handled
559 # in this proc, but the global variable may be overwritten if alternate
560 # fields should be obscured.
561 if { ![info exists ::SENSITIVES] } {
562 set ::SENSITIVES {
563 account-password
564 admin-encrypted-password
565 bind-pw
566 PASSWORD
567 password
568 passwd
569 proxy-ca-passphrase
570 secret
571 }
572 }
573
574 # look for any of the sensitive words, and replace the word that follows it
575 set regex "(\\m([join $::SENSITIVES |])\\M)\\s+\[^\\s\]*"
576 regsub -all $regex [join $args] {\1 -OBSCURED-} args
577 regsub -all "(<Password.*>).*(</Password>)" $args {\1-OBSCURED-\2} args
578
579 set lev [tmsh::get_field_value [lindex [tmsh::get_config sys scriptd \
580 log-level] 0] log-level]
581 if { $lev eq {debug} } {
582 puts $args
583 }
584}
585
586# The apm_config proc provides a tmsh pre-processor for APM
587# configuration, which in most cases will drastically reduce
588# implementation code. To configure APM with this proc, pass
589# it an array of object names and associated meta-tag substitutions.
590# Each object must be categorized as a profile, a resource, or
591# a policy-item. APM agents and customization-groups are derived
592# from these 3 categories as needed.
593#
594# apm_config's return value is a list of the APM profiles defined
595# in the argument and instantiated by the proc. This allows the
596# procedure call to be embedded directly into a virtual server
597# definition.
598#
599# These universal meta-tags may be placed anywhere in the array:
600# <ITEM> The object name, eg. apm_access
601# <PREFIX> The app name, including folder, eg. /Common/my_app.app/my_app
602#
603# Profile objects require the following meta-tags:
604# <PROFILE_TYPE> The tmsh object type, eg. "apm profile access"
605# <PROFILE_DEF> The body of the object, eg.:
606# "access-policy <PREFIX>
607# defaults-from /Common/access
608# eps-group <PREFIX>_eps
609# errormap-group <PREFIX>_errormap
610# general-ui-group <PREFIX>_general_ui"
611#
612# apm_config will automatically create default customization-groups
613# for the "-group" lines specified in access profile definitions.
614# In the above example, there is no need to additionally specify a
615# customization-group for errormap and general-ui.
616#
617# <PROFILE_TYPE> is a catch-all for other APM types, eg:
618# apm_sso {
619# <PROFILE_TYPE> {apm sso kerberos}
620# <PROFILE_DEF> "account-name <USER>
621# account-password <PASS>
622# realm <REALM>" }
623#
624# In the example above, <PROFILE_TYPE> and <PROFILE_DEF> are
625# apm_config meta-tags, while <USER>, <PASS>, and <REALM> must
626# be substituted before calling apm_config, eg. if these tags are
627# defined in $pre_proc_map, they may be substituted with:
628# array set apm_map [string map [subst $pre_proc_map] [array get apm_map]]
629#
630# Resource objects require the following meta-tags:
631# <RESOURCE_TYPE> The apm resource object type, eg. "webtop"
632# <RESOURCE_DEF> The body of the object, eg.:
633# "customization-group <ITEM>
634# minimize-to-tray false
635# webtop-type full"
636#
637# In the above example, a customization-group is specified. Any
638# customization-group is assumed to be blank unless further defined by the
639# <GROUP_DEF> meta-tag, eg. <GROUP_DEF> {type webtop}
640#
641# Policy-item objects are defined by the following meta-tags:
642# <AGENT_TYPE> default "resource-assign"
643# <AGENT_DEF> default "customization-group <ITEM>"
644# <ITEM_AGENT> default "agents { <ITEM>_ag { type <AGENT_TYPE> }}"
645# <ITEM_CAPTION> default "<ITEM>"
646# <ITEM_COLOR> default "1"
647# <ITEM_TYPE> default "action"
648# <ITEM_RULES> defaults to a set of expressions/next-items where specified
649# <RULE_CAPTION_0> default "fallback"
650# <RULE_CAPTION_1> default "Successful"
651# <RULE_CAPTION_2> default "successful"
652#
653# apm_config generates the APM agent and customization-group definitions
654# as required for each policy-item, but specific objects may be defined
655# by using the <AGENT_DEF> and <GROUP_DEF> meta-tags.
656# To suppress the formation of an APM agent, specify <ITEM_AGENT> {}.
657
658proc iapp_apm_config { args } {
659
660 set app_service ""
661 array set flags {
662 -noapp { [set app_service "app-service none\n "] }
663 }
664 iapp_process_flags flags args
665
666 upvar [lindex $args 0] map_array
667
668 # Pull $prefix from the array
669 set prefix $map_array(prefix)
670 unset map_array(prefix)
671
672 # Stencils for creating apm objects
673 set access_form \
674 "<TMSH_CREATE> apm policy access-policy <ITEM> {\n \
675 $app_service caption general\n \
676 start-item <ACCESS_START_ITEM>\n \
677 default-ending <ACCESS_ENDING>\n \
678 items replace-all-with {\n<ACCESS_ITEMS> }\n}"
679
680 set profile_form "<TMSH_CREATE> <PROFILE_TYPE> <ITEM> {\n \
681 $app_service <PROFILE_DEF>\n}"
682
683 set resource_form "<TMSH_CREATE> apm resource <RESOURCE_TYPE> <ITEM> {\n \
684 $app_service <RESOURCE_DEF>\n}"
685
686 set agent_form "<TMSH_CREATE> apm policy agent <AGENT_TYPE> <ITEM>_ag {\n \
687 $app_service <AGENT_DEF>\n}"
688
689 set group_form "<TMSH_CREATE> apm policy customization-group <ITEM> {\
690 $app_service <GROUP_DEF>}"
691
692 set agent_group_form "<TMSH_CREATE> apm policy customization-group <ITEM>_ag {\
693 $app_service <GROUP_DEF>}"
694
695 set policy_item_form "<TMSH_CREATE> apm policy policy-item <ITEM> {
696 $app_service <ITEM_AGENT>caption <ITEM_CAPTION>
697 color <ITEM_COLOR>
698 <ITEM_TYPE>
699 <ITEM_RULES>\n}"
700
701 # 1st round apm string map
702 set default_map_1 {
703 <ACCESS_ITEM> {}
704 <AGENT_DEF> "customization-group <ITEM>_ag"
705 <ITEM_AGENT> "agents replace-all-with {
706 <ITEM>_ag { type <AGENT_TYPE> }}\n "
707 <ITEM_CAPTION> <ITEM>
708 <ITEM_COLOR> {1}
709 <ITEM_TYPE> "item-type action"
710 <ITEM_RULES> "rules
711 {[expr {[string first <RULE_NEXT_2> $map_array($item)] != -1 ? "{
712 caption <RULE_CAPTION_2>
713 expression <RULE_EXPR_2>
714 next-item ${prefix}_<RULE_NEXT_2>
715 }":""}][expr {[string first <RULE_NEXT_1> $map_array($item)] != -1 ? "{
716 caption <RULE_CAPTION_1>
717 expression <RULE_EXPR_1>
718 next-item ${prefix}_<RULE_NEXT_1>
719 }":""}]{
720 caption <RULE_CAPTION_0>
721 next-item ${prefix}_<RULE_NEXT_0>
722 }}"
723 }
724
725 # 2nd round apm string map
726 set default_map_2 {
727 <ITEM> [expr { $item eq {default} ? "$prefix" : "${prefix}_$item" }]
728 <PREFIX> $prefix
729 <LOCAL_PATH> [string map {/ :} $prefix]
730 <GROUP_DEF> ""
731 <AGENT_TYPE> "resource-assign"
732 <RULE_CAPTION_2> "successful"
733 <RULE_CAPTION_1> "Successful"
734 <RULE_CAPTION_0> "fallback"
735 }
736
737 # Build APM access profile and access-policy from the access_form.
738 # Tags <ACCESS_ITEM> and <ACCESS_ENDING> are picked up from
739 # $map_array items. <ITEM> and <GROUP_DEF> are picked up from
740 # $default_map_2.
741 foreach item [lsort [array names map_array]] {
742
743 # Pick up the <ACCESS_ENDING> tag. There should be just 1.
744 set access_form [string map $map_array($item) $access_form]
745
746 # Filter out items that do not belong in the access-policy.
747 # Anything with an ITEM_xxx tag belongs
748 if { [string first <ITEM_ $map_array($item)] == -1 } {
749 continue
750 }
751
752 # Add to the items list for the access-policy, e.g. priority
753 append access_items " ${prefix}_$item {<ACCESS_ITEM>}\n"
754 set access_items [string map $map_array($item) $access_items]
755 set access_items [string map [subst $default_map_1] $access_items]
756 }
757
758 # Build APM resources, policy-items, agents, and customization-groups from
759 # the policy_item_form and resource_form.
760 foreach item [lsort [array names map_array]] {
761
762 # Each item starts as a profile, a resource, or a policy-item.
763 # Profiles are free-form, so other apm objects can use the profile form.
764 # In most cases, a policy-item spawns an agent.
765 # Any definition specifying a customization-group will spawn that group.
766 if { [string first "<PROFILE_DEF>" $map_array($item)] != -1 } {
767
768 # Collect profile names for attachment to the virtual server
769 if { [string first "apm profile " $map_array($item)] != -1 } {
770 lappend profiles [expr { $item eq {default}
771 ? "$prefix" : "${prefix}_$item" }]
772 # When an access profile is found, built a policy of the same name
773 if { [string first "apm profile access" $map_array($item)] != -1 } {
774 set def [string map "<ACCESS_ITEMS> {$access_items}" $access_form]
775 append cmds "[string map [subst $default_map_2] $def]\n"
776 }
777 }
778 set def $profile_form
779 } elseif { [string first "<RESOURCE_DEF>" $map_array($item)] != -1 } {
780 set def $resource_form
781 } else {
782 set def $policy_item_form
783 if { [string first "<ITEM_AGENT> {}" $map_array($item)] == -1 } {
784 append def $agent_form
785 }
786 }
787
788 # Apply 1st pass of string maps
789 set def [string map $map_array($item) $def]
790 set def [string map [subst $default_map_1] $def]
791
792 # If a customization-group is specified, add its definition
793 if { [string first "customization-group" $def] != -1 } {
794 if { [string first "apm policy agent" $def] != -1 } {
795 append def $agent_group_form
796 } elseif { [string first "apm profile access" $def] == -1 } {
797 append def $group_form
798 }
799 }
800
801 # Apply 2nd pass of string maps
802 set def [string map $map_array($item) $def]
803 append cmds [string map [subst $default_map_2] $def]
804 }
805
806 # Divide and execute tmsh commands
807 set tag "<TMSH_CREATE>"
808 set tag_length [string length $tag]
809 set last [expr { [string first $tag $cmds] + $tag_length }]
810 while { [set pos [string first $tag $cmds $last]] != -1 } {
811 incr pos -1
812 iapp_conf create [string range $cmds $last $pos]
813 set last [expr { $pos + $tag_length + 1 }]
814 }
815 iapp_conf create [string range $cmds $last end]
816 return $profiles
817}
818
819proc iapp_upgrade_template { upgrade_var upgrade_trans } {
820 upvar $upgrade_var upgrade_var_arr
821 upvar $upgrade_trans upgrade_trans_arr
822
823 # create the new variables from the old
824 foreach { var } [array names upgrade_var_arr] {
825
826 # substitute old variable name for abbreviation "##"
827 regsub -all {##} $upgrade_var_arr($var) \$$var map_cmd
828
829 # run the mapping command from inside the array
830 if { [catch { subst $map_cmd } err] } {
831 if { [string first "no such variable" $err] == -1 } {
832 puts "ERROR $err"
833 }
834 }
835 }
836
837 # move variables over and apply translations
838 set var_mods ""
839 set var_adds ""
840 foreach var [array names vx] {
841
842 # if the APL variable name is in the translation array,
843 # then use the custom translation built for that variable.
844 if { [info exists upgrade_trans_arr($var)] } {
845 array set sub_arr [subst $upgrade_trans_arr($var)]
846 if { [info exists sub_arr($vx($var))] } {
847 set vx($var) $sub_arr($vx($var))
848 }
849 array unset sub_arr
850 # else, if the APL variable value is in the translation array,
851 # then use the generic translation of that value.
852 } elseif { [info exists upgrade_trans_arr($vx($var))] } {
853 set vx($var) [subst $upgrade_trans_arr($vx($var))]
854 }
855
856 # add to tmsh command string
857 if { [info exists ::$var] } {
858 append var_mods "\n $var \{ value \"$vx($var)\" \} "
859 } else {
860 append var_adds "\n $var \{ value \"$vx($var)\" \} "
861 }
862 }
863
864 # move tables over
865 set tbl_mods ""
866 set tbl_adds ""
867 foreach tbl [array names tx] {
868
869 # convert table from APL format to TMSH format
870 if { ![llength $tx($tbl)] } {
871 set tbl_def "column-names none"
872 } else {
873 set rows_def ""
874 foreach apl_row $tx($tbl) {
875 array set row_arr [join $apl_row]
876 append rows_def "\n \{ row \{ "
877 foreach apl_col [array names row_arr] {
878 append rows_def "$row_arr($apl_col) "
879 }
880 append rows_def "\}\}"
881 }
882 set tbl_def \
883 "\n column-names \{ [array names row_arr] \} rows \{ $rows_def \}"
884 array unset row_arr
885 }
886
887 # add to tmsh command string
888 if { [info exists ::$tbl] } {
889 append tbl_mods "\n $tbl \{ $tbl_def \} "
890 } else {
891 append tbl_adds "\n $tbl \{ $tbl_def \} "
892 }
893 }
894
895 # construct the "tmsh modify" command
896 set cmd "sys application service $tmsh::app_name "
897 if { [llength $var_mods] } {
898 append cmd "\nvariables modify { $var_mods }"
899 }
900 if { [llength $var_adds] } {
901 append cmd "\nvariables add { $var_adds }"
902 }
903 if { [llength $tbl_mods] } {
904 append cmd "\ntables modify { $tbl_mods }"
905 }
906 if { [llength $tbl_adds] } {
907 append cmd "\ntables add { $tbl_adds }"
908 }
909
910 # Execute with debug output. This conversion takes place within the
911 # existing ASO, so tmsh modify is used instead of tmsh create.
912 iapp_debug "TEMPLATE UPGRADE"
913 iapp_conf modify $cmd
914 return
915}
916
917proc iapp_downgrade_template { pivot_var upgrade_var downgrade_table } {
918 upvar $downgrade_table downgrade_tbl_arr
919
920 # The ASO variable "offload_history" is used to recover the legacy
921 # choice a user made about SSL offload. It should be present in all cases.
922 # This conditional only handles the case where a user has deliberately
923 # deleted it by manipulating the ASO directly from tmsh.
924 if { ![info exists ::offload_history] } {
925 set ::offload_history "No"
926 }
927
928 # BIG-IP erases table contents when the APL optional hides the table.
929 # Since the prior data is not available, this downgrade must back-convert
930 # existing table data. Unlike tables, variables remain intact from the
931 # legacy ASO.
932 set tbl_def ""
933 foreach tbl [array names downgrade_tbl_arr] {
934 # Check for existence of each table in the current context.
935 # If not, skip to next.
936 if { ![info exists [set tbl]] } {
937 continue
938 }
939 # Check for existence of each table in the legacy context.
940 # If not, add an empty table so "tmsh tables modify" does not fail.
941 if { ![info exists ::$downgrade_tbl_arr($tbl)] } {
942 iapp_conf modify sys app ser $tmsh::app_name tables add \{ $downgrade_tbl_arr($tbl) \}
943 }
944 append tbl_def "$downgrade_tbl_arr($tbl) \{ "
945 if { [llength [subst $$tbl]] } {
946 set rows_def ""
947 foreach apl_row [subst $$tbl] {
948 array set row_arr [join $apl_row]
949 append rows_def "\n \{ row \{ "
950 foreach apl_col [array names row_arr] {
951 append rows_def "$row_arr($apl_col) "
952 }
953 append rows_def "\}\}"
954 }
955 append tbl_def \
956 "column-names \{ [array names row_arr] \} rows \{ $rows_def \}"
957 array unset row_arr
958 } else {
959 append tbl_def "rows none"
960 }
961 append tbl_def " \} "
962 }
963 regsub -all "\n" $tbl_def {} tbl_def
964 set cmd "sys app ser $tmsh::app_name \
965 variables modify \{ \
966 $pivot_var \{ value $::offload_history \} \
967 $upgrade_var \{ value No \} \
968 \} \
969 tables modify \{ $tbl_def \}"
970 iapp_debug "TEMPLATE DOWNGRADE"
971 iapp_conf modify $cmd
972 return
973}
974
975proc iapp_get_ca_certs { args } {
976 # Procedure formats and returns ca-bundle 509 certificates from ca-bundle.bak
977 # (copy of tmos supplied ca-bundle.crt)
978 # Returns backup files when using -files flag
979 # Returns specified restore file certificates when using -restore -return flags
980 # Returns specified restore file table certificates when using -restore -tablename
981 # Returns selected certificates
982 #
983 # Set defaults. Flag actions may overwrite defaults later.
984 set rest_files 0
985 set do_restore 0
986 set restore_return 0
987 set restore_table_name 0
988 set do_certs 0
989 set user_get [iapp_get_user]
990 set username [string range $user_get [expr {[string last user $user_get] +5 }] end-3 ]
991 # Set up flag-based actions.
992 array set flags {
993 -files { [set rest_files 1] }
994 -return { [set do_restore 1] [set restore_return 1] }
995 -tablename { [set do_restore 1] [set restore_table_name 1] }
996 -certs { [set do_certs 1] }
997 }
998 iapp_process_flags flags args
999 set fn_ca_bundle "[lindex $args 0]"
1000 set cert_choices "[lindex $args 1]"
1001 set duplicate " "
1002 if { $rest_files eq 0 || $do_restore } {
1003 set fh_ca_bundle [open $fn_ca_bundle r]
1004 set ca_bundle_data [read $fh_ca_bundle]
1005 close $fh_ca_bundle
1006 set ca_bundle_split [split [string map "{-----END CERTIFICATE-----} \001" $ca_bundle_data] "\001"]
1007 set final ""
1008 set r 0
1009 # Grab Subject Name and Serial number from each certificate
1010 foreach subject $ca_bundle_split {
1011 if {$subject eq {}} {
1012 continue
1013 }
1014 incr r
1015 set a [string first Subject: $subject]
1016 set b [string first \n $subject $a]
1017 set ab [string range $subject $a $b]
1018 set c [expr {[string first O= $ab] +2}]
1019 if { $c < 2 }{
1020 set c [expr {[string first CN= $ab] +2}]
1021 }
1022 set d [expr {[string first , $ab $c] -1}]
1023 # Deal with case were comma is not present after subject name
1024 if { $d < 0 }{
1025 set dc [string range $ab $c end-1]
1026 # Deal with case were text is not able to be located using common name, just grab the first 30 characters
1027 } elseif { $d > 2000 }{
1028 set dc [string range $ab $c 47]
1029 } else {
1030 set dc [string range $ab $c $d]
1031 }
1032 set f [expr {[string first Number: $subject] +7}]
1033 set g [expr {[string first Signature $subject $f] -1}]
1034 set fg [string range $subject $f $g]
1035 # Remove spaces and new line characters from serial number
1036 set fg_nospace [string map {" " "" "\n" "" ":" ""} $fg]
1037 set ref $r
1038 # -cert flag returns list of selected root certificates
1039 if { $do_certs }{
1040 foreach selection $cert_choices {
1041 if { $ref eq $selection }{
1042 # add certificate
1043 append final "${subject}-----END CERTIFICATE-----\n"
1044 puts [tmsh::log notice "User:'${username}' Modified CA-Bundle, adding the following Root CA:(SN) ${fg_nospace} Name:${dc}"]
1045 append duplicate "$ref "
1046 }
1047 }
1048 } elseif { $dc !="" || $fg_nospace !="" || $restore_table_name eq 1 }{
1049 if { $restore_return eq 0 && $restore_table_name eq 0 }{
1050 append final "${dc},(${r})\t${ref}\n"
1051 } elseif { $restore_table_name eq 1 }{
1052 set table_cert [string first ### $subject]
1053 if { $table_cert > -1 && $table_cert < 500 } {
1054 set ending "$subject-----END CERTIFICATE-----"
1055 set table_certificate [string range $ending [string first -----BEGIN $ending] [ expr { [string first -----END $ending] +24 }]]
1056 append final "{ row { \"[string map {"\n" " "} $table_certificate]\" \"[string range $subject 4 [expr { [string first \n $subject 1] -1 }]]\" } }"
1057 }
1058
1059 } else {
1060 set table_cert [string first ### $subject]
1061 if { $table_cert < 0 || $table_cert > 500 } {
1062 append final "${ref} "
1063 }
1064 }
1065 }
1066 }
1067 if { $do_restore && $restore_table_name eq 0 }{
1068 set final [string map {"(" ""} $final]
1069 }
1070 return $final
1071 }
1072 if { $rest_files }{
1073 # Pull TMOS ca-bundle file into list
1074 catch { set fn_bak_ca_bundle [exec ls -t /config/ssl/ssl.crt/] } err
1075 if { $::errorCode != "" && $::errorCode != "NONE"} {
1076 puts "Error during file lookup in ssl certificate directory: ${err}"
1077 error "Error during file lookup in ssl certificate directory: ${err}"
1078 }
1079 foreach bak [join "$fn_bak_ca_bundle"] {
1080 set full_path "/config/ssl/ssl.crt/$bak"
1081 if { [iapp_is full_path $fn_ca_bundle] }{
1082 set fn_bak_exists 1
1083 break
1084 } else {
1085 set fn_bak_exists 0
1086 }
1087 }
1088 if { $fn_bak_exists }{
1089 puts "Backup of factory TMOS ca-bundle /config/ssl/ssl.crt/ca-bundle.crt, at:${fn_ca_bundle}, already exists. No need to backup"
1090 } elseif { $fn_bak_exists eq 0 }{
1091 puts "Backing up factory TMOS ca-bundle /config/ssl/ssl.crt/ca-bundle.crt, to ${fn_ca_bundle}."
1092 catch { exec cp /config/ssl/ssl.crt/ca-bundle.crt ${fn_ca_bundle} } err
1093 if { $::errorCode != "" && $errorCode != "NONE" } {
1094 puts "Error creating backup file:${fn_ca_bundle}: ${err}"
1095 error "Error creating backup file:${fn_ca_bundle}: ${err}"
1096 }
1097 }
1098 set restore_list [lsearch -all -inline $fn_bak_ca_bundle *_bak*]
1099 set restore_final ""
1100 foreach res $restore_list {
1101 append restore_final "${res}\t${res}\n"
1102 }
1103 if { $restore_final == "" }{
1104 return "No restore files found"
1105 } else {
1106 return $restore_final
1107 }
1108 }
1109}
1110 app-service none
1111 description none
1112 ignore-verification false
1113 script-checksum none
1114 script-signature none
1115 signing-key none
1116}
1117sys application template /Common/f5.microsoft_adfs.v1.2.0rc6 {
1118 actions {
1119 definition {
1120 html-help {
1121 }
1122 implementation {
1123 tmsh::include f5.iapp.1.5.6.cli
1124iapp_template start
1125
1126#constants
1127set DEFAULT_ANSWER /#default#
1128set DO_NOT_USE_ANSWER /#do_not_use#
1129set CREATE_NEW_ANSWER /#create_new#
1130
1131proc arrange_tcp_profiles { client_profile server_profile } {
1132 if { $client_profile == $server_profile } {
1133 set profile_list "$client_profile \{ context all \} "
1134 } else {
1135 set profile_list "$client_profile \{ context clientside \} \
1136 $server_profile \{ context serverside \} "
1137 }
1138 return $profile_list
1139}
1140
1141array set forms {
1142 adfs_monitor_eav_script {#!/bin/sh
1143# These arguments supplied automatically for all external monitors:
1144# $1 = IP (nnn.nnn.nnn.nnn notation)
1145# $2 = port (decimal, host byte order)
1146#
1147# This script expects the following Name/Value pairs:
1148# HOST = the host name of the SNI-enabled site
1149# URI = the URI to request
1150# RECV = the expected response
1151#
1152# Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
1153NODE=`echo ${1} | sed 's/::ffff://'`
1154if [[ $NODE =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
1155NODE=${NODE}
1156else
1157NODE=[${NODE}]
1158fi
1159PORT=${2}
1160PIDFILE="/var/run/`basename ${0}`.sni_monitor_${HOST}_${PORT}_${NODE}.pid"
1161if [ -f $PIDFILE ]
1162then
1163echo "EAV exceeded runtime needed to kill ${HOST}:${PORT}:${NODE}" | logger -p local0.error
1164kill -9 `cat $PIDFILE` > /dev/null 2>&1
1165fi
1166echo "$$" > $PIDFILE
1167<CURL> -k -i --resolve $HOST:$PORT:$NODE https://$HOST$URI | grep -i "${RECV}" > /dev/null 2>&1
1168STATUS=$?
1169rm -f $PIDFILE
1170if [ $STATUS -eq 0 ]
1171then
1172echo "UP"
1173fi
1174exit
1175 }
1176}
1177# Writes the external monitor for the autodiscover service.
1178proc create_eav_script { script_name } {
1179 set app $tmsh::app_name
1180 set eav_script_name /config/monitors/${app}_$script_name
1181 set map "microsoft_adfs $app
1182 <CURL> [expr { [file exists /usr/bin/curl-apd] ? "curl-apd" : "curl" }]"
1183 set fn [open "$eav_script_name" "w" "0755"]
1184 # This string map pulls the static bash script out of the forms array and
1185 # customizes it for http or https based on the user's SSL selections.
1186 puts $fn [string map $map $::forms($script_name)]
1187 close $fn
1188 return $eav_script_name
1189}
1190# Create the APM message box file for Azure MFA
1191proc create_apm_custom_file { script_name } {
1192 set app $tmsh::app_name
1193 set eav_script_name /var/tmp/${app}_$script_name
1194 set customization_file {<?xml version="1.0" encoding="utf-8"?>
1195 <customization_group name="default_4" type="4">
1196 <item language="en">
1197 <form_message>Multi-Factor Authentication(MFA) is required before access to the service is granted, please click below to start the process</form_message>
1198 <link>Click here to start MFA</link>
1199 </item>
1200 </customization_group>}
1201 set fn [open "$eav_script_name" "w" "0755"]
1202 puts $fn $customization_file
1203 close $fn
1204 return $eav_script_name
1205}
1206
1207proc configure_apm { } {
1208 tmsh::include f5.iapp.1.5.6.cli
1209 set is_120 [iapp_tmos_version >= 12.0]
1210 set app $tmsh::app_name
1211 set advanced [expr { [iapp_is ::basic__advanced "yes"] }]
1212
1213 # Check if using existing APM profile and simply return profile name and exit proc if so
1214 # Cant't get here without apm being 'create new profile' or custom profile so just need to check if it isn't 'create new profile'
1215 if { [iapp_is ::apm__use_apm "yes"] && ![iapp_is ::apm__apm_profile "/#create_new#"] } {
1216 return $::apm__apm_profile
1217 }
1218
1219 # APM
1220 # AAA config
1221 # array keys: $advanced,$::apm__ad_secure
1222 array set aaa_port {
1223 1,ssl {$::apm__ad_port_ssl}
1224 1,tls {$::apm__ad_port_not_ssl}
1225 1,none {$::apm__ad_port_not_ssl}
1226 0,ssl {636}
1227 0,tls {389}
1228 0,none {389}
1229 }
1230
1231 # array key: $::apm__ad_monitor
1232 array set aaa_monitor {
1233 /#create_new# { [iapp_conf create ltm monitor ldap ${app}_ldap \
1234 base \"$::apm__ad_tree\" \
1235 chase-referrals yes \
1236 debug no \
1237 defaults-from ldap \
1238 destination *:[subst $aaa_port($advanced,$::apm__ad_secure)] \
1239 filter \"cn=$::apm__ad_user\" \
1240 interval [expr { $advanced ? $::apm__ad_interval : "10" }] \
1241 timeout [expr {$advanced ? ($::apm__ad_interval * 3 + 1):"31"}] \
1242 mandatory-attributes no \
1243 password [iapp_make_safe_password $::apm__ad_password] \
1244 security $::apm__ad_secure \
1245 time-until-up 0 \
1246 username \"cn=${::apm__ad_user},${::apm__ad_tree}\"] }
1247 /#use_icmp# { [iapp_conf create ltm monitor gateway-icmp ${app}_icmp \
1248 defaults-from gateway_icmp \
1249 interval 5 \
1250 timeout 16] }
1251 /#do_not_use# { none }
1252 }
1253
1254 # array key: $multiple_ad
1255 array set aaa_pool {
1256 1 { domain-controllers [iapp_pool_members -aaa_domain -fields { host fqdn } $::apm__active_directory_servers] \
1257 pool [iapp_conf create ltm pool ${app}_aaa [iapp_pool_members $::apm__active_directory_servers -port any -aaa_pool] \
1258 load-balancing-mode "round-robin" \
1259 monitor [expr { [iapp_is ::apm__ad_monitor "/#create_new#"] \
1260 || [iapp_is ::apm__ad_monitor "/#use_icmp#"] \
1261 || [iapp_is ::apm__ad_monitor "/#do_not_use#"] \
1262 ? [subst $aaa_monitor($::apm__ad_monitor)] \
1263 : $::apm__ad_monitor } ] \
1264 min-active-members 1] }
1265 0 { domain-controller $::apm__active_directory_server }
1266 }
1267
1268 set do_new_aaa [iapp_is ::apm__aaa_profile "/#create_new#"]
1269 set credentials [iapp_is ::apm__credentials "yes"]
1270 set multiple_ad 1
1271
1272 # array key: $do_new_aaa
1273 array set aaa_server {
1274 1 {[iapp_conf create apm aaa active-directory ${app}_apm_aaa \
1275 \{ admin-encrypted-password [expr { $credentials ? "[iapp_make_safe_password $::apm__active_directory_password]" : "none" }] \
1276 admin-name [expr { $credentials ? "$::apm__active_directory_username" : "none" }] \
1277 domain "$::apm__login_domain" [subst $aaa_pool($multiple_ad)] \}] }
1278 0 { $::apm__aaa_profile }
1279 }
1280
1281 set ad_aaa [iapp_substa aaa_server($do_new_aaa)]
1282
1283
1284 # Configure RADIUS pool for Azure MFA servers
1285 # array key: $::apm__mfa_radius_monitor
1286 array set mfa_radius_monitor {
1287 /#use_icmp# { [iapp_conf create ltm monitor gateway-icmp ${app}_icmp \
1288 defaults-from gateway_icmp \
1289 interval 5 \
1290 timeout 16] }
1291 /#do_not_use# { none }
1292 }
1293
1294 set do_new_mfa_radius_aaa [iapp_is ::apm__mfa_aaa_profile "/#create_new#"]
1295 # array key: $do_new_mfa_radius_aaa
1296 array set mfa_radius_aaa_server {
1297 1 {[iapp_conf create apm aaa radius ${app}_mfa_aaa secret [iapp_make_safe_password $::apm__mfa_radius_secret] \
1298 pool [iapp_conf create ltm pool ${app}_mfa_aaa [iapp_pool_members $::apm__mfa_radius_servers -port any -aaa_pool] \
1299 load-balancing-mode "round-robin" \
1300 monitor [expr { [iapp_is ::apm__mfa_radius_monitor "/#use_icmp#"] \
1301 || [iapp_is ::apm__mfa_radius_monitor "/#do_not_use#"] \
1302 ? [subst $mfa_radius_monitor($::apm__mfa_radius_monitor)] \
1303 : $::apm__mfa_radius_monitor } ] \
1304 min-active-members 1] auth-port $::apm__mfa_radius_port] acct-port $::apm__mfa_radius_acct_port }
1305 0 { $::apm__mfa_aaa_profile }
1306 }
1307 set do_mfa [expr { [info exists ::apm__mfa] && [iapp_is ::apm__mfa "yes"] }]
1308 set mfa_yes_no [expr { $do_mfa ? "apm_mfa_message_box" : "apm_credentials" }]
1309 set mfa_radius_aaa [expr { $do_mfa ? "[iapp_substa mfa_radius_aaa_server($do_new_mfa_radius_aaa)]" : "no_mfa_radius" }]
1310
1311 # APM config
1312 set pre_proc_map "
1313 <NTLM_DOMAIN> $::apm__login_domain
1314 <AAA> $ad_aaa
1315 <MFA_YES_NO> $mfa_yes_no"
1316
1317 if { $do_mfa } {
1318 append pre_proc_map { <MFA_RADIUS_AAA> $mfa_radius_aaa <MFA_MSG_BOX_CUSTOM_FILE> [create_apm_custom_file msg_box_custom_file] }
1319 }
1320 if { $is_120 } {
1321 if { $::apm__log_settings == "/#do_not_use#" } {
1322 append pre_proc_map { <LOG_SETTINGS> "log-settings none" }
1323 } else {
1324 append pre_proc_map { <LOG_SETTINGS> "log-settings replace-all-with \{ $::apm__log_settings \}" }
1325 }
1326 } else {
1327 append pre_proc_map { <LOG_SETTINGS> "" }
1328 }
1329
1330 array set apm_map {
1331 apm_ntlm_sso {
1332 <PROFILE_TYPE> {apm sso ntlmv1}
1333 <PROFILE_DEF> "ntlm-domain <NTLM_DOMAIN>" }
1334 default {
1335 <PROFILE_TYPE> {apm profile access}
1336 <GROUP_DEF> {type logout }
1337 <PROFILE_DEF> "accept-languages replace-all-with { en }
1338 access-policy <PREFIX>
1339 defaults-from /Common/access
1340 generation-action increment
1341 domain-mode single-domain
1342 domain-cookie none
1343 persistent-cookie false
1344 secure-cookie true
1345 logout-uri-include none
1346 logout-uri-timeout 5
1347 customization-group <PREFIX>_logout
1348 eps-group <PREFIX>_eps
1349 errormap-group <PREFIX>_errormap
1350 framework-installation-group <PREFIX>_frameworkinstallation
1351 general-ui-group <PREFIX>_general_ui
1352 sso-name <PREFIX>_apm_ntlm_sso
1353 <LOG_SETTINGS>" }
1354 apm_ent {
1355 <ITEM_AGENT> {}
1356 <ITEM_CAPTION> {"Start"}
1357 <ITEM_TYPE> {}
1358 <RULE_NEXT_0> apm_logon }
1359 apm_logon {
1360 <ACCESS_ITEM> { priority 2 }
1361 <AGENT_TYPE> logon-page
1362 <ITEM_CAPTION> {"Logon Page"}
1363 <RULE_NEXT_0> apm_auth }
1364 apm_auth {
1365 <ACCESS_ITEM> { priority 3 }
1366 <AGENT_TYPE> aaa-active-directory
1367 <AGENT_DEF> "server <AAA>\n type auth"
1368 <ITEM_CAPTION> {"AD Auth"}
1369 <RULE_EXPR_1> {"expr {[mcget {session.ad.last.authresult}] == \"1\"}"}
1370 <RULE_NEXT_1> <MFA_YES_NO>
1371 <RULE_NEXT_0> apm_deny }
1372 apm_mfa_message_box {
1373 <ACCESS_ITEM> { priority 4 }
1374 <ITEM_TYPE> {item-type action}
1375 <GROUP_DEF> {type message-box local-path <MFA_MSG_BOX_CUSTOM_FILE>}
1376 <AGENT_TYPE> message-box
1377 <ITEM_CAPTION> {"Azure MFA Prompt"}
1378 <ITEM_MESSAGE> {"Please click the link below to begin Multi-Factor Authentication"}
1379 <RULE_NEXT_0> apm_mfa_radius_auth }
1380 apm_mfa_radius_auth {
1381 <ACCESS_ITEM> { priority 5 }
1382 <AGENT_TYPE> aaa-radius
1383 <AGENT_DEF> "server <MFA_RADIUS_AAA>"
1384 <ITEM_CAPTION> {"Azure MFA Auth(RADIUS)"}
1385 <RULE_EXPR_1> {"expr { [mcget {session.radius.last.result}] == 1 }"}
1386 <RULE_NEXT_1> apm_credentials
1387 <RULE_NEXT_0> apm_deny }
1388 apm_credentials {
1389 <ACCESS_ITEM> { priority 6 }
1390 <AGENT_TYPE> variable-assign
1391 <AGENT_DEF> "type sso-cred-mapping
1392 variables {{
1393 expression \"mcget {session.logon.last.username}\"
1394 varname session.sso.token.last.username }{
1395 expression \"mcget {session.logon.last.password}\"
1396 varname session.sso.token.last.password }}"
1397 <ITEM_CAPTION> {"SSO Credential Mapping"}
1398 <RULE_NEXT_0> apm_allow }
1399 apm_allow {
1400 <ACCESS_ITEM> { priority 7 }
1401 <AGENT_DEF> {}
1402 <AGENT_TYPE> ending-allow
1403 <ITEM_CAPTION> {"Allow"}
1404 <ITEM_TYPE> {item-type ending}
1405 <ITEM_RULES> {} }
1406 apm_deny {
1407 <ACCESS_ITEM> { priority 8 }
1408 <ACCESS_START_ITEM> <PREFIX>_apm_ent
1409 <ACCESS_ENDING> <PREFIX>_apm_deny
1410 <AGENT_TYPE> ending-deny
1411 <GROUP_DEF> {type logout }
1412 <ITEM_CAPTION> {"Deny"}
1413 <ITEM_TYPE> {item-type ending}
1414 <ITEM_COLOR> {2}
1415 <ITEM_RULES> {} }
1416 form_basedv2_sso {
1417
1418 <PROFILE_TYPE> {apm sso form-basedv2}
1419
1420 <PROFILE_DEF> "forms replace-all-with {
1421
1422 adfs_ls_endpoint_form {
1423
1424 controls add {
1425
1426 UserName {
1427
1428 secure false value \"%{session.sso.token.last.username}@%{session.ad.last.actualdomain}\"
1429
1430 }
1431
1432 Password {
1433
1434 secure true value \"%{session.sso.token.last.password}\"
1435
1436 }
1437
1438 }
1439
1440 request-value \"/adfs/ls\"
1441
1442 id-type id
1443
1444 attribute-value loginForm
1445
1446 submit-javascript-type auto
1447
1448 success-match-type cookie
1449
1450 success-match-value MSISAuth
1451
1452 }
1453
1454 }" }
1455 }
1456 ## Unset certain optional items as needed
1457 if { [info exists ::apm__use_forms_sso] && [iapp_is ::apm__use_forms_sso "no"] } {
1458 unset -nocomplain apm_map(form_basedv2_sso)
1459 } else {
1460 # Need to Create iRule to Select /adfs/ls endpoint Forms SSO, will be handled in iRule section
1461 }
1462 if { !$do_mfa } {
1463 unset -nocomplain apm_map(apm_mfa_message_box)
1464 unset -nocomplain apm_map(apm_mfa_radius_auth)
1465 } else {
1466 # Using Azure MFA so will leave objects in the APM policy
1467 }
1468
1469 set apm_map(prefix) [tmsh::pwd]/$app
1470
1471 # Instantiate the APM configuration (plus websso and rba)
1472 array set apm_map [string map [subst $pre_proc_map] [array get apm_map]]
1473 set apm_profiles "[iapp_apm_config apm_map] /Common/websso /Common/rba"
1474
1475 # APM policies do not commit in a reliable manner when configured via iApp.
1476 # This time-bomb script insures that the policy gets committed.
1477 catch {
1478 set dir [tmsh::pwd]
1479 set fn "/var/tmp/iapp_${app}.sh"
1480 set fh [open $fn w]
1481 puts $fh "sleep 5"
1482 puts $fh "tmsh modify apm profile access ${dir}/${app} generation-action increment"
1483 close $fh
1484 exec chmod 777 $fn
1485 exec $fn &
1486 } err
1487 return $apm_profiles
1488}
1489
1490proc configure_adfs_deployment { } {
1491 tmsh::include f5.iapp.1.5.6.cli
1492 set app $tmsh::app_name
1493 set dir [tmsh::pwd]
1494 set scenario [expr { [info exists ::basic__scenario] && [iapp_is ::basic__scenario "adfs"] }]
1495 set lb_lcm_licensed [expr {[string first ltm_lb_least_conn [tmsh::show sys license detail]] != -1}]
1496 set advanced [expr { [iapp_is ::basic__advanced "yes"] }]
1497 set adfs_version $::basic__version
1498 set use_apm [expr { [info exists ::apm__use_apm] && [iapp_is ::apm__use_apm "yes"] }]
1499 set is_v11_5 [iapp_tmos_version >= 11.5]
1500 set is_v13_1 [iapp_tmos_version >= 13.1]
1501 set adfs_proxy_flag [expr { $scenario && ($adfs_version != "v2") && $is_v13_1 && \
1502 ([info exists ::apm__adfs_proxy_setup] && [iapp_is ::apm__adfs_proxy_setup "yes"]) }]
1503 set do_cert_auth [expr { [info exists ::vs_pool__cert_auth] && $::vs_pool__cert_auth }]
1504 set do_fastl4 [expr { ( ![info exists ::apm__use_apm] || [iapp_is ::apm__use_apm "no"] ) && \
1505 !$adfs_proxy_flag && [iapp_is ::ssl__mode "passthru"]}]
1506
1507 # MONITOR
1508 set need_monitor [expr { $::vs_pool__pool_to_use == "/#create_new#" }]
1509
1510 set new_monitor [iapp_is ::app_health__monitor "/#create_new#"]
1511 set app_health_frequency [expr { [info exists ::app_health__frequency] ? $::app_health__frequency : "30" }]
1512 # array keys: $need_monitor,$new_monitor,$adfs_version
1513 array set monitor_arr {
1514 1,1,v2 { monitor [iapp_conf create ltm monitor https ${app}_adfs_https \
1515 defaults-from https \
1516 interval $app_health_frequency \
1517 timeout [ expr {( $app_health_frequency * 3 ) + 1} ] \
1518 send $::app_health__send\
1519 recv \"$::app_health__recv\"] }
1520 1,1,v3 { monitor [iapp_conf create ltm monitor external ${app}_adfs_eav \
1521 run [iapp_conf create sys file external-monitor adfs_eav \
1522 source-path file:[create_eav_script adfs_monitor_eav_script]] \
1523 user-defined HOST $::vs_pool__fqdn \
1524 user-defined URI $::app_health__send \
1525 user-defined RECV \"$::app_health__recv\" \
1526 interval $app_health_frequency \
1527 timeout [ expr {( $app_health_frequency * 3 ) + 1} ] ] }
1528 1,1,v4 { monitor [iapp_conf create ltm monitor external ${app}_adfs_eav \
1529 run [iapp_conf create sys file external-monitor adfs_eav \
1530 source-path file:[create_eav_script adfs_monitor_eav_script]] \
1531 user-defined HOST $::vs_pool__fqdn \
1532 user-defined URI $::app_health__send \
1533 user-defined RECV \"$::app_health__recv\" \
1534 interval $app_health_frequency \
1535 timeout [ expr {( $app_health_frequency * 3 ) + 1} ] ] }
1536 1,0,v2 { monitor $::app_health__monitor }
1537 1,0,v3 { monitor $::app_health__monitor }
1538 1,0,v4 { monitor $::app_health__monitor }
1539 * { monitor none }
1540 }
1541
1542 # POOL
1543 set use_slow_ramp [iapp_is ::vs_pool__use_slow_ramp yes]
1544 # array keys: $advanced,$use_slow_ramp
1545 array set pool_slow_ramp {
1546 * { slow-ramp-time 300 }
1547 1,0 { slow-ramp-time 10 }
1548 1,1 { slow-ramp-time $::vs_pool__slow_ramp_setvalue }
1549 }
1550
1551 set use_pga [iapp_is ::vs_pool__use_pga yes]
1552 # array keys: $advanced,$use_pga
1553 array set pool_pga {
1554 1,1 { min-active-members $::vs_pool__min_active_members }
1555 * { min-active-members 0 }
1556 }
1557
1558 set tcp_queuing [expr { $advanced && !$do_fastl4 && [iapp_is ::vs_pool__tcp_req_queuing "yes"] }]
1559 # array keys: $advanced,$tcp_queuing
1560 array set tcp_req_queuing {
1561 1,1 { queue-on-connection-limit enabled \
1562 queue-depth-limit $::vs_pool__tcp_queue_length \
1563 queue-time-limit $::vs_pool__tcp_queue_timeout }
1564 * { queue-on-connection-limit disabled queue-depth-limit 0 queue-time-limit 0 }
1565 }
1566
1567 # array keys: $advanced,$lb_lcm_licensed
1568 array set pool_lb_method {
1569 0,0 { load-balancing-mode round-robin }
1570 0,1 { load-balancing-mode least-connections-member }
1571 * { load-balancing-mode $::vs_pool__lb_method_choice }
1572 }
1573
1574 set new_pool [iapp_is ::vs_pool__pool_to_use "/#create_new#"]
1575 set primary_pool ${app}_adfs_pool_${::vs_pool__vs_port}
1576 # array keys: $new_pool,$cert_auth_flag
1577 array set pool {
1578 1,1 { pool [expr { !$adfs_proxy_flag ? [iapp_conf create ltm pool ${app}_adfs_pool_${vs_port} \
1579 [iapp_substa pool_lb_method($advanced,$lb_lcm_licensed)] \
1580 [iapp_pool_members $::vs_pool__members \
1581 -fields {connection-limit conn_limit} -port $vs_port] \
1582 monitor [iapp_conf create ltm monitor tcp ${app}_adfs_tcp \
1583 defaults-from tcp \
1584 interval $app_health_frequency \
1585 timeout [ expr {( $app_health_frequency * 3 ) + 1} ]] \
1586 [iapp_substa pool_slow_ramp($advanced,$use_slow_ramp)] \
1587 [iapp_substa tcp_req_queuing($advanced,$tcp_queuing)] \
1588 [iapp_substa pool_pga($advanced,$use_pga)] ] : $primary_pool }] }
1589 1,0 { pool [iapp_conf create ltm pool $primary_pool \
1590 [iapp_substa pool_lb_method($advanced,$lb_lcm_licensed)] \
1591 [iapp_pool_members $::vs_pool__members \
1592 -fields {connection-limit conn_limit}] \
1593 [iapp_substa monitor_arr($need_monitor,$new_monitor,$adfs_version)] \
1594 [iapp_substa pool_slow_ramp($advanced,$use_slow_ramp)] \
1595 [iapp_substa tcp_req_queuing($advanced,$tcp_queuing)] \
1596 [iapp_substa pool_pga($advanced,$use_pga)] ] }
1597 0,1 { pool $::vs_pool__cert_auth_pool_to_use }
1598 0,0 { pool $::vs_pool__pool_to_use }
1599 }
1600
1601 # PROFILES
1602 # CLIENT TCP OPTIMIZATION PROFILE
1603 # In order to show the correct recommendation per the chosen topology,
1604 # the presentation of client tcp optimization has a split presentation.
1605 # Only one of tcp_lan_opt or tcp_wan_opt contains the user's selection.
1606 # This statement identifies whether the user has selected the recommended
1607 # option from this split presentation.
1608 set new_client_tcp [expr { !$advanced || ( \
1609 [iapp_is ::net__client_mode lan] ? \
1610 [iapp_is ::client_opt__tcp_lan_opt "/#create_new#"] : \
1611 [iapp_is ::client_opt__tcp_wan_opt "/#create_new#"] )}]
1612
1613 # array keys: $new_client_tcp,$::net__client_mode
1614 array set client_tcp {
1615 0,lan { $::client_opt__tcp_lan_opt }
1616 0,wan { $::client_opt__tcp_wan_opt }
1617 1,lan { [iapp_conf create ltm profile tcp ${app}_lan-optimized-tcp \
1618 defaults-from tcp-lan-optimized idle-timeout 1200] }
1619 * { [iapp_conf create ltm profile tcp ${app}_wan-optimized-tcp \
1620 defaults-from tcp-wan-optimized idle-timeout 1200] }
1621 }
1622
1623 # SERVER TCP OPTIMIZATION PROFILE
1624 # See above comments regarding the client tcp optimization array.
1625 set new_server_tcp [expr { !$advanced || ( \
1626 [iapp_is ::net__server_mode lan] ? \
1627 [iapp_is ::server_opt__tcp_lan_opt "/#create_new#"] : \
1628 [iapp_is ::server_opt__tcp_wan_opt "/#create_new#"] )}]
1629
1630 # array keys: $new_server_tcp,$::net__server_mode
1631 array set server_tcp {
1632 0,lan { $::server_opt__tcp_lan_opt }
1633 0,wan { $::server_opt__tcp_wan_opt }
1634 1,lan { [iapp_conf create ltm profile tcp ${app}_lan-optimized-tcp \
1635 defaults-from tcp-lan-optimized] }
1636 * { [iapp_conf create ltm profile tcp ${app}_wan-optimized-tcp \
1637 defaults-from tcp-wan-optimized] }
1638 }
1639
1640 set client_mode [expr { $advanced ? $::net__client_mode : "wan" }]
1641 set server_mode [expr { $advanced ? $::net__server_mode : "lan" }]
1642
1643 # array keys: type = tcp
1644 array set profiles {
1645 tcp { profiles add \{ \
1646 [arrange_tcp_profiles \
1647 [iapp_substa client_tcp($new_client_tcp,$client_mode)] \
1648 [iapp_substa server_tcp($new_server_tcp,$server_mode)] ] \} }
1649 }
1650
1651 # HTTP PROFILE
1652 set new_http [expr { !$advanced || \
1653 [iapp_is ::vs_pool__http "/#create_new#"] }]
1654
1655 set xff_action [expr { !$adfs_proxy_flag && (!$advanced || \
1656 ([info exists ::vs_pool__xff] && [iapp_is ::vs_pool__xff "yes"])) ? "insert-xforwarded-for enabled" : "" }]
1657
1658 #array keys: $advanced, $new_http
1659 array set http_arr {
1660 1,0 { $::vs_pool__http }
1661 1,1 { [iapp_conf create ltm profile http ${app}_http \
1662 defaults-from http \
1663 $xff_action] }
1664 * { [iapp_conf create ltm profile http ${app}_http \
1665 defaults-from http \
1666 $xff_action] }
1667 }
1668
1669 # ADFS Proxy Profile (APM acting fully as ADFS Proxy role)
1670 #array keys: $adfs_proxy_flag, $is_v13_1
1671 array set adfs_proxy_arr {
1672 1,1 { /Common/adfs_proxy }
1673 * { }
1674 }
1675
1676 # SSL PROFILES
1677 # Client SSL
1678 set new_client_ssl [expr {[iapp_is ::ssl__client_ssl_profile "/#create_new#"]}]
1679
1680 set do_chain_cert [expr { $new_client_ssl && $advanced && \
1681 [info exists ::ssl__use_chain_cert] && ![iapp_is ::ssl__use_chain_cert "/#do_not_use#"] }]
1682
1683 set cssl_cmd "ltm profile client-ssl ${app}_client-ssl defaults-from clientssl"
1684 set cert_auth_trusted_ca [expr { $adfs_proxy_flag && $do_cert_auth ? $::vs_pool__cert_auth_trusted_ca : "none" }]
1685 set cssl_cmd_cert_auth "ltm profile client-ssl ${app}_client-ssl-cert-auth defaults-from clientssl ca-file $cert_auth_trusted_ca"
1686
1687
1688 # If doing client cert auth modify client ssl cert as needed
1689 set cert_auth_cssl_cmd [expr { $do_cert_auth ? "peer-cert-mode require" : "peer-cert-mode ignore" }]
1690
1691 # array keys: $new_client_ssl,$do_chain_cert,$cert_auth_flag
1692 array set client_ssl_arr {
1693 1,1,0 { [iapp_conf create $cssl_cmd key $::ssl__key cert $::ssl__cert \
1694 chain $::ssl__use_chain_cert] \{ context clientside \} }
1695 1,0,0 { [iapp_conf create $cssl_cmd key $::ssl__key cert $::ssl__cert \
1696 chain none ] \{ context clientside \} }
1697 1,1,1 { [iapp_conf create $cssl_cmd_cert_auth key $::ssl__key cert $::ssl__cert \
1698 chain $::ssl__use_chain_cert $cert_auth_cssl_cmd] \{ context clientside \} }
1699 1,0,1 { [iapp_conf create $cssl_cmd_cert_auth key $::ssl__key cert $::ssl__cert \
1700 chain none $cert_auth_cssl_cmd] \{ context clientside \} }
1701 0,0,1 { $::vs_pool__cert_auth_client_ssl_profile \{ context clientside \} }
1702 * { $::ssl__client_ssl_profile \{ context clientside \} }
1703 }
1704
1705 # Server SSL
1706 set new_server_ssl [expr {[iapp_is ::ssl__server_ssl_profile "/#create_new#"]}]
1707 set partition [lindex [split [tmsh::pwd] /] 1]
1708
1709 # array keys:$new_server_ssl,$adfs_proxy_flag
1710 array set server_ssl_arr {
1711 1,1 { [iapp_conf create [expr { ![iapp_is adfs_version "v2"] ? "ltm profile server-ssl ${app}_server-ssl defaults-from serverssl server-name \
1712 $::vs_pool__fqdn cert none key none" : "ltm profile server-ssl ${app}_server-ssl defaults-from serverssl server-name none cert none key none"}]] \{ context serverside \} }
1713 1,0 { [iapp_conf create [expr { ![iapp_is adfs_version "v2"] ? "ltm profile server-ssl ${app}_server-ssl defaults-from serverssl server-name \
1714 $::vs_pool__fqdn cert none key none" : "ltm profile server-ssl ${app}_server-ssl defaults-from serverssl server-name none cert none key none"}]] \{ context serverside \} }
1715 0,1 { $::ssl__server_ssl_profile \{ context serverside \} }
1716 0,0 { $::ssl__server_ssl_profile \{ context serverside \} }
1717 * {}
1718 }
1719
1720 # SNAT
1721 set do_snat [expr { [iapp_is ::net__same_subnet yes] \
1722 || ![iapp_is ::net__route_to_bigip yes] }]
1723 set do_automap [expr { [iapp_is ::net__snat_type automap] }]
1724 set new_snatpool [iapp_is ::net__snatpool "/#create_new#"]
1725
1726 # array keys: $do_snat,$do_automap,$new_snatpool
1727 array set snat {
1728 1,1,1 { snat automap }
1729 1,1,0 { snat automap }
1730 1,0,1 { snatpool [iapp_conf create ltm snatpool ${app}_snatpool \
1731 members replace-all-with \{ \
1732 [string map {"addr " "" \{ "" \} ""} $::net__snatpool_members] \
1733 \}] }
1734 1,0,0 { snatpool $::net__snatpool }
1735 * { snat none }
1736 }
1737
1738 # VLANS
1739 # array keys: $advanced
1740 array set vlans {
1741 1 { vlans-enabled \
1742 vlans replace-all-with \{ $::net__client_vlan \} }
1743 * { vlans-disabled vlans none }
1744 }
1745
1746 # RULES
1747 # Add rule array for hybrid iRules
1748array set irule_arr {
1749
1750ws_trust_irule {
1751when HTTP_REQUEST {
1752 # For external Lync client access all external requests to the
1753 # /trust/mex URL must be routed to /trust/proxymex. Analyze and modify the URI
1754 # where appropriate
1755 HTTP::uri [string map {/trust/mex /trust/proxymex} [HTTP::uri]]
1756
1757 # Disable APM enforcement of WS-Trust calls
1758 if {[HTTP::uri] contains "/adfs/services/trust"} {
1759 ACCESS::disable
1760 }
1761
1762 # OPTIONAL ---- To allow publishing of the federation service metadata
1763 if {[HTTP::uri] ends_with "FederationMetadata/2007-06/FederationMetadata.xml"} {
1764 ACCESS::disable
1765 }
1766}
1767}
1768
1769ws_trust_irule_adfs_proxy {
1770when HTTP_REQUEST {
1771 # For external Lync client access all external requests to the /trust/mex
1772 # URL must be routed to /trust/proxymex. ADFS Proxy trust established via BIG-IP handles this
1773
1774 # Disable APM enforcement of WS-Trust calls
1775 if {[HTTP::uri] contains "/adfs/services/trust"} {
1776 ACCESS::disable
1777 }
1778
1779 # OPTIONAL ---- To allow publishing of the federation service metadata
1780 if {[HTTP::uri] ends_with "FederationMetadata/2007-06/FederationMetadata.xml"} {
1781 ACCESS::disable
1782 }
1783}
1784}
1785
1786ms_adfs_pip_irule {
1787when CLIENT_ACCEPTED {
1788 set client_ip [IP::remote_addr]
1789}
1790when HTTP_REQUEST {
1791 # Add headers required for certain rules on ADFS backend servers
1792 HTTP::header insert X-MS-Proxy [HTTP::host]
1793 HTTP::header insert X-MS-Forwarded-Client-IP $client_ip
1794 HTTP::header insert X-MS-Endpoint-Absolute-Path [HTTP::uri]
1795 HTTP::header insert X-MS-Target-Role "PrimaryComputer"
1796 HTTP::header insert X-MS-ADFS-Proxy-Client-IP $client_ip
1797}
1798}
1799adfs_ls_endpoint_sso_select_irule {
1800when CLIENT_ACCEPTED {
1801 event HTTP_RESPONSE disable
1802 set no_referer_flag false
1803}
1804# Set SSO for /adfs/ls endpoint
1805when ACCESS_ACL_ALLOWED {
1806 set req_uri [HTTP::uri]
1807 if { $req_uri starts_with "/adfs/ls" } {
1808 set ssoconfig <FORMS_SSO_NAME>
1809 WEBSSO::select $ssoconfig
1810 unset ssoconfig
1811 }
1812 unset req_uri
1813}
1814# Delete session when application redirects back to ADFS for sign out
1815when HTTP_REQUEST {
1816 if { [string tolower [HTTP::uri]] contains "/adfs/ls/?wa=wsignout1.0" } {
1817 if { [HTTP::header exists "Referer"] } {
1818 ACCESS::session remove
1819 HTTP::redirect [HTTP::header value "Referer"]
1820 } else {
1821 event HTTP_RESPONSE enable
1822 set no_referer_flag true
1823 }
1824 }
1825}
1826# If no referer header, we will just allow client through to ADFS sign out page and then kill the APM session
1827when HTTP_RESPONSE {
1828 if { $no_referer_flag } {
1829 ACCESS::session remove
1830 }
1831}
1832}
1833}
1834
1835set irule_map [subst { \
1836
1837 <FORMS_SSO_NAME> {[tmsh::pwd]/${app}_form_basedv2_sso}
1838
1839}]
1840
1841 set ws_trust_rule_name [expr { $adfs_proxy_flag ? "ws_trust_irule_adfs_proxy" : "ws_trust_irule" }]
1842 set use_ws_trust [expr { $use_apm && $scenario ? [iapp_conf create ltm rule ${app}_ws_trust [string map $irule_map $irule_arr($ws_trust_rule_name)]] : "" }]
1843 set use_adfs_pip [expr { $use_apm && $scenario && !$adfs_proxy_flag ? [iapp_conf create ltm rule ${app}_adfs_pip $irule_arr(ms_adfs_pip_irule)] : "" }]
1844 set use_forms_sso [expr { $use_apm && $scenario && [iapp_is ::apm__apm_profile "/#create_new#"] && [iapp_is ::apm__use_forms_sso "yes"] ? \
1845 [iapp_conf create ltm rule ${app}_adfs_forms_select_sso [string map $irule_map $irule_arr(adfs_ls_endpoint_sso_select_irule)]] : "" }]
1846 set using_rule_flag 1
1847 set have_custom_rules [expr { ![iapp_is ::irules__irules ""] }]
1848 # array keys $advanced,$have_custom_rules,$using_rule_flag
1849 array set irules {
1850 1,1,1 { rules \{ $use_ws_trust $use_adfs_pip $use_forms_sso $::irules__irules \} }
1851 1,0,1 { rules \{ $use_ws_trust $use_adfs_pip $use_forms_sso\} }
1852 0,1,1 { rules \{ $use_ws_trust $use_adfs_pip $use_forms_sso\} }
1853 0,0,1 { rules \{ $use_ws_trust $use_adfs_pip $use_forms_sso\} }
1854 * { rules none }
1855 }
1856
1857 # FIREWALL POLICY
1858 # beware: syntactically correct AFM commands fail when AFM is not provisioned
1859 # extra info exists test benefits BIG-IQ apps that bypass presentation
1860
1861 set afm_provisioned [expr { [iapp_get_provisioned afm] && [iapp_tmos_version >= 11.4] }]
1862
1863 set do_firewall [expr { $afm_provisioned && \
1864 [info exists ::afm__policy] && \
1865 ![iapp_is ::afm__policy $::DO_NOT_USE_ANSWER] }]
1866
1867 set new_firewall [iapp_is ::afm__policy $::DEFAULT_ANSWER]
1868
1869 set allow_by_reputation [iapp_is ::afm__restrict_by_reputation "accept"]
1870
1871 set staging_policy [expr { $do_firewall && \
1872 ![iapp_is ::afm__staging_policy $::DO_NOT_USE_ANSWER] \
1873 ? "$::afm__staging_policy" : "none" }]
1874
1875 set security_logging [expr { $do_firewall && \
1876 ![iapp_is ::afm__security_logging $::DO_NOT_USE_ANSWER] \
1877 ? "\"$::afm__security_logging\"" : "" }]
1878
1879 # array key: $afm_provisioned,$do_firewall,$new_firewall
1880 array set firewall_arr {
1881 1,1,1 { fw-enforced-policy \
1882 [iapp_conf create security firewall policy ${app}_firewall \
1883 rules replace-all-with \{ \
1884 acceptPackets \{ \
1885 action accept \
1886 log no \
1887 ip-protocol tcp \
1888 status enabled \
1889 source \{ [iapp_substa afm_restrict($::afm__restrict_by_addr)] \}\} \
1890 dropPackets \{ \
1891 action drop \
1892 log yes \
1893 ip-protocol tcp \
1894 status enabled \
1895 source \{ addresses replace-all-with \{ any/any \}\} \
1896 \}\}] \
1897 fw-staged-policy [subst $staging_policy] }
1898 1,1,0 { fw-enforced-policy $::afm__policy \
1899 fw-staged-policy [subst $staging_policy] }
1900 1,0,1 { fw-enforced-policy none \
1901 fw-staged-policy none }
1902 1,0,0 { fw-enforced-policy none \
1903 fw-staged-policy none }
1904 * { }
1905 }
1906
1907 # array key: $::afm__restrict_by_addr
1908 array set afm_restrict {
1909 /#create_new# {addresses replace-all-with \{ $::afm__allowed_addr \}}
1910 /#do_not_use# {addresses replace-all-with \{ any/any \}}
1911 * {address-lists replace-all-with \{ $::afm__restrict_by_addr \}}
1912 }
1913
1914 # ip-intelligence was a profile in 11.4, is a policy in 11.5
1915 # array keys:
1916 # $afm_provisioned,$do_firewall,$allow_by_reputation,$is_v11_5
1917 array set ip_intelligence_arr {
1918 1,1,0,0 { profiles add \{ [iapp_conf create security ip-intelligence profile ${app}_ip_intelligence defaults-from ip-intelligence botnets $::afm__restrict_by_reputation denial-of-service $::afm__restrict_by_reputation infected-sources $::afm__restrict_by_reputation phishing $::afm__restrict_by_reputation proxy $::afm__restrict_by_reputation scanners $::afm__restrict_by_reputation spam-sources $::afm__restrict_by_reputation web-attacks $::afm__restrict_by_reputation windows-exploits $::afm__restrict_by_reputation] \} }
1919 1,1,1,0 { profiles add \{ [iapp_conf create security ip-intelligence profile ${app}_ip_intelligence defaults-from ip-intelligence botnets $::afm__restrict_by_reputation denial-of-service $::afm__restrict_by_reputation infected-sources $::afm__restrict_by_reputation phishing $::afm__restrict_by_reputation proxy $::afm__restrict_by_reputation scanners $::afm__restrict_by_reputation spam-sources $::afm__restrict_by_reputation web-attacks $::afm__restrict_by_reputation windows-exploits $::afm__restrict_by_reputation] \} }
1920 1,1,0,1 { ip-intelligence-policy [iapp_conf create security ip-intelligence policy ${app}_ip_intelligence default-action $action($::afm__restrict_by_reputation) blacklist-categories replace-all-with \{ botnets \{ action use-policy-setting \} cloud_provider_networks \{ action use-policy-setting \} denial_of_service \{ action use-policy-setting \} infected_sources \{ action use-policy-setting \} phishing \{ action use-policy-setting \} proxy \{ action use-policy-setting \} scanners \{ action use-policy-setting \} spam_sources \{ action use-policy-setting \} web_attacks \{ action use-policy-setting \} windows_exploits \{ action use-policy-setting \} [expr { $is_v13_1 ? "mobile_threats \{ action use-policy-setting \}" : "" }] [expr { $is_v13_1 ? "tor_proxy \{ action use-policy-setting \}" : "" }] [expr { $is_v13_1 ? "" : "illegal_websites \{ action use-policy-setting \}" }]\}] }
1921 1,0,0,1 { ip-intelligence-policy none }
1922 1,0,1,1 { ip-intelligence-policy none }
1923 1,1,1,1 { ip-intelligence-policy none }
1924 * { }
1925 }
1926
1927 # array key: $::afm__restrict_by_reputation
1928 array set action {
1929 accept { accept default-log-blacklist-hit-only no }
1930 reject { drop default-log-blacklist-hit-only yes }
1931 warn { accept default-log-blacklist-hit-only yes }
1932 }
1933
1934 # VIRTUAL SERVER(S)
1935 set destination [iapp_destination $::vs_pool__vs_addr $::vs_pool__vs_port]
1936 set mask_action "mask [iapp_destination -mask $::vs_pool__vs_addr]"
1937 set apm_profiles [expr { $use_apm ? [configure_apm] : "" }]
1938 set vs_port $::vs_pool__vs_port
1939 set cert_auth_flag 0
1940 # Set up ADFS Proxy Trust Establishment - only exists in v13.1 and above
1941 set ::adfs_vs_loc ${dir}/${app}_adfs_vs_${vs_port}
1942
1943 # array key: $do_fastl4
1944 array set vs_arr {
1945 0 {[iapp_conf create ltm virtual ${app}_adfs_vs_${vs_port} \
1946 destination $destination \
1947 $mask_action \
1948 ip-protocol tcp \
1949 [iapp_substa pool($new_pool,$cert_auth_flag)] \
1950 [iapp_substa firewall_arr($afm_provisioned,$do_firewall,$new_firewall)] \
1951 [iapp_substa \
1952 ip_intelligence_arr($afm_provisioned,$do_firewall,$allow_by_reputation,$is_v11_5)] \
1953 security-log-profiles replace-all-with \{ $security_logging \} \
1954 [iapp_substa profiles(tcp)] \
1955 profiles add \{ [iapp_substa client_ssl_arr($new_client_ssl,$do_chain_cert,$cert_auth_flag)] \
1956 [iapp_substa server_ssl_arr($new_server_ssl,$adfs_proxy_flag)] \} \
1957 profiles add \{ $apm_profiles \
1958 [iapp_substa http_arr($advanced,$new_http)] \
1959 [iapp_substa adfs_proxy_arr($adfs_proxy_flag,$is_v13_1)]\} \
1960 [iapp_substa snat($do_snat,$do_automap,$new_snatpool)] \
1961 [iapp_substa vlans($advanced)] \
1962 [iapp_substa irules($advanced,$have_custom_rules,$using_rule_flag)] \
1963 persist none]}
1964
1965 1 {[iapp_conf create ltm virtual ${app}_adfs_vs_${vs_port} \
1966 destination $destination \
1967 $mask_action \
1968 ip-protocol tcp \
1969 profiles add \{ fastL4 \} \
1970 [iapp_substa pool($new_pool,$cert_auth_flag)] \
1971 [iapp_substa firewall_arr($afm_provisioned,$do_firewall,$new_firewall)] \
1972 [iapp_substa \
1973 ip_intelligence_arr($afm_provisioned,$do_firewall,$allow_by_reputation,$is_v11_5)] \
1974 security-log-profiles replace-all-with \{ $security_logging \} \
1975 [iapp_substa snat($do_snat,$do_automap,$new_snatpool)] \
1976 [iapp_substa vlans($advanced)] \
1977 [iapp_substa irules($advanced,$have_custom_rules,$using_rule_flag)] \
1978 persist none]}
1979 }
1980
1981 iapp_substa vs_arr($do_fastl4)
1982
1983 # Configure client certificate authentication
1984 if { $do_cert_auth } {
1985 set vs_port 49443
1986 set destination [iapp_destination $::vs_pool__vs_addr $vs_port]
1987 set mask_action "mask [iapp_destination -mask $::vs_pool__vs_addr]"
1988 set apm_profiles ""
1989 set cert_auth_flag 1
1990 set using_rule_flag 0
1991 set do_cert_auth_l4 [expr { !$adfs_proxy_flag }]
1992
1993 iapp_substa vs_arr($do_cert_auth_l4)
1994 }
1995
1996 ## Attempt to establish trust with the ADFS servers
1997 proc post_implementation { } {
1998 # Special proc that is basically an event handler for post implementation tmos transaction work
1999 proc iapp::on_transaction_end {} {
2000 tmsh::include f5.iapp.1.5.6.cli
2001 if { [catch {
2002 # No escaping appears to be required for username or password
2003 exec /usr/bin/adfs_establish_trust --vs $::adfs_vs_loc --cert $::adfs_trust_cert_name \
2004 --username $::apm__adfs_admin_user --password $::apm__adfs_admin_password
2005 } err] } {
2006 error "ADFS Trust Establishment Failed: $err"
2007 }
2008 }
2009 }
2010 if { $adfs_proxy_flag } {
2011 if { !$new_server_ssl } {
2012 # For existing server ssl profile include name in adfs proxy cert,
2013 # to allow for switching from create new profile to existing based on how utility works
2014 if { [catch { set server_ssl_profile_name [lindex [split $::ssl__server_ssl_profile /] 2] } err] } {
2015 set server_ssl_profile_name "custom_ssl_profile"
2016 }
2017 set ::adfs_trust_cert_name ${dir}/adfs_proxy_cert_${app}_${server_ssl_profile_name}
2018 } else {
2019 set ::adfs_trust_cert_name ${dir}/adfs_trust_cert_${app}
2020 }
2021 # Run post implementation proc
2022 post_implementation
2023 }
2024}
2025# MAIN
2026configure_adfs_deployment
2027iapp_template stop
2028 }
2029 macro {
2030 }
2031 presentation {
2032 define choice lb_method display "xxlarge" tcl {
2033 if { [string first ltm_lb_least_conn [tmsh::show sys license detail]] != -1 } {
2034 set choices "Least Connections (member)\tleast-connections-member\nLeast Connections (node)\tleast-connections-node\nLeast Sessions\tleast-sessions\nDynamic Ratio (member)\tdynamic-ratio-member\nDynamic Ratio (node)\tdynamic-ratio-node\nFastest (application)\tfastest-app-response\nFastest (node)\tfastest-node\nObserved (member)\tobserved-member\nObserved (node)\tobserved-node\nPredictive (member)\tpredictive-member\nPredictive (node)\tpredictive-node\nRound Robin\tround-robin\nRatio (member)\tratio-member\nRatio (node)\tratio-node\nRatio (session)\tratio-session\nRatio Least Connections (member)\tratio-least-connections-member\nRatio Least Connections (node)\tratio-least-connections-node\nWeighted Least Connections (member)\tweighted-least-connections-member"
2035 } else {
2036 set choices "Round Robin\tround-robin\nRatio (member)\tratio-member\nRatio (node)\tratio-node"
2037 }
2038 return $choices
2039}
2040
2041section intro {
2042
2043 message early_release "This template has not yet been fully tested at F5. It has limited support, like other community-contributed iApps. When testing is complete, it will be moved to downloads.f5.com."
2044 message intro "Configure high availability and acceleration for AD FS implementations. For detailed information and configuration assistance, see http://www.f5.com/pdf/deployment-guides/microsoft-adfs-dg.pdf"
2045 message check_for_updates "Check for new versions of this template on DevCentral (https://devcentral.f5.com/wiki/iApp.Microsoft-Applications.ashx)."
2046
2047 optional ( intro == "NEVER_SHOW_THIS" ) {
2048 choice ltm_provisioned tcl {
2049 return [expr {[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_provisioned ltm] ? "yes" : "no"}]
2050 }
2051 choice apm_provisioned tcl {
2052 return [expr {[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_provisioned apm] ? "yes" : "no"}]
2053 }
2054 choice afm_provisioned tcl {
2055 return [expr {[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_provisioned afm] && [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_tmos_version >= 11.4] ? "yes" : "no"}]
2056 }
2057 choice is_120 tcl {
2058 return [expr {[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_tmos_version >= 12.0] ? "yes" : "no"}]
2059 }
2060 choice is_13_1 tcl {
2061 return [expr {[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_tmos_version >= 13.1] ? "yes" : "no"}]
2062 }
2063 }
2064 optional ( ltm_provisioned == "no" ) {
2065 message sorry "You must license and provision the Local Traffic Manager (LTM) module to use this template."
2066 }
2067}
2068optional ( intro.ltm_provisioned == "yes" ) {
2069 section basic {
2070 choice display_help display "xxlarge" default "hide" {
2071 "Yes, show inline help" => "max" ,
2072 "No, do not show inline help" => "hide"
2073 }
2074 optional ( basic.display_help == "max" ) {
2075 message display_help_max "Inline help is available to provide contextual descriptions to aid in the completion of this configuration. Select to show or hide the inline help in this template. Important notes and warnings are always visible, no matter which selection you make here."
2076 }
2077 choice advanced display "xxlarge" default "no" {
2078 "Basic - Use F5's recommended settings" => "no" ,
2079 "Advanced - Configure advanced options" => "yes"
2080 }
2081 optional ( basic.display_help == "max" ) {
2082 message advanced_max "This template supports two configurations modes. Basic mode exposes the most commonly used settings, and automatically configures the rest of the options. Advanced mode allows you to review and change all settings."
2083 }
2084 choice version display "xxlarge" default "v4" {
2085 "AD FS 2.0" => "v2" ,
2086 "AD FS 3.0" => "v3" ,
2087 "AD FS 4.0" => "v4"
2088 }
2089 optional ( basic.display_help == "max" ) {
2090 message version_max "Select the version of Active Directory Federation Services you are using."
2091 }
2092 choice scenario display "xxlarge" default "adfs" {
2093 "AD FS" => "adfs" ,
2094 "AD FS Proxy" =>"adfs_proxy"
2095 }
2096 optional ( basic.display_help == "max" ) {
2097 message scenario_max "Select the Active Directory Federation Services role you are deploying. You can deploy AD FS Proxy, or AD FS with optional Access Policy configuration, to protect your AD FS servers."
2098 }
2099 }
2100
2101 section net {
2102 optional ( basic.advanced == "yes" ) {
2103 choice client_mode display "xxlarge" default "wan" {
2104 "Local area network ( LAN ) " => "lan" ,
2105 "Wide area network ( WAN ) " => "wan"
2106 }
2107 }
2108 optional ( basic.display_help == "max" && basic.advanced == "yes" ) {
2109 message client_mode_max "Select the type of network that connects the clients to the BIG-IP system. This is used to determine the client-side TCP optimizations the system uses."
2110 }
2111 optional ( basic.advanced == "yes" ) {
2112 multichoice client_vlan default tcl {
2113
2114 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items net vlan]
2115 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2116 } tcl {
2117
2118 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items net vlan]
2119 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2120 }
2121 optional ( basic.display_help == "max" && basic.advanced == "yes" ) {
2122 message client_vlan_max "You can optionally configure the BIG-IP system to accept client traffic from specific VLANs you have configured. By default, the BIG-IP system accepts traffic from all VLANs configured on the system. The VLAN objects must already be configured on this BIG-IP system before you can select them. If you do not move any VLANs to the Selected box, the BIG-IP system accepts traffic from all VLANs"
2123 }
2124 }
2125 optional ( basic.advanced == "yes" ) {
2126 choice server_mode display "xxlarge" default "lan" {
2127 "Local area network ( LAN ) " => "lan" ,
2128 "Wide area network ( WAN ) " => "wan"
2129 }
2130 }
2131 optional ( basic.display_help == "max" && basic.advanced == "yes" ) {
2132 message server_mode_max "Select the type of network that connects the servers to the BIG-IP system. This is used to determine the server-side TCP optimizations the system uses."
2133 }
2134 choice same_subnet display "xxlarge" default "no" {
2135 "BIG-IP virtual server IP and AD FS servers are on different subnets" => "no" ,
2136 "BIG-IP virtual server IP and AD FS servers are on the same subnet" => "yes"
2137 }
2138 optional ( basic.display_help == "max" ) {
2139 message subnet_1_max "It is important to ensure that responses to client requests made using the BIG-IP virtual server address are returned through the BIG-IP system. If the client receives a response directly from the AD FS server, the connection is dropped. The way the BIG-IP system handles this depends on your network topology."
2140 message subnet_2_max "For environments in which the virtual server IP address is on a subnet different from the AD FS servers, select BIG-IP virtual server IP and the AD FS servers are on different subnets."
2141 message subnet_3_max "For environments in which the virtual server IP address provided is on the same subnet as the AD FS servers in the associated pool, select BIG-IP virtual server IP and the AD FS servers are on the same subnet. This enables Secure Network Address Translation (SNAT Auto Map). This configuration results in the BIG-IP system replacing the client IP address of an incoming connection with its local floating self IP address, ensuring the server response returns through the BIG-IP system."
2142 }
2143 optional ( same_subnet == "no" ) {
2144 choice route_to_bigip display "xxlarge" default "no" {
2145 "AD FS servers have a route to clients through the BIG-IP" => "yes" ,
2146 "AD FS servers do not have a route to clients through the BIG-IP" => "no"
2147 }
2148 }
2149 optional ( basic.display_help == "max" ) {
2150 message def_rt_1_max "For environments in which the virtual server IP is on a subnet different from the AD FS servers, information regarding the IP setting of the AD FS servers is required to ensure the correct BIG-IP system configuration."
2151 message def_rt_2_max "If the AD FS servers use the BIG-IP system as their default gateway, select AD FS servers have a route for clients through the BIG-IP. In this scenario, no configuration is needed to support your environment to ensure correct server response handling."
2152 message def_rt_3_max "If the AD FS servers do not have a route through the BIG-IP system, select AD FS servers do not have a route for clients through the BIG-IP. This enables Secure Network Address Translation (SNAT Auto Map). This configuration results in the BIG-IP system replacing the client IP address of an incoming connection with its local floating self IP address ensuring the server response returns through the BIG-IP system."
2153 }
2154 optional ( same_subnet == "yes"
2155 || ( same_subnet == "no"
2156 && route_to_bigip == "no" )) {
2157 choice snat_type display "xxlarge" default "automap" {
2158 "Fewer than 64,000 concurrent connections per server" => "automap" ,
2159 "More than 64,000 concurrent connections per server" => "snatpool"
2160 }
2161 optional ( basic.display_help == "max" ) {
2162 message snat_max "For environments with fewer than 64,000 concurrent connections per server, the BIG-IP system enables SNAT Auto Map, which uses a unique IP:port combination for each client request it sends to the AD FS server. For environments with more than 64,000 concurrent connections per AD FS server, the BIG-IP system enables a SNAT pool, and additional IP addresses are reserved to ensure the system has enough unique combinations. If the system exhausts all combinations, new client connections are refused until one is available."
2163 }
2164 optional ( snat_type == "snatpool" ) {
2165 choice snatpool display "xxlarge" default "/#create_new#" tcl {
2166 set ::choices "Create a new SNAT pool\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm snatpool]"
2167 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2168 }
2169 optional ( basic.display_help == "max" ) {
2170 message snatpool_max "Choose whether you want the iApp template to create a new SNAT Pool for this implementation. If you have already created a custom SNAT Pool, you can select it from the list."
2171 }
2172 optional ( snatpool == "/#create_new#" ) {
2173 table snatpool_members {
2174 string addr required validator "IpAddress" display "xlarge"
2175 }
2176 optional ( basic.display_help == "max" ) {
2177 message snatpool_members_max "SNAT Pool addresses should be available IP addresses, not the self-IP address(es) of the BIG-IP system"
2178 }
2179 }
2180 }
2181
2182 }
2183 }
2184 optional ( intro.apm_provisioned == "yes" && basic.scenario == "adfs" ) {
2185 section apm {
2186 choice use_apm display "xxlarge" default "no" {
2187 "Yes, provide secure authentication using APM" => "yes" ,
2188 "No, do not provide secure authentication using APM" => "no"
2189 }
2190 optional ( basic.display_help == "max") {
2191 message use_apm_max "If you have fully licensed and provisioned the BIG-IP Access Policy Manager, you have the option of using it to provide proxy authentication and secure remote access for AD FS."
2192 }
2193 optional ( basic.version != "v2" && intro.is_13_1 == "yes" ) {
2194 choice adfs_proxy_setup display "xxlarge" default "no" {
2195 "Yes, configure BIG-IP as an ADFS Proxy" => "yes" ,
2196 "No, do not configure BIG-IP as an ADFS Proxy" => "no"
2197 }
2198 optional ( basic.display_help == "max" ) {
2199 message adfs_proxy_setup_help "Choose whether you want the iApp template to configure BIG-IP ADFS Proxy profile and attempt to establish trust with AD FS servers. If yes is selected trust will be established and will result in BIG-IP communicating with the AD FS to determine valid uri endpoints, will include the X-MS set of headers, and others. Reference the deployment guide or documentation for more details"
2200 }
2201 optional ( adfs_proxy_setup == "yes" ) {
2202 message adfs_proxy_note "Please be aware that in order to setup BIG-IP as an ADFS Proxy, it requires running a utility on the management plane. This utility will report back errors that occur, such as incorrect credentials. Once the iApp is run you can check the ADFS virtual server to determine if trust was successfully established (located under the Access Policy section as a check box called ADFS Proxy)."
2203 string adfs_admin_user required display "xxlarge"
2204 optional ( basic.display_help == "max" ) {
2205 message adfs_admin_user_help "The ADFS administrator account you specify here must have permissions to be used for establishing a proxy trust. Format can be just username or can include a domain prefix if needed."
2206 }
2207 password adfs_admin_password required display "xxlarge"
2208 optional ( basic.display_help == "max" ) {
2209 message adfs_admin_password_help "Type the associated password."
2210 }
2211 }
2212 }
2213 optional ( use_apm == "yes" ) {
2214 choice apm_profile display "xxlarge" default "/#create_new#" tcl {
2215 set ::choices "Use the iApp to create a new Access Profile\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain apm profile access]"
2216 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2217 }
2218 optional ( basic.display_help == "max" ) {
2219 message apm_profile_help "Choose whether you want the iApp template to create a new Access Profile for your BIG-IP APM implementation, or use an existing Access Policy. Unless you have created a custom Access Profile specifically for this implementation, we recommend allowing the iApp to create a new profile. "
2220 }
2221 optional ( apm_profile == "/#create_new#" ) {
2222 choice use_forms_sso display "xxlarge" default "yes" {
2223 "No, do not configure Forms SSO for AD FS (/adfs/ls endpoint)" => "no" ,
2224 "Yes, configure Forms SSO for AD FS (/adfs/ls endpoint)" => "yes"
2225 }
2226 optional ( basic.display_help == "max") {
2227 message use_forms_sso_max "Choose whether you want the iApp to configure Forms SSO. If you select Yes, the iApp creates a Forms (Client-Initiated) SSO and associated objects for the ADFS endpoint(/adfs/ls) used commonly with SharePoint, CRM and other claims-based authentication configured applications."
2228 }
2229 choice aaa_profile display "xxlarge" default "/#create_new#" tcl {
2230 set ::choices "Create a new AAA Server\t/#create_new#\n"
2231 append ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain -filter use-pool !~ "disabled" apm aaa active-directory]
2232 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2233 }
2234 optional ( basic.display_help == "max") {
2235 message aaa_profile_max "Choose whether you want the template to create a new BIG-IP APM AAA Server object for your implementation or use an existing one. The AAA Server contains information about your Active Directory deployment. Unless you have created a custom AAA server specifically for this implementation, we recommend allowing the iApp to create a new one."
2236 }
2237 optional ( aaa_profile != "/#create_new#" ) {
2238 message aaa_warning "You have selected an existing AAA server. For correct functionality, you must use an AAA server configured to use a pool of Domain Controllers."
2239 }
2240 optional ( aaa_profile == "/#create_new#" ) {
2241 table active_directory_servers {
2242 string fqdn display "large" required validator "FQDN"
2243 string addr display "large" required validator "IpAddress"
2244 }
2245 optional ( basic.display_help == "max") {
2246 message active_directory_servers_help "Specify each of your Active Directory domain controllers, both FQDN and associated IP address, used for this environment. Click the Add button for additional rows."
2247 }
2248 choice credentials display "xxlarge" default "no" {
2249 "Anonymous binding is allowed" => "no" ,
2250 "Require credentials for authentication" => "yes"
2251 }
2252 optional ( basic.display_help == "max") {
2253 message credentials_help "Choose whether your Active Directory implementation allows anonymous binding or not. If it does not, you must provide a user name and password with administrative permissions."
2254 }
2255 optional ( credentials == "yes" ) {
2256 string active_directory_username display "xxlarge" required
2257 optional ( basic.display_help == "max") {
2258 message active_directory_username_help "You must type the user name of an Active Directory account that has administrative permissions."
2259 }
2260 password active_directory_password display "xxlarge" required
2261 optional ( basic.display_help == "max") {
2262 message active_directory_password_help "Type the associated password."
2263 }
2264 }
2265 choice ad_monitor display "xxlarge" default "/#create_new#" tcl {
2266 set ::choices "Yes, create a new Active Directory monitor\t/#create_new#\nYes, create a simple ICMP monitor\t/#use_icmp#\nNo, do not monitor Active Directory\t/#do_not_use#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -filter NAME != \"ldap\" ltm monitor ldap]"
2267 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2268 }
2269 optional ( basic.display_help == "max") {
2270 message active_directory_monitor_help "This monitor is for the Active Directory servers you entered in the APM Authentication section, and is attached to the Active Directory pool the template will create. Specify whether you want to create a new Active Directory monitor, use a simple ICMP/ping monitor, or choose an existing monitor. The remaining questions in this section are all related to the Active Directory monitor."
2271 }
2272 optional ( ad_monitor == "/#create_new#" ) {
2273 string ad_user required display "xxlarge"
2274 message ad_user_critical "The Active Directory service account you specify here must be set to never expire. A deleted or locked account will cause the BIG-IP system to mark your Active Directory pool members as unavailable, which takes them offline."
2275 password ad_password required display "xxlarge"
2276 message ad_password_important "Credentials are stored in plaintext on your BIG-IP system."
2277 string ad_tree required display "xxlarge"
2278 optional ( basic.display_help == "max") {
2279 message ad_tree_info "Specify the LDAP tree for the user name you provided. ADSI editor, an administration tool for Active Directory LDAP administration, is useful for determining the correct LDAP tree value. For example, if the user name is 'user1' which is in the organizational unit 'F5 Users' and is in the domain 'f5.example.com', the LDAP tree would be: ou=F5 Users, dc=f5, dc=example, dc=com."
2280 }
2281 choice ad_secure display "xxlarge" {
2282 "No, a secure protocol is not required" => "none" ,
2283 "Yes, SSL communication is required" => "ssl" ,
2284 "Yes, TLS communication is required" => "tls"
2285 }
2286 optional ( basic.display_help == "max") {
2287 message ad_secure_info "Select whether your Active Directory implementation requires a secure protocol (SSL or TLS) for communication, or if it does not use a secure protocol."
2288 }
2289 optional ( basic.advanced == "yes" ) {
2290 string ad_interval default "10" validator "NonNegativeNumber"
2291 optional ( basic.display_help == "max") {
2292 message ad_interval_info "Specify the number of seconds to use between each health monitor attempt. Members of this pool are marked down after four incorrect responses, and marked available after one correct response. "
2293 }
2294 optional ( ad_secure == "ssl" ) {
2295 string ad_port_ssl default "636" required
2296 }
2297 optional ( ad_secure != "ssl" ) {
2298 string ad_port_not_ssl default "389" required
2299 }
2300 optional ( basic.display_help == "max") {
2301 message ad_port_info "Specify the port being used by your Active Directory deployment. The default port when using the TLS security protocol, or no security, is port 389. The default port used when using the SSL security protocol is 636."
2302 }
2303 }
2304 }
2305 }
2306 string login_domain display "xxlarge" required
2307 optional ( basic.display_help == "max") {
2308 message login_domain_help "Specify the FQDN of the Active Directory deployment for your AD FS users. This is the FQDN for your domain, such as example.com, rather than the FQDN for any specific host."
2309 }
2310 choice mfa display "xxlarge" default "no" {
2311 "No, do not configure support for Azure MFA" => "no" ,
2312 "Yes, configure support for Azure MFA" => "yes"
2313 }
2314 optional ( basic.display_help == "max") {
2315 message mfa_help "Select 'Yes' if you would like the objects created for inclusion of Azure MFA support in the APM policy. APM will connect using RADIUS to Azure MFA servers. See the documentation for more information on how to setup the Azure MFA service/servers."
2316 }
2317 optional ( mfa == "yes" ) {
2318 choice mfa_aaa_profile display "xxlarge" default "/#create_new#" tcl {
2319 set ::choices "Create a new Azure MFA RADIUS Server\t/#create_new#\n"
2320 append ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain -filter use-pool !~ "disabled" apm aaa radius]
2321 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2322 }
2323 optional ( basic.display_help == "max") {
2324 message mfa_aaa_profile_help "Choose whether you want the template to create a new BIG-IP APM AAA Server object for your implementation or use an existing one. The AAA Server contains information about your Azure MFA server deployment. Unless you have created a custom AAA server specifically for this implementation, we recommend allowing the iApp to create a new one."
2325 }
2326 message aaa_mfa_warning "If you plan on using an existing AAA server object, it must be configured to use a pool of Azure MFA servers (via RADIUS); only AAA servers configured to use a pool appear in the list. If necessary, you can create a pool in the AAA server configuration with a single member."
2327
2328 optional ( mfa_aaa_profile == "/#create_new#" ) {
2329 table mfa_radius_servers {
2330 string addr display "large" required validator "IpAddress"
2331 }
2332 optional ( basic.display_help == "max") {
2333 message mfa_radius_servers_help "Specify the IP address of each of your Azure MFA servers used in this environment. Click the Add button for additional rows."
2334 }
2335 string mfa_radius_port display "medium" required default "1812"
2336 optional ( basic.display_help == "max") {
2337 message mfa_radius_port_help "Specify the port to be used to connect to the Azure MFA servers via RADIUS (typically 1645 or 1812)."
2338 }
2339 string mfa_radius_acct_port display "medium" required default "1813"
2340 optional ( basic.display_help == "max") {
2341 message mfa_radius_acct_port_help "Specify the port to be used for RADIUS accounting."
2342 }
2343 password mfa_radius_secret display "xxlarge" required
2344 optional ( basic.display_help == "max") {
2345 message mfa_radius_secret_help "You must type the secret to be used for RADIUS communication."
2346 }
2347 choice mfa_radius_monitor display "xxlarge" default "/#create_new#" tcl {
2348 set ::choices "Yes, create a simple ICMP monitor\t/#use_icmp#\nNo, do not monitor MFA (RADIUS) servers\t/#do_not_use#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -filter NAME != \"radius\" ltm monitor]"
2349 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2350 }
2351 optional ( basic.display_help == "max") {
2352 message mfa_radius_monitor_help "This monitor is for the Azure MFA servers you entered in the APM Authentication section, and is attached to the MFA (RADIUS) pool the template creates. Specify whether you want to create a new simple ICMP/ping monitor, or choose an existing monitor."
2353 }
2354 }
2355 }
2356 optional ( intro.is_120 == "yes") {
2357 choice log_settings display "xxlarge" default "/Common/default-log-setting" tcl {
2358 set log ""
2359 catch {
2360 set log [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items apm log-setting]
2361 } err
2362 set ::choices "Do not specify a logging profile for the APM profile\t/#do_not_use#\n$log"
2363 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2364 }
2365 optional ( basic.display_help == "max" ) {
2366 message log_settings_help "Select APM logging profile to use for the Access Policy created for this iApp deployment. You must have previously created the profile before it will appear in the list."
2367 }
2368 }
2369 }
2370 }
2371 }
2372 }
2373 optional ( intro.afm_provisioned == "yes" ) {
2374 section afm {
2375 choice policy default "/#do_not_use#" display "xxlarge" tcl {
2376 set ::choices "Yes, use network firewall and IP Intelligence\t/#default#\nNo, do not use network firewall or IP Intelligence\t/#do_not_use#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain security firewall policy]"
2377 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2378 }
2379 optional ( basic.display_help == "max" ) {
2380 message policy_max "BIG-IP Advanced Firewall Manager (AFM) is a high-performance, stateful, full-proxy network firewall designed to guard data centers against incoming threats that enter the network on the most widely deployed protocols. BIG-IP AFM must be fully licensed and provisioned to use this functionality. If you have already created an AFM Network Firewall Policy on this BIG-IP system for this implementation, you can select it from the list."
2381 }
2382 optional ( policy == "/#default#" ) {
2383 choice restrict_by_addr default "/#do_not_use#" display "xxlarge" tcl {
2384 set ::choices "No, do not forbid client addresses (allow all)\t/#do_not_use#\nYes, forbid specific client addresses\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain security firewall address-list]"
2385 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2386 }
2387 optional ( basic.display_help == "max" ) {
2388 message restrict_max "You can use the BIG-IP AFM to restrict access to your application by either IP address or network address. If enabled, the system will only allow access to the virtual server from the address(es) you specify."
2389 }
2390 optional ( restrict_by_addr == "/#create_new#" ) {
2391 string allowed_addr display "xxlarge" required
2392 optional ( basic.display_help == "max" ) {
2393 message allowed_addr_max "Specify the IP or network address that should have access to the application. You can use a single IP address, a list of IP addresses separated by spaces, a range of IP addresses separated by a dash (for example 192.0.2.10-192.0.2.100), a single network address, such as 192.0.2.200/24, or any combination of these."
2394 }
2395 }
2396 }
2397 optional ( policy != "/#do_not_use#" ) {
2398 choice restrict_by_reputation default "accept" display "xxlarge" {
2399 "Accept all connections and log nothing" => "accept" ,
2400 "Reject connections from IP addresses with poor reputations" => "reject" ,
2401 "Accept all connections but log those from suspicious networks" => "warn"
2402 }
2403 optional ( basic.display_help == "max" ) {
2404 message restrict_by_reputation_max "The BIG-IP AFM uses an IP intelligence database to categorize IP addresses coming into the system. Select the way you want the system to handle IP addresses with a low reputation score."
2405 }
2406 optional ( basic.display_help == "max" && restrict_by_reputation != "accept" ) {
2407 message restrict_by_reputation_log "By default, IP Intelligence events are logged to Security > Event Logs > Network > IP Intelligence. For the best performance, F5 recommends creating a remote logging profile to log IP Intelligence events."
2408 }
2409 message restrict_by_reputation_warn "You must have an active IP Intelligence license for IP reputation-based access control to function correctly."
2410
2411 choice staging_policy default "/#do_not_use#" display "xxlarge" tcl {
2412 set ::choices "Do not apply a staging policy\t/#do_not_use#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -nocomplain security firewall policy]"
2413 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2414 }
2415 message staging_policy1_max "A policy in Staging mode does not block any traffic, and only logs what would be blocked if the policy were placed into production."
2416
2417 optional ( basic.display_help == "max" ) {
2418 message staging_policy_max "A staged policy allows you to evaluate the effect a policy has on traffic by analyzing the system logs, without actually modifying traffic based on the firewall rules. You must already have a policy on the system in order to select it from the list. For specific information on creating a staging policy, see the AFM documentation."
2419 }
2420 choice security_logging default "/#do_not_use#" display "xxlarge" tcl {
2421 # Menu should display all log profiles with "network none".
2422 # tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items will not filter security log profiles,
2423 # so the filter has been written inline here.
2424 set ::choices "Do not use a logging profile\t/#do_not_use#\n"
2425 if { [catch {
2426 set profile_list [tmsh::list security log profile all-properties recursive]
2427 } err] } {
2428 set profile_list " "
2429 }
2430 array set profiles \
2431 [string map {"security log profile" ""} $profile_list]
2432 foreach name [array names profiles] {
2433 array set subprofile $profiles($name)
2434 if { [info exists subprofile(network)] && \
2435 $subprofile(network) != "none" } {
2436 append ::choices "$name\n"
2437 }
2438 }
2439 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2440 }
2441 optional ( basic.display_help == "max" ) {
2442 message security_logging_max "The logging profile enables you to log detailed information about BIG-IP system Network Firewall events and store those logs on the BIG-IP system or a remote logging server (syslog or Splunk). If you want to use a logging profile, we recommend creating one outside this template. Only logging profiles with Network Firewall enabled appear in the list."
2443 message security_logging1_max "If you are also using BIG-IP ASM, and the logging profile you created has both Application Security and Network Firewall enabled in the same profile, you must also select that profile here. See the BIG-IP AFM documentation for specific information on Logging profiles."
2444 }
2445 }
2446 }
2447 }
2448 section ssl {
2449 optional ( basic.scenario == "adfs_proxy" || ( basic.scenario == "adfs" && ( intro.apm_provisioned == "no" || ( intro.apm_provisioned == "yes" && ( apm.use_apm == "no" && apm.adfs_proxy_setup == "no" ) ) ) ) ) {
2450 choice mode display "xxlarge" default "bridging" {
2451 "Terminate SSL from clients, re-encrypt to servers (SSL bridging)" => "bridging" ,
2452 "Encrypted traffic is forwarded without decryption (SSL pass-through)" => "passthru"
2453 }
2454 optional ( basic.display_help == "max" ) {
2455 message mode_max "Select how BIG-IP should handle encrypted traffic from AD FS clients. SSL bridging is mandatory when protecting AD FS server(s) with F5 Access Policy Manager (APM)."
2456 message mode_bridging_max "Select SSL bridging if you need to inspect or optimize encrypted client traffic before forwarding it to AD FS server(s). A standard BIG-IP virtual server is created."
2457 message mode_passthru_max "Select SSL pass-through for best performance, or when SSL decryption is disallowed. A Performance (Layer 4) BIG-IP virtual server is created."
2458 }
2459 }
2460 optional ( intro.apm_provisioned == "yes" && apm.use_apm == "yes" || ( mode == "bridging" ) ) {
2461 choice client_ssl_profile display "xxlarge"
2462 default "/#create_new#" tcl {
2463 set ::choices "Create a new Client SSL profile\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile client-ssl]"
2464 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2465 }
2466 optional ( basic.display_help == "max" ) {
2467 message client_ssl_profile_max "If you have already created an Client SSL profile that includes the appropriate certificate and key, you can select it from the list. Otherwise, the iApp creates a new Client SSL profile. "
2468 }
2469 optional (client_ssl_profile == "/#create_new#" ) {
2470 choice cert default "/Common/default.crt"
2471 display "xxlarge" tcl {
2472 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -norecursive -filter NAME !~ ca-bundle.crt|f5-irule.crt sys file ssl-cert]
2473 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2474 }
2475 optional ( basic.display_help == "max" ) {
2476 message cert_max "To establish encrypted communication, a client and server negotiate security parameters that are used for the session. As part of this handshake, a certificate is provided by the server to the client to identify itself. The client can then validate the certificate with an authority for authenticity before sending data. When the BIG-IP system is decrypting communication between the client and server, an SSL certificate and key pair for each fully-qualified DNS name related to this application instance must be configured on the system."
2477 message cert1_max "Select the SSL certificate you imported for this deployment. Importing certificates and keys is not a part of this template, see System > File Management > SSL Certificate List. To select any new certificates and keys you import, you need to restart or reconfigure this template."
2478 }
2479 choice key default "/Common/default.key"
2480 display "xxlarge" tcl {
2481 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -norecursive -filter security-type ne "password" sys file ssl-key]
2482 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2483 }
2484 optional ( basic.display_help == "max" ) {
2485 message key_max "Select the associated SSL key you imported."
2486 }
2487 optional ( cert == "/Common/default.crt"
2488 || key == "/Common/default.key" ) {
2489 message ssl_warn_1 "The BIG-IP system's default certificate and key are not secure. For proper security, acquire a certificate and key from a trusted certificate authority, and then import it onto the BIG-IP system."
2490 }
2491 optional ( basic.display_help == "max" ) {
2492 message ssl_warn_3 "If your key is password-protected, you must manually create a Client SSL profile outside the iApp, and then select it from the list above."
2493 }
2494 optional ( basic.advanced == "yes" ) {
2495 choice use_chain_cert display "xxlarge"
2496 default "/#do_not_use#" tcl {
2497 set ::choices "Do not use an intermediate certificate\t/#do_not_use#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -norecursive sys file ssl-cert]"
2498 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2499 }
2500 optional ( basic.display_help == "max" ) {
2501 message use_chain_cert_1_max "Intermediate certificates, also called intermediate certificate chains or chain certificates, are used to help systems which depend on SSL certificates for peer identification. These certificates are intended to create a chain of trust between the CA that signed the certificate and the CA that is already trusted by the recipient of the certificate. This allows the recipient to verify the validity of the certificates presented, even when the signing CA is unknown."
2502 message use_chain_cert_2_max "Intermediate certificates must be created or imported onto this BIG-IP system prior to running this iApp. See http://support.f5.com/kb/en-us/solutions/public/13000/300/sol13302.html for help on creating an intermediate certificate chain."
2503 }
2504 }
2505 }
2506 choice server_ssl_profile display "xxlarge"
2507 default "/#create_new#" tcl {
2508 set ::choices "Create a new Server SSL profile based on serverssl (recommended)\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile server-ssl]"
2509 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2510 }
2511 optional ( basic.display_help == "max" ) {
2512 message server_ssl_profile_max "If you have already created an Server SSL profile on this BIG-IP system, you can select it from the list. Otherwise, the iApp creates a new Server SSL profile."
2513 }
2514 }
2515 }
2516 section vs_pool {
2517 string vs_addr display "xxlarge" validator "IPAddress" required
2518 optional ( basic.display_help == "max" ) {
2519 message vs_addr_max "This IP and port combination become the BIG-IP virtual server address and port, which clients use to access the application. The system intercepts requests to this IP:Port and distributes them to the AD FS servers."
2520 }
2521 string vs_port display "medium" validator "PortNumber" default "443" required
2522 optional ( basic.display_help == "max" ) {
2523 message vs_port_max "Specify the service port you want to use for the virtual server. The default port for AD FS is 443."
2524 }
2525 string fqdn display "xxlarge" validator "Fqdn" required
2526 optional ( basic.display_help == "max" ) {
2527 message fqdn_max "Specify the FQDN (Fully Qualified Domain Name) clients will use to access the AD FS implementation."
2528 }
2529 optional ( basic.advanced == "yes" ) {
2530 optional ( intro.apm_provisioned == "yes" && apm.use_apm == "yes" || ( ssl.mode == "bridging" ) ) {
2531 choice http display "xxlarge" default "/#create_new#" tcl {
2532 set ::choices "Create a new HTTP profile (recommended)\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile http]"
2533 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2534 }
2535 optional ( basic.display_help == "max" ) {
2536 message http_max "The HTTP profile contains settings that tell the BIG-IP system how to handle the HTTP protocol. If you have created a custom HTTP profile for this application, you can select it from the list."
2537 }
2538 optional ( http == "/#create_new#" && apm.adfs_proxy_setup == "no" ) {
2539 choice xff display "xxlarge" default "yes" {
2540 "Insert X-Forwarded-For HTTP header" => "yes" ,
2541 "Do not insert X-Forwarded-For HTTP header" => "no"
2542 }
2543 optional ( basic.display_help == "max" ) {
2544 message xff_max "If you choose to insert the X-Forwarded-For header, the BIG-IP system inserts the original client IP address in the HTTP header for logging purposes. Additional configuration may be required on the server to log the value of the X-Forwarded-For header."
2545 }
2546 }
2547 }
2548 }
2549 choice pool_to_use display "xxlarge" default "/#create_new#" tcl {
2550
2551 set ::choices "Create a new pool\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm pool]"
2552 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2553 }
2554 optional ( basic.display_help == "max" ) {
2555 message pool_max "A load balancing pool is a logical set of devices, such as AD FS servers, grouped together to receive and process traffic. When clients attempt to access the application via the BIG-IP virtual server, the BIG-IP system distributes requests to any of the servers that are members of that pool."
2556 }
2557 optional ( pool_to_use == "/#create_new#" ) {
2558 optional ( basic.advanced == "yes" ) {
2559 lb_method lb_method_choice
2560 optional ( basic.display_help == "max" ) {
2561 message lb_method_max "A load balancing method is an algorithm that the BIG-IP system uses to select a pool member for processing a request. F5 recommends the Least Connections load balancing method, where new connections are routed to the node that has the least number of current connections. This is ideal for environments in which pool members have similar performance and capacity capabilities."
2562 }
2563 optional ( ssl.mode == "bridging" ) {
2564 choice tcp_req_queuing display "xxlarge" default "no" {
2565 "Enable TCP request queuing" => "yes" ,
2566 "Do not enable TCP request queuing" => "no"
2567 }
2568 optional ( basic.display_help == "max" ) {
2569 message tcp_request_queue_2_max "TCP request queuing provides the ability to queue connection requests that exceed the capacity of connections for a pool, pool member, or node, as determined by the connection limit. If you enable TCP request queuing, you must specify a queue length and timeout for queued requests based on server capability, load, and need for shared resources."
2570 }
2571 optional ( tcp_req_queuing == "yes" ) {
2572 message tcp_request_queue_1_max "Improper use or misconfiguration of TCP Request Queuing/Connection Limits can result in unwanted application behavior and poor performance of your BIG-IP system. For this reason we recommended you verify these settings impact prior to deployment in a production environment. You MUST add a Connection Limit to your pool members for TCP Request Queuing."
2573 string tcp_queue_length display "medium"
2574 default "0" required
2575 validator "NonNegativeNumber"
2576 optional ( basic.display_help == "max" ) {
2577 message tcp_queue_length_max "Specify a number for the length of the queue. You should not use a value of '0', which indicates an unlimited queue length, and is only constrained by available memory."
2578 }
2579 string tcp_queue_timeout display "medium"
2580 default "0" required
2581 validator "NonNegativeNumber"
2582 optional ( basic.display_help == "max" ) {
2583 message tcp_queue_timeout_max "Specify a number of milliseconds that requests should remain in the queue before timing out."
2584 }
2585 }
2586 }
2587 choice use_slow_ramp default "yes" display "xxlarge" {
2588 "Use Slow Ramp" => "yes" ,
2589 "Do not use Slow Ramp" => "no"
2590 }
2591 optional ( basic.display_help == "max" ) {
2592 message slow_ramp_max "With Slow Ramp, the BIG-IP system gradually adds connections to a newly-enabled or newly-added AD FS server over a time period you specify, rather than sending a full proportion of the traffic immediately. Slow Ramp is essential when using load balancing methods like Least Connections, as the BIG-IP system would otherwise send all new connections to a new server immediately, potentially overwhelming that server. The time period you select for Slow Ramp is highly dependent on the speed of your server hardware and the behavior of your AD FS services. "
2593 }
2594 optional ( use_slow_ramp == "yes" ) {
2595 string slow_ramp_setvalue display "medium"
2596 default "300" required
2597 validator "NonNegativeNumber"
2598 }
2599 optional ( basic.display_help == "max" ) {
2600 message slow_ramp_setvalue_max "Specify the duration (in seconds) for Slow Ramp time (the amount of time the system sends less traffic to a newly-enabled pool member). The default setting of 300 seconds (5 minutes) is very conservative in most cases."
2601 }
2602 choice use_pga default "no" display "xxlarge" {
2603 "Do not use Priority Group Activation" => "no" ,
2604 "Use Priority Group Activation" => "yes"
2605 }
2606 optional ( basic.display_help == "max" ) {
2607 message pga_max "Priority Group Activation allows you to segment your servers into priority groups. With Priority Group Activation, the BIG-IP system load balances traffic according to the priority number you assign to the pool members. A higher number indicates higher priority. Traffic is only sent to the servers with the highest priority, unless the number of available servers in that priority group falls below the value you specify as the minimum. The BIG-IP system then sends traffic to the group of servers with the next highest priority, and so on. See the BIG-IP documentation for more details."
2608 }
2609 optional ( use_pga == "yes" ) {
2610 string min_active_members display "medium"
2611 default "0" required
2612 validator "NonNegativeNumber"
2613 optional ( basic.display_help == "max" ) {
2614 message min_active_members_max "Specify the minimum number of servers which must be available before the system sends traffic to servers with a lower priority."
2615 }
2616 }
2617 }
2618 table members {
2619 editchoice addr display "large" tcl {
2620
2621 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm node]
2622 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2623 }
2624 string port display "small" required
2625 default "443" validator "PortNumber"
2626 string conn_limit display "small" required
2627 default "0" validator "NonNegativeNumber"
2628 optional ( lb_method_choice == "ratio-member"
2629 || lb_method_choice == "ratio-node"
2630 || lb_method_choice == "ratio-session"
2631 || lb_method_choice == "ratio-least-connections-member"
2632 || lb_method_choice == "ratio-least-connections-node"
2633 || lb_method_choice == "dynamic-ratio-member"
2634 || lb_method_choice == "dynamic-ratio-node") {
2635 string ratio default "1" validator "NonNegativeNumber"
2636 display "small"
2637 }
2638 optional ( use_pga == "yes" ) {
2639 string priority default "0" required
2640 validator "NonNegativeNumber" display "small"
2641 }
2642 }
2643 optional ( basic.display_help == "max" ) {
2644 message members_max "Specify the IP address(es) of your AD FS servers. If you have existing nodes on this BIG-IP system, you can select them from the list, otherwise type the addresses. Click Add to include additional servers."
2645 }
2646 }
2647 choice cert_auth display "xxlarge" default "true" {
2648 "Yes, configure support for certificate authentication" => "true" ,
2649 "No, do not create the configuration" => "false"
2650 }
2651 optional ( basic.display_help == "max" ) {
2652 message cert_auth_max "Choose whether you want the iApp to configure BIG-IP to support client certificate authentication. If you select Yes, the iApp creates the objects needed for client certificate authentication. This uses port 49443, which is based on Microsoft's alternate port configuration."
2653 }
2654 optional ( pool_to_use != "/#create_new#" && cert_auth == "true" ) {
2655 choice cert_auth_pool_to_use display "xxlarge" tcl {
2656 set ::choices "[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm pool]"
2657 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2658 }
2659 optional ( basic.display_help == "max" ) {
2660 message cert_auth_pool_to_use_max "A load balancing pool is a logical set of devices, such as AD FS servers, grouped together to receive and process traffic. When clients attempt to access the application via the BIG-IP virtual server, the BIG-IP system distributes requests to any of the servers that are members of that pool."
2661 }
2662 }
2663 optional ( cert_auth == "true" && apm.adfs_proxy_setup == "yes" && basic.scenario == "adfs" ) {
2664 optional ( ssl.client_ssl_profile == "/#create_new#" ) {
2665 choice cert_auth_trusted_ca default "/Common/default.crt" display "xxlarge" tcl {
2666 set ::choices "[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -norecursive -filter NAME !~ f5-irule.crt sys file ssl-cert]"
2667 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2668 }
2669 optional ( basic.display_help == "max" ) {
2670 message cert_auth_trusted_ca_max "As an additional feature of BIG-IP requiring user certificates be presented during TLS negotiation for ADFS certificate authentication, the BIG-IP will also check that the certificate chain provided in those user certificates includes a specific Root or Intermediate CA, if the Root/Intermediate CA chosen is not in the chain the TLS connection will get dropped. It is required to include a valid Trusted CA."
2671 }
2672 }
2673 optional ( ssl.client_ssl_profile != "/#create_new#" ) {
2674 choice cert_auth_client_ssl_profile display "xxlarge" tcl {
2675 set ::choices "[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile client-ssl]"
2676 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2677 }
2678 optional ( basic.display_help == "max" ) {
2679 message cert_auth_client_ssl_profile_max "If you have already created an Client SSL profile that includes the appropriate configuration for certificate authentication, you can select it from the list. Otherwise, the iApp creates a new Client SSL profile. "
2680 }
2681 }
2682 }
2683 }
2684
2685 optional ( vs_pool.pool_to_use == "/#create_new#" ) {
2686 section app_health {
2687 choice monitor display "xxlarge" default "/#create_new#" tcl {
2688 set ::choices "Create a new monitor\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -filter NAME != "https" \
2689 ltm monitor https]\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -filter NAME != "external" \
2690 ltm monitor external]"
2691 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2692 }
2693 optional ( basic.display_help == "max" ) {
2694 message monitor_max "Monitors are used to determine the health of the endpoint on each AD FS server. If an endpoint does not respond or responds incorrectly the system will cease to send client requests to that AD FS server. The system will continue to monitor the instance and will begin sending requests once the endpoint responds correctly."
2695 }
2696 optional ( monitor == "/#create_new#" ) {
2697 string frequency display "medium" required default "30"
2698 optional ( basic.display_help == "max" ) {
2699 message freq_max "This is the duration, in seconds, of a single monitor cycle. At this interval, the system checks the health of the endpoint on each AD FS server configured in the AD FS server pool."
2700 }
2701 string send required display "xxlarge" default "/adfs/fs/federationserverservice.asmx"
2702 optional ( basic.display_help == "max" ) {
2703 message send_max "The HTTP URI is used to specify the resource on the AD FS server for a given request. This parameter can be customized to request a specific federation endpoint."
2704 }
2705 string recv required display "xxlarge" default "200 OK"
2706 optional ( basic.display_help == "max" ) {
2707 message recv_max "When the HTTP response arrives for a monitor request, its contents are searched for the value specified here. If it is not found, the monitoring attempt fails."
2708 }
2709 }
2710 }
2711 }
2712 optional ( basic.advanced == "yes" ) {
2713 optional ( intro.apm_provisioned == "yes" && apm.use_apm == "yes" || ( ssl.mode == "bridging" ) ) {
2714 section client_opt {
2715 optional ( net.client_mode == "lan" ) {
2716 choice tcp_lan_opt display "xxlarge"
2717 default "/#create_new#" tcl {
2718
2719 set ::choices "New profile based on tcp-lan-optimized ( recommended )\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile tcp]"
2720 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2721 }
2722 }
2723 optional ( net.client_mode != "lan" ) {
2724 choice tcp_wan_opt display "xxlarge"
2725 default "/#create_new#" tcl {
2726
2727 set ::choices "New profile based on tcp-wan-optimized ( recommended )\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile tcp]"
2728 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2729 }
2730 }
2731 optional ( basic.display_help == "max" ) {
2732 message tcp_max "The client-side TCP profile optimizes the communication between the BIG-IP system and the client by controlling the behavior of the traffic which results in higher transfer rates, improved connection reliability and increased bandwidth efficiency."
2733 }
2734 }
2735 section server_opt {
2736 optional ( net.server_mode == "lan" ) {
2737 choice tcp_lan_opt display "xxlarge"
2738 default "/#create_new#" tcl {
2739
2740 set ::choices "New profile based on tcp-lan-optimized ( recommended )\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile tcp]"
2741 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2742 }
2743 }
2744 optional ( net.server_mode != "lan" ) {
2745 choice tcp_wan_opt display "xxlarge"
2746 default "/#create_new#" tcl {
2747
2748 set ::choices "New profile based on tcp-wan-optimized ( recommended )\t/#create_new#\n[tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items ltm profile tcp]"
2749 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2750 }
2751 }
2752 optional ( basic.display_help == "max" ) {
2753 message tcp_max "The server-side TCP profile optimizes the communication between the BIG-IP system and the server by controlling the behavior of the traffic which results in higher transfer rates, improved connection reliability and increased bandwidth efficiency."
2754 }
2755 }
2756 }
2757 section irules {
2758 message irule_1_max "Improper use or misconfigurations of an iRule can result in unwanted application behavior and poor performance of your BIG-IP system. For this reason we recommended you verify the impact of an iRule prior to deployment in a production environment."
2759 optional ( basic.display_help == "max" ) {
2760 message irule_2_max "The BIG-IP system supports a scripting language to allow an administrator to instruct the system to intercept, inspect, transform, direct and track inbound or outbound application traffic. An iRule contains the set of instructions the system uses to process data flowing through it, either in the header or payload of a packet."
2761 message irule_3_max "Correct event priority is critical when assigning multiple iRules. For more information about iRule event priority, see https://devcentral.f5.com/wiki/iRules.priority.ashx."
2762 }
2763 multichoice irules display "xlarge" tcl {
2764 set ::choices [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_get_items -filter NAME !~ "^_sys_" ltm rule]
2765 return [tmsh::run_proc f5.iapp.1.5.6.cli:iapp_safe_display ::choices]
2766 }
2767 }
2768 }
2769 optional ( basic.display_help == "max" ) {
2770 section addl_steps {
2771 message dns "You must configure a DNS entry for each fully qualified host name that the clients use to access the AD FS servers. Each DNS record must resolve to the IP address you configured for the BIG-IP virtual server defined in the High Availability section."
2772 }
2773 }
2774}
2775
2776text {
2777 intro "Welcome to the iApp template for Microsoft Active Directory Federation Services"
2778 intro.early_release "EARLY RELEASE"
2779 intro.intro "Introduction"
2780 intro.check_for_updates "Check for Updates"
2781 intro.sorry "We're sorry"
2782
2783
2784 basic "Template Options"
2785 basic.display_help "Do you want to see inline help?"
2786 basic.display_help_max ""
2787 basic.advanced "Which configuration mode do you want to use?"
2788 basic.advanced_max ""
2789 basic.version "Which version of AD FS are you deploying?"
2790 basic.version_max ""
2791 basic.scenario "Which AD FS server role is BIG-IP being deployed in front of?"
2792 basic.scenario_max ""
2793
2794 net "Network"
2795 net.client_vlan "Which VLANs transport client traffic?"
2796 net.client_vlan_max ""
2797 net.client_mode "What type of network connects clients to the BIG-IP?"
2798 net.client_mode_max ""
2799 net.server_mode "What type of network connects servers to the BIG-IP?"
2800 net.server_mode_max ""
2801 net.same_subnet "Where will the virtual servers be in relation to the AD FS servers?"
2802 net.subnet_1_max ""
2803 net.subnet_2_max ""
2804 net.subnet_3_max ""
2805 net.route_to_bigip "How have you configured routing on your AD FS servers?"
2806 net.def_rt_1_max ""
2807 net.def_rt_2_max ""
2808 net.def_rt_3_max ""
2809 net.snat_type "How many connections per server do you expect?"
2810 net.snatpool "Create a new SNAT pool or use an existing one?"
2811 net.snatpool_max ""
2812 net.snatpool_members "What are the IP addresses you want to use for the SNAT pool?"
2813 net.snatpool_members.addr "IP"
2814 net.snatpool_members_max ""
2815 net.snat_max ""
2816
2817 apm "Access Policy Manager (BIG-IP APM)"
2818 apm.use_apm "Do you want to provide secure authentication with BIG-IP APM?"
2819 apm.use_apm_max ""
2820 apm.adfs_proxy_note "NOTE:"
2821 apm.adfs_proxy_setup "Would you like to configure BIG-IP as an ADFS Proxy?"
2822 apm.adfs_proxy_setup_help ""
2823 apm.adfs_admin_user "What is the account to be used for establishing proxy trust with ADFS?"
2824 apm.adfs_admin_user_help ""
2825 apm.adfs_admin_password "What is the password associated with that account?"
2826 apm.adfs_admin_password_help ""
2827 apm.apm_profile "Which Access Profile do you want to use?"
2828 apm.apm_profile_help ""
2829 apm.use_forms_sso "Do you want the iApp to configure Forms SSO?"
2830 apm.use_forms_sso_max ""
2831 apm.aaa_profile "Which AAA Server object do you want to use?"
2832 apm.aaa_profile_max ""
2833 apm.aaa_warning "IMPORTANT"
2834 apm.active_directory_servers "Which Active Directory server IP address in your domain can this BIG-IP system contact?"
2835 apm.active_directory_servers_help ""
2836 apm.active_directory_servers.fqdn "FQDN"
2837 apm.active_directory_servers.addr "IP"
2838 apm.login_domain "What is the FQDN of the Active Directory implementation for your AD FS users?"
2839 apm.login_domain_help ""
2840 apm.credentials "Does your Active Directory domain allow anonymous binding?"
2841 apm.credentials_help ""
2842 apm.active_directory_username "Which Active Directory user with administrative permissions do you want to use?"
2843 apm.active_directory_username_help ""
2844 apm.active_directory_password "What is the password associated with that account?"
2845 apm.active_directory_password_help ""
2846 apm.ad_monitor "Create a new monitor for the Active Directory servers?"
2847 apm.active_directory_monitor_help ""
2848 apm.ad_user "Which Active Directory user name should the monitor use?"
2849 apm.ad_user_critical "CRITICAL"
2850 apm.ad_password "What is the associated password?"
2851 apm.ad_password_important "IMPORTANT"
2852 apm.ad_tree "What is the LDAP tree for this user account?"
2853 apm.ad_tree_info ""
2854 apm.ad_secure "Does your Active Directory domain require a secure protocol for communication?"
2855 apm.ad_secure_info ""
2856 apm.ad_interval "How many seconds between Active Directory health checks?"
2857 apm.ad_interval_info ""
2858 apm.ad_port_ssl "Which port is used for Active Directory communication?"
2859 apm.ad_port_not_ssl "Which port is used for Active Directory communication?"
2860 apm.ad_port_info ""
2861 apm.mfa "Do you want to configure support for Azure MFA (via Azure MFA servers)?"
2862 apm.mfa_help ""
2863 apm.mfa_aaa_profile "Which MFA (RADIUS) AAA Object would you like to use?"
2864 apm.mfa_aaa_profile_help ""
2865 apm.aaa_mfa_warning "IMPORTANT"
2866 apm.mfa_radius_servers "Which Azure MFA servers would you like to use?"
2867 apm.mfa_radius_servers_help ""
2868 apm.mfa_radius_servers.addr "IP"
2869 apm.mfa_radius_port "What port are the Azure MFA servers listening on for RADIUS connections?"
2870 apm.mfa_radius_port_help ""
2871 apm.mfa_radius_acct_port "What port are the Azure MFA servers listening on for RADIUS accounting?"
2872 apm.mfa_radius_acct_port_help ""
2873 apm.mfa_radius_secret "What is the RADIUS secret configured on the Azure MFA servers for this connection?"
2874 apm.mfa_radius_secret_help ""
2875 apm.mfa_radius_monitor "Create a new monitor for Azure MFA (RADIUS) servers?"
2876 apm.mfa_radius_monitor_help ""
2877 apm.log_settings "Which log settings would you like to use to log APM events?"
2878 apm.log_settings_help ""
2879
2880 afm "Advanced Firewall Manager (BIG-IP AFM)"
2881 afm.policy "Do you want to use AFM network firewall and IP Intelligence to protect your application?"
2882 afm.policy_max ""
2883 afm.restrict_by_addr "Do you want to forbid access to your application from specific networks or IP addresses?"
2884 afm.restrict_max ""
2885 afm.allowed_addr "What IP or network addresses should be allowed to access your application?"
2886 afm.allowed_addr_max ""
2887 afm.security_logging "Which logging profile would you like to use?"
2888 afm.security_logging_max ""
2889 afm.security_logging1_max ""
2890 afm.restrict_by_reputation "How should the system control connections from networks suspected of malicious activity?"
2891 afm.restrict_by_reputation_max ""
2892 afm.restrict_by_reputation_log ""
2893 afm.restrict_by_reputation_warn "IMPORTANT"
2894 afm.staging_policy "Would you like to stage a policy for testing purposes?"
2895 afm.staging_policy_max ""
2896 afm.staging_policy1_max "CRITICAL"
2897
2898 ssl "SSL Encryption"
2899 ssl.mode "How should the BIG-IP system handle SSL traffic?"
2900 ssl.mode_max ""
2901 ssl.mode_bridging_max ""
2902 ssl.mode_passthru_max ""
2903 ssl.cert "Which SSL certificate do you want to use?"
2904 ssl.cert_max ""
2905 ssl.cert1_max ""
2906 ssl.key "Which SSL private key do you want to use?"
2907 ssl.key_max ""
2908 ssl.use_chain_cert "Which intermediate certificate do you want to use?"
2909 ssl.use_chain_cert_1_max ""
2910 ssl.use_chain_cert_2_max ""
2911 ssl.ssl_warn_1 "WARNING:"
2912 ssl.ssl_warn_3 "NOTE:"
2913 ssl.client_ssl_profile "Which Client SSL profile do you want to use?"
2914 ssl.client_ssl_profile_max ""
2915 ssl.server_ssl_profile "Which Server SSL profile do you want to use?"
2916 ssl.server_ssl_profile_max ""
2917
2918 vs_pool "High Availability"
2919 vs_pool.vs_addr "What IP address do you want to use for the virtual server?"
2920 vs_pool.vs_addr_max ""
2921 vs_pool.vs_port "What service port do you want to use for the virtual server?"
2922 vs_pool.vs_port_max ""
2923 vs_pool.fqdn "Which FQDN will clients use to access AD FS?"
2924 vs_pool.fqdn_max ""
2925 vs_pool.http "Which HTTP profile do you want to use?"
2926 vs_pool.http_max ""
2927 vs_pool.xff "Should the BIG-IP system insert the X-Forwarded-For header?"
2928 vs_pool.xff_max ""
2929 vs_pool.pool_to_use "Do you want to create a new pool or use an existing one?"
2930 vs_pool.pool_max ""
2931 vs_pool.members "Which servers should be included in this pool?"
2932 vs_pool.members_max ""
2933 vs_pool.members.addr "IP Address"
2934 vs_pool.members.port "Port"
2935 vs_pool.members.conn_limit "Connection limit"
2936 vs_pool.members.ratio "Ratio"
2937 vs_pool.members.priority "Priority"
2938 vs_pool.lb_method_choice "Which load balancing method do you want to use?"
2939 vs_pool.lb_method_max ""
2940 vs_pool.tcp_req_queuing "Should the BIG-IP system queue TCP requests?"
2941 vs_pool.tcp_queue_length "What is the maximum number of queued TCP requests?"
2942 vs_pool.tcp_queue_length_max ""
2943 vs_pool.tcp_queue_timeout "How many milliseconds should requests stay in the queue?"
2944 vs_pool.tcp_queue_timeout_max ""
2945 vs_pool.tcp_request_queue_1_max "WARNING"
2946 vs_pool.tcp_request_queue_2_max ""
2947 vs_pool.use_slow_ramp "Use a Slow Ramp time for newly added servers?"
2948 vs_pool.slow_ramp_max ""
2949 vs_pool.slow_ramp_setvalue "How many seconds should Slow Ramp time last?"
2950 vs_pool.slow_ramp_setvalue_max ""
2951 vs_pool.use_pga "Do you want to give priority to specific groups of servers?"
2952 vs_pool.pga_max ""
2953 vs_pool.min_active_members "What is the minimum number of active members in a group?"
2954 vs_pool.min_active_members_max ""
2955 vs_pool.cert_auth "Do you want the iApp to configure support for client certificate authentication?"
2956 vs_pool.cert_auth_max ""
2957 vs_pool.cert_auth_pool_to_use "What pool would you like to use for certificate authentication?"
2958 vs_pool.cert_auth_pool_to_use_max ""
2959 vs_pool.cert_auth_trusted_ca "What Trusted CA would you like to use to validate the client certificate chain presented during certificate authentication?"
2960 vs_pool.cert_auth_trusted_ca_max ""
2961 vs_pool.cert_auth_client_ssl_profile "What Client SSL Profile would you like to use for certificate authentication?"
2962 vs_pool.cert_auth_client_ssl_profile_max ""
2963
2964 app_health "Application Health"
2965 app_health.monitor "Create a new health monitor or use an existing one?"
2966 app_health.monitor_max ""
2967 app_health.send "What HTTP URI should be sent to the server(s)"
2968 app_health.send_max ""
2969 app_health.recv "What is the expected response to the HTTP request?"
2970 app_health.recv_max ""
2971 app_health.frequency "How many seconds between each health check?"
2972 app_health.freq_max ""
2973
2974 client_opt "Client Optimization"
2975 client_opt.tcp_lan_opt "How do you want to optimize client-side connections?"
2976 client_opt.tcp_wan_opt "How do you want to optimize client-side connections?"
2977 client_opt.tcp_max ""
2978
2979 server_opt "Server Optimization"
2980 server_opt.tcp_lan_opt "How do you want to optimize server-side connections?"
2981 server_opt.tcp_wan_opt "How do you want to optimize server-side connections?"
2982 server_opt.tcp_max ""
2983
2984 irules "iRules"
2985 irules.irules "Do you want to add any custom iRules to the AD FS virtual server?"
2986 irules.irule_1_max "WARNING"
2987 irules.irule_2_max ""
2988 irules.irule_3_max ""
2989
2990 addl_steps "Additional Steps"
2991 addl_steps.dns "AD FS"
2992}
2993 }
2994 role-acl { admin manager resource-admin }
2995 run-as none
2996 }
2997 }
2998 description none
2999 ignore-verification false
3000 requires-bigip-version-max none
3001 requires-bigip-version-min 11.3.0
3002 requires-modules { ltm }
3003 signing-key none
3004 tmpl-checksum none
3005 tmpl-signature none
3006}