Skip to content

Commit dae2ec7

Browse files
Merge pull request #1651 from BrianSantivanez/issue1650
Update `slcli firewall detail` to handle multi vlan firewalls
2 parents d269e60 + 24f6a35 commit dae2ec7

File tree

4 files changed

+262
-18
lines changed

4 files changed

+262
-18
lines changed

SoftLayer/CLI/firewall/detail.py

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,77 @@
1212

1313
@click.command(cls=SoftLayer.CLI.command.SLCommand, )
1414
@click.argument('identifier')
15+
@click.option('--credentials', type=click.BOOL,
16+
help="Display FortiGate username and FortiGate password to multi vlans.")
1517
@environment.pass_env
16-
def cli(env, identifier):
17-
"""Detail firewall."""
18+
def cli(env, identifier, credentials):
19+
"""Detail firewall.
20+
21+
EXAMPLES:
22+
23+
slcli firewall detail vs:12345
24+
25+
slcli firewall detail --credentials true multiVlan:456789
26+
"""
1827

1928
mgr = SoftLayer.FirewallManager(env.client)
2029

2130
firewall_type, firewall_id = firewall.parse_id(identifier)
22-
_firewall = mgr.get_instance(firewall_id)
2331

24-
table = formatting.KeyValueTable(['name', 'value'])
25-
table.align['name'] = 'r'
26-
table.align['value'] = 'l'
32+
if firewall_type in ('vs', 'server', 'vlan', 'multiVlan'):
33+
34+
if firewall_type == 'vlan':
35+
_firewall = mgr.get_instance(firewall_id)
36+
37+
table = formatting.KeyValueTable(['name', 'value'])
38+
table.align['name'] = 'r'
39+
table.align['value'] = 'l'
40+
41+
table.add_row(['id', _firewall.get('id')])
42+
table.add_row(['primaryIpAddress', _firewall.get('primaryIpAddress')])
43+
table.add_row(['datacenter', utils.lookup(_firewall, 'datacenter', 'longName')])
44+
table.add_row(['networkVlan', utils.lookup(_firewall, 'networkVlan', 'name')])
45+
table.add_row(['networkVlaniD', utils.lookup(_firewall, 'networkVlan', 'id')])
46+
47+
rules = mgr.get_dedicated_fwl_rules(firewall_id)
48+
table.add_row(['rules', get_rules_table(rules)])
49+
50+
if firewall_type == 'multiVlan':
51+
_firewall = mgr.get_instance(firewall_id)
52+
53+
table = formatting.KeyValueTable(['name', 'value'])
54+
table.align['name'] = 'r'
55+
table.align['value'] = 'l'
56+
57+
table.add_row(['name', utils.lookup(_firewall, 'networkGateway', 'name')])
58+
table.add_row(['datacenter', utils.lookup(_firewall, 'datacenter', 'longName')])
59+
table.add_row(['public ip', utils.lookup(_firewall, 'networkGateway', 'publicIpAddress', 'ipAddress')])
60+
table.add_row(['private ip', utils.lookup(_firewall, 'networkGateway', 'privateIpAddress', 'ipAddress')])
61+
table.add_row(['public ipv6', utils.lookup(_firewall, 'networkGateway', 'publicIpv6Address', 'ipAddress')])
62+
table.add_row(['public vlan', utils.lookup(_firewall, 'networkGateway', 'publicVlan', 'vlanNumber')])
63+
table.add_row(['private vlan', utils.lookup(_firewall, 'networkGateway', 'privateVlan', 'vlanNumber')])
64+
table.add_row(['type', _firewall.get('firewallType')])
65+
66+
if credentials:
67+
table.add_row(['fortiGate username', utils.lookup(_firewall, 'managementCredentials', 'username')])
68+
table.add_row(['fortiGate password', utils.lookup(_firewall, 'managementCredentials', 'password')])
69+
70+
rules = mgr.get_dedicated_fwl_rules(firewall_id)
71+
if len(rules) != 0:
72+
table.add_row(['rules', get_rules_table(rules)])
73+
else:
74+
table.add_row(['rules', '-'])
75+
76+
if firewall_type == 'vs' or firewall_type == 'server':
77+
rules = mgr.get_standard_fwl_rules(firewall_id)
78+
table = get_rules_table(rules)
2779

28-
table.add_row(['id', _firewall.get('id')])
29-
table.add_row(['primaryIpAddress', _firewall.get('primaryIpAddress')])
30-
table.add_row(['datacenter', utils.lookup(_firewall, 'datacenter', 'longName')])
31-
table.add_row(['networkVlan', utils.lookup(_firewall, 'networkVlan', 'name')])
32-
table.add_row(['networkVlaniD', utils.lookup(_firewall, 'networkVlan', 'id')])
80+
env.fout(table)
3381

34-
if firewall_type == 'vlan':
35-
rules = mgr.get_dedicated_fwl_rules(firewall_id)
3682
else:
37-
rules = mgr.get_standard_fwl_rules(firewall_id)
38-
table.add_row(['rules', get_rules_table(rules)])
39-
env.fout(table)
83+
click.secho('Invalid firewall type %s: firewall type should be either vlan, multiVlan, vs or server.'
84+
% firewall_type, fg='red')
85+
return
4086

