Skip to content

Commit 475fe55

Browse files
jason-wgcopybara-github
authored andcommitted
add get_rule v1alpha sample, and standardize code comments in other rules engine v1alpha samples APIs
PiperOrigin-RevId: 605144824
1 parent 1302d85 commit 475fe55

File tree

6 files changed

+213
-48
lines changed

6 files changed

+213
-48
lines changed

common/regions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,21 @@ def url(base_url: str, region: str) -> str:
5252
if region != "us":
5353
base_url = base_url.replace("https://", f"https://{region}-")
5454
return base_url
55+
56+
57+
def url_always_prepend_region(base_url: str, region: str) -> str:
58+
"""Returns a regionalized URL.
59+
60+
Args:
61+
base_url: URL pointing to Chronicle API
62+
region: region in which the target project is located
63+
64+
Returns:
65+
A string containing a regionalized URL. Unlike the url() function,
66+
this function always prepends region; this function also checks whether
67+
the URL already has the region prefix, and if so, returns the URL unchanged.
68+
v1alpha samples should use this function.
69+
"""
70+
if not base_url.startswith(f"https://{region}-"):
71+
base_url = base_url.replace("https://", f"https://{region}-")
72+
return base_url

common/regions_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ def test_url_europe(self):
3333
def test_url_us(self):
3434
self.assertEqual(regions.url("https://test", "us"), "https://test")
3535

36+
def test_url_always_prepend_region_us(self):
37+
self.assertEqual(
38+
regions.url_always_prepend_region("https://test", "us"),
39+
"https://us-test",
40+
)
41+
42+
def test_url_always_prepend_region_europe(self):
43+
self.assertEqual(
44+
regions.url_always_prepend_region("https://test", "europe"),
45+
"https://europe-test",
46+
)
47+
48+
def test_url_always_prepend_region_twice(self):
49+
url_once = regions.url_always_prepend_region("https://test", "europe")
50+
url_twice = regions.url_always_prepend_region(url_once, "europe")
51+
self.assertEqual(
52+
"https://europe-test",
53+
url_twice,
54+
)
55+
3656

3757
if __name__ == "__main__":
3858
unittest.main()

detect/v1alpha/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright 2024 Google LLC
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+
#

detect/v1alpha/create_rule.py

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,29 @@
1616
#
1717
r"""Executable and reusable sample for creating a detection rule.
1818
19-
HTTP request
20-
POST https://chronicle.googleapis.com/v1alpha/{parent}/rules
21-
22-
python3 -m detect.v1alpha.create_rule \
23-
--project_instance $project_instance \
24-
--project_id $PROJECT_ID \
25-
--rule_file=./ip_in_abuseipdb_blocklist.yaral
26-
27-
Requires the following IAM permission on the parent resource:
28-
chronicle.rules.create
29-
30-
API reference:
31-
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules/create
32-
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules#Rule
19+
Sample Commands (run from api_samples_python dir):
20+
python3 -m detect.v1alpha.create_rule \
21+
--region $region \
22+
--project_instance $project_instance \
23+
--project_id $PROJECT_ID \
24+
--rule_file=./path/to/rule/rulename.yaral
25+
26+
API reference:
27+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules/create
28+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules#Rule
3329
"""
3430

3531
import argparse
3632
import json
3733
from typing import Any, Mapping
3834

39-
from google.auth.transport import requests
40-
4135
from common import chronicle_auth
4236
from common import project_id
4337
from common import project_instance
4438
from common import regions
39+
from google.auth.transport import requests
40+
41+
CHRONICLE_API_BASE_URL = "https://chronicle.googleapis.com"
4542

