Skip to content

Commit 7494378

Browse files
committed
add rule management to Defense policy API
1 parent fa5cfb9 commit 7494378

File tree

2 files changed

+113
-35
lines changed

2 files changed

+113
-35
lines changed

examples/defense/policy_operations.py

Lines changed: 97 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,43 @@
33

44
import sys
55
from cbapi.defense import Policy
6-
from cbapi.example_helpers import build_cli_parser, get_cb_defense_object, get_object_by_name_or_id
6+
from cbapi.example_helpers import build_cli_parser, get_cb_defense_object
77
from cbapi.errors import ServerError
88
import logging
99
import json
1010

1111
log = logging.getLogger(__name__)
1212

1313

14+
def get_policy_by_name_or_id(cb, id=None, name=None, return_all_if_none=False):
15+
policies = []
16+
17+
try:
18+
if id:
19+
attempted_to_find = "ID of {0}".format(id)
20+
policies = [cb.select(Policy, id, force_init=True)]
21+
elif name:
22+
attempted_to_find = "name {0}".format(name)
23+
policies = [p for p in cb.select(Policy) if p.name == name]
24+
if not len(policies):
25+
raise Exception("No policies match")
26+
elif return_all_if_none:
27+
attempted_to_find = "all policies"
28+
policies = list(cb.select(Policy))
29+
except Exception as e:
30+
print("Could not find policy with {0}: {1}".format(attempted_to_find, str(e)))
31+
32+
return policies
33+
34+
1435
def list_policies(cb, parser, args):
1536
for p in cb.select(Policy):
16-
print("Policy id {0}: {1}".format(p.id, p.name))
17-
print(" {0}".format(p.description))
37+
print("Policy id {0}: {1} {2}".format(p.id, p.name, "({0})".format(p.description) if p.description else ""))
38+
print("Rules:")
39+
for r in p.rules.values():
40+
print(" {0}: {1} when {2} {3} is {4}".format(r.get('id'), r.get("action"),
41+
r.get("application", {}).get("type"),
42+
r.get("application", {}).get("value"), r.get("operation")))
1843

1944

2045
def import_policy(cb, parser, args):
@@ -37,56 +62,70 @@ def import_policy(cb, parser, args):
3762

3863

3964
def delete_policy(cb, parser, args):
40-
try:
41-
if args.id:
42-
attempted_to_find = "ID of {0}".format(args.id)
43-
policies = [cb.select(Policy, args.id, force_init=True)]
44-
else:
45-
attempted_to_find = "name {0}".format(args.name)
46-
policies = [p for p in cb.select(Policy) if p.name == args.name]
47-
if not len(policies):
48-
raise Exception("No policies match")
49-
except Exception as e:
50-
print("Could not find policy with {0}: {1}".format(attempted_to_find, str(e)))
65+
policies = get_policy_by_name_or_id(cb, args.id, args.name)
66+
if len(policies) == 0:
5167
return
5268

5369
num_matching_policies = len(policies)
5470
if num_matching_policies > 1 and not args.force:
55-
print("{0:d} policies match {1:s} and --force not specified. No action taken.".format(num_matching_policies,
56-
attempted_to_find))
71+
print("{0:d} policies match and --force not specified. No action taken.".format(num_matching_policies))
5772
return
5873

5974
for p in policies:
6075
try:
6176
p.delete()
6277
except Exception as e:
63-
print("Could not delete policy with {0}: {1}".format(attempted_to_find, str(e)))
78+
print("Could not delete policy: {0}".format(str(e)))
6479
else:
6580
print("Deleted policy id {0} with name {1}".format(p.id, p.name))
6681

6782

6883
def export_policy(cb, parser, args):
69-
try:
70-
if args.id:
71-
attempted_to_find = "ID of {0}".format(args.id)
72-
policies = [cb.select(Policy, args.id, force_init=True)]
73-
elif args.name:
74-
attempted_to_find = "name {0}".format(args.name)
75-
policies = [p for p in cb.select(Policy) if p.name == args.name]
76-
if not len(policies):
77-
raise Exception("No policies match")
78-
else:
79-
attempted_to_find = "all policies"
80-
policies = list(cb.select(Policy))
81-
82-
except Exception as e:
83-
print("Could not find policy with {0}: {1}".format(attempted_to_find, str(e)))
84-
return
84+
policies = get_policy_by_name_or_id(cb, args.id, args.name, return_all_if_none=True)
8585

