Skip to content

Commit c0af5fa

Browse files
authored
docs(webrisk-samples): init add samples and tests (#8810)
* docs(webrisk-samples): init add samples and tests * added pytest to requirements * added test and fixed lint errors * modified acc to review comments * modified acc to review comments * modified acc to review comments * deleted commented out code
1 parent c4441cb commit c0af5fa

9 files changed

+343
-0
lines changed

webrisk/snippets/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2022 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.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright 2022 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+
15+
# [START webrisk_compute_threatlist_diff]
16+
from google.cloud import webrisk_v1
17+
18+
19+
def compute_threatlist_diff(
20+
threat_type: webrisk_v1.ThreatType,
21+
version_token: bytes,
22+
max_diff_entries: int,
23+
max_database_entries: int,
24+
compression_type: webrisk_v1.CompressionType,
25+
) -> None:
26+
"""Gets the most recent threat list diffs. These diffs should be applied to a local database of
27+
hashes to keep it up-to-date.
28+
29+
If the local database is empty or excessively out-of-date,
30+
a complete snapshot of the database will be returned. This Method only updates a
31+
single ThreatList at a time. To update multiple ThreatList databases, this method needs to be
32+
called once for each list.
33+
34+
Args:
35+
threat_type: The threat list to update. Only a single ThreatType should be specified per request.
36+
threat_type = webrisk_v1.ThreatType.MALWARE
37+
38+
version_token: The current version token of the client for the requested list. If the
39+
client does not have a version token (this is the first time calling ComputeThreatListDiff),
40+
this may be left empty and a full database snapshot will be returned.
41+
42+
max_diff_entries: The maximum size in number of entries. The diff will not contain more entries
43+
than this value. This should be a power of 2 between 2**10 and 2**20.
44+
If zero, no diff size limit is set.
45+
max_diff_entries = 1024
46+
47+
max_database_entries: Sets the maximum number of entries that the client is willing to have in the local database.
48+
This should be a power of 2 between 2**10 and 2**20. If zero, no database size limit is set.
49+
max_database_entries = 1024
50+
51+
compression_type: The compression type supported by the client.
52+
compression_type = webrisk_v1.CompressionType.RAW
53+
"""
54+
55+
webrisk_client = webrisk_v1.WebRiskServiceClient()
56+
57+
constraints = webrisk_v1.ComputeThreatListDiffRequest.Constraints()
58+
constraints.max_diff_entries = max_diff_entries
59+
constraints.max_database_entries = max_database_entries
60+
constraints.supported_compressions = [compression_type]
61+
62+
request = webrisk_v1.ComputeThreatListDiffRequest()
63+
request.threat_type = threat_type
64+
request.version_token = version_token
65+
request.constraints = constraints
66+
67+
response = webrisk_client.compute_threat_list_diff(request)
68+
69+
# The returned response contains the following information:
70+
# https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#computethreatlistdiffresponse
71+
# Type of response: DIFF/ RESET/ RESPONSE_TYPE_UNSPECIFIED
72+
print(response.response_type)
73+
74+
# New version token to be used the next time when querying.
75+
print(response.new_version_token)
76+
77+
# Recommended next diff timestamp.
78+
print(response.recommended_next_diff)
79+
80+
print("Obtained threat list diff.")
81+
# [END webrisk_compute_threatlist_diff]

webrisk/snippets/noxfile_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2022 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+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7", "3.6"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {},
42+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==7.2.0

webrisk/snippets/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-cloud-webrisk==1.9.0

webrisk/snippets/search_hashes.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2022 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+
15+
# [START webrisk_search_hash]
16+
from google.cloud import webrisk_v1
17+
18+
19+
def search_hashes(hash_prefix: bytes, threat_type: webrisk_v1.ThreatType) -> None:
20+
"""Gets the full hashes that match the requested hash prefix.
21+
22+
This is used after a hash prefix is looked up in a threatList and there is a match.
23+
The client side threatList only holds partial hashes so the client must query this method
24+
to determine if there is a full hash match of a threat.
25+
26+
Args:
27+
hash_prefix: A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 hash.
28+
For JSON requests, this field is base64-encoded. Note that if this parameter is provided
29+
by a URI, it must be encoded using the web safe base64 variant (RFC 4648).
30+
Example:
31+
uri = "http://example.com"
32+
sha256 = sha256()
33+
sha256.update(base64.urlsafe_b64encode(bytes(uri, "utf-8")))
34+
hex_string = sha256.digest()
35+
36+
threat_type: The ThreatLists to search in. Multiple ThreatLists may be specified.
37+
For the list on threat types, see:
38+
https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threattype
39+
threat_type = [webrisk_v1.ThreatType.MALWARE, webrisk_v1.ThreatType.SOCIAL_ENGINEERING]
40+
"""
41+
webrisk_client = webrisk_v1.WebRiskServiceClient()
42+
43+
# Set the hashPrefix and the threat types to search in.
44+
request = webrisk_v1.SearchHashesRequest()
45+
request.hash_prefix = hash_prefix
46+
request.threat_types = [threat_type]
47+
48+
response = webrisk_client.search_hashes(request)
49+
50+
# Get all the hashes that match the prefix. Cache the returned hashes until the time
51+
# specified in threat_hash.expire_time
52+
# For more information on response type, see:
53+
# https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threathash
54+
for threat_hash in response.threats:
55+
print(threat_hash.hash)
56+
57+
print("Completed searching threat hashes.")
58+
59+
# [END webrisk_search_hash]

webrisk/snippets/search_uri.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2022 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+
15+
# [START webrisk_search_uri]
16+
from google.cloud import webrisk_v1
17+
18+
19+
def search_uri(uri: str, threat_type: webrisk_v1.ThreatType.MALWARE) -> None:
20+
"""Checks whether a URI is on a given threatList.
21+
22+
Multiple threatLists may be searched in a single query. The response will list all
23+
requested threatLists the URI was found to match. If the URI is not
24+
found on any of the requested ThreatList an empty response will be returned.
25+
26+
Args:
27+
uri: The URI to be checked for matches
28+
Example: "http://testsafebrowsing.appspot.com/s/malware.html"
29+
30+
threat_type: The ThreatLists to search in. Multiple ThreatLists may be specified.
31+
Example: threat_type = webrisk_v1.ThreatType.MALWARE
32+
"""
33+
webrisk_client = webrisk_v1.WebRiskServiceClient()
34+
35+
request = webrisk_v1.SearchUrisRequest()
36+
request.threat_types = [threat_type]
37+
request.uri = uri
38+
39+
response = webrisk_client.search_uris(request)
40+
if response.threat.threat_types:
41+
print(f"The URI has the following threat: {response}")
42+
return
43+
44+
print("The URL is safe!")
45+
# [END webrisk_search_uri]

webrisk/snippets/submit_uri.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2022 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+
15+
# [START webrisk_submit_uri]
16+
from google.cloud import webrisk_v1
17+
18+
19+
def submit_uri(project_id: str, uri: str) -> None:
20+
"""Submits a URI suspected of containing malicious content to be reviewed.
21+
22+
Returns a google.longrunning.Operation which, once the review is complete, is updated with its result.
23+
If the result verifies the existence of malicious content, the site will be added to the
24+
Google's Social Engineering lists in order to protect users that could get exposed to this
25+
threat in the future. Only allow-listed projects can use this method during Early Access.
26+
27+
Args:
28+
project_id: The name of the project that is making the submission.
29+
uri: The URI that is being reported for malicious content to be analyzed.
30+
uri = "http://testsafebrowsing.appspot.com/s/malware.html"
31+
"""
32+
webrisk_client = webrisk_v1.WebRiskServiceClient()
33+
34+
submission = webrisk_v1.Submission()
35+
submission.uri = uri
36+
37+
request = webrisk_v1.CreateSubmissionRequest()
38+
request.parent = f"projects/{project_id}"
39+
request.submission = submission
40+
41+
response = webrisk_client.create_submission(request)
42+
print(f"Submission response: {response}")
43+
44+
# [END webrisk_submit_uri]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright 2022 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+
import base64
15+
import hashlib
16+
import re
17+
18+
from _pytest.capture import CaptureFixture
19+
import google
20+
from google.cloud import webrisk_v1
21+
22+
from .compute_threatlist_diff import compute_threatlist_diff
23+
from .search_hashes import search_hashes
24+
from .search_uri import search_uri
25+
from .submit_uri import submit_uri
26+
27+
PROJECT = google.auth.default()[1]
28+
29+
30+
def test_search_uri_with_threat(capsys: CaptureFixture) -> None:
31+
search_uri("http://testsafebrowsing.appspot.com/s/malware.html", webrisk_v1.ThreatType.MALWARE)
32+
assert re.search("The URI has the following threat: ", capsys.readouterr().out)
33+
34+
35+
def test_search_uri_without_threat(capsys: CaptureFixture) -> None:
36+
search_uri("http://testsafebrowsing.appspot.com/malware.html", webrisk_v1.ThreatType.MALWARE)
37+
assert re.search("The URL is safe!", capsys.readouterr().out)
38+
39+
40+
def test_submit_uri(capsys: CaptureFixture) -> None:
41+
submit_uri(PROJECT, "http://testsafebrowsing.appspot.com/s/malware.html")
42+
assert re.search("Submission response: ", capsys.readouterr().out)
43+
44+
45+
def test_search_hashes(capsys: CaptureFixture) -> None:
46+
uri = "http://example.com"
47+
sha256 = hashlib.sha256()
48+
sha256.update(base64.urlsafe_b64encode(bytes(uri, "utf-8")))
49+
hex_string = sha256.digest()
50+
51+
search_hashes(hex_string, webrisk_v1.ThreatType.MALWARE)
52+
assert re.search("Completed searching threat hashes.", capsys.readouterr().out)
53+
54+
55+
def test_compute_threatdiff_list(capsys: CaptureFixture) -> None:
56+
compute_threatlist_diff(webrisk_v1.ThreatType.MALWARE, b'', 1024, 1024, webrisk_v1.CompressionType.RAW)
57+
assert re.search("Obtained threat list diff.", capsys.readouterr().out)

0 commit comments

Comments
 (0)