55#++
66
77module SoftLayer
8+ # The VLANFirewall class represents the firewall that protects
9+ # all the servers on a VLAN in the SoftLayer Environment. It is
10+ # also known as a "Dedicated Firewall" in some documentation.
11+ #
12+ # Instances of this class are a bit odd because they actually represent
13+ # VLANs (the VLAN protected by the firewall) and not the physical hardware
14+ # implementing the firewall itself. (although the device is accessible as
15+ # the "networkVlanFirewall" property)
16+ #
17+ # As a result, instances of this class correspond to certain instances
18+ # in the SoftLayer_Network_Vlan service.
19+ #
820 class VLANFirewall < SoftLayer ::ModelBase
21+ include ::SoftLayer ::DynamicAttribute
22+
23+ ##
24+ #:attr_reader:
25+ #
26+ # The number of the VLAN protected by this firewall
27+ #
928 sl_attr :VLAN_number , 'vlanNumber'
1029
1130 ##
12- # return the name of the router the firewall is attached to
31+ # :attr_reader:
32+ #
33+ # The set of rules applied by this firewall to incoming traffic.
34+ # The object will retrieve the rules from the network API every
35+ # time you ask it for the rules.
36+ #
37+ # The code will sort the rules by their "orderValue" which is the
38+ # order that the firewall applies the rules, however please see
39+ # the important note in change_rules! concerning the "orderValue"
40+ # property of the rules.
41+ sl_dynamic_attr :rules do |firewall_rules |
42+ firewall_rules . should_update? do
43+ # firewall rules update every time you ask for them.
44+ return true
45+ end
46+
47+ firewall_rules . to_update do
48+ acl_id = rules_ACL_id ( )
49+ rules_data = self . softlayer_client [ :Network_Firewall_AccessControlList ] . object_with_id ( acl_id ) . object_mask ( self . class . default_rules_mask ) . getRules
50+ rules_data . sort { |lhs , rhs | lhs [ 'orderValue' ] <=> rhs [ 'orderValue' ] }
51+ end
52+ end
53+
54+ ##
55+ # Change the set of rules for the firewall.
56+ # The rules_data parameter should be an array of hashes where
57+ # each hash gives the conditions of the rule. The keys of the
58+ # hashes should be entries from the array returned by
59+ # SoftLayer::ServerFirewall.default_rules_mask_keys
60+ #
61+ # *NOTE!* The rules themselves have an "orderValue" property.
62+ # It is this property, and *not* the order that the rules are
63+ # found in the rules_data array, which will determine in which
64+ # order the firewall applies it's rules to incomming traffic.
65+ #
66+ # *NOTE!* Changes to the rules are not applied immediately
67+ # on the server side. Instead, they are enqueued by the
68+ # firewall update service and updated periodically. A typical
69+ # update will take about one minute to apply, but times may vary
70+ # depending on the system load and other circumstances.
71+ def change_rules! ( rules_data )
72+ change_object = {
73+ "firewallContextAccessControlListId" => self . id ,
74+ "rules" => rules_data
75+ }
76+
77+ self . softlayer_client [ :Network_Firewall_Update_Request ] . createObject ( change_object )
78+ end
79+
80+ ##
81+ # Returns the name of the primary router the firewall is attached to.
82+ # This is often a "customer router" in one of the datacenters.
1383 def primaryRouter
1484 return self [ 'primaryRouter' ] [ 'hostname' ]
1585 end
1686
1787 ##
18- # The fully qualified domain name of the firewall
88+ # The fully qualified domain name of the physical device the
89+ # firewall is implemented by.
1990 def fullyQualifiedDomainName
2091 if self . has_sl_property? ( 'networkVlanFirewall' )
2192 return self [ 'networkVlanFirewall' ] [ 'fullyQualifiedDomainName' ]
@@ -25,51 +96,71 @@ def fullyQualifiedDomainName
2596 end
2697
2798 ##
28- # returns true if the firewall has the high availability flag set
29- #
99+ # Returns true if this is a " high availability" firewall, that is a firewall
100+ # that exists as one member of a redundant pair.
30101 def high_availability?
31102 # note that highAvailabilityFirewallFlag is a boolean in the softlayer hash
32103 return self . has_sl_property? ( 'highAvailabilityFirewallFlag' ) && self [ 'highAvailabilityFirewallFlag' ]
33104 end
34105
35- def rule_set
36- rule_set = nil
37-
38- # Search down through the firewall's data to find the AccessControlList (ACL) for the
39- # "outside" interface which handles "in"-wardly directed traffic. This is the list that
40- # has the rules we're interested in.
41- outside_interface_data = self [ "firewallInterfaces" ] . find { |firewall_interface_data | firewall_interface_data [ 'name' ] == 'outside' }
42- if outside_interface_data
43- incoming_ACL = outside_interface_data [ 'firewallContextAccessControlLists' ] . find { |firewallACL_data | firewallACL_data [ 'direction' ] == 'in' }
44-
45- firewall_ACL = self . softlayer_client [ :Network_Firewall_AccessControlList ] . object_with_id ( incoming_ACL [ 'id' ] ) . getObject
46- rule_set = VLANFirewallRuleset . new ( self . softlayer_client , firewall_ACL )
47- end
48-
49- return rule_set
50- end
51-
52106 ##
53- # collect a list of the firewalls on the account
107+ # Collect a list of the firewalls on the account.
54108 #
109+ # This list is obtained by asking the account for all the VLANs
110+ # it has that also have a networkVlanFirewall component.
55111 def self . find_firewalls ( client )
56112 softlayer_client = client || Client . default_client
57113 raise "#{ __method__ } requires a client but none was given and Client::default_client is not set" if !softlayer_client
58114
115+ # only VLAN firewallas have a networkVlanFirewall component
59116 vlan_firewall_filter = SoftLayer ::ObjectFilter . new ( ) { |filter |
60117 filter . accept ( "networkVlans.networkVlanFirewall" ) . when_it is_not_null
61118 }
62119
63120 vlan_firewalls = client [ :Account ] . object_mask ( vlan_firewall_mask ) . object_filter ( vlan_firewall_filter ) . getNetworkVlans
64121 vlan_firewalls . collect { |firewall_data | SoftLayer ::VLANFirewall . new ( client , firewall_data ) }
65122 end
123+
124+ def service
125+ # Objects of this class are a bit odd because they actually represent VLANs (the VLAN protected by the firewall)
126+ # and not the physical hardware implementing the firewall itself. (although the device is accessible as the
127+ # "networkVlanFirewall" property)
128+ self . softlayer_client [ :Network_Vlan ] . object_with_id ( self . id )
129+ end
130+
131+ def softlayer_properties ( object_mask = nil )
132+ service = self . service
133+ service = service . object_mask ( object_mask ) if object_mask
134+ service . object_mask ( self . class . vlan_firewall_mask ) . getObject
135+ end
66136
67137 private
68138
139+ # Searches the set of access control lists for the firewall device in order to locate the one that
140+ # sits on the "outside" side of the network and handles 'in'coming traffic.
141+ def rules_ACL_id
142+ outside_interface_data = self [ 'firewallInterfaces' ] . find { |interface_data | interface_data [ 'name' ] == 'outside' }
143+ incoming_ACL = outside_interface_data [ 'firewallContextAccessControlLists' ] . find { |firewallACL_data | firewallACL_data [ 'direction' ] == 'in' } if outside_interface_data
144+
145+ if incoming_ACL
146+ return incoming_ACL [ 'id' ]
147+ else
148+ return nil
149+ end
150+ end
151+
69152 def self . vlan_firewall_mask
70- return "mask[primaryRouter,dedicatedFirewallFlag, highAvailabilityFirewallFlag," +
153+ return "mask[primaryRouter,highAvailabilityFirewallFlag," +
71154 "firewallInterfaces.firewallContextAccessControlLists," +
72155 "networkVlanFirewall[id, datacenter, primaryIpAddress, firewallType, fullyQualifiedDomainName]]"
73156 end
157+
158+ def self . default_rules_mask
159+ return { "mask" => default_rules_mask_keys } . to_sl_object_mask
160+ end
161+
162+ def self . default_rules_mask_keys
163+ [ 'orderValue' , 'action' , 'destinationIpAddress' , 'destinationIpSubnetMask' , "protocol" , "destinationPortRangeStart" , "destinationPortRangeEnd" , 'sourceIpAddress' , "sourceIpSubnetMask" , "version" ]
164+ end
74165 end # class Firewall
75166end # module SoftLayer
0 commit comments