Skip to content

Commit 4aa8e89

Browse files
authored
fix!: get_user_falco_rules now returns the text and is updated with the new API endpoint (#151)
* fix: Custom rules are now correctly set and retrieved as string * style: Change imports with concrete types * fix: Update get_secure_user_falco_rules example to match the changes * fix: Remove old outdated test
1 parent 6718738 commit 4aa8e89

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

examples/get_secure_user_falco_rules.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
# Return the result
3232
#
3333
if ok:
34-
sys.stdout.write(res["userRulesFile"]["content"])
34+
sys.stdout.write(res)
3535
else:
3636
print(res)
3737
sys.exit(1)

sdcclient/_secure.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,16 @@ def get_user_falco_rules(self):
6565
**Example**
6666
`examples/get_secure_user_falco_rules.py <https://github.com/draios/python-sdc-client/blob/master/examples/get_secure_user_falco_rules.py>`_
6767
'''
68-
return self._get_falco_rules("user")
68+
ok, res = self._get_user_falco_rules()
69+
return res if not ok else [True, res["customFalcoRulesFiles"]["files"][0]["variants"][0]["content"]]
70+
71+
def _get_user_falco_rules(self):
72+
res = requests.get(self.url + '/api/settings/falco/customRulesFiles', headers=self.hdrs, verify=self.ssl_verify)
73+
74+
if not self._checkResponse(res):
75+
return [False, self.lasterr]
76+
77+
return [True, (res.json())]
6978

7079
def _set_falco_rules(self, kind, rules_content):
7180
payload = self._get_falco_rules(kind)
@@ -111,7 +120,21 @@ def set_user_falco_rules(self, rules_content):
111120
`examples/set_secure_user_falco_rules.py <https://github.com/draios/python-sdc-client/blob/master/examples/get_secure_user_falco_rules.py>`_
112121
113122
'''
114-
return self._set_falco_rules("user", rules_content)
123+
ok, res = self._get_user_falco_rules()
124+
125+
if not ok:
126+
return res
127+
128+
res["customFalcoRulesFiles"]["files"][0]["variants"][0]["content"] = rules_content
129+
130+
res = requests.put(self.url + '/api/settings/falco/customRulesFiles', headers=self.hdrs,
131+
data=json.dumps(res), verify=self.ssl_verify)
132+
133+
if not self._checkResponse(res):
134+
return [False, self.lasterr]
135+
res_json = res.json()
136+
return [True, res_json["customFalcoRulesFiles"]["files"][0]["variants"][0]["content"]]
137+
115138

116139
# Only one kind for now called "default", but might add a "custom" kind later.
117140
def _get_falco_rules_files(self, kind):

specs/secure/custom_rules_spec.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import os
2+
3+
from expects import equal, expect, start_with, contain
4+
from mamba import before, context, description, it
5+
6+
from sdcclient import SdSecureClient
7+
from specs import be_successful_api_call
8+
9+
with description("Custom Rules") as self:
10+
with before.each:
11+
self.client = SdSecureClient(sdc_url=os.getenv("SDC_SECURE_URL", "https://secure.sysdig.com"),
12+
token=os.getenv("SDC_SECURE_TOKEN"))
13+
14+
with context("when the custom rules file exists"):
15+
with it("can be retrieved"):
16+
ok, res = self.client.get_user_falco_rules()
17+
18+
expect((ok, res)).to(be_successful_api_call)
19+
expect(res).to(start_with("####################\n# Your custom rules!\n####################\n"))
20+
21+
with it("can push custom rules"):
22+
_, previous_rules = self.client.get_user_falco_rules()
23+
empty_rules = self.empty_falco_rules()
24+
custom_rules = self.user_falco_rules()
25+
26+
ok, res = self.client.set_user_falco_rules(custom_rules)
27+
expect((ok, res)).to(be_successful_api_call)
28+
expect(res).to(equal(custom_rules))
29+
30+
ok, res = self.client.set_user_falco_rules(empty_rules)
31+
expect((ok, res)).to(be_successful_api_call)
32+
expect(res).to(equal(empty_rules))
33+
34+
ok, res = self.client.set_user_falco_rules(self.rules_without_header())
35+
expect((ok, res)).to(be_successful_api_call)
36+
# The endpoint automatically fills the header for the user.
37+
expect(res).to(start_with("####################\n# Your custom rules!\n####################\n\n"))
38+
expect(res).to(contain(self.rules_without_header()))
39+
40+
ok, res = self.client.set_user_falco_rules(previous_rules)
41+
expect((ok, res)).to(be_successful_api_call)
42+
expect(res).to(equal(previous_rules))
43+
44+
45+
def user_falco_rules(self):
46+
with open("fixtures/custom_rules.yaml", "r") as f:
47+
return f.read()
48+
49+
50+
def empty_falco_rules(self):
51+
return """####################
52+
# Your custom rules!
53+
####################
54+
55+
# Add new rules, like this one
56+
# - rule: A shell is run in a container
57+
# desc: An event will trigger every time you run a shell in a container
58+
# condition: evt.type = execve and evt.dir=< and container.id != host and proc.name = bash
59+
# output: "Suspect shell run in container (user=%user.name %container.info shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)"
60+
# priority: ERROR
61+
# tags: [shell]
62+
63+
# Or override any rule, macro, or list from the Default Rules
64+
"""
65+
66+
67+
def rules_without_header(self):
68+
return """\
69+
---
70+
- rule: "Testing rule"
71+
desc: "Description"
72+
condition: "always_true"
73+
output: "Sample output"
74+
priority: "WARNING"
75+
tags: []
76+
source: "syscall"
77+
"""

test/test_secure_apis.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ EOF
3535

3636
$SCRIPTDIR/../examples/set_secure_user_falco_rules.py $PYTHON_SDC_TEST_API_TOKEN /tmp/test_apis_user_rules.yaml
3737
$SCRIPTDIR/../examples/get_secure_user_falco_rules.py $PYTHON_SDC_TEST_API_TOKEN > /tmp/falco_rules.yaml
38-
diff /tmp/falco_rules.yaml /tmp/test_apis_user_rules.yaml
38+
# Removed comparison. The new endpoint automatically adds a header to the YAML file,
39+
# and this use case is already covered in the custom_rules_spec.py test file.
40+
# diff /tmp/falco_rules.yaml /tmp/test_apis_user_rules.yaml
3941

4042

4143
# Delete all policies and then get them. There should be none.

0 commit comments

Comments
 (0)