series-getting started with iapps
5 TopicsGetting Started with iApps: Modifying an Existing iApp
Now that the esteemed Chase Abbott has blazed the trail with all the iApps foundational goodness surrounding concepts and componentsin the first two articles in this Getting Started with iApps series, we can move into the practical! In this article, we'll start small, copying an existing iApp template and modifying it slightly. The IP Forwarding iApp Before we rip open the hood and dismount the engine, let's first take a walk through to evaluate the existing options. As indicated in the video above, we're going to make a couple modifications to this iApp. I don't want the end user of the iApp to have ability to forward all traffic as a default option, regardless of IP version. I want to make sure the port is all ports; no port specification supported. I want to disable the advanced features altogether, removing the ability to specify the fastL4 profile and iRules. Now that we've established what we're going to do, let's get it done! Existing Template The existing template is shown by section below: Implementation Presentation package require iapp 1.0.0 iapp::template start set app $tmsh::app_name set advanced [iapp::is ::options__advanced yes] # destination & mask array # array keys: $::basic__forward_all array set destination { IPv4 { destination any:any mask 0.0.0.0 } IPv6 { destination 0::0.any mask 0::0 } * { destination [iapp::destination $::basic__addr $::basic__port] \ mask $::basic__mask \ [expr { [string match "*:*:*" $::basic__addr] ? "source ::/0" : "" }]} } # PROFILES set use_default_profile [iapp::is ::basic__l4_profile_to_use "/#default#"] # array keys: $advanced,$use_default_profile array set profiles { 1,0 { profiles replace-all-with \{ $::basic__l4_profile_to_use \} } * { profiles replace-all-with \{ \ [iapp::conf create \ ltm profile fastl4 ${app}_fastL4 \ defaults-from fastL4 \ reset-on-timeout disabled \ loose-close enabled \ loose-initialization enabled] \} } } # VLANS # array keys: $::basic__vlan_listening array set vlans { enabled { vlans-enabled vlans replace-all-with \{ $::basic__vlan_selections \} } disabled { vlans-disabled vlans replace-all-with \{ $::basic__vlan_selections \} } default { vlans-disabled vlans none } } # RULES set have_irules [expr { ![iapp::is ::irules__irules ""] }] # array keys $advanced,$have_irules array set rules { 1,1 { rules \{ $::irules__irules \} } * { rules none } } # VIRTUALS set virtual { [iapp::conf create ltm virtual ${app}_VER_Forwarding \ ip-forward \ [iapp::substa destination(VER)] \ [iapp::substa profiles($advanced,$use_default_profile)] \ [iapp::substa vlans($::basic__vlan_listening)] \ [iapp::substa rules($advanced,$have_irules)]] } switch $::basic__forward_all { Yes { subst [string map "VER IPv4" $virtual] subst [string map "VER IPv6" $virtual] } No { subst [string map "VER IP" $virtual] } default { subst [string map "VER $::basic__forward_all" $virtual] } } iapp::template stop section intro { message hello message check_for_updates } section options { choice display_help display "xxlarge" default "hide" optional ( options.display_help == "max" ) { message display_help_max } choice advanced display "xxlarge" default "no" optional ( options.display_help == "max" ) { message conf_mode_max } } section basic { choice forward_all display "xxlarge" default "No" optional ( options.display_help == "max" ) { message forward_all_max } optional ( forward_all == "No" ) { string addr default "0.0.0.0" required validator "IpAddress" optional ( options.display_help == "max" ) { message addr_max } string mask default "0.0.0.0" required validator "IpAddress" optional ( options.display_help == "max" ) { message mask_max } string port default "0" required validator "PortNumber" optional ( options.display_help == "max" ) { message port_max } } choice vlan_listening default "default" display "xxlarge" optional ( options.display_help == "max" ) { message vlan_listening_max } optional ( vlan_listening != "default" ) { multichoice vlan_selections display "xlarge" tcl { package require iapp 1.0.0 set ::choices [iapp::get_items net vlan] return [iapp::safe_display ::choices] } optional ( vlan_listening == "enabled" ) { optional ( options.display_help == "max" ) { message vlan_selections_enabled_max } } optional ( vlan_listening == "disabled" ) { optional ( options.display_help == "max" ) { message vlan_selections_disabled_max } } } optional ( options.advanced == "yes" ) { choice l4_profile_to_use default "/#default#" display "xxlarge" tcl { package require iapp 1.0.0 set ::choices "/#default#\n[iapp::get_items ltm profile fastl4]" return [iapp::safe_display ::choices] } optional ( options.display_help == "max" ) { message l4_profile_to_use_max } } } optional ( options.advanced == "yes" ) { section irules { message irule_1_max optional ( options.display_help == "max" ) { message irule_2_max message irule_3_max } multichoice irules display "xlarge" tcl { package require iapp 1.0.0 set ::choices [iapp::get_items -filter NAME !~ "^_sys_" ltm rule] return [iapp::safe_display ::choices] } } } text { intro "Welcome to the IP Forwarding template" intro.hello "Introduction" "This template supports configuring the BIG-IP to perform IP traffic forwarding." intro.check_for_updates "Check for Updates" "Check for new versions of this template on the AskF5 Knowledge Base website (http://support.f5.com/kb/en-us/solutions/public/13000/400/sol13422.html)." options "Template Options" options.display_help "Do you want to see inline help?" { "Yes, show inline help" => "max", "No, do not show inline help" => "hide" } options.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." options.advanced "Which configuration mode do you want to use?" { "Basic - Use F5's recommended settings" => "no", "Advanced - Expose advanced options" => "yes" } options.conf_mode_max "" "This template supports twp 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." basic "Virtual Server Questions" basic.forward_all "Should this forward all traffic not destined for virtual servers?" { "Forward all IPv4 traffic" => "IPv4", "Forward all IPv6 traffic" => "IPv6", "Forward all IPv4 and IPv6 traffic" => "Yes", "Forward specific traffic" => "No" } basic.forward_all_max "" "Choose whether to have the BIG-IP system forward all traffic that is not destined for a virtual server, or only forward traffic on a specific network, port and/or VLAN that you define. If you select Yes, the system forwards all traffic. If you select No, you must enter the address, mask, and port that define the traffic you want to forward." basic.addr "What network address do you want to use for this virtual server?" basic.addr_max "" "Specifies the address of the destination network, for example, 10.0.0.0. The default 0.0.0.0 is a wildcard for all addresses, however you can still limit what is forwarded by netmask, port, or VLAN." basic.mask "What is the netmask for that address?" basic.mask_max "" "Specifies the netmask, for example 255.255.255.0. The default 0.0.0.0 is a wildcard for any netmask." basic.port "What port do you want this virtual server to use?" basic.port_max "" "Specifies a specific port for forwarding traffic, for example 22. The default 0 is a wildcard for any port." basic.vlan_listening "What VLANs should this IP Forwarding virtual server listen on?" { "All VLANs" => "default", "Enabled on ..." => "enabled", "Disabled on ..." => "disabled" } basic.vlan_listening_max "" "You can choose to forward traffic from all VLANs or just from some of them. If you don't want to enable all VLANs, you can choose to include or exclude named VLANs and forward traffic from all of the rest." basic.vlan_selections "On which VLAN(s) should this IP Forwarding virtual server listen?" basic.vlan_selections_enabled_max "" "Select the VLANs from which traffic will be forwarded." basic.vlan_selections_disabled_max "" "Select the VLANs from which traffic NOT will be forwarded." basic.l4_profile_to_use "What Fast L4 profile do you want to use?" {"Use F5's recommended Fast L4 profile" => "/#default#"} basic.l4_profile_to_use_max "" "If you created a custom Fast L4 profile, you can select it from the list. This is not required for most purposes, and only necessary if you need to replace the default Fast L4 profile functionality." irules "iRules" irules.irules "Do you want to add any custom iRules to this configuration?" irules.irule_1_max "WARNING" "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." irules.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." irules.irule_3_max "" "Correct event priority is critical when assigning multiple iRules. For more information about iRule event priority, see https://devcentral.f5.com/s/wiki/iRules.priority.ashx" } To get started with modifying this template, we want to create a copy. In the GUI, click iApps->Templates->f5.ip_forwarding, and then at the very bottom, click copy. At the iApps >> Clone Template screen, change the Template Name(s) field to the name you want your template to have. I called mine f5_stripped.ip_forwarding. You can edit from here, but at this step I just clicked Finish before re-entering to do the editing work. Back at the iApps template listing, you should see your new iApp, which other than title, should be the same as the original, with the exception of validation (which should now read None.) Click into your new template and now we'll get to work editing. Presentation In the presentation section, we can weed out the basic/advanced section since we aren't allowing profile or iRule manipulation (lines 13-19.) Next we'll eliminate the forward_all option since we're not giving them the choice of of IPv4/IPv6 defaults or all networks (lines 23-28; 41.) Moving on, we'll trim the port section (lines 37-40.) Finally, we'll pull the advanced section altogether, which deals with the profiles and iRules (lines 69-96.) In the text area of the presentation, we pull out all the unnecessary text now that those GUI objects will not be present (lines 110-14; 117-123; 130-131; 137; 142-153.) This is best shown in the following images. Implementation The changes in the implementation section follow suit. We remove the arrays for destination (lines 7-15) and profiles (lines 17-29,) as well as the army for rules (lines 38-46,) and the switch for the type of forwarding virtual this will be since we're forcing end users to specify the networks (lines 56-61.) The only thing we need to slightly modify is the virtuals section (lines 48-54.) Here, we are removing the need for the variable and just creating the virtual server with the iapp::conf command. We are not passing a port from the iApp, so we use :any here (line 15) and then use the array as is for vlans to configure those. Screenshot to show these updates is below. Easy enough! Updated iApp code is below. Implementation Presentation package require iapp 1.0.0 iapp::template start set app $tmsh::app_name # VLANS # array keys: $::basic__vlan_listening array set vlans { enabled { vlans-enabled vlans replace-all-with \{ $::basic__vlan_selections \} } disabled { vlans-disabled vlans replace-all-with \{ $::basic__vlan_selections \} } default { vlans-disabled vlans none } } iapp::conf create ltm virtual ${app}_IPv4_Forwarding \ ip-forward \ destination $::basic__addr:any mask $::basic__mask \ [iapp::substa vlans($::basic__vlan_listening)] iapp::template stop section intro { message hello message check_for_updates } section options { choice display_help display "xxlarge" default "hide" optional ( options.display_help == "max" ) { message display_help_max } } section basic { string addr default "0.0.0.0" required validator "IpAddress" optional ( options.display_help == "max" ) { message addr_max } string mask default "0.0.0.0" required validator "IpAddress" optional ( options.display_help == "max" ) { message mask_max } choice vlan_listening default "default" display "xxlarge" optional ( options.display_help == "max" ) { message vlan_listening_max } optional ( vlan_listening != "default" ) { multichoice vlan_selections display "xlarge" tcl { package require iapp 1.0.0 set ::choices [iapp::get_items net vlan] return [iapp::safe_display ::choices] } optional ( vlan_listening == "enabled" ) { optional ( options.display_help == "max" ) { message vlan_selections_enabled_max } } optional ( vlan_listening == "disabled" ) { optional ( options.display_help == "max" ) { message vlan_selections_disabled_max } } } } text { intro "Welcome to the IP Forwarding template" intro.hello "Introduction" "This template supports configuring the BIG-IP to perform IP traffic forwarding." intro.check_for_updates "Check for Updates" "Check for new versions of this template on the AskF5 Knowledge Base website (http://support.f5.com/kb/en-us/solutions/public/13000/400/sol13422.html)." options "Template Options" options.display_help "Do you want to see inline help?" { "Yes, show inline help" => "max", "No, do not show inline help" => "hide" } options.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." basic "Virtual Server Questions" basic.addr "What network address do you want to use for this virtual server?" basic.addr_max "" "Specifies the address of the destination network, for example, 10.0.0.0. The default 0.0.0.0 is a wildcard for all addresses, however you can still limit what is forwarded by netmask, port, or VLAN." basic.mask "What is the netmask for that address?" basic.mask_max "" "Specifies the netmask, for example 255.255.255.0. The default 0.0.0.0 is a wildcard for any netmask." basic.vlan_listening "What VLANs should this IP Forwarding virtual server listen on?" { "All VLANs" => "default", "Enabled on ..." => "enabled", "Disabled on ..." => "disabled" } basic.vlan_listening_max "" "You can choose to forward traffic from all VLANs or just from some of them. If you don't want to enable all VLANs, you can choose to include or exclude named VLANs and forward traffic from all of the rest." basic.vlan_selections "On which VLAN(s) should this IP Forwarding virtual server listen?" basic.vlan_selections_enabled_max "" "Select the VLANs from which traffic will be forwarded." basic.vlan_selections_disabled_max "" "Select the VLANs from which traffic NOT will be forwarded." } With the finished stripped version of the ip forwarding iApp, we can now deploy the template in a new application service. Join us for the next article in this series, where we'll tackle writing an iApp from scratch!1.8KViews0likes0CommentsGetting Started with iApps: A Conceptual Overview
tl;dr - iApps provide admins and service desks a template solution for application deployment and management services. Deploying and managing applications require a lot of information across several disciplines. Architects have their holistic view of the application ecosystem and relevant lifecycles. Developers have their granular relationship with each application under their umbrella. Networks admins make sure applications are behaving appropriately on the network instead of hijacking QoS classes or hijacking DNS. Then there are those missing details that no one wants to own until something breaks (looking at you Java CA store). Originally F5 introduced deployment guides to help administrators understand the requirements and configurations needed to deploy popular applications behind BIG-IP. However, after the deployment was complete, those configurations were still managed through object types alone (e.g. virtual servers, pools, profiles, iRules, monitors). That can get quite tedious when you have hundreds of applications on a single BIG-IP stack. Someone somewhere said “Wouldn’t it be nice if we could have an application-based view of all the different objects that help us deploy, manage, and secure each application”? Enter iApps Introduced in BIG-IP 11.0, iApps are a customizable framework for deploying and managing application as a service. Using out-of-the-box templates, administrators can deploy commonly-used applications such as Oracle, SAP, or Exchange by completing a series of questions that relate to their management and infrastructure needs. Rather than create a bunch of virtual servers, followed by a handful of monitors, then a plethora of whatever, the responses to iApps questions create all of the BIG-IP objects needed to properly run your application. The iApps application service becomes the responsible manager of all virtual servers, monitors, policies, profiles, and iRules required to run. Consolidating these into a single view makes management and troubleshooting much easier to handle. iApps Framework iApps consist of two main elements, the template and application services created by publishing a template. We’ll dive into this in our next article, Getting Started With iApps: Components. Templates: The base configuration object which contains the layout and scripting used to configure and publish application instances. Some templates are prebuilt and included in BIG-IP, while others can be download from DevCentral (are not officially supported) or F5 support (certified and supported). Developer-oriented teams can also build custom templates for frequently used configurations or services. Application Service: An application service is the result of using an iApps template to drive the configuration process. The Administrator uses the configuration utility to create a new application service from the selected iApps template. Created objects are grouped into components of the application service and are managed accordingly. The iApps Advantage iApps are not for everyone. If you like keeping tribal control over your BIG-IP ecosystem or if you like naming virtual servers after your pets, iApps may not be for you. iApps do have an advantage if you want to templatize your deployment scenarios or wish to allow other administrators access to the services they manage. iApps reduce a lot of the mystique and intimidation a lengthy set of profiles, policies, and pools can sometimes cause to the new or intermediate administrator. Above we show an example of building a highly available LDAP namespace for internal applications with the default built-in LDAP iApps template. By providing a certificate and and answering a few questions, an LDAP environment is created for all of your internal directory authentication or lookup requirements. From there, modifying the configuration is easy as selecting the Reconfigure tab in the existing application service. Changing settings within iApps Sometimes you just want a template to assist with application deployment and from there you’re perfectly fine managing the individual object types. The Component view will show you all objects affected by the application service but if you try to apply a change, you’ll receive an error similar to: This is by design because the iApps application service is the rightful owner of the system object and shouldn’t be edited directly. However in certain cases you don’t the iApp anymore or want more granular control of some features the iApps my not have, there is an option. Each application service published via iApps have a Properties tab which allow you to disable the Strict Updates method of management. Unchecked, each object is configurable on it’s own but will deviate from the templates last known state. Some administrators prefer to operate this way, only using the iApp as a deployment method, and that’s perfectly fine. We’re leaving your application management style and method up to you. As BIG-IP expands to cover more of the application landscape, people are increasingly taking advantage of more programmatic features and iApps is no exception. Allowing our administrators to improve their ease of deployment and use is why iApps exist and we’ll continue to develop and improve these features. Our next article Getting Started with iApps: Components will dive into more detail on the properties required to create and manage iApps. Take the time to get to know iApps, they’re your ally for keeping your applications in order.1.8KViews1like1CommentGetting Started with iApps: Creating an iApp
In the previous article in this series, we took a stock iApp shipped with the product and stripped it down to show how to modify an existing iApp. In this article, we’ll tackle creating a simple iApp from scratch. The Scenario You have a test environment where all your iRules are created and validated. You then send them off to other devices in test or stage environments, and finally, production. Wouldn’t it be nice to have a quick validation that the rules out there in the other environments match the ones in yours? This is possible by adding a checksum or signature to your iRules. You can do this in the GUI of course, and with checksums, you can do it all at the same time by checking all the iRules and clicking the Add Checksum box. Now in list view, you’ll see that the verification has changed from None to Checksum Verified. If you click into one of the iRules, you’ll see the checksum definition at the end of the iRule (I know, lamest “test” iRule ever!) If you want to add signatures to all iRules simultaneously like you can with checksums though, well that doesn’t work. It is this very situation that we will attempt to solve with an iApp! The tmsh Underbelly Before beginning the iApp, let’s figure out what we actually need to do in tmsh since the implementation section will rely on this. For this iApp, it’s pretty simple. Take a list of iRules, and generate a signature or checksum. The tmsh commands are thus: # Generate a signature tmsh generate ltm rule signature signing-key # Generate a checksum tmsh generate ltm rule checksum So in the presentation section, we’re going to need to provide for the following to pass to the implementation: Determine if they want to generate a checksum or a signature If a signature, display a list of keys they can select a single key from for signing Display a list of iRules they can select one or more from Creating the Presentation Section If you recall from the previous articles in this series, the presentation section of the template is created with the APL language. Within the presentation, there is an area where your inputs are defined, and then an area where the text supporting those inputs are defined. section basic_info { choice validation default "Checksum" { "Checksum", "Signature" } optional (validation == "Signature") { choice key tcl { set objs [tmsh::get_config /sys crypto key] foreach obj $objs { append results [tmsh::get_name $obj] append results "\n" } return $results } } multichoice rules tcl { set objs [tmsh::get_config /ltm rule] foreach obj $objs { append results [tmsh::get_name $obj] append results "\n" } return $results } } text { basic_info "Add Signature or Checksum to iRules" basic_info.validation "Please select Signature or Checksum." basic_info.key "Please select the key for iRule signature." basic_info.rules "Please select one or more iRules." } First thing we’ll do is title the section basic_info (lines 1-21.) The first choice we’ll present, which we’ll name validation, is whether the user would like to apply a checksum or a signature to the iRules (line 2.) If that choice is a signature, we’ll run a tcl function to retrieve all the crypto keys on the system to present that in a choice object (lines 3-11,) storing those values in key. Next, we want to be able to select more than one iRule from the list, so we’ll use a multichoice instead of just a choice object. We’ll run a similar tcl function to retrieve the iRule names for display (lines 13-20,) storing those values in rules. In the text section (lines 22-27) we use the names from above to apply the helper text to those objects. Each object within the section gets a name of section.object, so for the information that we have so far, that results in: basic_info (line 23) -> section basic_info (line 1) basic_info.validation (line 24) -> section basic_info choice validation (line 2) basic_info.key (line 25) -> section basic_info choice key (line 4) basic_info.rules (line 26) -> section basic_info multichoice rules (line 13) That’s it! With the presentation section of the template complete, we can move on to implementation. Creating the Implementation Section For (most?) iApps, the presentation is the easy part. But that is not the case in this iApp. This implementation code is 12 lines long including braces, and it’s a single switch statement. Before we get to the code, however, a few points: To reference names from the presentations so you can retrieve the values you set, the format is $::section__objName. So for basic_info.validation, the variable name is $::basic_info__validation. Don’t let that double colon or the double underscore throw you. If you are including the built-in iApps packages, there are newer iapp:: namespace commands that you can use for configuration and for retrieval. Rather than confuse the functionality of what the iApp is actually doing, I left that out of this article, but as you begin developing iApps, you’ll want to use the package. The generate command in tmsh does not have a scripting sibling, so rather than using tmsh::generate (which does not exist,) you need to use the exec command. switch -exact $::basic_info__validation { "Checksum" { foreach obj $::basic_info__rules { exec "tmsh" "generate" "ltm" "rule" $obj "checksum" } } "Signature" { foreach obj $::basic_info__rules { exec "tmsh" "generate" "ltm" "rule" $obj "signature" "signing-key" $::basic_info__key } } } As you can see from the code, a single switch statement (line 1) checks to see whether it matches Checksum (line 2) or Signature (line 7.) Given a match, it will loop through the iRules (lines 3, 8) and then run the tmsh command to add the Checksum (line 4) or the Signature (line.) Creating the Help Section This is the section where I punt. It’s just html, and I think we can all agree that is out of the scope of this article. Creating the iApp Template Now that we have our sections complete, we can actually create the iApp. Go to iApps->Templates and click Create. Give the template a name. I named mine f5.add_irules_validation. Set the required BIG-IP Modules field to LTM. I haven’t tested this iApp on other versions, so I’ll be picky and set the minimum version to my test VE’s 12.1 version and leave the maximum blank. I haven’t used a macro, so I’ll leave that alone. Paste the implementation into that section. Paste the presentation into that section. Ignore the HTML Help. (A quick aside…my robotics students will have a field day if they find out I didn’t document here. Shhhhh…) Click Finish My template before saving looks like this: Creating the Application Service Final steps! Now we can create the application service. The original scenario described our problem: we want to apply a signature to all the iRules at once. So let’s do that. Go to iApps->Application Services and click Create. Name it. I named mine add_irules_signatures. Select the Template from the list. Select Signature Select the appropriate key. I selected the default. Select the appropriate iRules. I selected test1 and test2. Click Finish. Before clicking Finish, my application service looked like this: No errors locally. Whew! The components view is not too exciting: The reason for this is the iApp doesn’t own any components. It just acted on existing components, so there is nothing for it to own. However, we can see the results of its action by going to the iRules section to see if the verification column on test1 and test2 has changed from None (caveat…I did remove the checksums from earlier, you can’t apply a checksum and a signature, it’s one or the other.) Low and behold, we have signatures now! Conclusion This article covered the steps required to get to a functional template for deploying an application service. As demonstrated, iApps don’t necessarily have to be a configuration engine, they can be used for other purposes. The steps were purposefully kept very simple and uncluttered to make all the pieces clear. Obviously, iApps can get very complex and there are some best practices and lessons learned that we’ll cover in the next article in this series.1.4KViews0likes1CommentGetting Started With iApps: Components
Our last article, Getting Started with iApps: Conceptual Overview we breezed through iApps are and how they can benefit deployment and management of your nastiest applications. That’s fine and dandy, but the real benefit of iApps is through creation and customization of your very own iApps. To get you started, it’s helpful to understand how iApps are put together, specifically the components involved. This article will get you familiar with the internal workings of iApps and by doing so, lower the intimidation factor they sometimes cause. The iApps Framework: Templates iApp templates generate an application servicefrom user answers related totheir applicationrequirements. Templates provide a procedural graphic interface and context-sensitive help for the administrator. A new deployment uses a a single template to create an interface and guide the user through the configuration process, deploying the configuration when published. For common-deployed infrastructure, a well-defined template can be reused for multiple application services creation. During deployment a template can: Create new configuration objects Reference existing BIG-IP configuration objects, i.e. profiles or monitors Create additional configuration objects dynamically based on template requirements. For example, if an iApp creates a pool member with an IP address that does not already exist as a node, the BIG-IP will create the node automatically Objects created by templates are identified as components of the application service, and can be viewed on the deployed application service component tab. There are 5 sections to make up an iApp Template: Attributes Required BIG-IP modules Min/Max BIG-IP version Presentation Defines User Interface Application Presentation Language (APL is used to build the interface) Implementation Processing code TCL and TMSH commands Macro Creates an iRule dynamically Help HTML-based help tab Inline help (in presentation section) iApps Templates: Attributes The template attributes defined by the developer designate what versions and modules the template needs to execute one or more of the commands defined int presentation and implementation sections. These include: System-supplied property: Indicates if the template is provided with the installed version of BIG-IP or if it was copied/imported elsewhere. This is a read-only field. Required BIG-IP Modules property: This is used to set the required modules that must be provisioned before the template can be used by an application service. Minimum BIG-IP Version property: Displays minimum version of BIG-IP the template supports. If the system does not meet the min requirement, the system will post an invalid-template alert, and does not include make that template available for deployment. Maximum BIG-IP Version property: Displays the maximum version of software supported by the template. Similar to the above minimum version, BIG-IP will issue the same alert and mark it unavailable for deployment. Verification property: Indicates if the template is verified by F5 Support. iApps Templates: Presentation Using the Application Presentation Language (APL), the presentation section builds the user interface for the iApps template being deployed. The user is given a series of questions and options, and answers provided determine the configuration objects created and/or referenced. The APL describes what questions to ask, in what order to ask, how the questions are presented (free form, drop down, lists…), and the names of the variables used to store configuration data prior to publishing the template. Below we can see the APL code defined in F5 NIST SP800-53 RC4 template for the question related to access control. sc10 "Idle Timeouts for Management Access -- AC-2(5), SC-10" sc10.purpose "" sc10.mins "How many minutes for each Idle Timeout value? " sc10.mins_help "" sc10.mins.timeout_gui "Management GUI" sc10.mins.timeout_ssh "SSH" sc10.mins.timeout_console "Console" sc10.mins.timeout_tmsh "TMSH" section sc10 { message purpose "Configure idle timeouts for management access facilities. For each facility the value zero selects a 12-hour timeout." row mins { string timeout_gui required display "small" validator "nonnegativenumber" default tcl { set tmp [tmsh::run_proc nist80053:my_item \ /sys httpd auth-pam-idle-timeout] return [expr {int(($tmp + 59) / 60)}] } string timeout_ssh required display "small" validator "nonnegativenumber" default tcl { set tmp [tmsh::run_proc nist80053:my_item \ /sys sshd inactivity-timeout] return [expr {int(($tmp + 59) / 60)}] } string timeout_console required display "small" validator "nonnegativenumber" default tcl { set tmp [tmsh::run_proc nist80053:my_item \ /sys global-settings console-inactivity-timeout] return [expr {int(($tmp + 59) / 60)}] } string timeout_tmsh required display "small" validator "nonnegativenumber" default tcl { set tmp [tmsh::run_proc nist80053:my_item \ /cli global-settings idle-timeout] return [expr {($tmp eq "disabled") ? 0 : $tmp}] } } optional (intro.help == "show") { message mins_help "For each field, type the number of minutes of idle time that should elapse before the session times out. Using a value of zero (0) sets the timeout to 12 hours (720 minutes)." } } iApps Template: Implementation Using our ol’ standby TCL, this section of the template is written in the TMSH scripting language. This is the programmatic heart of the iApp template and builds the configuration needed to run your application as a unique service. We’re using the same F5 NIST SP800-53 iApp template and the Implementation code shown below is responsible for converting the answers defined in the presentation section into BIG-IP usable commands. #various login timeout settings if {[set tmp [expr {$::sc10__mins__timeout_gui * 60}]] == 0} { set tmp 43200 } elseif {$tmp < 120} { set tmp 120 } iapp_conf "modify /sys httpd auth-pam-idle-timeout ${tmp}" iapp_conf "modify /sys httpd auth-pam-dashboard-timeout on" if {[set tmp [expr {$::sc10__mins__timeout_ssh * 60}]] == 0} { set tmp 43200 } iapp_conf "modify /sys sshd inactivity-timeout ${tmp}" if {[set tmp [expr {$::sc10__mins__timeout_console * 60}]] == 0} { set tmp 43200 } iapp_conf "modify /sys global-settings console-inactivity-timeout ${tmp}" if {[set tmp $::sc10__mins__timeout_tmsh] == 0} { set tmp 720 } iapp_conf "modify /cli global-settings idle-timeout ${tmp}" iApps Templates: Help The help section is html defined and used to either give a large overview of the iApp template being used. The snippet below shows inline help questions that the user might need for specific questions they may not be sure of. This can also be used to help define formatting for more complex questions, such as an LDAP baseDN or LDAP filter to be used. <h6>SC-7 - Boundary Protection</h6> <p>This iApp lets you manage the IP subnets from which BIG-IP management may be accessed as well as services accessible on self IP’s.</p> <h6>SC-10 - Network Disconnect</h6> <p>This iApp exposes several timeout settings for access to the system.</p> <h6>SC-17 - Public Key Infrastructure Certificates</h6> <p>This iApp does not manage TLS/SSL PKI certificates or cryptographic material as such. However, you can select the appropriate certificates and keys for single-ended and mutual authentication of connections to external authentication/directory services.</p> The iApps Framework: Application Services We’ve configured an iApps Template, and clicked Finished. This starts the deployment and creation process of converting your answers into a unique application service and if we have good connections and all services are up, a functional application. A running application service can be administered by clicking reconfigure after selecting it in the iApps Application Services menu. From there, the same questions previously answered during deployment are available for modification. This is useful when IP’s or certificate profiles change and simple and quick updates are needed. The Application Service also provides a Components view that lists each object in use to manage the specific application service and if applicable, it’s operational status. Below is a completed LDAP application service. Note the familiar red diamonds because none of the LDAP servers referenced in this service are available. I’m a bad admin, I know. Also note that I created a CA and made wicked awesome certs just for this example (really I accidentally deleted my old virtual machine with the previous CA). iApps Template: Availability and Support Some of you that frequent DevCentral know there’s a lot of information on iApps available in Codeshare and the Wiki (The wiki is managed by the iApps team so make sure to check it out). However, DevCentral is not on officialsupport channelso here’s a quick breakdown of where to get your variously supported/unsupported iApps.. iApps on the BIG-IP system: Those are created and supported by F5. Enjoy iApps on F5 Support: If there is no RC status (release candidate) then they are supported by F5. iApps on DevCentral’s Codeshare: These are usuallyworks-in-progress, release candidate, user submitted, or F5 submitted; but not certified;none are officially supported. These are use-at-your-own risk but of course you have dev and test environments for just such occasions. You wouldn’t DARE test out an unsupported iApp off DevCentral in your production environment right??? That wasn’t so bad, was it. Now that you have a better understanding of what goes into an iApp, they’re not so intimidating. If you’ve done any iRule coding, you probably have an urge to start modifying one after finishing this article. Check out the different iApps out there on DevCentral and see if you have any upcoming deployments that may benefit from using iApps. Get your developers involved too as iApps are a natural progression in your DevOp’ish plans. Tomorrow our very own Jason “Lord of the Dance and TCL” Rahm will cover modifying and creating iApps so please stay tuned and get your dev hat ready.1.2KViews1like0CommentsGetting Started with iApps: Best Practices
In this final article in the Getting Started with iApps series, we’ll ship gears from concepts and code to best practices and lessons learned. Start Small As stated earlier--iApps are complex. If you don’t know tmsh, or better, tmsh scripting, I’d recommend spending some time getting comfortable at the command line writing scripts before moving to an iApp. Once you have the foundational tmsh skills, start with a simple task like what we covered in the modifying and creating articles in this series. After the pieces start to fit together more clearly, expand from there. Start Basic I mentioned the iApp utility package in the previous article. It’s available and it’s awesome. But it also abstracts some of the work that might confuse what’s actually happening in the iApp. I’d recommend you avoid the utility package while you are learning, then once you’re comfortable, convert your test work to the utility package. Afterwards, starting with the utility package unlocks a lot of functionality that will save you time and headaches. Attributes This is a small but important section of the iApp. When developing an iApp, there may be features that exist on your version that either didn’t exist or changed significantly from previous or later versions. Setting the minimum and maximum versions where applicable might save you or others in the event of upgrades or imports. Also, establishing the required modules up front is important, so don’t forget this step. Presentation This is the user interface for those deploying your template, so it’s important to consider not only the required information, but also the layout. Some best practices for the template design: Use a question and answer format Be simple Be clear Be complete Follow your organization’s nomenclature Gotcha: You may be tempted to expose only a few settings on any particular configuration object, leaving the remaining settings default. But a default when creating objects via the GUI is not necessarily the same default when creating them via tmsh. Example: a virtual server created via the GUI defaults to the tcp profile, but creating a virtual server via tmsh defaults to the fastL4 profile. Make sure to use the layout elements to your advantage. Use the section element to group like features/functionality in your iApp. Hide stuff that isn't required for particular deployments by using the optional element. This makes readability much better Underscores in section variable names are possible, but discouraged. Yes, I broke this rule in the creating an iApp article yesterday! The reason is because the section.variable on the implementation ends up section__variable (double underscore) and if your section also has an underscore, it makes it easy to overlook the differences. Use validators for input fields where they are supported. These are some common validators: Number: Any integer NonNegativeNumber: Any integer >= 0 IpAddress: * for all addresses, or an IPv4 or IPv6 address PortNumber: * for all ports, or an integer value between 0 and 65535 inclusive FQDN:RFC 1034 compliant domain name IpOrFQDN:IPv4, IPv6, or an RFC 1034 complaint domain name. * not allowed Gotcha: validators are not available with the edit choice element, so make sure to add validation on the implementation section for the values returned from these elements. Also very helpful: you can display user-friendly wording while setting a different value that is passed on to the implementation. This is nice for things like the load balancing method, where least-connections-member isn’t awesome to look at, but is the required text string for the tmsh::pool create/modify command. Finally, you can test all your variable setting and such by using the puts command in the implementation section that will log all your values from the presentation section. This information is useful for debugging and is dumped in the /var/tmp/scriptd.out file for review. Examples: puts $::basic_info__validation puts $::basic_info__key puts $::basic_info__rules [root@ltm3:Active:Standalone] config # tail -f /var/tmp/scriptd.out Signature default.key test1 test2 Implementation The implementation section is pretty much a tmsh script, without the required skeleton. the hierarchy of tmsh, for those not well versed, looks like this: The general syntax of tmsh commands is: tmsh <command> <module> [<submodule>] <component> <parameters> The syntax varies slightly depending on where the commands are issued. For example: Location where command is run Syntax tmsh root (tmos) # create /ltm virtual virtual_name... virtual server component of tmsh (tmos.ltm.virtual) # create virtual_name... linux bash prompt config # tmsh create /ltm virtual virtual_name... iApp implementation section tmsh::create "/ltm virtual virtual_name..." iapp::conf create ltm virtual virtual_name... In addition to the declared variables from the presentation section, you can set variables in the implementation section as well. This foreach loop shows the use of a local variable (obj) and the presentation declared variable ($::basic_info__rules) foreach obj $::basic_info__rules { exec "tmsh" "generate" "ltm" "rule" $obj "checksum" } There’s also tmsh::app_name which stores the name of your application service. When creating objects, it’s helpful to name them with your application name as a header. This can be done like so: set app $tmsh::app_name tmsh::create “/ltm pool ${app}_MyPool ... The { } brackets are there so the interpreter to only interprets app when doing the variable lookup. There are a lot more general tcl best practices, but those are out of scope for this article. Reentrancy iApps were created with serving an application over time, not just a Ron Popeil “set it and forget it” experience. That’s more the point of a wizard. This presents a challenge, as you need to create objects initially, but when you reconfigure your iApp, you’re modifying existing objects. In tmsh, this is problematic: if you try to create an existing object, it’ll complain. Why does this work in an iApp then? The answer is, through a process called mark-and-sweep. When the iApp user selects an existing application service and clicks the Reconfigure tab, they are reentering your template and its code. They can keep and/or change their responses to the presentation section prompts. If they make changes that result in a new configuration, the mark-and-sweep process is designed to help transform the old configuration to the new configuration. On reentrancy, the code in the template’s implementation section is re-executed. Conditional code is executed based on the variable values set by you or by the user’s responses. Any tmsh::create commands that are “touched” are marked and converted to tmsh::modify commands. Any objects that are “untouched” are deleted in the sweep. Strict Updates Strike updates protect all the objects generated by an iApp. So if you created an iApp that owns the pool app_myPool, that pool cannot be modified outside of the iApp. This is good when a lot of cooks are in the kitchen and someone inadvertently tries to delete your pool. Because the iApp owns it, that attempt will fail. There are situations where you might be tempted to disable the strict updates, but the better option is to modify the template. If you do disable the strict updates, redeploying the iApp will sometimes overwrite the out-of-band changes. Sometimes. The outcome is not so easily predicted. To illustrate the difficulties, consider two scenarios. Changing an HTTP Profile In this scenario, a simple iApp accepts 2 inputs and constructs a virtual server with a custom HTTP profile: presentation { section virtual { string ip required choice xff { “enabled”, “disabled” } } } implementation { tmsh::create ltm profile http ${tmsh::app_name}_http \ insert-xforwarded-for $::virtual__xff tmsh::create ltm virtual ${tmsh::app_name}_vs \ destination $::virtual__ip:80 \ profiles add \{ ${tmsh::app_name}_http \} } Suppose you deploy this iApp with X-Forwarded-For enabled, then disable strict-updates and edit the HTTP profile directly as shown: Now, re-enter and re-deploy the iApp without changing any inputs. What is the result? You might expect your manual customization of response chunking to remain in place, because there is no mention of response chunking in the iApp code. In this case, however, iApp re-deployment causes chunking to be set back to its default value. Disabling Virtual Server Address Translation In this scenario, you need to disable address translation on a virtual server, which was not possible in the iApp. Disable address translation, then re-enter and re-deploy the iApp again. What is the result this time? You might expect your customization to be overwritten as it was in the previous example. In this case, however, address translation remains disabled. The TMSH “modify” command does not handle defaults consistently across all key-value pairs. This makes tampering with a strictly-enforced configuration especially hazardous. Conclusion iApps are amazingly powerful tools for taking a lot of the guesswork and potential errors out of application deployments. There is so much more to iApps than we could possibly cover in this five article series, but the intention this week was not to make you experts; merely to expose you to the concepts and get your feet wet with some examples. The great thing about iApps is the are not compiled code: all of them, whether F5 supported, F5 contributed, or community contributed, can be analyzed and repurposed for your use.999Views0likes0Comments