Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions 18 linode_api4/groups/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
VLAN,
Base,
Firewall,
FirewallTemplate,
Instance,
IPAddress,
IPv6Pool,
Expand Down Expand Up @@ -94,6 +95,23 @@ def firewall_create(self, label, rules, **kwargs):
f = Firewall(self.client, result["id"], result)
return f

def firewall_templates(self, *filters):
"""
Returns a list of Firewall Templates available to the current user.

API Documentation: Not yet available.

NOTE: This feature may not currently be available to all users.

:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.

:returns: A list of Firewall Templates available to the current user.
:rtype: PaginatedList of FirewallTemplate
"""
return self.client._get_and_filter(FirewallTemplate, *filters)

def ips(self, *filters):
"""
Returns a list of IP addresses on this account, excluding private addresses.
Expand Down
16 changes: 16 additions & 0 deletions 16 linode_api4/objects/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ def device_create(self, id, type="linode", **kwargs):
return c


class FirewallTemplate(Base):
"""
Represents a single Linode Firewall template.

API documentation: Not yet available.

NOTE: This feature may not currently be available to all users.
"""

api_endpoint = "/networking/firewalls/templates/{slug}"

id_attribute = "slug"

properties = {"slug": Property(identifier=True), "rules": Property()}


class NetworkTransferPrice(Base):
"""
An NetworkTransferPrice represents the structure of a valid network transfer price.
Expand Down
93 changes: 93 additions & 0 deletions 93 test/fixtures/networking_firewalls_templates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"data": [
{
"slug": "public",
"rules": {
"outbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"outbound_policy": "DROP",
"inbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"inbound_policy": "DROP"
}
},
{
"slug": "vpc",
"rules": {
"outbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"outbound_policy": "DROP",
"inbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"inbound_policy": "DROP"
}
}
],
"page": 1,
"pages": 1,
"results": 2
}
43 changes: 43 additions & 0 deletions 43 test/fixtures/networking_firewalls_templates_public.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"slug": "public",
"rules": {
"outbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"outbound_policy": "DROP",
"inbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"inbound_policy": "DROP"
}
}
43 changes: 43 additions & 0 deletions 43 test/fixtures/networking_firewalls_templates_vpc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"slug": "vpc",
"rules": {
"outbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"outbound_policy": "DROP",
"inbound": [
{
"action": "ACCEPT",
"addresses": {
"ipv4": [
"192.0.2.0/24",
"198.51.100.2/32"
],
"ipv6": [
"2001:DB8::/128"
]
},
"description": "test",
"label": "test-rule",
"ports": "22-24, 80, 443",
"protocol": "TCP"
}
],
"inbound_policy": "DROP"
}
}
33 changes: 33 additions & 0 deletions 33 test/integration/models/firewall/test_firewall_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from linode_api4 import FirewallTemplate, MappedObject


def __assert_firewall_template_rules(rules: MappedObject):
# We can't confidently say that these rules will not be changed
# in the future, so we can just do basic assertions here.
assert isinstance(rules.inbound_policy, str)
assert len(rules.inbound_policy) > 0

assert isinstance(rules.outbound_policy, str)
assert len(rules.outbound_policy) > 0

assert isinstance(rules.outbound, list)
assert isinstance(rules.inbound, list)


def test_list_firewall_templates(test_linode_client):
templates = test_linode_client.networking.firewall_templates()
assert len(templates) > 0

for template in templates:
assert isinstance(template.slug, str)
assert len(template.slug) > 0

__assert_firewall_template_rules(template.rules)


def test_get_firewall_template(test_linode_client):
template = test_linode_client.load(FirewallTemplate, "vpc")

assert template.slug == "vpc"

__assert_firewall_template_rules(template.rules)
17 changes: 17 additions & 0 deletions 17 test/unit/groups/networking_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from test.unit.base import ClientBaseCase
from test.unit.objects.firewall_test import FirewallTemplatesTest


class NetworkingGroupTest(ClientBaseCase):
"""
Tests methods under the NetworkingGroup class.
"""

def test_get_templates(self):
templates = self.client.networking.firewall_templates()

assert templates[0].slug == "public"
FirewallTemplatesTest.assert_rules(templates[0].rules)

assert templates[1].slug == "vpc"
FirewallTemplatesTest.assert_rules(templates[1].rules)
41 changes: 41 additions & 0 deletions 41 test/unit/objects/firewall_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from test.unit.base import ClientBaseCase

from linode_api4 import FirewallTemplate, MappedObject
from linode_api4.objects import Firewall, FirewallDevice


Expand Down Expand Up @@ -81,3 +82,43 @@ def test_get_device(self):
self.assertEqual(device.entity.url, "/v4/linode/instances/123")

self.assertEqual(device._populated, True)


class FirewallTemplatesTest(ClientBaseCase):
@staticmethod
def assert_rules(rules: MappedObject):
assert rules.outbound_policy == "DROP"
assert len(rules.outbound) == 1

assert rules.inbound_policy == "DROP"
assert len(rules.inbound) == 1

outbound_rule = rules.outbound[0]
assert outbound_rule.action == "ACCEPT"
assert outbound_rule.addresses.ipv4[0] == "192.0.2.0/24"
assert outbound_rule.addresses.ipv4[1] == "198.51.100.2/32"
assert outbound_rule.addresses.ipv6[0] == "2001:DB8::/128"
assert outbound_rule.description == "test"
assert outbound_rule.label == "test-rule"
assert outbound_rule.ports == "22-24, 80, 443"
assert outbound_rule.protocol == "TCP"

inbound_rule = rules.outbound[0]
assert inbound_rule.action == "ACCEPT"
assert inbound_rule.addresses.ipv4[0] == "192.0.2.0/24"
assert inbound_rule.addresses.ipv4[1] == "198.51.100.2/32"
assert inbound_rule.addresses.ipv6[0] == "2001:DB8::/128"
assert inbound_rule.description == "test"
assert inbound_rule.label == "test-rule"
assert inbound_rule.ports == "22-24, 80, 443"
assert inbound_rule.protocol == "TCP"

def test_get_public(self):
template = self.client.load(FirewallTemplate, "public")
assert template.slug == "public"
self.assert_rules(template.rules)

def test_get_vpc(self):
template = self.client.load(FirewallTemplate, "vpc")
assert template.slug == "vpc"
self.assert_rules(template.rules)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.