8686
for p in policies:
8787
json.dump(p.policy, open("policy-{0}.json".format(p.id), "w"), indent=2)
8888
print("Wrote policy {0} {1} to file policy-{0}.json".format(p.id, p.name))
89-
89+
90+
91+
def add_rule(cb, parser, args):
92+
policies = get_policy_by_name_or_id(cb, args.id, args.name)
93+
94+
num_matching_policies = len(policies)
95+
if num_matching_policies != 1:
96+
print("{0:d} policies match. No action taken.".format(num_matching_policies))
97+
98+
policy = policies[0]
99+
policy.add_rule(json.load(open(args.rulefile, "r")))
100+
101+
print("Added rule from {0} to policy {1}.".format(args.rulefile, policy.name))
102+
103+
104+
def del_rule(cb, parser, args):
105+
policies = get_policy_by_name_or_id(cb, args.id, args.name)
106+
107+
num_matching_policies = len(policies)
108+
if num_matching_policies != 1:
109+
print("{0:d} policies match. No action taken.".format(num_matching_policies))
110+
111+
policy = policies[0]
112+
policy.delete_rule(args.ruleid)
113+
114+
print("Removed rule id {0} from policy {1}.".format(args.ruleid, policy.name))
115+
116+
117+
def replace_rule(cb, parser, args):
118+
policies = get_policy_by_name_or_id(cb, args.id, args.name)
119+
120+
num_matching_policies = len(policies)
121+
if num_matching_policies != 1:
122+
print("{0:d} policies match. No action taken.".format(num_matching_policies))
123+
124+
policy = policies[0]
125+
policy.replace_rule(args.ruleid, json.load(open(args.rulefile, "r")))
126+
127+
print("Replaced rule id {0} from policy {1} with rule from file {2}.".format(args.ruleid, policy.name,
128+
args.rulefile))
90129

91130
def main():
92131
parser = build_cli_parser("Policy operations")
@@ -115,6 +154,24 @@ def main():
115154
del_command.add_argument("--force", help="If NAME matches multiple policies, delete all matching policies",
116155
action="store_true", default=False)
117156

157+
add_rule_command = commands.add_parser("add-rule", help="Add rule to existing policy from JSON rule file")
158+
add_rule_specifier = add_rule_command.add_mutually_exclusive_group(required=True)
159+
add_rule_specifier.add_argument("-i", "--id", type=int, help="ID of policy")
160+
add_rule_specifier.add_argument("-N", "--name", help="Name of policy")
161+
add_rule_command.add_argument("-f", "--rulefile", help="Filename containing the JSON rule", required=True)
162+
163+
del_rule_command = commands.add_parser("del-rule", help="Delete rule from existing policy")
164+
del_rule_specifier = del_rule_command.add_mutually_exclusive_group(required=True)
165+
del_rule_specifier.add_argument("-i", "--id", type=int, help="ID of policy")
166+
del_rule_specifier.add_argument("-N", "--name", help="Name of policy")
167+
del_rule_command.add_argument("-r", "--ruleid", type=int, help="ID of rule", required=True)
168+
169+
replace_rule_command = commands.add_parser("replace-rule", help="Replace existing rule with a new one")
170+
replace_rule_specifier = replace_rule_command.add_mutually_exclusive_group(required=True)
171+
replace_rule_specifier.add_argument("-i", "--id", type=int, help="ID of policy")
172+
replace_rule_specifier.add_argument("-N", "--name", help="Name of policy")
173+
replace_rule_command.add_argument("-r", "--ruleid", type=int, help="ID of rule", required=True)
174+
118175
args = parser.parse_args()
119176
cb = get_cb_defense_object(args)
120177

@@ -126,6 +183,12 @@ def main():
126183
return export_policy(cb, parser, args)
127184
elif args.command_name == "delete":
128185
return delete_policy(cb, parser, args)
186+
elif args.command_name == "add-rule":
187+
return add_rule(cb, parser, args)
188+
elif args.command_name == "del-rule":
189+
return del_rule(cb, parser, args)
190+
elif args.command_name == "replace-rule":
191+
return replace_rule(cb, parser, args)
129192

130193

131194
if __name__ == "__main__":

src/cbapi/defense/models.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,19 @@ class Policy(DefenseMutableModel, CreatableModelMixin):
146146
_change_object_http_method = "PUT"
147147
_change_object_key_name = "policyId"
148148

149-
149+
@property
150+
def rules(self):
151+
return dict([(r.get("id"), r) for r in self.policy.get("rules", [])])
152+
153+
def add_rule(self, new_rule):
154+
self._cb.post_object("{0}/rule".format(self._build_api_request_uri()), {"ruleInfo": new_rule})
155+
self.refresh()
156+
157+
def delete_rule(self, rule_id):
158+
self._cb.delete_object("{0}/rule/{1}".format(self._build_api_request_uri(), rule_id))
159+
self.refresh()
160+
161+
def replace_rule(self, rule_id, new_rule):
162+
self._cb.put_object("{0}/rule/{1}".format(self._build_api_request_uri(), rule_id),
163+
{"ruleInfo": new_rule})
164+
self.refresh()

0 commit comments

Comments
 (0)