4643
SCOPES = [
4744
"https://www.googleapis.com/auth/cloud-platform",
@@ -71,39 +68,20 @@ def create_rule(
7168
requests.exceptions.HTTPError: HTTP request resulted in an error
7269
(response.status_code >= 400).
7370
"""
71+
base_url_with_region = regions.url_always_prepend_region(
72+
CHRONICLE_API_BASE_URL,
73+
args.region
74+
)
7475
# pylint: disable-next=line-too-long
7576
parent = f"projects/{proj_id}/locations/{proj_region}/instances/{proj_instance}"
76-
url = f"https://{proj_region}-chronicle.googleapis.com/v1alpha/{parent}/rules"
77+
url = f"{base_url_with_region}/v1alpha/{parent}/rules"
78+
7779
body = {
7880
"text": rule_file_path.read(),
7981
}
82+
83+
# See API reference links at top of this file, for response format.
8084
response = http_session.request("POST", url, json=body)
81-
# Expected server response:
82-
# {
83-
# # pylint: disable=line-too-long
84-
# "name": "projects/{project}/locations/{location}/instances/{instance}/rules/{rule_id}",
85-
# "revisionId": "v_{10_digits}_{9_digits}",
86-
# "displayName": "{rule_name}",
87-
# "text": "{rule_content}",
88-
# "author": str,
89-
# "severity": {
90-
# "displayName": str
91-
# },
92-
# "metadata": {
93-
# "{key_1}": "{value_1}",
94-
# ...
95-
# },
96-
# "createTime": "yyyy-MM-ddThh:mm:ss.ssssssZ",
97-
# "revisionCreateTime": "yyyy-MM-ddThh:mm:ss.ssssssZ"
98-
# "compilationState": "SUCCEEDED",
99-
# "type": "{{SINGLE,MULTI}_EVENT,RULE_TYPE_UNSPECIFIED}",
100-
# "referenceLists": [str],
101-
# "allowedRunFrequencies": [
102-
# str,
103-
# ...
104-
# ],
105-
# "etag": str
106-
# }
10785
if response.status_code >= 400:
10886
print(response.text)
10987
response.raise_for_status()

detect/v1alpha/get_rule.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright 2024 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
r"""Executable sample for getting a rule.
18+
19+
Sample Commands (run from api_samples_python dir):
20+
python3 -m detect.v1alpha.get_rule -r=<region> -p=<project_id> \
21+
-i=<instance_id> -rid=<rule_id>
22+
23+
python3 -m detect.v1alpha.get_rule -r=<region> -p=<project_id> \
24+
-i=<instance_id> -rid=<rule_id>@v_<seconds>_<nanoseconds>
25+
26+
API reference:
27+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules/get
28+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules#Rule
29+
"""
30+
31+
import argparse
32+
import json
33+
34+
from typing import Any, Mapping
35+
from common import chronicle_auth
36+
from common import project_id
37+
from common import project_instance
38+
from common import regions
39+
from google.auth.transport import requests
40+
41+
CHRONICLE_API_BASE_URL = "https://chronicle.googleapis.com"
42+
43+
SCOPES = [
44+
"https://www.googleapis.com/auth/cloud-platform",
45+
]
46+
47+
48+
def get_rule(
49+
http_session: requests.AuthorizedSession,
50+
proj_region: str,
51+
proj_id: str,
52+
proj_instance: str,
53+
rule_id: str,
54+
) -> Mapping[str, Any]:
55+
"""Get a rule.
56+
57+
Args:
58+
http_session: Authorized session for HTTP requests.
59+
proj_region: region in which the target project is located
60+
proj_id: GCP project id or number which the target instance belongs to
61+
proj_instance: uuid of the instance (with dashes)
62+
rule_id: Unique ID of the detection rule to retrieve ("ru_<UUID>" or
63+
"ru_<UUID>@v_<seconds>_<nanoseconds>"). If a version suffix isn't
64+
specified we use the rule's latest version.
65+
66+
Returns:
67+
a rule object containing relevant rule's information
68+
Raises:
69+
requests.exceptions.HTTPError: HTTP request resulted in an error
70+
(response.status_code >= 400).
71+
"""
72+
base_url_with_region = regions.url_always_prepend_region(
73+
CHRONICLE_API_BASE_URL,
74+
args.region
75+
)
76+
# pylint: disable-next=line-too-long
77+
parent = f"projects/{proj_id}/locations/{proj_region}/instances/{proj_instance}"
78+
url = f"{base_url_with_region}/v1alpha/{parent}/rules/{rule_id}"
79+
80+
# See API reference links at top of this file, for response format.
81+
response = http_session.request("GET", url)
82+
if response.status_code >= 400:
83+
print(response.text)
84+
response.raise_for_status()
85+
return response.json()
86+
87+
88+
if __name__ == "__main__":
89+
parser = argparse.ArgumentParser()
90+
chronicle_auth.add_argument_credentials_file(parser)
91+
project_instance.add_argument_project_instance(parser)
92+
project_id.add_argument_project_id(parser)
93+
regions.add_argument_region(parser)
94+
parser.add_argument(
95+
"-rid",
96+
"--rule_id",
97+
type=str,
98+
required=True,
99+
help=(
100+
'rule ID to get rule for. can use both "ru_<UUID>" or'
101+
' "ru_<UUID>@v_<seconds>_<nanoseconds>"'
102+
),
103+
)
104+
args = parser.parse_args()
105+
auth_session = chronicle_auth.initialize_http_session(
106+
args.credentials_file,
107+
SCOPES
108+
)
109+
print(
110+
json.dumps(
111+
get_rule(
112+
auth_session,
113+
args.region,
114+
args.project_id,
115+
args.project_instance,
116+
args.rule_id
117+
),
118+
indent=2,
119+
)
120+
)

detect/v1alpha/list_rules.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,28 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616
#
17-
"""Executable and reusable sample for retrieving a list of rules."""
17+
r"""Executable and reusable sample for retrieving a list of rules.
18+
19+
Sample Commands (run from api_samples_python dir):
20+
python3 -m detect.v1alpha.list_rules -r=<region> \
21+
-p=<project_id> -i=<instance_id>
22+
23+
API reference:
24+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules/list
25+
https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.rules#Rule
26+
"""
1827

1928
import argparse
2029
import json
21-
from typing import Mapping, Any
22-
23-
from google.auth.transport import requests
30+
from typing import Any, Mapping
2431

2532
from common import chronicle_auth
2633
from common import project_id
2734
from common import project_instance
2835
from common import regions
36+
from google.auth.transport import requests
37+
38+
CHRONICLE_API_BASE_URL = "https://chronicle.googleapis.com"
2939

3040
SCOPES = [
3141
"https://www.googleapis.com/auth/cloud-platform",
@@ -51,10 +61,15 @@ def list_rules(
5161
requests.exceptions.HTTPError: HTTP request resulted in an error
5262
(response.status_code >= 400).
5363
"""
64+
base_url_with_region = regions.url_always_prepend_region(
65+
CHRONICLE_API_BASE_URL,
66+
args.region
67+
)
5468
# pylint: disable-next=line-too-long
5569
parent = f"projects/{proj_id}/locations/{proj_region}/instances/{proj_instance}"
56-
url = f"https://{proj_region}-chronicle.googleapis.com/v1alpha/{parent}/rules"
70+
url = f"{base_url_with_region}/v1alpha/{parent}/rules"
5771

72+
# See API reference links at top of this file, for response format.
5873
response = http_session.request("GET", url)
5974
if response.status_code >= 400:
6075
print(response.text)

0 commit comments

Comments
 (0)