Forum Discussion

John_45587's avatar
John_45587
Icon for Nimbostratus rankNimbostratus
Apr 20, 2014

how to run a bash script in irule (with a parameter to that bash script)?

once i get the server service port from irule (by [TCP::local_port clientside]), i like the irule to check if there is the port related virtual server (such as VS named "VS-[TCP::local_port clientside]") exsited. If not, then create a VS (using the VS name "VS-[TCP::local_port clientside]"). I have created a BASH script to achieve this function. However, how to launch that BASH script from the irule (and transfer the [TCP::local_port clientside] to that BASH script)?

 

If there have better ways to achieve same features, please also let me know.

 

Thanks alot.

 

3 Replies

  • However, how to launch that BASH script from the irule (and transfer the [TCP::local_port clientside] to that BASH script)?

     

    is action on log (generating log using irule and then executing script using alertd) or icall usable?

     

    Action On Log

     

    https://devcentral.f5.com/wiki/AdvDesignConfig.ActionOnLog.ashx

     

    iCall - All New Event-Based Automation System by Jason Rahm

     

    https://devcentral.f5.com/articles/icall-all-new-event-based-automation-system.U1NX8ldhdQI

     

    by the way, why do you need to create a new virtual server? the irule should already be able to control traffic, shouldn't it?

     

  • There is now an even easier way to do this. With 11.5 and the REST-based iControl, you can issue a sideband call to the (icrd) REST interface to perform just about any TMSH functions your heart desires. Here's an example:

    proc send_to_sideband { data } {
         this is the sideband processing procedure (function)
    
        set sbserver [connect -protocol TCP -timeout 500 -idle 10 -status conn_status "10.80.0.103:80"]
    
         send the sideband request
        send -status send_status -timeout 100 $sbserver $data
    
         return the sideband response
        return [recv -status recv_status -timeout 300 $sbserver]
    }
    when CLIENT_ACCEPTED {
        set req "GET /mgmt/tm/ltm/virtual/VS-[TCP::local_port] HTTP/1.1\r\nHost: localhost\r\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n"
        set sb [call send_to_sideband $req]
    
        if { $sb starts_with "HTTP/1.1 404 Not Found" } {
             this is where you'd make a separate iControl REST call to create the virtual server
        }
    }
    

    A few notes about the above:

    1. The example combines two of my favorite things: sideband and procs. You do not, however, need to use a proc and can stuff all of the sideband logic into the core events.

    2. Sideband is difficult to do with SSL. Further, you cannot (as far as I've tested) point directly back to 127.0.0.1 via sideband. To make this work then, I create a separate VIP on an internal network, listening on port 80, with an applied server SSL profile, and the following iRule:

      when CLIENT_ACCEPTED {
          node 127.0.0.1 443
      }
      

      The sideband iRule calls the 10.80.0.103 VIP, which then forwards the traffic to 127.0.0.1:443.

    3. The "Authorization: Basic YWRtaW46cGFzc3dvcmQ=" header in the request is a Basic authentication function. The garbled string is actually the base64-encoded form of the username and password:

      admin:password
      

      This would be analogous to the following command line cURL statement:

      curl -u admin:password http://10.80.0.103/mgmt/tm/ltm/virtual/VS-444
      
    4. The performance and security speech: first, understand that the management plane runs on a fraction of the resources consumed by the data plane. If you start reaching into the management plane at the speed of incoming data plane traffic, you're very likely to overwhelm the management plane and quite possibly topple the whole box. Second, the management plane has historically always been shielded from data plane access, for obvious security reasons. The iControl REST capability above, iCalls, user_alert scripts, and the various other methods employed to reach the management shell, all have one very important caution in common. You must take extreme care to filter what you send to the management plane and not allow unfettered access from clients.

    5. iCalls, user_alert scripts, and syslog options to reach the management shell are all unidirectional. That is, they only send to the management plane and do not receive a response. In the case above, using an iCall you'd be sending the request to the management plane, and blindly expecting the Bash script to do its job without any verification. The iControl REST option allows you to be interactive with the entire process.

    6. Last, and probably most important, as Nitass alludes, you cannot listen on a port [TCP::local_port] that isn't already defined. You'd necessarily need a separate VIP listening on all ports (x.x.x.x:0) that would create a new VIP on the specified port (and arbitrary IP address).

  • Hi,Kevin can I use icontrol in sideband? I tried to reuse your code to get which monitor marks pool member down(REST api),it never gives me a formatted response and I can't find the exact url to get the monitor which marks pool member down

     

    2 quick questions

     

    1:how to format this response to a readable text?

     

    2:I don't know which REST API url to get monitor which marks pool member down.if it is not achieveable in REST API,can I use icontrol in sideband send to get the info I want and how?

     

    Here is the code I reused from your sample.

     

    proc send_to_sideband { data } {
        set sbserver [connect -protocol TCP -timeout 500 -idle 10 -status conn_status "ip:port"]
        send -status send_status -timeout 500 $sbserver $data
        return [recv -status recv_status -timeout 300 $sbserver]
    }
    when LB_FAILED {
        set current_pool [string range [LB::server pool] 8 end]
        set req "GET /mgmt/tm/ltm/pool/$current_pool/    HTTP/1.1\r\nHost: localhost\r\nAuthorization: xxxxxxxx\r\n\r\n"
        set sb [call send_to_sideband $req]
    HTTP::respond 200 content [subst  -nobackslashes [ifile get f5_new_txt]]
    }

    This is piece of the $sb I got:

     

     sb is HTTP/1.1 200 OK  Date: 25 Apr 2015 02:40:14 UTC  Server: com.f5.rest.common.RestRequestSender  Set-Cookie: BIGIPAuthCookie=xxx; path=/; Secure; HttpOnly  Set-Cookie: BIGIPAuthUsernameCookie=xx; path=/; Secure; HttpOnly  X-Frame-Options: SAMEORIGIN  Cache-Control: no-cache  Content-Length: 630  Content-Type: application/json  X-Content-Type-Options: nosniff  X-XSS-Protection: 1; mode=block  Content-Security-Policy: default-src 'self'  'unsafe-inline' 'unsafe-eval'  Strict-Transport-Security: max-age=16070400; includeSubDomains    {"kind":"tm:ltm:pool:members:memberscollectionstate","selfLink":"https://localhost/mgmt/tm/ltm/pool/XYZ/members?ver=11.5.1","items":

    Have a nice day