blob: 26a47360b64cad1f11f4fe9b69a3e3045cae9642 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Zack Williams9a42f872019-02-15 17:56:04 -070015from __future__ import absolute_import
16from __future__ import print_function
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040017import unittest
Scott Baker1f7791d2018-10-04 13:21:20 -070018from xosgenx.generator import XOSProcessor, XOSProcessorArgs
19from helpers import XProtoTestHelpers, FakeObject
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040020
Zack Williams045b63d2019-01-22 16:30:57 -070021
Sapan Bhatiae294aae2017-09-06 11:21:15 -040022def output_security_check(x, y):
Zack Williams9a42f872019-02-15 17:56:04 -070023 """
24 This function eliminates warnings arising due to the missing
25 output_security_check, which is generated and loaded dynamically. This is
26 defined in the global namespace, and in python3 the globals() namespace has
27 to be passed to calls to "exec()" for the xproto-generated version to
28 redefine this function.
29 """
30
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040031 raise Exception("Security enforcer not generated. Test failed.")
32 return False
33
Zack Williams045b63d2019-01-22 16:30:57 -070034
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040035class XProtoSecurityTest(unittest.TestCase):
Zack Williams9a42f872019-02-15 17:56:04 -070036 """
37 Use the Python code target to generate Python security policies, set up an
38 appropriate environment and execute the Python.
39 """
40
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040041 def setUp(self):
Zack Williams045b63d2019-01-22 16:30:57 -070042 self.target = XProtoTestHelpers.write_tmp_target(
43 """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040044{% for name, policy in proto.policies.items() %}
45{{ xproto_fol_to_python_test(name, policy, None, '0') }}
46{% endfor %}
Zack Williams045b63d2019-01-22 16:30:57 -070047"""
48 )
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040049
50 def test_constant(self):
Zack Williams045b63d2019-01-22 16:30:57 -070051 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040052 policy output < True >
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040053"""
Zack Williams045b63d2019-01-22 16:30:57 -070054 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080055 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -070056 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040057
58 """
Sapan Bhatiae294aae2017-09-06 11:21:15 -040059 def output_security_check(obj, ctx):
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040060 i1 = True
61 return i1
62 """
63
Sapan Bhatiae294aae2017-09-06 11:21:15 -040064 verdict = output_security_check({}, {})
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040065 self.assertTrue(verdict)
66
67 def test_equal(self):
Zack Williams045b63d2019-01-22 16:30:57 -070068 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040069 policy output < ctx.user = obj.user >
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040070"""
71
Zack Williams045b63d2019-01-22 16:30:57 -070072 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080073 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -070074 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040075
76 """
Sapan Bhatiae294aae2017-09-06 11:21:15 -040077 def output_security_check(obj, ctx):
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040078 i1 = (ctx.user == obj.user)
79 return i1
80 """
81
Scott Baker1f7791d2018-10-04 13:21:20 -070082 obj = FakeObject()
83 obj.user = 1
84 ctx = FakeObject()
85 ctx.user = 1
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040086
Sapan Bhatiae294aae2017-09-06 11:21:15 -040087 verdict = output_security_check(obj, ctx)
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -040088
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040089 def test_call_policy(self):
Zack Williams045b63d2019-01-22 16:30:57 -070090 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040091 policy sub_policy < ctx.user = obj.user >
92 policy output < *sub_policy(child) >
93"""
94
Zack Williams045b63d2019-01-22 16:30:57 -070095 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080096 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -070097 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040098
99 """
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400100 def sub_policy_security_check(obj, ctx):
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400101 i1 = (ctx.user == obj.user)
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400102 return i1
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400103
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400104 def output_security_check(obj, ctx):
105 if obj.child:
Zack Williams045b63d2019-01-22 16:30:57 -0700106 i1 = sub_policy_security_check(obj.child, ctx)
107 else:
108 i1 = True
109 return i1
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400110 """
111
Scott Baker1f7791d2018-10-04 13:21:20 -0700112 obj = FakeObject()
113 obj.child = FakeObject()
114 obj.child.user = 1
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400115
Scott Baker1f7791d2018-10-04 13:21:20 -0700116 ctx = FakeObject()
117 ctx.user = 1
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400118
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400119 verdict = output_security_check(obj, ctx)
120 self.assertTrue(verdict)
121
122 def test_call_policy_child_none(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700123 xproto = """
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400124 policy sub_policy < ctx.user = obj.user >
125 policy output < *sub_policy(child) >
126"""
127
Zack Williams045b63d2019-01-22 16:30:57 -0700128 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800129 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -0700130 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400131
132 """
133 def sub_policy_security_check(obj, ctx):
134 i1 = (ctx.user == obj.user)
135 return i1
136
137 def output_security_check(obj, ctx):
138 if obj.child:
Zack Williams045b63d2019-01-22 16:30:57 -0700139 i1 = sub_policy_security_check(obj.child, ctx)
140 else:
141 i1 = True
142 return i1
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400143 """
144
Scott Baker1f7791d2018-10-04 13:21:20 -0700145 obj = FakeObject()
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400146 obj.child = None
147
Scott Baker1f7791d2018-10-04 13:21:20 -0700148 ctx = FakeObject()
149 ctx.user = 1
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400150
Sapan Bhatiac6543dd2017-12-07 11:40:36 -0500151 verdict = output_security_check(obj, ctx)
152 self.assertTrue(verdict)
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400153
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400154 def test_bin(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700155 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400156 policy output < ctx.is_admin = True | obj.empty = True>
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400157"""
158
Zack Williams045b63d2019-01-22 16:30:57 -0700159 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800160 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -0700161 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400162
163 """
Zack Williams045b63d2019-01-22 16:30:57 -0700164 def output_security_check(obj, ctx):
165 i2 = (ctx.is_admin == True)
166 i3 = (obj.empty == True)
167 i1 = (i2 or i3)
168 return i1
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400169 """
170
Scott Baker1f7791d2018-10-04 13:21:20 -0700171 obj = FakeObject()
172 obj.empty = True
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400173
Scott Baker1f7791d2018-10-04 13:21:20 -0700174 ctx = FakeObject()
175 ctx.is_admin = True
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400176
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400177 verdict = output_security_check(obj, ctx)
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400178
179 self.assertTrue(verdict)
180
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400181 def test_exists(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700182 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400183 policy output < exists Privilege: Privilege.object_id = obj.id >
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400184"""
Zack Williams045b63d2019-01-22 16:30:57 -0700185 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800186 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -0700187 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400188
189 """
Zack Williams045b63d2019-01-22 16:30:57 -0700190 def output_security_check(obj, ctx):
191 i1 = Privilege.objects.filter(object_id=obj.id)
192 return i1
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400193 """
194
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400195 self.assertTrue(output_security_check is not None)
Zack Williams045b63d2019-01-22 16:30:57 -0700196
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400197 def test_python(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700198 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400199 policy output < {{ "jack" in ["the", "box"] }} = False >
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400200"""
Zack Williams045b63d2019-01-22 16:30:57 -0700201 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800202 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -0700203 exec(output, globals()) # This loads the generated function, which should look like this:
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400204
205 """
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400206 def output_security_check(obj, ctx):
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400207 i2 = ('jack' in ['the', 'box'])
208 i1 = (i2 == False)
209 return i1
210 """
211
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400212 self.assertTrue(output_security_check({}, {}) is True)
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400213
214 def test_forall(self):
215 # This one we only parse
Zack Williams045b63d2019-01-22 16:30:57 -0700216 xproto = """
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400217 policy output < forall Credential: Credential.obj_id = obj_id >
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400218"""
219
Zack Williams045b63d2019-01-22 16:30:57 -0700220 args = XOSProcessorArgs(inputs=xproto, target=self.target)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800221 output = XOSProcessor.process(args)
Zack Williams9a42f872019-02-15 17:56:04 -0700222 exec(output, globals())
223
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400224 """
Sapan Bhatiae294aae2017-09-06 11:21:15 -0400225 def output_security_check(obj, ctx):
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400226 i2 = Credential.objects.filter((~ Q(obj_id=obj_id)))[0]
227 i1 = (not i2)
228 return i1
229 """
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400230
Zack Williams045b63d2019-01-22 16:30:57 -0700231
232if __name__ == "__main__":
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400233 unittest.main()