ruby
23 TopicsMitigating Ruby YAML.load Universal RCE Deserialization Gadget with BIG-IP ASM
Recently a new YAML deserialization gadget was published that may lead to arbitrary code execution when deserialized by supplying it to Ruby's YAML.load function as input. Prior to this new gadget it was known that calling YAML.load on user supplied input is a bad idea, but this was only relevant to applications that are based on the Ruby on Rails web framework. In this case the published gadget is universal, meaning it will only depend on the existence of classes that are shipped with the default installation of Ruby, and thus it will be able to execute code in any Ruby application that deserializes YAML documents using the YAML.load function. Mitigating the vulnerability with BIG-IP ASM BIG-IP ASM customers under any supported BIG-IP version are already protected against this vulnerability. The exploitation attempt will be detected by existing Ruby code injection attack signatures which can be found in signature sets that include the “Server Side Code Injection” attack type or “Ruby” System. Figure 1: Exploit blocked with attack signature 200004159 Additional Reading https://staaldraad.github.io/post/2019-03-02-universal-rce-ruby-yaml-load/816Views0likes0Commentsdoes iControl GTM pool create_v2 method actually work as documented?
I am trying to create a GTM pool using the create_v2 method as described here:https://devcentral.f5.com/wiki/iControl.GlobalLB__Pool__create_v2.ashx which says to pass in a type of VirtualServerID. This type includes only parameters, name-the virtual server name, and server-the name of the server object that hosts the virtual server. when i try run this method passing in the paramters described I get back this error message: Exception: Common::OperationFailed primary_error_code: 17236515 (0x01070223) secondary_error_code: 0 error_string: 01070223:3: Pool Member must contain VS IP and Pool Name this is surprising since the method documentation doesn't indicate it needs an IP address at all. i've tried this against a GTM-VE running 11.0 and 11.4.0HF4 with the same results. I'm using the ruby icontrol gem for 11.x. I tried using wsdls from 11.0 and 11.4 with no change. I'm going to go back and use the original create method, but i was hoping someone has had more success using the create_v2 method?335Views0likes3CommentsSSL Certificate Report
Problem this snippet solves: This is a script will generate a report of all or some of the certificates managed by a BIG-IP. It will output a multitude of information including: subject and issuers properties, serial, public key bit-length, and expiration dates. How to use this snippet: Requirements Ruby Ruby Gems F5 iControl for Ruby library (http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086421/Getting-Started-With-Ruby-and-iControl.aspx) other dependencies will be installed with the iControl gem Installation Steps Install Ruby, Ruby's OpenSSL library, Ruby Gems, and the Ruby iControl libraries http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086421/Getting-Started-With-Ruby-and-iControl.aspx Copy this code to /usr/local/bin and chmod +x to make the script executable Run it! ssl-certificate-report.rb -b 192.168.1.245 -u admin -p admin -v Code : #!/usr/bin/ruby require "rubygems" require "f5-icontrol" require "getoptlong" options = GetoptLong.new( [ "--bigip-address", "-b", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-user", "-u", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-pass", "-p", GetoptLong::REQUIRED_ARGUMENT ], [ "--cert-name", "-n", GetoptLong::OPTIONAL_ARGUMENT ], [ "--cert-list", "-l", GetoptLong::NO_ARGUMENT ], [ "--watermark-days", "-d", GetoptLong::OPTIONAL_ARGUMENT ], [ "--no-color", "-c", GetoptLong::NO_ARGUMENT ], [ "--verbose", "-v", GetoptLong::OPTIONAL_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ] ) def usage puts $0 + " -b -u " puts " -b (--bigip-address) BIG-IP management-accessible address" puts " -u (--bigip-user) BIG-IP username" puts " -p (--bigip-pass) BIG-IP password (will prompt if left blank" puts " -n (--cert-name) name of certificate to display (display all by default)" puts " -l (--cert-list) list of certificates managed by the BIG-IP" puts " -d (--watermark-days) certificates expiring inside this number of days will" puts " be marked as \"expiring soon\", default is 30 days" puts " -c (--no-color) disable color coding for the shell (useful if piping" puts " output to less or are using Windows)" puts " -v (--verbose) show all certificate information (brief by default)" puts " -h (--help) shows this help/usage dialog" exit end # initial parameter values bigip_address = '' bigip_user = '' bigip_pass = '' cert_name = '' cert_list = false watermark_days = 30 verbose = false # the color_code variable must be global to be read within the format_text method $color_code = true options.each do |option, arg| case option when "--bigip-address" bigip_address = arg when "--bigip-user" bigip_user = arg when "--bigip-pass" bigip_pass = arg when "--cert-name" cert_name = arg when "--cert-list" cert_list = true when "--watermark-days" arg = arg.to_i watermark_days = arg when "--no-color" $color_code = false when "--verbose" verbose = true when "--help" usage end end usage if bigip_address.empty? or bigip_user.empty? if bigip_pass.empty? puts "Please enter the BIG-IPs password..." print "Password: " system("stty", "-echo") bigip_pass = gets.chomp system("stty", "echo") end bigip = F5::IControl.new(bigip_address, bigip_user, bigip_pass, ["Management.KeyCertificate"]).get_interfaces def format_text(text, code) if $color_code "#{code}#{text}\e[00m" else text end end def red(text) format_text(text, "\e[01;31m") end def green(text) format_text(text, "\e[01;32m") end def yellow(text) format_text(text, "\e[01;33m") end def bold(text) format_text(text, "\e[1m") end def underline(text) format_text(text, "\e[4m") end def bold_underline(text) format_text(text, "\e[4;1m") end def cert_validity_label(expire_text) case expire_text when "VTYPE_CERTIFICATE_VALID" green("valid") when "VTYPE_CERTIFICATE_EXPIRED" red("expired") when "VTYPE_CERTIFICATE_WILL_EXPIRE" yellow("expiring soon") when "VTYPE_CERTIFICATE_INVALID" red("invalid") else yellow("unknown") end end def key_strength_label(key_length) case(key_length) when 0..1023 red("low") when 1024..2047 yellow("medium") else green("strong") end end def key_type_label(key_type) case key_type when "KTYPE_RSA_PRIVATE" "RSA private key" when "KTYPE_RSA_PUBLIC" "RSA public key" when "KTYPE_DSA_PRIVATE" "DSA private key" when "KTYPE_DSA_PUBLIC" "DSA public key" else "Unkown" end end # collect certificate properties certs = {} bigip["Management.KeyCertificate"].get_certificate_list("MANAGEMENT_MODE_DEFAULT").each do |cert| id = cert['certificate']['cert_info']['id'] certs[id] = {} # general properties certs[id]['expires'] = Time.at(cert['certificate']['expiration_date']).strftime("%b %e, %Y") certs[id]['version'] = cert['certificate']['version'] certs[id]['serial'] = cert['certificate']['serial_number'] certs[id]['serial'] = 'unavailable' if certs[id]['serial'].empty? # subject and issuers properties ['subject', 'issuer'].each do |x| certs[id][x] = {} ['common_name', 'organization_name', 'division_name', 'locality_name', 'state_name', 'country_name'].each do |y| certs[id][x][y] = cert['certificate'][x][y] end end certs[id]['key'] = {} certs[id]['key']['length'] = cert['certificate']['bit_length'] certs[id]['key']['length_text'] = key_strength_label(cert['certificate']['bit_length'].to_i) certs[id]['key']['type'] = key_type_label(cert['certificate']['key_type']) end # collect certificate validity information validity_states = bigip["Management.KeyCertificate"].certificate_check_validity('MANAGEMENT_MODE_DEFAULT', certs.keys, ([watermark_days] * certs.keys.size)) x = 0 certs.each do |id,cert| cert['expire_text'] = cert_validity_label(validity_states[x]) x += 1 end # display BIG-IP information puts bold("\nConnected to BIG-IP at #{bigip_address} with user '#{bigip_user}'...") # if user only wants list, display it and exit if cert_list puts puts underline("Available certificates\n") puts certs.keys.sort.collect { |id| id = " " + id } puts exit end unless cert_name.empty? if certs.key? cert_name certs = { cert_name => certs[cert_name] } else puts "Error: could not locate a certificate by that name, try '-l' for a list" exit end end puts bold_underline(" " * 80) puts certs.keys.sort.each do |id| puts underline("General Properties") puts "\t" + bold("Name: ") + id puts "\t" + bold("Certificate Subject(s): ") + certs[id]['subject']['common_name'] + ", " + certs[id]['subject']['organization_name'] + "\n\n" puts underline("Certificate Properties") puts "\t" + bold("Expires: \t") + certs[id]['expires'] + " (" + certs[id]['expire_text'] + ")" puts "\t" + bold("Version: \t") + certs[id]['version'].to_s puts "\t" + bold("Serial: \t") + certs[id]['serial'] if verbose ['subject', 'issuer'].each do |section| puts "\t" + bold(section.capitalize) + ":" subsections = { 'Common Name' => 'common_name', \ 'Organization' => 'organization_name', \ 'Division' => 'division_name', \ 'Locality' => 'locality_name', \ 'State (Prov)' => 'state_name', \ 'Country' => 'country_name' } \ subsections.each do |key, subsection| puts "\t\t\t" + key + ": \t" + certs[id][section][subsection] unless certs[id][section][subsection].empty? end end puts end puts underline("Public Key Properties") puts "\t" + bold("Key Type: ") + certs[id]['key']['type'] puts "\t" + bold("Size: ") + certs[id]['key']['length'].to_s + " (" + certs[id]['key']['length_text'] + ")" puts puts bold_underline(" " * 80) puts end325Views0likes0CommentsiControlREST: Ruby: To Output a List of Virtual Servers and their Associated Pools and Pool Members.
Problem this snippet solves: This script enumerates virtual servers and their associated pools and pool members and their status, each virtual server on a line of its own in the ";' delimited format. Essentially, the code shows a way to parse the 'ltm/virtual' object and get the information required. It had a specific need to address when it was written, and it can be modified to suit other similar requirements. How to use this snippet: This code has been tested with Ruby 2.3.1p112. Code : #!/usr/local/bin/ruby -w # # This script enumerates virtual servers and their associated pools and # pool members and their status, each virtual server on a line of its own # in the ";' delimited format. # #------------------------------------------------------------------------- require 'rubygems' require 'rest-client' require 'json' # define program-wide variables BIGIP_ADDRESS = 'mgmt_IP_addr' BIGIP_USER = 'admin' BIGIP_PASS = 'admin' SLEEP_TIME = 20 bigip = RestClient::Resource.new( "https://#{BIGIP_ADDRESS}/mgmt/tm/", :user => BIGIP_USER, :password => BIGIP_PASS, :headers => { :content_type => 'application/json' }, :verify_ssl => false ) # Get virtual servers: vservers = bigip['ltm/virtual'].get vservers_obj = JSON.parse(vservers) # Get pools: pools = bigip['ltm/pool?expandSubcollections=true'].get pools_obj = JSON.parse(pools) # Output header: puts "Virtual Server Name;Virtual Server Destination;Virtual Server Partition;Pool Name;Pool LB Mode;Pool Member Name (address)(state)" $output = '' # Process data: vservers_obj.each do |vserver_obj| vserver_obj.each do |vserver_obj_element| if vserver_obj_element.is_a?(Array) vserver_obj_element.each do |vserver_obj_element_property| if vserver_obj_element_property.is_a?(Hash) if vserver_obj_element_property.has_key?("name") vs_name = vserver_obj_element_property.fetch("name") $output = $output + vs_name + ';' end if vserver_obj_element_property.has_key?("destination") vs_destination = vserver_obj_element_property.fetch("destination") $output = $output + vs_destination + ';' end if vserver_obj_element_property.has_key?("partition") vs_partition = vserver_obj_element_property.fetch("partition") $output = $output + vs_partition + ';' end if vserver_obj_element_property.has_key?("pool") pool_name_from_vs = vserver_obj_element_property.fetch("pool") pools_obj.each_pair do |key, val| next if key == "kind" next if key == "selfLink" for x in 0..(val.length-1) if val[x]["fullPath"] == pool_name_from_vs $output = $output + val[x]["name"] + ";" + val[x]["loadBalancingMode"] if val[x].has_key?("membersReference") val[x]["membersReference"].each_pair do |mrefkey,mrefval| next if mrefkey == "link" next if mrefkey == "isSubcollection" for i in 0..(mrefval.length-1) if i == 0 $output = $output + ";" + mrefval[i]["name"] + "(" + mrefval[i]["address"] + ")(" + mrefval[i]["state"] + ")," else $output = $output + mrefval[i]["name"] + "(" + mrefval[i]["address"] + ")(" + mrefval[i]["state"] + ")," end if i == mrefval.length-1 $output.chop! $output += "\n" end end end else $output = $output + ";;\n" end break end end end else $output = $output + ";;\n" end end end end end end puts $output #---END--- Tested this on version: 11.6314Views0likes0CommentsRuby VIP Maker
Problem this snippet solves: This is a utility created for the purpose of producing large numbers of virtual servers, including pools. This was created to make our testing efforts easier. Configuration For MakeVips and DeleteVips to work, the following files need the following edits: ltmbigip-config.yml needs to be updated with the correct IP address of the LTM and the username and password. LocalLB.Pool.wsdl needs to have the IP address on the second to last line of the file updated to the correct IP of the LTM LocalLB.VirtualServer.wsdl needs to have the IP address on the second to last line of the file updated to the correct IP of the LTM How to use this snippet: Tool Usage Add Virtual Servers MakeVips.rb namePrefix numberOfVIPs vipStartIP port ipsPerPool poolStartIP This will create numberOfVIPs virtual servers on the BIG-IP. These virtual servers will have names that begin with namePrefix. Each VIP will answer on its own IP address beginning with vipStartIP and counting up. The IP addresses roll over at their boundaries. Every VIP will answer on the specified port. Every VIP will have its own unique pool containing ipsPerPool number of IP addresses as members. These nodes begin at poolStartIP IP address and count up just as the VIP IP addresses do. There will be numberOfVips multiplied by ipsPerPool number of nodes created by this utility. Delete Virtual Servers DeleteVips.rb namePrefix numberOfVIPs This will delete the first numberOfVIPs virtual servers from the BIG-IP beginning with namePrefix, along with the pools associated with those virtual servers, assuming that they were created with the same utility as described above.314Views0likes0CommentsRuby Web Accelerator Policy Switcher Class
Problem this snippet solves: The WAPolicySwitcher class will connect to two BIG-IPs and allow for Web Accelerator application policies to be added and removed from a Web Accelerator. In our testing, we use this class to adjust how the web accelerator is dealing with traffic. Important: This class must be called from within a Ruby program. Configuration The following files need to be changed: Edit the bigip-config.ylm and bigip2-config.ylm files to include the addresses and credentials for the two BIG-IPs. Edit the WebAccelerator.Applications.wsdl and WebAccelerator.Applications2.wsdl files to include the correct IP addresses for the two BIG-IPs. (4th to last line in each file) How to use this snippet: Methods: deleteAppPolicy Requires the name of the application to delete. createPolicy Takes the name for the application, the local policy name, the remote policy name, and a list of domain names to use for the application. makePolicySymmetric Takes the name for the application, a single policy name, and a list of one or more host domain names to use for the application. Calls createPolicy. Will use the specified policy for both the local and remote policies. makePolicyAsymmetric Takes the name for the application, a single policy name, and a list of one or more host domain names to use for the application. Calls createPolicy. Will use the specified policy for the local policy and “Symmetric Deployment” for the remote policy. Code : # missing file306Views0likes0CommentsSSLKeyAndCSRCreator
Problem this snippet solves: This is a script will generate a private key and output a certificate signing request. This is all done from a workstation command line and communicated to the BIG-IP via iControl. How to use this snippet: Requirements Ruby Ruby Gems F5 iControl for Ruby library other dependencies will be installed with the iControl gem Installation Steps Install Ruby, Ruby's ""OpenSSL"" library, Ruby Gems, and the Ruby iControl libraries Getting-Started-With-Ruby-and-iControl.aspx Copy this code to /usr/local/bin and chmod +x to make the script executable Run it! minimal options: ssl-key-and-csr-creator.rb -b 192.168.1.245 -u admin -i test-key-001 full options: ssl-key-and-csr-creator.rb -b 192.168.1.245 -u admin -p admin -i test-key-001 -t RSA -l 4096 -s fips --common-name=www.example.com --country=US --state=Washington --locality=Seattle --organization="Example Company, Inc." --division="Information Technology" -o /my-ssl-directory/ -k -c Code : #!/usr/bin/ruby require "rubygems" require "f5-icontrol" require "getoptlong" options = GetoptLong.new( [ "--bigip-address", "-b", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-user", "-u", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-pass", "-p", GetoptLong::REQUIRED_ARGUMENT ], [ "--key-id", "-i", GetoptLong::REQUIRED_ARGUMENT ], [ "--key-type", "-t", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-bit-length", "-l", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-security", "-s", GetoptLong::OPTIONAL_ARGUMENT ], [ "--common-name", GetoptLong::OPTIONAL_ARGUMENT ], [ "--country", GetoptLong::OPTIONAL_ARGUMENT ], [ "--state", GetoptLong::OPTIONAL_ARGUMENT ], [ "--locality", GetoptLong::OPTIONAL_ARGUMENT ], [ "--organization", GetoptLong::OPTIONAL_ARGUMENT ], [ "--division", GetoptLong::OPTIONAL_ARGUMENT ], [ "--output-dir", "-o", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-output", "-k", GetoptLong::NO_ARGUMENT ], [ "--csr-output", "-c", GetoptLong::NO_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ] ) def usage puts $0 + " -b -u -i " puts puts "BIG-IP connection parameters" puts "-" * 20 puts " -b (--bigip-address) BIG-IP management-accessible address" puts " -u (--bigip-user) BIG-IP username" puts " -p (--bigip-pass) BIG-IP password (will prompt if left blank" puts puts "Private key parameters" puts "-" * 20 puts " -i (--key-id) key ID: must be unique and should be indicative of the purpose (required)" puts " -t (--key-type) key type: [RSA|DSA] (default is 'RSA')" puts " -l (--key-bit-length) key bit length: should be a minimum of 1024-bit (default is 2048; most CAs won't sign weaker keys)" puts " -s (--key-security) key security: [normal|fips|password] (default is 'normal' with no passphrase)" puts puts "X.509 data parameters (if blank, you'll be prompted for the answers)" puts "-" * 20 puts " (--common-name) common name: FQDN for virtual server (www.example.com)" puts " (--country) country: two letter country abbreviation (US, CN, etc.)" puts " (--state) state: two letter state abbreviation (WA, OR, CA, etc.)" puts " (--locality) locality: locality or city name (Seattle, Portland, etc.)" puts " (--organization) organization: organization or company name (F5 Networks, Company XYZ, etc.)" puts " (--division) division: department or division name (IT, HR, Finance, etc.)" puts puts "Output options" puts "-" * 20 puts " -o (--output-dir) CSR/key output directory: location to output private key and CSR files (defaults to current working directory)" puts " -k (--key-output) key output: save private key to a local file (saved as key_id.key)" puts " -c (--csr-output) CSR output: save certificate signing request to a local file (saved as key_id.csr)" puts puts "Help and usage" puts "-" * 20 puts " -h (--help) shows this help/usage dialog" puts exit end # set STDOUT buffer to synchronous STDOUT.sync = true # global variables KEY_TYPES = { "RSA" => "KTYPE_RSA_PRIVATE", "DSA" => "KTYPE_DSA_PRIVATE" } KEY_SECURITIES = { "normal" => "STYPE_NORMAL", "fips" => "STYPE_FIPS", "password" => "STYPE_PASSWORD" } # initial parameter values overwrite_key = false # key/CSR default output file values key_output = false csr_output = false output_dir = Dir.pwd # BIG-IP connection parameters bigip = {} bigip['address'] = '' bigip['user'] = '' bigip['pass'] = '' # private key parameters key_data = {} key_data['id'] = '' key_data['key_type'] = KEY_TYPES["RSA"] key_data['bit_length'] = 2048 key_data['security'] = KEY_SECURITIES["normal"] # X.509 data parameters x509_data = {} x509_data['common_name'] = '' x509_data['country_name'] = '' x509_data['state_name'] = '' x509_data['locality_name'] = '' x509_data['organization_name'] = '' x509_data['division_name'] = '' # loop through command line options options.each do |option, arg| case option when "--bigip-address" bigip['address'] = arg when "--bigip-user" bigip['user'] = arg when "--bigip-pass" bigip['pass'] = arg when "--key-id" key_data['id'] = arg when "--key-type" if KEY_TYPES.keys.include? arg.upcase key_data['key_type'] = KEY_TYPES[arg.upcase] else puts "Error: Invalid key type. Exiting." exit 1 end when "--key-bit-length" key_data['bit_length'] = arg.to_i when "--key-security" if KEY_SECURITIES.keys.include? arg.downcase key_data['security'] = KEY_SECURITIES[arg.downcase] else puts "Error: Invalid key security type. Exiting." exit 1 end when "--common-name" x509_data['common_name'] = arg when "--country" if arg =~ /[a-z]{2}/i x509_data['country_name'] = arg.upcase else puts "Error: Use exactly two letters for the country code. Exiting." exit 1 end when "--state" x509_data['state_name'] = arg when "--locality" x509_data['locality_name'] = arg when "--organization" x509_data['organization_name'] = arg when "--division" x509_data['division_name'] = arg when "--output-dir" if File.directory? arg output_dir = arg else puts "Error: Invalid directory for output. Exiting." end when "--key-output" key_output = true when "--csr-output" csr_output = true when "--help" usage end end # we need at least the BIG-IP's address, user, and a key ID to proceed usage if bigip['address'].empty? or bigip['user'].empty? or key_data['id'].empty? if bigip['pass'].empty? puts "Please enter the BIG-IPs password..." print "Password: " system("stty", "-echo") bigip['pass'] = gets.chomp system("stty", "echo") puts end # set up connection to BIG-IP and Management.KeyCertificate interface bigip = F5::IControl.new(bigip['address'], bigip['user'], bigip['pass'], ["Management.KeyCertificate"]).get_interfaces #grab a list of existing keys and confirm overwrite if a conflict exists existing_keys = bigip["Management.KeyCertificate"].get_key_list('MANAGEMENT_MODE_DEFAULT').collect { |key| key["key_info"]["id"] } if existing_keys.include? key_data['id'] print "A key with an ID of '#{key_data['id']}' already exists. Overwrite it? (yes/no) " answer = gets.chomp if answer !~ /^yes$/i puts "Will not overwrite existing key. Exiting." exit else overwrite_key = true end end # time to play 20 questions with the X.509 data if x509_data.values.delete_if { |value| !value.empty? }.size > 0 puts "Please fill in the following X.509 data parameters..." end x509_data.sort.each do |key, value| if value.empty? print key.capitalize.gsub('_', ' ') + "? " x509_data[key] = gets.chomp end end bigip["Management.KeyCertificate"].key_generate('MANAGEMENT_MODE_DEFAULT', [key_data], [x509_data], true, overwrite_key) # write private key to local file if specified by user if key_output key_output_file = output_dir + "/" + key_data['id'] + ".key" key = bigip["Management.KeyCertificate"].key_export_to_pem('MANAGEMENT_MODE_DEFAULT', [key_data['id']])[0] File.open(key_output_file, 'w') { |file| file.write(key) } end # display subject information for CSR as well as the CSR puts "Certificate Request" puts "-" * 20 puts "Subject: C=#{x509_data['country_name']}, ST=#{x509_data['state_name']}, L=#{x509_data['locality_name']}, O=#{x509_data['organization_name']}, OU=#{x509_data['division_name']}, CN=#{x509_data['common_name']}" csr = bigip["Management.KeyCertificate"].certificate_request_export_to_pem('MANAGEMENT_MODE_DEFAULT', [key_data['id']]) # write csr key to local file if specified by user if csr_output csr_output_file = output_dir + "/" + key_data['id'] + ".csr" File.open(csr_output_file, 'w') { |file| file.write(csr) } end puts puts csr279Views0likes0CommentsHow AJAX can make a more agile enterprise
In general, we talk a lot about the benefits of SOA in terms of agility, aligning IT with the business, and risk mitigation. Then we talk about WOA (web oriented architecture) separately from SOA (service oriented architecture) but go on to discuss how the two architectures can be blended to create a giant application architecture milkshake that not only tastes good, but looks good. AJAX (Asynchronous JavaScript and XML) gets lumped under the umbrella of "Web 2.0" technologies. It's neither WOA nor SOA, being capable of participating in both architectural models easily. Some might argue that AJAX, being bound to the browser and therefore the web, is WOA. But WOA and SOA are both architectural models, and AJAX can participate in both - it is neither one or the other. It's seen as a tool; a means to an end, rather than as an enabling facet of either architectural model. It's seen as a mechanism for building interactive and more responsive user interfaces, as a cool tool to implement interesting tricks in the browser, and as yet another cross-browser incompatible scripting technology that makes developer's lives miserable. But AJAX, when used to build enterprise applications, can actually enable and encourage a more agile application environment. When AJAX is applied to user-interface elements to manipulate corporate data the applications or scripts on the server-side that interact with the GUI are often distilled into discrete blocks of functionality that can be reused in other applications and scripts in which that particular functionality is required. And thus services are born. Services that are themselves agile and thus enable broader agility within the application architecture. They aren't SOA services, at least that's what purists would say, but they are services, empowered with the same characteristics of their SOA-based cousins: reusable and granular. The problem is that AJAX is still seen as an allen wrench in an architecture that requires screwdrivers. It's often viewed only in terms of building a user interface, and the services it creates or takes advantage of on the back-end as being unequal to those specifically architected for inclusion in the enterprise SOA. Because AJAX drives the development of discrete services on the server-side, it can be a valued assistant in decomposing applications into its composite services. It can force you to think about the services and the operations required because AJAX necessarily interacts with granular functions of a service in a singular fashion. If we force AJAX development to focus on the user-interface, we lose some of the benefits we can derive from the design and development process by ignoring how well AJAX fits into the service-oriented paradigm. We lose the time and effort that goes into defining the discrete services that will be used by an AJAX-enabled component in the user-interface, and the possibility of reusing those services in the broader SOA. An SOA necessarily compels us to ignore platform and language and concentrate on the service. Services deployed on a web server utilizing PHP or ASP or Ruby as their implementation language are no different than those deployed on heavy application servers using JSP or Java or .NET. They can and should be included in the architectural design process to ensure they can be reused when possible. AJAX forces you to think in a service-oriented way. The services required by an AJAX-enabled user-interface should be consistent with the enterprise's architectural model and incorporated into that architecture whenever possible in order to derive agility and reuse from those services. AJAX is inherently an agile technology. Recognizing that early and incorporating the services required by AJAX-enabled components can help build a more agile, more consistent, more SOA-like application infrastructure.273Views0likes0CommentsRuby Virtual Server and Pool Creation
Problem this snippet solves: A simple script to add and delete both Virtual IPs and Pools in: Ruby Code : require 'rubygems' require 'rest-client' require 'json' # define program-wide variables BIGIP_ADDRESS = 'test-ltm-03.element.local' BIGIP_USER = 'admin' BIGIP_PASS = 'admin' SLEEP_TIME = 20 VS_NAME = 'test-http-virtual_ruby' VS_ADDRESS = '1.1.1.1' VS_PORT = '80' POOL_NAME = 'test-http-pool_ruby' POOL_LB_METHOD = 'least-connections-member' POOL_MEMBERS = [ '10.0.0.1:80', '10.0.0.2:80', '10.0.0.3:80' ] # create/delete methods def create_pool bigip, name, members, lb_method # convert member format members.collect { |member| { :kind => 'ltm:pool:members', :name => member} } # define test pool payload = { :kind => 'tm:ltm:pool:poolstate', :name => name, :description => 'A Ruby rest-client test pool', :loadBalancingMode => lb_method, :monitor => 'http', :members => members } bigip['ltm/pool'].post payload.to_json end def create_http_virtual bigip, name, address, port, pool # define test virtual payload = { :kind => 'tm:ltm:virtual:virtualstate', :name => name, :description => 'A Ruby rest-client test virtual server', :destination => "#{address}:#{port}", :mask => '255.255.255.255', :ipProtocol => 'tcp', :sourceAddressTranslation => { :type => 'automap' }, :profiles => [ { :kind => 'ltm:virtual:profile', :name => 'http' }, { :kind => 'ltm:virtual:profile', :name => 'tcp' } ], :pool => pool } bigip['ltm/virtual'].post payload.to_json end def delete_pool bigip, name url = "ltm/pool/#{name}" bigip[url].delete end def delete_virtual bigip, name url = "ltm/virtual/#{name}" bigip[url].delete end # REST resource for BIG-IP that all other requests will use bigip = RestClient::Resource.new( "https://#{BIGIP_ADDRESS}/mgmt/tm/", :user => BIGIP_USER, :password => BIGIP_PASS, :headers => { :content_type => 'application/json' } ) puts "created REST resource for BIG-IP at #{BIGIP_ADDRESS}..." # create pool create_pool bigip, POOL_NAME, POOL_MEMBERS, POOL_LB_METHOD puts "created pool \"#{POOL_NAME}\" with members #{POOL_MEMBERS.join(', ')}..." # create virtual create_http_virtual bigip, VS_NAME, VS_ADDRESS, VS_PORT, POOL_NAME puts "created virtual server \"#{VS_NAME}\" with destination #{VS_ADDRESS}:#{VS_PORT}..." # sleep for a little while puts "sleeping for #{SLEEP_TIME} seconds, check for successful creation..." sleep SLEEP_TIME # delete virtual delete_virtual bigip, VS_NAME puts "deleted virtual server \"#{VS_NAME}\"..." # delete pool delete_pool bigip, POOL_NAME puts "deleted pool \"#{POOL_NAME}\"..."266Views0likes1CommentRuby iControl throwing non-descript soap fault on NodeAddressV2.create
So I'm receiving a soap fault when I try and create a node. If anyone could help me out with a diagnosis I'd really appreciate it!! bigip = F5::IControl.new('*******', '*******', '*******', ['LocalLB.Pool', 'LocalLB.NodeAddressV2']) interfaces = bigip.get_interfaces interfaces['LocalLB.NodeAddressV2'].create ['test'], ['test.test.com'], [0] Throws the error: SOAP::FaultError: Exception caught in LocalLB::urn:iControl:LocalLB/NodeAddressV2::create() Common::InvalidArgument265Views0likes1Comment