4187

4288
def get_rules_table(rules):

SoftLayer/fixtures/SoftLayer_Network_Vlan_Firewall.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,133 @@
4949
}
5050
]
5151
},
52+
"firewallType": "fortigate-security-appliance-10gb",
53+
"managementCredentials": {
54+
"createDate": "2022-05-17T13:59:17-06:00",
55+
"id": 74604882,
56+
"modifyDate": "2022-05-17T13:59:17-06:00",
57+
"password": "test1234",
58+
"port": 23,
59+
"softwareId": 67804284,
60+
"username": "myusername"
61+
},
62+
"networkGateway": {
63+
"accountId": 307608,
64+
"groupNumber": 1,
65+
"id": 615448,
66+
"name": "testFirewall",
67+
"networkSpace": "BOTH",
68+
"privateIpAddressId": 188996652,
69+
"privateVlanId": 3228724,
70+
"publicIpAddressId": 188996794,
71+
"publicIpv6AddressId": 188996808,
72+
"publicVlanId": 3228726,
73+
"statusId": 1,
74+
"insideVlans": [],
75+
"members": [
76+
{
77+
"hardwareId": 3222842,
78+
"id": 687820,
79+
"networkGatewayId": 615448,
80+
"priority": 254,
81+
"networkGateway": None
82+
}
83+
],
84+
"privateIpAddress": {
85+
"id": 188996652,
86+
"ipAddress": "10.37.115.70",
87+
"isBroadcast": False,
88+
"isGateway": False,
89+
"isNetwork": False,
90+
"isReserved": True,
91+
"subnetId": 2552734,
92+
"subnet": {
93+
"broadcastAddress": "10.37.115.127",
94+
"cidr": 26,
95+
"gateway": "10.37.115.65",
96+
"id": 2552734,
97+
"isCustomerOwned": False,
98+
"isCustomerRoutable": False,
99+
"modifyDate": "2022-05-17T13:59:16-06:00",
100+
"netmask": "255.255.255.192",
101+
"networkIdentifier": "10.37.115.64",
102+
"networkVlanId": 3228724,
103+
"sortOrder": "1",
104+
"subnetType": "ADDITIONAL_PRIMARY",
105+
"totalIpAddresses": "64",
106+
"usableIpAddressCount": "61",
107+
"version": 4
108+
}
109+
},
110+
"privateVlan": {
111+
"accountId": 307608,
112+
"fullyQualifiedName": "dal13.bcr03.1330",
113+
"id": 3228724,
114+
"modifyDate": "2022-05-17T14:01:14-06:00",
115+
"primarySubnetId": 2625456,
116+
"vlanNumber": 1330
117+
},
118+
"publicIpAddress": {
119+
"id": 188996794,
120+
"ipAddress": "67.228.206.245",
121+
"isBroadcast": False,
122+
"isGateway": False,
123+
"isNetwork": False,
124+
"isReserved": True,
125+
"subnetId": 66444,
126+
"subnet": {
127+
"broadcastAddress": "67.228.206.247",
128+
"cidr": 29,
129+
"gateway": "67.228.206.241",
130+
"id": 66444,
131+
"isCustomerOwned": False,
132+
"isCustomerRoutable": False,
133+
"modifyDate": "2022-05-17T13:59:16-06:00",
134+
"netmask": "255.255.255.248",
135+
"networkIdentifier": "67.228.206.240",
136+
"networkVlanId": 3228726,
137+
"sortOrder": "1",
138+
"subnetType": "ADDITIONAL_PRIMARY",
139+
"totalIpAddresses": "8",
140+
"usableIpAddressCount": "5",
141+
"version": 4
142+
}
143+
},
144+
"publicIpv6Address": {
145+
"id": 188996808,
146+
"ipAddress": "2607:f0d0:2703:0039:0000:0000:0000:0004",
147+
"isBroadcast": False,
148+
"isGateway": False,
149+
"isNetwork": False,
150+
"isReserved": True,
151+
"subnetId": 2547678,
152+
"subnet": {
153+
"broadcastAddress": "",
154+
"cidr": 64,
155+
"gateway": "2607:f0d0:2703:0039:0000:0000:0000:0001",
156+
"id": 2547678,
157+
"isCustomerOwned": False,
158+
"isCustomerRoutable": False,
159+
"modifyDate": "2022-05-17T13:59:16-06:00",
160+
"netmask": "ffff:ffff:ffff:ffff:0000:0000:0000:0000",
161+
"networkIdentifier": "2607:f0d0:2703:0039:0000:0000:0000:0000",
162+
"networkVlanId": 3228726,
163+
"sortOrder": "4",
164+
"subnetType": "PRIMARY_6",
165+
"totalIpAddresses": "18446744073709551616",
166+
"usableIpAddressCount": "18446744073709551614",
167+
"version": 6
168+
}
169+
},
170+
"publicVlan": {
171+
"accountId": 307608,
172+
"fullyQualifiedName": "dal13.fcr03.1255",
173+
"id": 3228726,
174+
"modifyDate": "2022-05-17T14:00:42-06:00",
175+
"primarySubnetId": 2623338,
176+
"vlanNumber": 1255
177+
}
178+
},
52179
"rules": [
53180
{'destinationIpAddress': 'any on server',
54181
'protocol': 'tcp',

SoftLayer/managers/firewall.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ def get_instance(self, firewall_id, mask=None):
297297
:param integer firewall_id: the instance ID of the standard firewall
298298
"""
299299
if not mask:
300-
mask = 'mask[datacenter,networkVlan]'
300+
mask = 'mask[firewallType,networkGateway[insideVlans,members,privateIpAddress,publicIpAddress,' \
301+
'publicIpv6Address,privateVlan,publicVlan],datacenter,managementCredentials,networkVlan]'
301302

302303
svc = self.client['Network_Vlan_Firewall']
303304

tests/CLI/modules/firewall_tests.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_add_server(self, confirm_mock):
3939
self.assert_no_fail(result)
4040
self.assertIn("Firewall is being created!", result.output)
4141

42-
def test_detail(self):
42+
def test_detail_vlan_firewall(self):
4343
result = self.run_command(['firewall', 'detail', 'vlan:1234'])
4444
self.assert_no_fail(result)
4545
json_result = json.loads(result.output)
@@ -72,6 +72,76 @@ def test_detail(self):
7272
'src_ip': '0.0.0.0',
7373
'src_mask': '0.0.0.0'}]})
7474

75+
def test_detail_multi_vlan_firewall(self):
76+
result = self.run_command(['firewall', 'detail', 'multiVlan:1234', '--credentials', 'true'])
77+
self.assert_no_fail(result)
78+
json_result = json.loads(result.output)
79+
self.assertEqual(json_result['rules'][0]['action'], 'permit')
80+
self.assertEqual(json.loads(result.output),
81+
{'name': 'testFirewall',
82+
'datacenter': 'Amsterdam 1',
83+
'public ip': '67.228.206.245',
84+
'private ip': '10.37.115.70',
85+
'public ipv6': '2607:f0d0:2703:0039:0000:0000:0000:0004',
86+
'public vlan': 1255,
87+
'private vlan': 1330,
88+
'type': 'fortigate-security-appliance-10gb',
89+
'fortiGate username': 'myusername',
90+
'fortiGate password': 'test1234',
91+
'rules': [{'#': 1,
92+
'action': 'permit',
93+
'dest': 'any on server:80-80',
94+
'dest_mask': '255.255.255.255',
95+
'protocol': 'tcp',
96+
'src_ip': '0.0.0.0',
97+
'src_mask': '0.0.0.0'},
98+
{'#': 2,
99+
'action': 'permit',
100+
'dest': 'any on server:1-65535',
101+
'dest_mask': '255.255.255.255',
102+
'protocol': 'tmp',
103+
'src_ip': '193.212.1.10',
104+
'src_mask': '255.255.255.255'},
105+
{'#': 3,
106+
'action': 'permit',
107+
'dest': 'any on server:80-800',
108+
'dest_mask': '255.255.255.255',
109+
'protocol': 'tcp',
110+
'src_ip': '0.0.0.0',
111+
'src_mask': '0.0.0.0'}]})
112+
113+
def test_detail_vs_firewall(self):
114+
result = self.run_command(['firewall', 'detail', 'vs:1234'])
115+
self.assert_no_fail(result)
116+
self.assertEqual(json.loads(result.output),
117+
[{'#': 1,
118+
'action': 'permit',
119+
'dest': 'any on server:80-80',
120+
'dest_mask': '255.255.255.255',
121+
'protocol': 'tcp',
122+
'src_ip': '0.0.0.0',
123+
'src_mask': '0.0.0.0'},
124+
{'#': 2,
125+
'action': 'permit',
126+
'dest': 'any on server:1-65535',
127+
'dest_mask': '255.255.255.255',
128+
'protocol': 'tcp',
129+
'src_ip': '193.212.1.10',
130+
'src_mask': '255.255.255.255'},
131+
{'#': 3,
132+
'action': 'permit',
133+
'dest': 'any on server:80-800',
134+
'dest_mask': '255.255.255.255',
135+
'protocol': 'tcp',
136+
'src_ip': '0.0.0.0',
137+
'src_mask': '0.0.0.0'}])
138+
139+
def test_detail_fails(self):
140+
result = self.run_command(['firewall', 'detail', 'abc:1234'])
141+
self.assert_no_fail(result)
142+
expected_output = 'Invalid firewall type abc: firewall type should be either vlan, multiVlan, vs or server.\n'
143+
self.assertEqual(result.output, expected_output)
144+
75145
@mock.patch('SoftLayer.CLI.formatting.confirm')
76146
def test_cancel_firewall(self, confirm_mock):
77147
confirm_mock.return_value = True

0 commit comments

Comments
 (0)