Skip to content

Commit

Permalink
Add support for some connection sub tokens in openconfig generator vi…
Browse files Browse the repository at this point in the history
…z. tcp_established, established, initial, is-fragment.

PiperOrigin-RevId: 693100078
  • Loading branch information
Capirca Team committed Nov 4, 2024
1 parent c983181 commit a8838a2
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 13 deletions.
41 changes: 33 additions & 8 deletions capirca/lib/openconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,39 @@ def ConvertToDict(self):
f'Protocol {proto} unknown. Use an integer.'
) from e
ace_dict[family]['config']['protocol'] = proto_num
rules.append(copy.deepcopy(ace_dict))
rule_dict = copy.deepcopy(ace_dict)
else:
proto_num = proto
ace_dict[family]['config']['protocol'] = proto_num
# This is the business end of ace explosion.
# A dict is a reference type, so deepcopy is atually required.
rules.append(copy.deepcopy(ace_dict))
rule_dict = copy.deepcopy(ace_dict)

# options
for opt in self.term.option:
if opt == 'tcp-established' and proto != 'udp':
rule_dict['transport']['config']['detail-mode'] = 'BUILTIN'
rule_dict['transport']['config'][
'builtin-detail'
] = 'TCP_ESTABLISHED'
if opt == 'established' and proto != 'udp':
rule_dict['transport']['config']['detail-mode'] = 'BUILTIN'
rule_dict['transport']['config'][
'builtin-detail'
] = 'TCP_ESTABLISHED'
# initial only for tcp
if opt == 'initial' and proto == 'tcp':
rule_dict['transport']['config']['detail-mode'] = 'BUILTIN'
rule_dict['transport']['config'][
'builtin-detail'
] = 'TCP_INITIAL'
# is-fragment only for ipv4
if opt == 'is-fragment' and term_af == 4:
rule_dict['transport']['config']['detail-mode'] = 'BUILTIN'
rule_dict['transport']['config'][
'builtin-detail'
] = 'FRAGMENT'
rules.append(rule_dict)

return rules

Expand Down Expand Up @@ -271,12 +297,11 @@ def _TranslatePolicy(self, pol, exp_info):
filter_name,
)
continue
# TODO(b/196430344): Add support for options such as
# established/rst/first-fragment
if term.option:
raise OcFirewallError(
'OpenConfig firewall does not support term options.'
)
for opt in term.option:
if opt in ['first-fragment', 'sample', 'rst']:
raise OcFirewallError(
'OpenConfig firewall does not support term option %s.' % opt
)

t = Term(term, term_af)
for rule in t.ConvertToDict():
Expand Down
72 changes: 67 additions & 5 deletions tests/lib/openconfig_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@
}
"""

GOOD_MULTI_PROTO_DPORT = """
GOOD_TCP_ESTABLISHED = """
term good-term-1 {
comment:: "Allow TCP & UDP 53."
comment:: "Allow TCP 53 dest."
destination-port:: DNS
protocol:: udp tcp
protocol:: tcp
action:: accept
option:: tcp-established
}
"""

Expand All @@ -84,6 +85,8 @@
destination-port:: DNS
protocol:: udp tcp
action:: accept
option:: is-fragment
option:: initial
}
"""

Expand Down Expand Up @@ -504,6 +507,51 @@
}
"""

GOOD_JSON_DPORT_TCP_ESTABLISHED = """
{
"acl-sets": {
"acl-set": [
{
"acl-entries": {
"acl-entry": [
{
"actions": {
"config": {
"forwarding-action": "ACCEPT"
}
},
"config": {
"description": "[good-term-1]: Allow TCP 53 dest.",
"sequence-id": 1
},
"ipv4": {
"config": {
"protocol": 6
}
},
"sequence-id": 1,
"transport": {
"config": {
"builtin-detail": "TCP_ESTABLISHED",
"destination-port": 53,
"detail-mode": "BUILTIN"
}
}
}
]
},
"config": {
"name": "test-filter",
"type": "ACL_IPV4"
},
"name": "test-filter",
"type": "ACL_IPV4"
}
]
}
}
"""

GOOD_JSON_EVERYTHING = """
{
"acl-sets": {
Expand Down Expand Up @@ -531,7 +579,9 @@
"sequence-id": 1,
"transport": {
"config": {
"destination-port": 53
"builtin-detail": "FRAGMENT",
"destination-port": 53,
"detail-mode": "BUILTIN"
}
}
},
Expand All @@ -555,7 +605,9 @@
"sequence-id": 2,
"transport": {
"config": {
"destination-port": 53
"builtin-detail": "TCP_INITIAL",
"destination-port": 53,
"detail-mode": "BUILTIN"
}
}
}
Expand Down Expand Up @@ -683,6 +735,16 @@ def testDport(self):
expected = json.loads(GOOD_JSON_DPORT)
self.assertEqual(expected, json.loads(str(acl)))

self.naming.GetServiceByProto.assert_has_calls([
mock.call('DNS', 'tcp')])
def testDportWithTCPEstablished(self):
self.naming.GetServiceByProto.side_effect = [['53'], ['53']]

acl = openconfig.OpenConfig(policy.ParsePolicy(
GOOD_HEADER + GOOD_TCP_ESTABLISHED, self.naming), EXP_INFO)
expected = json.loads(GOOD_JSON_DPORT_TCP_ESTABLISHED)
self.assertEqual(expected, json.loads(str(acl)))

self.naming.GetServiceByProto.assert_has_calls([
mock.call('DNS', 'tcp')])

Expand Down

0 comments on commit a8838a2

Please sign in to comment.